/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Netscape Public License * Version 1.0 (the "NPL"); you may not use this file except in * compliance with the NPL. You may obtain a copy of the NPL at * http://www.mozilla.org/NPL/ * * Software distributed under the NPL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL * for the specific language governing rights and limitations under the * NPL. * * The Initial Developer of this code under the NPL is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All Rights * Reserved. */ #include "CBrowserView.h" // need these for various routine calls #include "CHTMLClickrecord.h" #include "msgcom.h" //#include "proto.h" #include "RandomFrontEndCrap.h" #include "CBrowserContext.h" //#include "CBookmarksAttachment.h" #include "ufilemgr.h" #include "CURLDispatcher.h" #include "CEditorWindow.h" // cmd_EditFrame //#include "secnav.h" //#include "ntypes.h" //#include "shist.h" #include "macutil.h" #include "CViewUtils.h" //#include "CApplicationEventAttachment.h" //#include "uerrmgr.h" // GetPString prototype #include "CTargetFramer.h" extern "C" { #include "layout.h" } // ₯₯₯ I don't want to include this, but I need the ID of the popup menu #include "resgui.h" #include "CMochaHacks.h" #include "privacy.h" class CBrowserViewDoDragReceiveMochaCallback; void MochaDragDrop(MWContext* inContext, CBrowserViewDoDragReceiveMochaCallback * cb, Point inDragMouse, short inDragModifiers ); Boolean HasFTPUpload(CBrowserContext * context); // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ CBrowserView::CBrowserView(LStream* inStream) : CHTMLView(inStream) { } CBrowserView::~CBrowserView() { } void CBrowserView::MoveBy( Int32 inHorizDelta, Int32 inVertDelta, Boolean inRefresh) { Inherited::MoveBy(inHorizDelta, inVertDelta, inRefresh); if (mContext != NULL && (inHorizDelta || inVertDelta)) { SPoint32 location; GetFrameLocation(location); CMochaHacks::SendMoveEvent(*mContext, location.h, location.v); } } // --------------------------------------------------------------------------- // ₯ DrawSelf // --------------------------------------------------------------------------- void CBrowserView::DrawSelf(void) { Inherited::DrawSelf(); ExecuteAttachments(CTargetFramer::msg_DrawSelfDone, this); } /* BeTarget and DontBeTarget enable and disable the drawing of the selection. This has the effect of not drawing the text as selected when the view is not currently the target. Using LO_ClearSelection instead would have the same effect, but the selection wouldn't be recovered when the target is given back to the view (as in, when its window is deactivated then reactivated). */ // --------------------------------------------------------------------------- // ₯ ScrollImageBy // --------------------------------------------------------------------------- void CBrowserView::ScrollImageBy( Int32 inLeftDelta, Int32 inTopDelta, Boolean inRefresh ) { Boolean mayAutoScrollLeavingTurds = inRefresh && IsTarget(); //&& mDropRow; if (mayAutoScrollLeavingTurds) ExecuteAttachments(CTargetFramer::msg_ResigningTarget, this); Inherited::ScrollImageBy(inLeftDelta, inTopDelta, inRefresh); if (mayAutoScrollLeavingTurds && FocusDraw()) ExecuteAttachments(CTargetFramer::msg_BecomingTarget, this); } // --------------------------------------------------------------------------- // ₯ BeTarget // --------------------------------------------------------------------------- void CBrowserView::BeTarget() { LO_HighlightSelection (*mContext, TRUE); ExecuteAttachments(CTargetFramer::msg_BecomingTarget, this); } // --------------------------------------------------------------------------- // ₯ DontBeTarget // --------------------------------------------------------------------------- void CBrowserView::DontBeTarget() { // LO_ClearSelection (*mContext); LO_HighlightSelection (*mContext, FALSE); ExecuteAttachments(CTargetFramer::msg_ResigningTarget, this); } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // #pragma mark --- COMMANDER OVERRIDES --- // // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CBrowserView::FindCommandStatus(CommandT inCommand, Boolean &outEnabled, Boolean &outUsesMark, Char16 &outMark, Str255 outName) { if (::StillDown()) { if (FindCommandStatusForContextMenu(inCommand, outEnabled,outUsesMark, outMark, outName)) return; } MWContext *mwcontext; outUsesMark = false; CBrowserWindow *browserWindow = dynamic_cast(CViewUtils::GetTopMostSuperView(this)); Boolean isHTMLHelp = browserWindow ? browserWindow->IsHTMLHelp() : false; // Restricted targets are Netcaster things, right? #ifdef MOZ_NETCAST // Disable commands which don't apply to restricted targets, at the request of javascript. // No special distinction needed for floaters here. if (browserWindow && browserWindow->CommandsAreDisabled() && inCommand == cmd_EditFrame) { outEnabled = false; return; } #endif // MOZ_NETCAST switch (inCommand) { #ifdef EDITOR case cmd_EditFrame: mwcontext = *GetContext(); if (mwcontext && !(XP_IsContextBusy(mwcontext)) && !Memory_MemoryIsLow()) { // we must have a frameset if this context has a non-grid parent if ( XP_GetNonGridContext( mwcontext ) != mwcontext ) outEnabled = true && !isHTMLHelp; } break; #endif // EDITOR // case cmd_SecurityInfo: // case cmd_DocumentInfo: // outEnabled = true; // break; case cmd_FTPUpload: outEnabled = HasFTPUpload( GetContext() ) && !isHTMLHelp; break; case cmd_PrivDisplayPolicy: mwcontext = *GetContext(); if (mwcontext && !XP_IsContextBusy(mwcontext)) outEnabled = PRVCY_CurrentHasPrivacyPolicy(mwcontext); else outEnabled = false; break; case cmd_PrivDisplaySiteInfo: outEnabled = true; break; default: Inherited::FindCommandStatus(inCommand, outEnabled, outUsesMark, outMark, outName); break; } } Boolean CBrowserView::ObeyCommand(CommandT inCommand, void* ioParam) { Boolean cmdHandled = false; MWContext* mwcontext; switch (inCommand) { #ifdef EDITOR case cmd_EditFrame: CEditorWindow::MakeEditWindowFromBrowser( *GetContext() ); break; #endif // EDITOR // case cmd_SecurityInfo: // mwcontext = *GetContext(); // if (mwcontext) // { // URL_Struct* url = // SHIST_CreateURLStructFromHistoryEntry( // mwcontext, // GetContext()->GetCurrentHistoryEntry() // ); // if (url) // SECNAV_SecurityAdvisor(mwcontext,url); // } // break; case cmd_FTPUpload: { // NOTE - the backend currently only supports uploading the data fork // of a file. A planned feature of 5.0 is to support MacBinary // encoding during the upload process. To this end the routine // UStdDialogs::AskUploadAsDataOrMacBin has been created to prompt // for the desired upload mode in place of the call to // StandardGetFile below. FSSpec spec; History_entry * he = GetContext()->GetCurrentHistoryEntry(); char * fileURL = CFileMgr::EncodedPathNameFromFSSpec(spec, TRUE); OSType myTypes[3]; StandardFileReply myReply; UDesktop::Deactivate(); StandardGetFile(NULL, -1, myTypes, &myReply); UDesktop::Activate(); if (myReply.sfGood) { URL_Struct * request = NET_CreateURLStruct(he->address, NET_SUPER_RELOAD); char ** newFileList = (char **) XP_ALLOC(2 * sizeof(char*)); ThrowIfNil_(request); ThrowIfNil_(newFileList); request->method = URL_POST_METHOD; newFileList[0] = CFileMgr::EncodedPathNameFromFSSpec(myReply.sfFile, TRUE); ThrowIfNil_(newFileList[0]); newFileList[1] = NULL; request->files_to_post = newFileList; GetContext()->SwitchLoadURL( request, FO_CACHE_AND_PRESENT ); } cmdHandled = true; } break; // case cmd_DocumentInfo: // URL_Struct* aboutURL = NET_CreateURLStruct( "about:document", NET_DONT_RELOAD ); // if ( aboutURL ) // CURLDispatcher::GetURLDispatcher()->DispatchToView(mContext, aboutURL, FO_CACHE_AND_PRESENT, false, 1010, false); // break; case cmd_PrivDisplayPolicy: mwcontext = *GetContext(); char * url = PRVCY_GetCurrentPrivacyPolicyURL(mwcontext); URL_Struct* theURL = NET_CreateURLStruct(url, NET_DONT_RELOAD); if (theURL) FE_MakeNewWindow(NULL, theURL, NULL, NULL); cmdHandled = true; break; case cmd_PrivDisplaySiteInfo: mwcontext = *GetContext(); PRVCY_SiteInfo(mwcontext); cmdHandled = true; break; default: cmdHandled = Inherited::ObeyCommand(inCommand, ioParam); break; } return cmdHandled; } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // #pragma mark --- CONTEXTUAL POPUP --- // // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ Boolean CBrowserView::FindCommandStatusForContextMenu( CommandT inCommand, Boolean &outEnabled, Boolean &/*outUsesMark*/, Char16 &/*outMark*/, Str255 /*outName*/) { // We come here only if a CContextMenuAttachment is installed. (This is the new way). // Return true if we want to bypass standard status processing. if (!mCurrentClickRecord) return false; CHTMLClickRecord& cr = *mCurrentClickRecord; // for brevity. Boolean isAnchor = FALSE; Boolean isImage = FALSE; if (cr.mElement) { isAnchor = cr.IsAnchor(); isImage = cr.mElement->type == LO_IMAGE && NET_URL_Type(mContext->GetCurrentURL()) != FTP_TYPE_URL; } CBrowserWindow *browserWindow = dynamic_cast(CViewUtils::GetTopMostSuperView(this)); Boolean isHTMLHelp = browserWindow ? browserWindow->IsHTMLHelp() : false; // We're overloading command disabling to handle menu items too. Boolean commandsAreDisabled = browserWindow ? browserWindow->CommandsAreDisabled() : false; switch (inCommand) { case cmd_NEW_WINDOW_WITH_FRAME: outEnabled = ((MWContext (*mContext)).is_grid_cell && (mContext->GetCurrentHistoryEntry() != NULL)) && !isHTMLHelp; return true; case cmd_OPEN_LINK: outEnabled = isAnchor && !commandsAreDisabled; return true; case cmd_AddToBookmarks: if (isAnchor) outEnabled = !isHTMLHelp; return true; // for now, only have a "add bookmark for this link" command. // return isAnchor; // we don't know unless it's an anchor case cmd_NEW_WINDOW: #ifdef MOZ_MAIL_NEWS Boolean newWindowProhibited = ::MSG_NewWindowProhibited(*mContext, cr.mClickURL); #else // MSG_NewWindowProhibited doesn't exist in a non-mail/news world so just say // we don't prohibit creating a new window Boolean newWindowProhibited = false; #endif // MOZ_MAIL_NEWS outEnabled = !newWindowProhibited && isAnchor && !isHTMLHelp; return true; case cmd_SAVE_LINK_AS: outEnabled = isAnchor && !IsMailToLink(cr.mClickURL) && !isHTMLHelp; return true; // we don't know unless it's an anchor case cmd_COPY_LINK_LOC: outEnabled = (isAnchor && mCurrentClickRecord->mClickURL.length() > 0) && !isHTMLHelp; return true; case cmd_VIEW_IMAGE: outEnabled = isImage && !isHTMLHelp && !commandsAreDisabled; return true; case cmd_SAVE_IMAGE_AS: case cmd_COPY_IMAGE: case cmd_COPY_IMAGE_LOC: outEnabled = isImage && !isHTMLHelp; return true; case cmd_LOAD_IMAGE: outEnabled = isImage && !commandsAreDisabled; return true; } return false; // we don't know about it } // CBrowserView::FindCommandStatusForContextMenu // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // #pragma mark --- DRAG AND DROP --- // // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // Drag and drop is now reflected into javascript. On drag drop, the browser view // packages the URLs received into a new event and sends it to javascript with a // callback. If javascript lets us have the drop, the callback dispatches the URLs. Boolean CBrowserView::DragIsAcceptable(DragReference inDragRef) { Boolean doAccept = false; DragAttributes theAttributes = {0}; (void) GetDragAttributes(inDragRef, &theAttributes); doAccept = !(theAttributes & kDragInsideSenderWindow); if (doAccept) { doAccept = Inherited::DragIsAcceptable(inDragRef); } return doAccept; } Boolean CBrowserView::ItemIsAcceptable(DragReference inDragRef, ItemReference inItemRef) { FlavorFlags theFlags; Boolean doAccept = false; doAccept |= (::GetFlavorFlags(inDragRef, inItemRef, 'TEXT', &theFlags) == noErr); doAccept |= (::GetFlavorFlags(inDragRef, inItemRef, flavorTypeHFS, &theFlags) == noErr); return doAccept; } /* void CBrowserView::ReceiveDragItem(DragReference inDragRef, DragAttributes inDragAttrs, ItemReference inItemRef, Rect& inItemBounds) // In local coordinates { FlavorFlags theFlags; OSErr anError = noErr; URL_Struct* request = nil; anError = ::GetFlavorFlags(inDragRef, inItemRef, 'TEXT', &theFlags); if (anError == noErr) { long theDataSize = 0; char* theData = nil; ::GetFlavorDataSize(inDragRef, inItemRef, 'TEXT', &theDataSize); if (theDataSize > 255) // ₯₯₯Κare there any limits to the URL string length? { theDataSize = 255; } theData = (char*) ::NewPtr(theDataSize+1); // assert(theData != nil); ::GetFlavorData(inDragRef, inItemRef, 'TEXT', theData, &theDataSize, nil); theData[theDataSize] = 0; request = NET_CreateURLStruct(theData, NET_DONT_RELOAD); // assert(request != nil); ::DisposePtr(theData); } anError = ::GetFlavorFlags(inDragRef, inItemRef, flavorTypeHFS, &theFlags); if (anError == noErr) { long theDataSize = 0; HFSFlavor theData; char* localURL; ::GetFlavorDataSize(inDragRef, inItemRef, flavorTypeHFS, &theDataSize); ::GetFlavorData(inDragRef, inItemRef, flavorTypeHFS, &theData, &theDataSize, nil); localURL = CFileMgr::GetURLFromFileSpec(theData.fileSpec); // assert(localURL != nil); request = NET_CreateURLStruct(localURL, NET_DONT_RELOAD); // assert(request != nil); XP_FREE(localURL); } if (request != nil) { XP_MEMSET(&request->savedData, 0, sizeof(SHIST_SavedData)); CURLDispatcher::GetURLDispatcher()->DispatchToView(mContext, request, FO_CACHE_AND_PRESENT, false); } } */ /* * CBrowserViewDoDragReceiveMochaCallback * callback for DoDragReceive */ class CBrowserViewDoDragReceiveMochaCallback : public CMochaEventCallback { public: CBrowserViewDoDragReceiveMochaCallback( CBrowserView * view, XP_List* inRequestList, char** inURLArray) : fBrowserView(view), fRequestList(inRequestList), fURLArray(inURLArray) {} virtual void Complete(MWContext *, LO_Element * , int32 /*type*/, ETEventStatus status) { if (status == EVENT_OK) { fBrowserView->DoDragReceiveCallback(fRequestList ); } else if (status == EVENT_PANIC || status == EVENT_CANCEL) { // free the URL_Structs we created in DoDragReceive since they weren't dispatched. for (int i = 1; i <= XP_ListCount(fRequestList); i++) { URL_Struct* request = (URL_Struct *)XP_ListGetObjectNum(fRequestList, i); NET_FreeURLStruct(request); } } XP_ListDestroy(fRequestList); XP_FREE(fURLArray); } int LengthURLArray() { return XP_ListCount(fRequestList); } char** GetURLArray() { return fURLArray; } private: CBrowserView * fBrowserView; XP_List* fRequestList; char** fURLArray; }; // This is handled through a callback from javascript now. // Creates a list of the URL_Structs to process in the callback because the DragReference // will no longer be valid. void CBrowserView::DoDragReceive(DragReference inDragRef) { // This gets freed in the callback. XP_List* requestList = XP_ListNew(); if ( !requestList ) return; FlavorFlags theFlags; OSErr anError = noErr; URL_Struct* request = nil; Uint16 itemCount; // Number of Items in Drag ::CountDragItems(inDragRef, &itemCount); for (Uint16 item = 1; item <= itemCount; item++) { ItemReference itemRef; ::GetDragItemReferenceNumber(inDragRef, item, &itemRef); // First check if this has a TEXT flavor. If so, this is either a URL dragged from // another app or a text clipping dragged from the desktop. Either way, we need // to guarantee that we don't try below to read the drop as an HFSFlavor // (which a clipping also has). anError = ::GetFlavorFlags(inDragRef, itemRef, 'TEXT', &theFlags); if (anError == noErr) { long theDataSize = 0; char* theData = nil; ::GetFlavorDataSize(inDragRef, itemRef, 'TEXT', &theDataSize); if (theDataSize > 1024) // ₯₯₯Κare there any limits to the URL string length? theDataSize = 1024; theData = (char*) ::NewPtr(theDataSize+1); // assert(theData != nil); if (theData != NULL) { ::GetFlavorData(inDragRef, itemRef, 'TEXT', theData, &theDataSize, nil); theData[theDataSize] = 0; request = NET_CreateURLStruct(theData, NET_DONT_RELOAD); if (request != NULL) XP_ListAddObjectToEnd(requestList, request); // assert(request != nil); ::DisposePtr(theData); } } // if has TEXT flavor else { // if this item was not a clipping or dragged text, then process it as an HTML // file long theDataSize = 0; HFSFlavor theData; char* localURL; Boolean ignore1, ignore2; ::GetFlavorDataSize(inDragRef, itemRef, flavorTypeHFS, &theDataSize); anError = ::GetFlavorData(inDragRef, itemRef, flavorTypeHFS, &theData, &theDataSize, nil); if (anError == badDragFlavorErr) anError = GetHFSFlavorFromPromise (inDragRef, itemRef, &theData, true); if (anError == noErr) { if (HasFTPUpload(GetContext())) { History_entry * he = GetContext()->GetCurrentHistoryEntry(); if (!request) { request = NET_CreateURLStruct(he->address, NET_SUPER_RELOAD); request->method = URL_POST_METHOD; } QueueFTPUpload(theData.fileSpec, request); } else { // if there's an error resolving the alias, the local file url will refer to the alias itself. ::ResolveAliasFile(&theData.fileSpec, true, &ignore1, &ignore2); localURL = CFileMgr::GetURLFromFileSpec(theData.fileSpec); // assert(localURL != nil); if (localURL != NULL) { request = NET_CreateURLStruct(localURL, NET_DONT_RELOAD); if (request != NULL) XP_ListAddObjectToEnd(requestList, request); // assert(request != nil); XP_FREE(localURL); } } } // if we are sure this is a file. } // if not a clipping or text } // for each drag item // After all that, do we have any files to post? if (HasFTPUpload(GetContext()) && request->files_to_post) XP_ListAddObjectToEnd(requestList, request); if (requestList != NULL) { int numItems = XP_ListCount(requestList); int size = sizeof(char*) * (numItems + 1); char ** urlArray = (char**)XP_ALLOC(size); XP_ASSERT(urlArray); int i; for (i = 0; i < numItems; i++) { // the URL_Struct already has the url allocated so use that. URL_Struct* request = (URL_Struct *)XP_ListGetObjectNum(requestList, i+1); // XP_Lists are 1-indexed urlArray[i] = request->address; } urlArray[i] = 0; Point dragMouse; short dragModifiers; ::GetDragMouse(inDragRef, &dragMouse, NULL); ::GetDragModifiers(inDragRef, &dragModifiers, NULL, NULL); MochaDragDrop(*mContext, new CBrowserViewDoDragReceiveMochaCallback(this, requestList, urlArray), dragMouse, dragModifiers); } // if requestList has things to process } // CBrowserView :: DoDragReceive // Dispatch the urls collected in DoDragReceive. // This is executed if javascript lets us have the event. void CBrowserView::DoDragReceiveCallback(XP_List* inRequestList) { for (int i = 1; i <= XP_ListCount(inRequestList); i++) { URL_Struct* request = (URL_Struct *)XP_ListGetObjectNum(inRequestList, i); if (request != nil) { XP_MEMSET(&request->savedData, 0, sizeof(SHIST_SavedData)); //CURLDispatcher::GetURLDispatcher()->DispatchToView(mContext->GetTopContext(mContext), //request, FO_CACHE_AND_PRESENT, false); // We need this to be delayed so that we can confirm ftp drag & drop since we can't confirm //inside the drag handler // CURLDispatcher::GetURLDispatcher()->DispatchToView(mContext->GetTopContext(mContext), //request, FO_CACHE_AND_PRESENT, false, 1010, true); CURLDispatcher::DispatchURL(request, mContext->GetTopContext(), true); } } } // Mocha allows drag receive to be cancelled, so send a dragdrop message. void MochaDragDrop(MWContext* inContext, CBrowserViewDoDragReceiveMochaCallback * cb, Point inDragMouse, short inDragModifiers) { JSEvent* event = XP_NEW_ZAP(JSEvent); if (event != NULL) { // event's data field is an array of urls. event->type = EVENT_DRAGDROP; event->data = (void *)cb->GetURLArray(); event->dataSize = cb->LengthURLArray(); event->screenx = inDragMouse.h; event->screeny = inDragMouse.v - ::GetMBarHeight(); event->modifiers = CMochaHacks::MochaModifiers(inDragModifiers); ET_SendEvent( inContext, 0, event, CMochaEventCallback::MochaCallback, cb ); } } // True if we might be able to do FTP upload. Boolean HasFTPUpload(CBrowserContext * context) { History_entry * he = context->GetCurrentHistoryEntry(); return (he && !strncasecomp(he->address, "ftp", 3) && he->address[strlen(he->address)-1] == '/' ); } // Adds file for FTP file upload void CBrowserView::QueueFTPUpload(const FSSpec & spec, URL_Struct* request) { FSSpec theResolvedSpec = spec; Boolean isFolder; Boolean wasAliased; // If we drop the whole HD, allow bailout if (CmdPeriod()) return; // If it's an alias to a folder - skip it! if (::ResolveAliasFile(&theResolvedSpec, TRUE, &isFolder, &wasAliased) == noErr && isFolder && wasAliased) return; // If it is a folder, add it recursively if (CFileMgr::IsFolder(spec)) { FSSpec newSpec; FInfo dummy; Boolean dummy2; CFileIter iter((FSSpec&)spec); while (iter.Next(newSpec, dummy, dummy2)) QueueFTPUpload(newSpec, request); return; } // We want to use the resolved alias spec here so we get the right file name char * fileURL = CFileMgr::EncodedPathNameFromFSSpec(theResolvedSpec, TRUE); // Add file argument to the URL struct (queued up as the fLatentRequest // Duplicate the current file list int newFilePos = 0; char ** newFileList; if (request->files_to_post) while (request->files_to_post[newFilePos] != NULL) newFilePos++; newFileList = (char **) XP_ALLOC((newFilePos+2) * sizeof(char*)); ThrowIfNil_(newFileList); for (int i = 0; i < newFilePos; i++) newFileList[i] = request->files_to_post[i]; // Add the new member newFileList[newFilePos] = fileURL; newFileList[newFilePos + 1] = NULL; if (request->files_to_post) XP_FREE(request->files_to_post); request->files_to_post = newFileList; } #pragma mark - // // DragIsAcceptable // // Since this is smack-dab in the middle of the chrome and shows only what we want // it to show, don't let the user drag urls here (say from bookmarks) and launch them. // Boolean CAdSpaceView :: DragIsAcceptable ( DragReference inDragRef ) { return false; } // DragIsAcceptable