/* -*- 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 "stdafx.h" #include "npapi.h" #include "np.h" #include "npassoc.h" #include "edview.h" #include "prefapi.h" #include "hiddenfr.h" #include "extgen.h" #define ASYNC_DNS #ifndef _AFXDLL #define new DEBUG_NEW // MSVC Debugging new...goes to regular new in release mode #endif CMapStringToOb DNSCacheMap(sizeof(CDNSObj)); extern char *FE_FindFileExt(char * path); /* Remove all objects from the dns cache map */ PUBLIC void FE_DeleteDNSList(MWContext * currentContext) { POSITION pos; CString key; CDNSObj *obj = NULL; /* Get the starting position. Actually, whether the position returned is actually the start is irrelevant. */ pos = DNSCacheMap.GetStartPosition(); while (pos) { /* GetNextAssoc sets pos to another position in the map. Again, we don't care where we just want to know that another position exists so we can continue removing objs. */ DNSCacheMap.GetNextAssoc(pos, key, (CObject *&)obj); /* Only delete from the list if the current context owns the particular lookup. */ if(obj->context == currentContext) { /* Only delete the dns object if there are no more sockets in the sock list */ if (XP_ListCount(obj->m_sock_list) == 0) { DNSCacheMap.RemoveKey(key); delete obj; } } } } int FE_AsyncDNSLookup(MWContext *context, char * host_port, PRHostEnt ** hoststruct_ptr_ptr, PRFileDesc *socket) { // Initialize our DNS objects. CDNSObj * dns_obj=NULL; *hoststruct_ptr_ptr = NULL; // Look up and see if the host is in our cached DNS lookups and if so.... if (DNSCacheMap.Lookup(host_port,(CObject *&)dns_obj)) { // See if the cached value was an error, and if so, return an error. // Should we retry the lookup if it was? if (dns_obj->m_iError != 0 && dns_obj->i_finished != 0) { // DNS error WSASetLastError(dns_obj->m_iError); DNSCacheMap.RemoveKey(host_port); // Only delete the dns object if there are no // more sockets in the sock list if (dns_obj && XP_ListCount(dns_obj->m_sock_list) == 0) delete dns_obj; return -1; } // If this isn't NULL, then we have a good match. Return it as such and clear the context. else if (dns_obj->m_hostent->h_name != NULL && dns_obj->i_finished != 0) { *hoststruct_ptr_ptr = (PRHostEnt *)dns_obj->m_hostent; return 0; } // There isn't an error, and there isn't a host name, return that we are waiting for the // lookup.... This doesn't make clear sense, unless you take into account that the // hostent structure is empty when another window is also looking this same host up, // so we return that we are waiting too. else { /* see if the socket we are looking up is already in * the socket list. If it isn't, add it. * The socket list provides us with a way to * send events to NET_ProcessNet for each socket * waiting for a lookup */ XP_List * list_ptr = dns_obj->m_sock_list; PRFileDesc *tmp_sock; if(list_ptr) list_ptr = list_ptr->next; while(list_ptr) { tmp_sock = (PRFileDesc *) list_ptr->object; if(tmp_sock == socket) return MK_WAITING_FOR_LOOKUP; list_ptr = list_ptr->next; } /* socket not in the list, add it */ XP_ListAddObject(dns_obj->m_sock_list, (void *) socket); return MK_WAITING_FOR_LOOKUP; } } else { // There is no cache entry, begin the async dns lookup. // Capture the current window handle, we pass this to the async code, for passing // back a message when the lookup is complete. // Actually, just pass the application's main window to avoid // needing a frame window to do DNS lookups. HWND hWndFrame = AfxGetApp()->m_pMainWnd->m_hWnd; // Create and initialize our dns object. Allocating hostent struct, host name and port string, // and error code from the lookup. dns_obj = new CDNSObj(); dns_obj->m_hostent = (struct hostent *)XP_ALLOC(MAXGETHOSTSTRUCT * sizeof(char)); if(dns_obj->m_hostent) { memset(dns_obj->m_hostent, 0, MAXGETHOSTSTRUCT * sizeof(char)); } dns_obj->m_host = XP_STRDUP(host_port); dns_obj->m_sock_list = XP_ListNew(); dns_obj->context = context; XP_ListAddObject(dns_obj->m_sock_list, (void *) socket); // Insert the entry into the cached DNS lookups. // Also, set the context, and actually begin the DNS lookup. // Return that we're waiting for it to complete. if( !(dns_obj->m_handle = WSAAsyncGetHostByName(hWndFrame, msg_FoundDNS, dns_obj->m_host, (char *)dns_obj->m_hostent, MAXGETHOSTSTRUCT) ) ) { delete dns_obj; return -1; } DNSCacheMap.SetAt(host_port,dns_obj); return MK_WAITING_FOR_LOOKUP; } } CDNSObj::CDNSObj() { // make sure we're clean. m_hostent = NULL; m_host = NULL; m_handle = NULL; context = NULL; m_iError = 0; i_finished = 0; m_sock_list = 0; } CDNSObj::~CDNSObj() { if(m_hostent) { XP_FREE(m_hostent); m_hostent = NULL; } if(m_host) { XP_FREE(m_host); m_host = NULL; } if (m_sock_list) { while (XP_ListRemoveTopObject(m_sock_list)) ; XP_ListDestroy(m_sock_list); } } #ifdef DEBUG char * NOT_NULL (const char *x) { if(!x) { TRACE("Panic! -- An assert of NOT_NULL is about to fail\n"); } ASSERT(x); return (char *)x; } #endif // converts a URL to a local (8+3) filename // the return must be freed by caller char * fe_URLtoLocalName(const char * url, const char *pMimeType) { CString *csURL, csExt,csName; // Determine the extension. char aExt[_MAX_EXT]; size_t stExt = 0; DWORD dwFlags = 0; #ifdef XP_WIN16 dwFlags = EXT_DOT_THREE; #endif aExt[0] = '\0'; stExt = EXT_Invent(aExt, sizeof(aExt), dwFlags, url, pMimeType); csExt = aExt; int idx; csURL = new CString(url); int iQuestionMark = csURL->Find('?'); int iPound = csURL->Find('#'); int iEnd; if ((iQuestionMark > 0) && (iPound > 0)) // wow both! *csURL = csURL->Left(min(iQuestionMark,iPound)); else if ((iQuestionMark > 0) || (iPound > 0)) { // 1 or the other if (iQuestionMark > 0) iEnd = iQuestionMark; else if (iPound > 0) iEnd = iPound; *csURL = csURL->Left(iEnd); } int iDot = csURL->ReverseFind('.'); int iSlash = csURL->ReverseFind('/'); if (iSlash > 0) { if (iDot < iSlash) { if( iSlash == csURL->GetLength() -1 ){ // CLM: If here, there was no filename after last slash // so lets try to make a name from end of URL path *csURL = csURL->Left(iSlash); iSlash = csURL->ReverseFind('/'); } if (iSlash > 0) { csName = csURL->Right(csURL->GetLength() - iSlash -1); } iDot = 0; } else csName = csURL->Mid(iSlash+1, iDot-iSlash-1); } // Should we really return NULL? // There will be cases that don't fit, and does this mean that they won't be able to save a file // locally since a name can't be formulated? if (csName.IsEmpty()) { delete(csURL); return NULL; } #ifdef XP_WIN16 csName = csName.Left(8); #endif char *name = csName.GetBuffer(0); // replace extra periods in 8 character name with underscores for (idx =0 ; idx < csName.GetLength(); idx++) { #ifdef XP_WIN16 if ((name[idx] == '.')||(name[idx] == ':')) name[idx] = '_'; #else // Long filename fix, allow multiple periods for Win32. // brian@inforum.net (Brian Wiles) if(':' == name[idx]) { name[idx] = '_'; } #endif } csName.ReleaseBuffer(-1); *csURL = csName + csExt; char *cp_retval = strdup((const char *)*csURL); delete csURL; return(cp_retval); } char* FE_URLToLocalName( char *pStr ){ return fe_URLtoLocalName( (const char*)pStr, NULL); } #ifdef XP_WIN16 PUBLIC void * WIN16_malloc(unsigned long size) { if((size <= 0) || (size > 64000)) { TRACE("WIN16_malloc() FUN FUN FUN %ld\n", size); return(NULL); } void *Ret = malloc((size_t) size); if (!Ret) TRACE("WIN16_malloc() failed to alloc %ld bytes\n", size); return(Ret); } PUBLIC void * WIN16_realloc(void * ptr, unsigned long size) { if((size <= 0) || (size > 64000)) { TRACE("WIN16_realloc() FUN FUN FUN %ld\n", size); return(NULL); } void * Ret = realloc(ptr, (size_t) size); if (!Ret) TRACE("WIN16_realloc() failed to realloc %ld bytes\n", size); return(Ret); } PUBLIC void WIN16_bcopy(char * from_ptr, char * to_ptr, unsigned long size) { if((!to_ptr) || (size > 64000)) { TRACE("WIN16_bcopy() FUN FUN FUN %ld\n", size); return; } memmove(to_ptr, from_ptr, (size_t) size); } #endif /* XP_WIN16 */ // // Add a temporary file to the list of files that get deleted on exit // void FE_DeleteFileOnExit(const char *pFilename, const char *pURL) { // Remember the information in the INI file. CString csFileName = pFilename; csFileName.MakeLower(); theApp.WriteProfileString("Temporary File URL Resolution", csFileName, pURL); } // // We are exiting now. Clean up any temp files we have generated // void FE_DeleteTempFilesNow() { char *pBuffer = new char[8192]; theApp.GetPrivateProfileString("Temporary File URL Resolution", NULL, "", pBuffer, 8192, AfxGetApp()->m_pszProfileName); // We have a double null terminated list of file names here. // Go ahead and go through each one, deleteing them all. char *pTraverse = pBuffer; int iRemoveResult = 0; while(*pTraverse != '\0') { // Remove this file. iRemoveResult = remove(pTraverse); ASSERT(!iRemoveResult); // Go on to the next entry. while(*pTraverse != '\0') { pTraverse++; } pTraverse++; } delete[] pBuffer; // Clear out the section in the INI file also. #ifdef XP_WIN16 ::WritePrivateProfileString("Temporary File URL Resolution", NULL, NULL, AfxGetApp()->m_pszProfileName); #else // To clear them out in the Registry, use RegDeleteKey. // Create the appropriate key. HKEY hKey; DWORD dwDisposition; char aBuffer[256]; sprintf(aBuffer, "Software\\%s\\%s", "Netscape", "Netscape Navigator"); long lResult = RegCreateKeyEx(HKEY_CURRENT_USER, aBuffer, NULL, NULL, NULL, KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition); if(lResult != ERROR_SUCCESS) { return; } RegDeleteKey(hKey, "Temporary File URL Resolution"); RegCloseKey(hKey); #endif } // // Since netlib is too stubborn to give us a flush cache function do it // by hand // PUBLIC void FE_FlushCache() { int32 prefInt; NET_SetMemoryCacheSize(0); PREF_GetIntPref("browser.cache.memory_cache_size",&prefInt); NET_SetMemoryCacheSize(prefInt * 1024); } void CheckLegalFileName(char* full_path) { CString temp = full_path; #ifdef XP_WIN16 static char funnychar[13] = "\\/:*?\"<>| ,+"; #else static char funnychar[10] = "\\/:*?\"<>|"; #endif int index; while ((index = temp.FindOneOf(funnychar)) != -1) { temp.SetAt(index, '_'); // replace the illegal char with space. } strcpy(full_path, temp); } int SetCurrentDir(char * pDir) { if( pDir ){ #ifdef XP_WIN16 // We need to double "\" characters when setting directory char dir[2*_MAX_PATH]; char * pSource = pDir; char * pDest = dir; while( *pSource ){ *pDest++ = *pSource; if( *pSource == '\\' ){ *pDest++ = '\\'; } pSource++; } *pDest = '\0'; // This is SLOW ( > 5 sec) on Win95! return _chdir(dir); #else BOOL bRet = SetCurrentDirectory(pDir); return bRet ? 0 : -1; #endif // XP_WIN16 } return -1; } // // Get a save file name from the user // If caller has an idea for the name it should be passed in initial else // initial should be NULL // Return a pointer (to be freed by callee) of full path name else NULL if // the selection was canceled // It is up to the user to free the filename // //CLM: Why the ?#$% is type passed in as a pointer??? // If pDocumentTitle is not null, then edit box is added to allow user to enter document title for edited documents MODULE_PRIVATE char * wfe_GetSaveFileName(HWND m_hWnd, char * prompt, char * initial, int * type, char** ppPageTitle) { OPENFILENAME fname; char * full_path; char name[2 * _MAX_FNAME]; char filter[256]; char * extension = NULL; char * pOldExt = NULL; int index = 1; Bool bAppendHTML_Ext = FALSE; BOOL bHtmlOnly = FALSE; char aIExt[_MAX_EXT]; // We restrict saving type to HTML in the editor CString htm_filter_used; // Only pre-4.0 version show the file filter bug BOOL bBadNT = sysInfo.m_bWinNT && sysInfo.m_dwMajor < 4; if(type && *type == HTM_ONLY){ bHtmlOnly = TRUE; if (bBadNT) htm_filter_used.LoadString(IDS_FILTERNT_HTM); else #ifdef XP_WIN16 htm_filter_used.LoadString(IDS_FILTER_HTM16); #else htm_filter_used.LoadString(IDS_FILTER_HTM32); #endif } else { if (bBadNT) // For NT, use same string as 16bit htm_filter_used.LoadString(IDS_HTM_FILTER16); else #ifdef XP_WIN16 htm_filter_used.LoadString(IDS_HTM_FILTER16); #else htm_filter_used.LoadString(IDS_HTM_FILTER32); #endif } // Default is to use the filter that includes *.htm/*.html, *.txt, and *.* strcpy(filter, htm_filter_used); // try to guess the type if(initial) { if( bHtmlOnly || strcasestr(initial, "htm") || strcasestr(initial, "html")) { /*__EDITOR__*/ // Use ".html" for 32-bit versions #ifdef XP_WIN16 extension = "htm"; #else extension = "html"; #endif if( bHtmlOnly ){ // This will force replacing any existing EXT with value "extension" bAppendHTML_Ext = TRUE; } /*__EDITOR__END*/ index = 1; } else if(strcasestr(initial, "gif")) { strcpy(filter, szLoadString(IDS_GIF_FILTER)); extension = "gif"; index = 1; } else if(strcasestr(initial, "xbm")) { strcpy(filter, szLoadString(IDS_XBM_FILTER)); extension = "xbm"; index = 1; } else if(strcasestr(initial, "jpg") || strcasestr(initial, "jpeg")) { #ifdef XP_WIN16 strcpy(filter, szLoadString(IDS_JPG_FILTER16)); #else strcpy(filter, szLoadString(IDS_JPG_FILTER32)); #endif extension = "jpg"; index = 1; } else if(strcasestr(initial, "txt")) { strcpy(filter, htm_filter_used); //htm_filter extension = "txt"; index = 2; } else if(strcasestr(initial, "p12")) { extension = "p12"; strcpy(filter, szLoadString(IDS_PKCS12_FILTER)); } else { extension = aIExt; aIExt[0] = '\0'; size_t stExt = 0; DWORD dwFlags = EXT_NO_PERIOD; #ifdef XP_WIN16 dwFlags |= EXT_DOT_THREE; #endif stExt = EXT_Invent(aIExt, sizeof(aIExt), dwFlags, initial, NULL); if(!stExt) { extension = NULL; } if(extension) { strcpy(filter, szLoadString(IDS_ALL_FILTER)); } else { // We have a name but no extension // Use the list for HTML files, *.txt, or *.* if ( !type || (*type == 0 || *type == ALL || *type == HTM || *type == HTM_ONLY) ) { // If HTM was requested type or no type requested, then build // a better suggested name bAppendHTML_Ext = TRUE; } } // Show *.htm as initial filter index = 1; } } if( (!initial && type && (*type == HTM || *type == HTM_ONLY)) || bAppendHTML_Ext ){ bAppendHTML_Ext = TRUE; // no initial name --- assume HTML if it was requested type index = 1; // Use ".html" for 32-bit versions #ifdef XP_WIN16 extension = "htm"; #else extension = "html"; #endif } else if (!initial && type && (*type == P12)) { extension = "p12"; strcpy(filter, szLoadString(IDS_PKCS12_FILTER)); } else if(!initial) { extension = "*"; index +=2; } // Replace '\n' with '\0' before pass to FileCommon dialog for (char *p = filter; *p ; p++) { if (*p == '\n') *p = '\0'; } // space for the full path name full_path = (char *) XP_ALLOC(2 * _MAX_PATH * sizeof(char)); if(!full_path) return(NULL); // clear stuff out name[0] = '\0'; full_path[0] = '\0'; char aDrive[_MAX_DRIVE]; char aPath[_MAX_PATH]; char aFName[_MAX_FNAME]; char aExt[_MAX_EXT]; CString defaultDir; BOOL bUsingDefault = FALSE; BOOL bUsingEditorDir = FALSE; char *fileName = initial; #ifdef XP_WIN16 char dosFileName[13]; #endif if(fileName) { #ifdef XP_WIN16 // convert file name to be 8.3 char *ext = FE_FindFileExt(fileName); // Fill with 0 to assure proper termination memset(dosFileName, 0, 13*sizeof(char)); if( ext ){ char *firstDot = strchr(fileName, '.'); if ((firstDot - fileName) > 8) // chop it to 8 characters firstDot = fileName+8; strncpy(dosFileName, fileName, (firstDot-fileName)); strncpy(dosFileName+(firstDot-fileName), ext, min(strlen(ext), 4)); fileName = dosFileName; } else if( strlen(fileName) > 8 ){ strncpy(dosFileName, fileName, 8); fileName = dosFileName; } #endif _splitpath(fileName, aDrive, aPath, aFName, aExt); XP_STRCPY(full_path, aFName); if(bAppendHTML_Ext){ // Here's where we build the better suggested name XP_STRCAT(full_path, "."); XP_STRCAT(full_path, extension); } else { XP_STRCAT(full_path, aExt); } defaultDir += aDrive; defaultDir += aPath; } char currentDir[_MAX_PATH+1]; char * HaveCurrentDir = NULL; char dir[_MAX_PATH]; if (defaultDir.IsEmpty()) { int iLen = _MAX_PATH; if(bHtmlOnly){ PREF_GetCharPref("editor.html_directory",dir,&iLen); bUsingEditorDir = TRUE; // Save current directory to restore later // This is Win16 Compatable (GetCurrentDirectory is available for Win32) HaveCurrentDir = _getdcwd(0, currentDir, _MAX_PATH); } else { PREF_GetCharPref("browser.download_directory",dir,&iLen); bUsingDefault = TRUE; } defaultDir = dir; } CheckLegalFileName(full_path); memset(&fname, 0, sizeof(fname)); fname.lStructSize = sizeof(OPENFILENAME); fname.hwndOwner = m_hWnd; fname.lpstrFilter = filter; fname.lpstrCustomFilter = NULL; fname.nFilterIndex = index; fname.lpstrFile = full_path; fname.nMaxFile = 2 * _MAX_PATH; fname.lpstrFileTitle = name; fname.nMaxFileTitle = 2 * _MAX_FNAME; fname.lpstrInitialDir = defaultDir; fname.lpstrTitle = prompt; fname.lpstrDefExt = extension; fname.Flags = OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST; BOOL bResult = FEU_GetSaveFileName(&fname); // see if the user selects a file or hits cancel if(bResult) { if (bUsingDefault || bUsingEditorDir ) { char *full_dir = (char *) XP_STRDUP(full_path); full_dir[fname.nFileOffset] = '\0'; if( bUsingDefault ){ PREF_SetCharPref("browser.download_directory", full_dir); } else { PREF_SetCharPref("editor.html_directory", full_dir); if( HaveCurrentDir ){ SetCurrentDir(currentDir); } } XP_FREE(full_dir); } // tell the caller if the user selected to save this as text // if a source file and we want to save as text pass it back else // just pass back that we want to save it as source if(type) { if(filter == htm_filter_used && fname.nFilterIndex == TXT) *type = TXT; else *type = HTM; } // tack the extension on at the end if the name doesn't have one // the Win9x dialog is not really respecting the DefExt as // explained in the help files char * pLastBit = strrchr(full_path, '\\'); if(!pLastBit) pLastBit = full_path; else pLastBit++; // skip over slash // figure out if the user has put an extension on the path name char * pNewExt = strrchr(pLastBit, '.'); // Common dialog will act incorrectly if user uses ".shtml". // We get the following: "fname.shtml.html" so strip off the ".html" if(pNewExt && !_stricmp(pNewExt, ".html")) { *pNewExt = '\0'; char * pExt = strrchr(pLastBit, '.'); if(pExt && !_stricmp(pExt, ".shtml")){ // We found the user's ".shtml", so return truncated version return(full_path); } // ".shtml" not found - restore the period *pNewExt = '.'; } // // so we have a new extension that is not equal to the original one // // see if it ends .txt if so then the user really wanted to save a text file // no matter what the selector is set to. Damn Win9x guidelines if(pNewExt && !_stricmp(pNewExt, ".txt")) { if(type) *type = TXT; return(full_path); } return(full_path); } else { // user hit cancel if( full_path) XP_FREE(full_path); return(NULL); } } // Appends the specified filter description and pattern to the end of szFilterString, // adding double NULL at the end. szFilterString must be a double NULL terminated // string upon entry // // This routine doesn't add a duplicate to the list of description/patterns that are // already there void wfe_AppendToFilterString(char* szFilterString, char* szDescription, char* szPattern) { if(!szFilterString || !szDescription || !szPattern) return; // Find the end of the existing filter (double NULL terminated). While we're at it, // check for an existing entry that's an exact match char* pStr = szFilterString; BOOL bDescriptionMatches; while (*pStr != '\0') { // See if the description matches bDescriptionMatches = stricmp(pStr, szDescription) == 0; // Skip over the description and get the filter pattern pStr = strchr(pStr, '\0') + 1; // Filter description and pattern really must exist as a pair ASSERT(*pStr != '\0'); if (*pStr == '\0') break; // found the double NULL terminator // If the description matched, then check the filter pattern if (bDescriptionMatches && stricmp(pStr, szPattern) == 0) return; // don't add a duplicate string // Skip over the filter pattern and get the next pair pStr = strchr(pStr, '\0') + 1; } // At this point we're pointing to the second NULL terminator. Add the new // description to the end strcpy(pStr, szDescription); // Append the filter pattern, leaving the NULL terminator at the end of the // description pStr += strlen(szDescription) + 1; strcpy(pStr, szPattern); // Add a final NULL terminator pStr += strlen(szPattern) + 1; *pStr = '\0'; } // Appends the szFilterAppendString to the end of the szFilterString, adding // double NULL at the end. szFilterString must be a double NULL terminated string // upon entry. szFilterAppendString must also be a double NULL terminated string void wfe_AppendFilterStringToFilterString(char* szFilterString, char* szFilterAppendString) { if((szFilterString == NULL) || (szFilterAppendString == NULL)) return; // find the end of the existing filter, (double NULL) // szFilterString MUST be a double NULL term'd string or bad things happen char* pCharFilterString = szFilterString; while(!((*pCharFilterString == '\0') && (*(pCharFilterString + 1) == '\0'))) pCharFilterString++; if(pCharFilterString != szFilterString) // if the string is not empty pCharFilterString++; // start at the second NULL // find the size of the szFilterAppendString char* pCharString = szFilterAppendString; int iStringSize = 0; while(!((*pCharString == '\0') && (*(pCharString + 1) == '\0'))) { pCharString++; iStringSize++; } // append the szFilterAppendString to the filter memcpy(pCharFilterString, szFilterAppendString, iStringSize); // double NULL terminate the string pCharFilterString += iStringSize; *pCharFilterString = '\0', pCharFilterString++, *pCharFilterString = '\0'; } static BOOL IsNullPlugin(NPFileTypeAssoc* pAssociation) { // The null plug-in is the default plug-in handler and has the wildcard // '*' as it's file extent return pAssociation->extentstring && strcmp(pAssociation->extentstring, "*") == 0; } // // construct a filter string from all the plugins file associations, and // from the previous filter template // //CLM: Modified this to allow restricting filter to just *.HTM;*.HTML // Use HTM_ONLY (-1) instead of HTM // char* wfe_ConstructFilterString(int type) { #ifdef MOZ_NGLAYOUT XP_ASSERT(0); return NULL; #else NPFileTypeAssoc* pAssociation = NULL; if (type != HTM_ONLY){ // get the list of associations for all plugin MIME types // ONLY if we are not looking for just HTM/HTML files (used for Editor) pAssociation = NPL_GetFileAssociation(NULL); } char filter[256]; int iFilterSize; // Pre-4.0 NT Common Dialog has a bug: *.htm;*.html shows ".htm" files as ".html" if ( sysInfo.m_bWinNT && sysInfo.m_dwMajor < 4 ) { if(type == HTM_ONLY) strcpy(filter, szLoadString(IDS_FILTERNT_HTM)); else strcpy(filter, szLoadString(IDS_FILTERNT)); iFilterSize = strlen(filter); } else { if (type == HTM_ONLY) #ifdef XP_WIN16 strcpy(filter, szLoadString(IDS_FILTER_HTM16)); #else strcpy(filter, szLoadString(IDS_FILTER_HTM32)); #endif else if(type == P12) strcpy(filter, szLoadString(IDS_PKCS12_FILTER)); else #ifdef XP_WIN16 strcpy(filter, szLoadString(IDS_FILTER16)); #else strcpy(filter, szLoadString(IDS_FILTER32)); #endif iFilterSize = strlen(filter); } // Replace '\n' with '\0' before pass to CommDialog for (char *p = filter; *p ; p++) if (*p == '\n') *p = '\0'; if(pAssociation == NULL) { char* pString = NULL; if(iFilterSize) { pString = (char *)XP_ALLOC(iFilterSize); } if(pString) { memcpy(pString, filter, iFilterSize); } return pString; } // Determine how much memory to allocate. The filter string consists of pairs of NULL // terminated strings. The first string describes the filter and the second string // specifies the filter pattern int iAccumulator = 0; do { if (pAssociation->fileType && pAssociation->extentlist) { // Add in space for the filter description iAccumulator += strlen((const char*)pAssociation->fileType); // NULL terminator between filter desciption and filter pattern iAccumulator++; // Determine the space needed for the filter pattern. There can be multiple // filter patterns per filter description by separating the filter patterns // with a semicolon for (char** ppExtentList = pAssociation->extentlist; *ppExtentList;) { // The extent list is just the file extension. The filter pattern should // include a "*." iAccumulator += strlen("*.") + strlen(*ppExtentList); // If there's another filter pattern then add a semicolon delimiter if (*++ppExtentList) iAccumulator++; } // Space for NULL terminating the filter pattern string iAccumulator++; } pAssociation = pAssociation->pNext; } while(pAssociation); // Add in room for the basic template (this size includes the final NULL // terminator) iAccumulator += iFilterSize; char* pFilterString = (char *) XP_ALLOC(iAccumulator); if (pFilterString) { // Start off with an empty filter string pFilterString[0] = '\0'; pFilterString[1] = '\0'; // Add the basic template wfe_AppendFilterStringToFilterString(pFilterString, filter); pAssociation = NPL_GetFileAssociation(NULL); // Add the plugin filters for (pAssociation = NPL_GetFileAssociation(NULL); pAssociation; pAssociation = pAssociation->pNext) { if (IsNullPlugin(pAssociation)) continue; if (pAssociation->fileType && pAssociation->extentlist) { // Build the filter pattern(s). There can be multiple filter patterns for a // filter description by separating the filter patterns with a semicolon CString strFilterPattern; for (char** ppExtentList = pAssociation->extentlist; *ppExtentList;) { // The extent list is just the file extension. The filter pattern should // include a "*." strFilterPattern += "*."; strFilterPattern += *ppExtentList; // If there's another filter pattern then add a semicolon delimiter if (*++ppExtentList) strFilterPattern += ';'; } // Add the filter description and filter pattern if it doesn't already exist // in the list. You can end up with duplicates if there is a plug-in that registers // more than one MIME type for a given extension, e.g. audio/aiff and audio/x-aiff wfe_AppendToFilterString(pFilterString, (char*)pAssociation->fileType, (char*)(const char*)strFilterPattern); } } } return pFilterString; #endif } #ifdef XP_WIN16 PRIVATE void wfe_InplaceToLower(char *pConvert) { while (pConvert && *pConvert) { *pConvert = XP_TO_LOWER(*pConvert); pConvert++; } } #endif // // Return the path name of a file the user has picked for a given task // It is up to the user to free the filename // The file must exist // Return NULL if the user cancels // If pOpenIntoEditor is not null, then radio buttons are added to select window type // set initial choice and read user's choice from this MODULE_PRIVATE char * wfe_GetExistingFileName(HWND m_hWnd, char * prompt, int type, XP_Bool bMustExist, BOOL * pOpenIntoEditor) { OPENFILENAME fname; char * full_path = NULL; char name[_MAX_FNAME]; char * defaultDir = NULL; char* filter = wfe_ConstructFilterString(type); /* initialize the OPENFILENAME struct */ BOOL result; UINT index = (type == HTM_ONLY) ? 1 : type; // space for the full path name full_path = (char *) XP_ALLOC(_MAX_PATH * sizeof(char)); if(!full_path){ XP_FREE(filter); return(NULL); } name[0] = '\0'; full_path[0] = '\0'; char currentDir[_MAX_PATH+1]; char * HaveCurrentDir = NULL; char dir[_MAX_PATH]; if(type == HTM_ONLY){ int iLen = _MAX_PATH; PREF_GetCharPref("editor.html_directory",dir,&iLen); defaultDir = dir; // Save current directory to restore later HaveCurrentDir = _getdcwd(0, currentDir, _MAX_PATH); } // set up the entries fname.lStructSize = sizeof(OPENFILENAME); fname.hwndOwner = m_hWnd; fname.lpstrFilter = filter; fname.lpstrCustomFilter = NULL; fname.nFilterIndex = index; fname.lpstrFile = full_path; fname.nMaxFile = _MAX_PATH; fname.lpstrFileTitle = name; fname.nMaxFileTitle = _MAX_FNAME; fname.lpstrInitialDir = defaultDir; fname.lpstrTitle = prompt; fname.Flags = OFN_HIDEREADONLY; fname.lpstrDefExt = NULL; if(bMustExist) fname.Flags |= OFN_FILEMUSTEXIST; result = FEU_GetOpenFileName(&fname); XP_FREE(filter); // see if the user selects a file or hits cancel if(result) { // On win16 force to lower case. #ifdef XP_WIN16 wfe_InplaceToLower(full_path); #endif if(type == HTM_ONLY){ char *full_dir = (char *) XP_STRDUP(full_path); full_dir[fname.nFileOffset] = '\0'; PREF_SetCharPref("editor.html_directory",full_dir); XP_FREE(full_dir); if( HaveCurrentDir ){ SetCurrentDir(currentDir); } } return(full_path); } else { // user hit cancel if(full_path) XP_FREE(full_path); return(NULL); } } // CLM: Similar to wfe_GetExistingFileName(), // but designed to select Image Files: *.jpg, *.gif // // Return the path name of a file the user has picked for a given task // It is up to the user to free the filename // Return NULL if the user cancels // MODULE_PRIVATE char * wfe_GetExistingImageFileName(HWND m_hWnd, char * prompt, XP_Bool bMustExist) { OPENFILENAME fname; char * full_path; char name[_MAX_FNAME]; char filter[256]; #ifdef XP_WIN16 strcpy(filter, szLoadString(IDS_IMAGE_FILTER16)); #else strcpy(filter, szLoadString(IDS_IMAGE_FILTER32)); #endif // replace '\n' with '\0' before pass to CommonDialog for (char *p = filter; *p ; p++) if (*p == '\n') *p = '\0'; /* initialize the OPENFILENAME struct */ // space for the full path name full_path = (char *) XP_ALLOC(_MAX_PATH * sizeof(char)); if(!full_path) return(NULL); name[0] = '\0'; full_path[0] = '\0'; // Save current directory to restore later char currentDir[_MAX_PATH+1]; char * HaveCurrentDir = _getdcwd(0, currentDir, _MAX_PATH); char defaultDir[_MAX_PATH]; int iLen = _MAX_PATH; PREF_GetCharPref("editor.image_directory",defaultDir,&iLen); // set up the entries fname.lStructSize = sizeof(OPENFILENAME); fname.hwndOwner = m_hWnd; fname.lpstrFilter = filter; fname.lpstrCustomFilter = NULL; fname.nFilterIndex = 0; fname.lpstrFile = full_path; fname.nMaxFile = _MAX_PATH; fname.lpstrFileTitle = name; fname.nMaxFileTitle = _MAX_FNAME; fname.lpstrInitialDir = defaultDir; fname.lpstrTitle = prompt; fname.Flags = OFN_HIDEREADONLY; fname.lpstrDefExt = NULL; if(bMustExist) fname.Flags |= OFN_FILEMUSTEXIST; // see if the user selects a file or hits cancel if(FEU_GetOpenFileName(&fname)) { // On win16 force to lower case. #ifdef XP_WIN16 wfe_InplaceToLower(full_path); #endif char *full_dir = (char *) XP_STRDUP(full_path); full_dir[fname.nFileOffset] = '\0'; PREF_SetCharPref("editor.image_directory",full_dir); XP_FREE(full_dir); if( HaveCurrentDir ){ SetCurrentDir(currentDir); } return(full_path); } else { // user hit cancel XP_FREE(full_path); return(NULL); } } // Just need a stub. Always fail // extern "C" int dupsocket(int foo) { return(-1); } // INTL_ResourceCharSet(void) // extern "C" char *INTL_ResourceCharSet(void) { return szLoadString(IDS_RESOURCE_CHARSET) ; }