home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / winfe / fegui.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  112.7 KB  |  3,875 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. #include "stdafx.h"
  20.  
  21. #include "res\appicon.h"
  22. #include "dialog.h"
  23. #include "mainfrm.h"
  24. #include "custom.h"
  25. #include "shcut.h"
  26. #include "edt.h"
  27. #include "prmon.h"
  28. #include "fegui.h"
  29. #include "prefapi.h"
  30. #include <io.h>
  31. #include "secrng.h"
  32. #include "mailmisc.h"
  33. #include "ipframe.h"
  34. #include "mnprefs.h"
  35.  
  36. //xpstrsw header is for resource switcher that will hold the proper instance handle for each stringloaded
  37. #include "xpstrsw.h"
  38.  
  39. #ifndef _AFXDLL
  40. #define new DEBUG_NEW  // MSVC Debugging new...goes to regular new in release mode
  41. #endif
  42. #ifdef __BORLANDC__
  43.     #define _lseek lseek
  44. #endif
  45.        
  46. MODULE_PRIVATE char * XP_CacheFileName();
  47.  
  48. static HPALETTE ghPalette = NULL;
  49. static CMapWordToPtr gBitmapMap;
  50. static HFONT ghFont = NULL;
  51.  
  52. // Load a string, stored as RCDATA, from the resource file. The
  53. // caller must free the pointer that is returned
  54. char *
  55. wfe_LoadResourceString (LPCSTR lpszName)
  56. {
  57.     HRSRC    hrsrc;
  58.     HGLOBAL    hRes;
  59.     LPSTR    lpszString;
  60.  
  61.     hrsrc = ::FindResource(AfxGetResourceHandle(), lpszName, RT_RCDATA);
  62.  
  63.     if (!hrsrc) {
  64.         TRACE1("wfe_LoadResourceString cannot find resource: %s\n", lpszName);
  65.         return NULL;
  66.     }
  67.  
  68.     hRes = ::LoadResource(AfxGetResourceHandle(), hrsrc);
  69.  
  70.     if (!hRes) {
  71.         TRACE1("wfe_LoadResourceString cannot load resource: %s\n", lpszName);
  72.         return NULL;        
  73.     }
  74.  
  75.     lpszString = (LPSTR)::LockResource(hRes);
  76.  
  77.     if (!lpszString) {
  78.         TRACE1("wfe_LoadResourceString cannot lock resource: %s\n", lpszName);
  79.         ::FreeResource(hRes);
  80.         return NULL;
  81.     }
  82.  
  83.     // Return a copy of the string
  84.     lpszString = XP_STRDUP(lpszString);
  85.  
  86. #ifndef XP_WIN32    
  87.     ::UnlockResource(hRes);
  88. #endif
  89.     ::FreeResource(hRes);
  90.     return lpszString;
  91. }
  92.  
  93. #define MAXSTRINGLEN 8192 
  94. // Load a string from resource table
  95. //Added pSwitcher to allow us to dictate which HINSTANCE to load the string from.  if NULL, we use AfxGetResourceHandle
  96. //mjudge 10-30-97
  97. char * szLoadString( UINT iID , ResourceSwitcher *pSwitcher/*=NULL*/)
  98. {
  99.     // These strings MUST be static so they don't live on the stack.  Since we
  100.     // will be returning a pointer to one of these strings, we want the info
  101.     // to be there once we exit this function
  102.     // This implements a circular buffer: its size depends on how many times the
  103.     // szLoadString function will be called in a single function call.  For
  104.     // example, if you do this:
  105.     //
  106.     //   MessageBox ( NULL, 
  107.     //                szLoadString(IDS_ERROR1), 
  108.     //                szLoadString(IDS_MSGBOXTITLE), 
  109.     //                MB_OK );
  110.     //
  111.     // We need at least 2 strings here.  We should be safe with four.
  112.  
  113.     static int iWhichString = 0;
  114.     static char *szLoadedStrings[4] = { NULL, NULL, NULL, NULL };
  115.  
  116.     if ( !szLoadedStrings[iWhichString] ) {
  117.         szLoadedStrings[iWhichString] = new char[MAXSTRINGLEN];
  118.     }
  119.  
  120.     // This implements a circular buffer using the four strings. This means that
  121.     // the pointer you get back from szLoadString will have the correct string in
  122.     // it until szLoadString has been called four more times.
  123.  
  124.     char *szLoadedString = szLoadedStrings[iWhichString];
  125.     iWhichString = (iWhichString + 1) % 4;
  126.  
  127.     szLoadedString[0] = 0;  // Init the string to emptyville.
  128.  
  129.     // This allows loading of strings greater than 255 characters. If the
  130.     // first character of the string is an exclamation point, this means to
  131.     // tack on the string with a value of ID+1.  This continues until
  132.     // the next string does not exist or the first character is not an
  133.     // exclamation point
  134.  
  135.     // These are just normal local variables used for looping and return values
  136.     // and string magic
  137.     char szLoadBuffer[256];
  138.  
  139.     BOOL bKeepLoading;
  140.     HINSTANCE hResourceHandle;
  141.     if (NULL== pSwitcher)
  142.         hResourceHandle=AfxGetResourceHandle();
  143.     else
  144.         hResourceHandle=pSwitcher->GetResourceHandle();
  145.     do {
  146.         bKeepLoading = FALSE;
  147.         if (LoadString ( hResourceHandle, iID, szLoadBuffer, sizeof(szLoadBuffer))) {
  148.  
  149.  
  150.             if ('!' == *szLoadBuffer) {
  151.                 // Continuation char found. Keep the loop going
  152.                 bKeepLoading = TRUE;
  153.                 // Assume next entry in string table is in numerical order
  154.                 iID++;
  155.                 strcat ( szLoadedString, szLoadBuffer + 1 );
  156.             } else {
  157.                 strcat ( szLoadedString, szLoadBuffer );
  158.             }
  159.         }
  160.     } while (bKeepLoading);
  161.  
  162.     return szLoadedString;
  163. }
  164.  
  165. #ifdef XP_WIN16
  166. #define INVALID_HANDLE_VALUE NULL 
  167.  
  168. //  16 Bit FindFirstFile, second parameter void *b must be of type struct
  169. //   _find_t *.  Return value if successful will just be this same
  170. //   structure, otherwise INVALID_HANDLE_VALUE.
  171.  
  172. PRIVATE char *cp_filesystems = "\\*.*";
  173.  
  174. //  See _dos_findfirst on how to read the structure _find_t members.
  175. void * 
  176. FindFirstFile(const char * a, void * b) 
  177. {
  178.   //  First off, our void * coming in is actually a dirStruct.
  179.   auto dirStruct *dSp = (dirStruct *)b;
  180.   
  181.   //  See if the dir we're looking at is a root of a file system; string indicates this.
  182.   //  If so, we have to hack a way to provide drive letters and such in the listing.
  183.   if(XP_STRCMP(a, cp_filesystems) == 0) {
  184.     dSp->c_checkdrive = 'A';
  185.   }
  186.   else  {
  187.     //  +2 because +1 means to return false in find next.
  188.     dSp->c_checkdrive = 'Z' + 2;
  189.   }
  190.   
  191.   //  If we're going after the root, then we have to loop through all the drives until we find one....  Ugh.
  192.   //  The way to tell if we're currently looking for file systems, is if c_checkdrive is a valid drive letter.
  193.   if(dSp->c_checkdrive == 'A')  {
  194.     //  Save the drive we're on currently.
  195.     auto int i_current = _getdrive();
  196.     
  197.     while(dSp->c_checkdrive <= 'Z') {
  198.       //  If we can change to a drive, then it is valid.
  199.       //  I would think that there is a better way to do this, but all the examples that I've seen do this
  200.       //    exact thing.
  201.       if(_chdrive(dSp->c_checkdrive - 'A' + 1) == 0)  {
  202.         break;
  203.       }
  204.       
  205.       //  Drive we checked wasn't valid.  Go on to the next one.
  206.       dSp->c_checkdrive++;
  207.     }
  208.     
  209.     //  Restore the original drive.
  210.     _chdrive(i_current);
  211.     
  212.     //  If we found a valid drive, we need to dup it's name in the findfirst stuff to pass it back in the name field.
  213.     //  Also, increment on to the next drive.
  214.     //  Members of the _find_t data structure aren't set up correctly....  They don't seem to be referenced anywhere,
  215.     //    so I'm not going to bother.
  216.     if(dSp->c_checkdrive <= 'Z')  {
  217.       dSp->file_data.name[0] = dSp->c_checkdrive;
  218.       dSp->file_data.name[1] = '|';
  219.       dSp->file_data.name[2] = '\0';
  220.       
  221.       dSp->c_checkdrive++;
  222.       
  223.       //  Just return b, as it is the void dSp, and we will soon be seeing it again in findnext....
  224.       return(b);
  225.     }
  226.     
  227.     //  If we found no valid drives, then we need to return an invalid state.
  228.     return(INVALID_HANDLE_VALUE);
  229.   }
  230.  
  231.   //  Specify what type of files you'd like to find.  See _dos_findfirst.
  232.   auto unsigned u_finding = _A_NORMAL | _A_RDONLY | _A_ARCH | _A_SUBDIR;
  233.   
  234.   if(_dos_findfirst(a, u_finding, &(dSp->file_data)) == 0)  {
  235.     //  Success, just return the structure containing the info.
  236.     //  b should not be altered!  Only read information from the
  237.     //  structure.
  238.  
  239.     return(b);
  240.   }
  241.   
  242.   return(INVALID_HANDLE_VALUE);
  243. }
  244.  
  245. int 
  246. FindNextFile(void * a, void * b)
  247. {
  248.   //  a and b are actually the same.
  249.   //  Check to see if we are still searching drives from findfirst.
  250.   auto dirStruct *dSp = (dirStruct *)a;
  251.   
  252.   if(dSp->c_checkdrive <= 'Z')  {
  253.     //  Save the drive we're on currently.
  254.     auto int i_current = _getdrive();
  255.     
  256.     while(dSp->c_checkdrive <= 'Z') {
  257.       //  If we can change to a drive, then it is valid.
  258.       if(_chdrive(dSp->c_checkdrive - 'A' + 1) == 0)  {
  259.         break;
  260.       }
  261.       
  262.       //  Drive we checked wasn't valid.  Go on to the next one.
  263.       dSp->c_checkdrive++;
  264.     }
  265.     
  266.     //  Restore the original drive.
  267.     _chdrive(i_current);
  268.     
  269.     //  If we found a valid drive, we need to dup it's name in the findfirst stuff to pass it back in the name field.
  270.     //  Also, increment on to the next drive.
  271.     //  Members of the _find_t data structure aren't set up correctly....  They don't seem to be referenced anywhere,
  272.     //    so I'm not going to bother.
  273.     if(dSp->c_checkdrive <= 'Z')  {
  274.       dSp->file_data.name[0] = dSp->c_checkdrive;
  275.       dSp->file_data.name[1] = '|';
  276.       dSp->file_data.name[2] = '\0';
  277.       
  278.       dSp->c_checkdrive++;
  279.       
  280.       //  Just return as findnext
  281.       return(TRUE);
  282.     }
  283.   }
  284.   
  285.   if(dSp->c_checkdrive == 'Z' + 1)  {
  286.     //  Special case where we will stop looking for file systems to list.  Return as though we failed.
  287.     return(FALSE);
  288.   }
  289.  
  290.   //  Just call _dos_findnext with a, since a and b are actually the
  291.   //  same.  Return true if successful.
  292.   if(_dos_findnext(&(dSp->file_data)) == 0) {
  293.     return(TRUE);
  294.   }
  295.   return(FALSE);
  296.  
  297. void 
  298. FindClose(void * a)
  299. {
  300.   //  Do nothing.  It's up to the caller to get rid of *a since we
  301.   //  created nothing.
  302. }
  303.  
  304. #endif
  305.  
  306. //
  307. // Return a string the same as the In string but with all of the \n's replaced
  308. //  with \r\n's 
  309. //
  310. MODULE_PRIVATE char * 
  311. FE_Windowsify(const char * In)
  312. {
  313.     char *Out;
  314.     char *o, *i; 
  315.     int32 len;
  316.  
  317.     if(!In)
  318.         return NULL;
  319.  
  320.     // if every character is a \n then new string is twice as long
  321.     len = (int32) XP_STRLEN(In) * 2 + 1;
  322.     Out = (char *) XP_ALLOC(len);
  323.     if(!Out)
  324.         return NULL;
  325.  
  326.   // Move the characters over one by one.  If the current character is
  327.   //  a \n replace add a \r before moving the \n over
  328.     for(i = (char *) In, o = Out; i && *i; *o++ = *i++)
  329.        if(*i == '\n')
  330.             *o++ = '\r';
  331.  
  332.     // Make sure our new string is NULL terminated
  333.     *o = '\0';
  334.     return(Out);
  335. }
  336.  
  337. // middle cuts string into a string of iNum length.  If bModifyString is
  338. // FALSE (the default), a copy is made which the caller must free
  339. PUBLIC char * fe_MiddleCutString(char *pString ,int iNum, BOOL bModifyString)
  340. {
  341.     ASSERT(pString);
  342.     if (!pString)
  343.         return NULL;
  344.  
  345.     // If the caller wants us to allocate a new string, just dup the string
  346.     // that was passed in since the result can't be any longer
  347.     if (!bModifyString) {
  348.         pString = strdup(pString);
  349.  
  350.         if (!pString) {
  351.             TRACE0("fe_MiddleCutString: strdup failed!\n");
  352.             return NULL;
  353.         }
  354.     }
  355.  
  356.     // Make sure the length to cut to is something sensible
  357.     ASSERT(iNum > 3);
  358.     if (iNum <= 3)
  359.         return pString;  // don't bother...
  360.  
  361.     // We need to call i18n function for multibyte charset (e.g. Japanese SJIS)
  362.     //
  363.     int16 csid = CIntlWin::GetSystemLocaleCsid();
  364.     if (csid & MULTIBYTE) {
  365.         INTL_MidTruncateString (csid, pString, pString, iNum);
  366.         return pString;
  367.     }
  368.  
  369.     // See if there is any work to do
  370.     int    nLen = strlen(pString);
  371.  
  372.     if (nLen > iNum) {
  373.         int    nLeftChars = (iNum - 3) / 2;
  374.         int    nRightChars = iNum - 3 - nLeftChars;
  375.  
  376.         // Insert the ellipsis
  377.         pString[nLeftChars] = '.';
  378.         pString[nLeftChars + 1] = '.';
  379.         pString[nLeftChars + 2] = '.';
  380.  
  381.         // Use the right "nRightChars" characters
  382.         strcpy(pString + nLeftChars + 3, pString + nLen - nRightChars);
  383.     }
  384.  
  385.     return pString;
  386. }
  387.  
  388. /* puts up a FE security dialog
  389.  *
  390.  * Should return TRUE if the url should continue to
  391.  * be loaded
  392.  * Should return FALSE if the url should be aborted
  393.  */
  394. PUBLIC Bool  
  395. FE_SecurityDialog(MWContext * context, int message, XP_Bool *prefs_toggle)
  396. {
  397.  
  398.     if (theApp.m_bKioskMode)
  399.         return TRUE;
  400.  
  401.     if(context) {
  402.         CDialogSecurity box(message, prefs_toggle, ABSTRACTCX(context)->GetDialogOwner());
  403.     return(box.DoModal());
  404.     } else {
  405.         CDialogSecurity box(message, prefs_toggle, NULL);
  406.     return(box.DoModal());
  407.     }
  408. }
  409.  
  410. // Save the cipher preference to the preferences file
  411. // XXX - jsw - remove me
  412. extern "C" void
  413. FE_SetCipherPrefs(MWContext *context, char *cipher)
  414. {
  415. }
  416.  
  417. // Retrieve the cipger preferences. The caller is expected to free
  418. // the returned string
  419. // XXX - jsw - remove me
  420. extern "C" char *
  421. FE_GetCipherPrefs(void)
  422. {
  423.     return NULL;
  424. }
  425.  
  426. //  Return some spanked out full path on the mac.
  427. //  For windows, we just return what was passed in.
  428. //  We must provide it in a seperate buffer, otherwise they might change
  429. //      the original and change also what they believe to be saved.
  430. extern "C"  char *WH_FilePlatformName(const char *pName)    {
  431.  
  432.     if(pName)   {
  433.         return XP_STRDUP(pName);
  434.     }
  435.     
  436.     return NULL;
  437. }
  438.  
  439. /* char ch;                // Byte, not Character, to be located
  440.  * const char* cpStr;    // Null-terminated string
  441.  * uint16 iCSID;        // file system id or win_csid
  442.  * jliu@09/08/97
  443.  */
  444. char* intl_strrchr( char* cpStr, char ch, uint16 iCSID )
  445. {
  446.     if( cpStr == NULL || *cpStr == NULL )
  447.         return NULL;
  448.  
  449.     if( ( iCSID & MULTIBYTE ) == 0  || ( ch & 0x80 ) != 0 )
  450.         return strrchr( cpStr, ch );
  451.  
  452.     char* cpLastChar = NULL;
  453.  
  454.     while( *cpStr != NULL ){
  455.         if( *cpStr == ch )
  456.             cpLastChar = cpStr++;
  457.         else if( ( *cpStr & 0x80 ) == 0 )
  458.             cpStr++;
  459.         else
  460.             cpStr = INTL_NextChar( iCSID, cpStr );
  461.     }
  462.  
  463.     return cpLastChar;
  464. }
  465.  
  466. /* const char* cpStr;    // Null-terminated string
  467.  * uint16 iCSID;        // file system id or win_csid
  468.  * jliu@09/08/97
  469.  */
  470. BOOL intl_IsEndWithBS( char* cpStr, uint16 iCSID )
  471. {
  472.     if( cpStr == NULL || *cpStr == NULL )
  473.         return FALSE;
  474.  
  475.     int len = strlen( cpStr );    // how many bytes in cpStr
  476.     if( cpStr[len-1] != '\\' )
  477.         return FALSE;
  478.  
  479.     if( ( iCSID & MULTIBYTE ) == 0 )
  480.         return TRUE;
  481.  
  482.     char* cpLastChar = NULL;
  483.     while( *cpStr != NULL ){
  484.         cpLastChar = cpStr;
  485.         cpStr = INTL_NextChar( iCSID, cpStr );
  486.     }
  487.  
  488.     return *cpLastChar == '\\';
  489. }
  490.  
  491. extern "C" char *
  492. FE_GetProgramDirectory(char *buffer, int length)
  493. {
  494.     ::GetModuleFileName(theApp.m_hInstance, buffer, length);
  495.  
  496.     //    Find the trailing slash.
  497.     //  char *pSlash = ::strrchr(buffer, '\\');
  498.     char* pSlash = intl_strrchr( buffer, '\\', CIntlWin::GetSystemLocaleCsid() );
  499.     if(pSlash)    {
  500.         *(pSlash+1) = '\0';
  501.     }
  502.     else    {
  503.         buffer[0] = '\0';
  504.     }
  505.     return (buffer);
  506. }
  507.  
  508.  
  509. char*
  510. XP_TempDirName(void)
  511. {
  512.     char *tmp = theApp.m_pTempDir;
  513.     if (!tmp)
  514.         return XP_STRDUP(".");
  515.     return XP_STRDUP(tmp);
  516. }
  517.  
  518. // Windows _tempnam() lets the TMP environment variable override things sent in
  519. //  so it look like we're going to have to make a temp name by hand
  520. //
  521. // The user should *NOT* free the returned string.  It is stored in static space
  522. //  and so is not valid across multiple calls to this function
  523. //
  524. // The names generated look like
  525. //   c:\netscape\cache\m0.moz
  526. //   c:\netscape\cache\m1.moz
  527. // up to...
  528. //   c:\netscape\cache\m9999999.moz
  529. // after that if fails
  530. //
  531. PUBLIC char *
  532. xp_TempFileName(int type, const char * request_prefix, const char * extension,
  533.                 char* file_buf)
  534. {
  535.   const char * directory = NULL; 
  536.   char * ext = NULL;           // file extension if any
  537.   char * prefix = NULL;        // file prefix if any
  538.   
  539.   
  540.   XP_StatStruct statinfo;
  541.   int status;     
  542.  
  543.   //
  544.   // based on the type of request determine what directory we should be
  545.   //   looking into
  546.   //  
  547.   switch(type) {
  548.     case xpCache:
  549.         directory = theApp.m_pCacheDir;
  550.         ext = ".MOZ";
  551.         prefix = CACHE_PREFIX;
  552.         break;
  553. #ifdef MOZ_MAIL_NEWS        
  554.     case xpSNewsRC:
  555.     case xpNewsRC:
  556.     case xpNewsgroups:
  557.     case xpSNewsgroups:
  558.     case xpTemporaryNewsRC:
  559.         directory = g_MsgPrefs.m_csNewsDir;
  560.         ext = (char *)extension;
  561.         prefix = (char *)request_prefix;
  562.         break;
  563.     case xpMailFolderSummary:
  564.     case xpMailFolder:
  565.         directory = g_MsgPrefs.m_csMailDir;
  566.         ext = (char *)extension;
  567.         prefix = (char *)request_prefix;
  568.         break;
  569.     case xpAddrBook:
  570.         //changed jonm-- to support multi-profile
  571.         //directory = theApp.m_pInstallDir->GetCharValue();
  572.         directory = (const char *)theApp.m_UserDirectory;
  573.         if ((request_prefix == 0) || (XP_STRLEN (request_prefix) == 0))
  574.             prefix = "abook";
  575.         ext = ".nab";
  576.         break;
  577. #endif // MOZ_MAIL_NEWS
  578.     case xpCacheFAT:
  579.         directory = theApp.m_pCacheDir;
  580.         prefix = "fat";
  581.         ext = "db";
  582.         break;
  583.     case xpJPEGFile:
  584.         directory = theApp.m_pTempDir;
  585.         ext = ".jpg";
  586.         prefix = (char *)request_prefix;
  587.         break;
  588.     case xpPKCS12File:
  589.         directory = theApp.m_pTempDir;
  590.         ext = ".p12";
  591.         prefix = (char *)request_prefix;
  592.         break;
  593.     case xpURL:
  594.       {
  595.          if (request_prefix)
  596.          {
  597.             if ( XP_STRRCHR(request_prefix, '/') )
  598.             {
  599.                XP_StatStruct st;
  600.  
  601.                directory = (char *)request_prefix;
  602.                if (XP_Stat (directory, &st, xpURL))
  603.                   XP_MakeDirectoryR (directory, xpURL);
  604.                ext = (char *)extension;
  605.                prefix = (char *)"su";
  606.                break;
  607.             }
  608.         }
  609.         // otherwise, fall through
  610.       }
  611.     case xpTemporary:
  612.     default:
  613.         directory = theApp.m_pTempDir;
  614.         ext = (char *)extension;
  615.         prefix = (char *)request_prefix;
  616.         break;
  617.     }
  618.  
  619.   if(!directory)
  620.     return(NULL);
  621.  
  622.   if(!prefix)
  623.     prefix = "X";
  624.  
  625.   if(!ext)
  626.     ext = ".TMP";
  627.  
  628.   //  We need to base our temporary file names on time, and not on sequential
  629.   //    addition because of the cache not being updated when the user
  630.   //    crashes and files that have been deleted are over written with
  631.   //    other files; bad data.
  632.   //  The 52 valid DOS file name characters are
  633.   //    0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_^$~!#%&-{}@`'()
  634.   //  We will only be using the first 32 of the choices.
  635.   //
  636.   //  Time name format will be M+++++++.MOZ
  637.   //    Where M is the single letter prefix (can be longer....)
  638.   //    Where +++++++ is the 7 character time representation (a full 8.3
  639.   //      file name will be made).
  640.   //    Where .MOZ is the file extension to be used.
  641.   //
  642.   //  In the event that the time requested is the same time as the last call
  643.   //    to this function, then the current time is incremented by one,
  644.   //    as is the last time called to facilitate unique file names.
  645.   //  In the event that the invented file name already exists (can't
  646.   //    really happen statistically unless the clock is messed up or we
  647.   //    manually incremented the time), then the times are incremented
  648.   //    until an open name can be found.
  649.   //
  650.   //  time_t (the time) has 32 bits, or 4,294,967,296 combinations.
  651.   //  We will map the 32 bits into the 7 possible characters as follows:
  652.   //    Starting with the lsb, sets of 5 bits (32 values) will be mapped
  653.   //      over to the appropriate file name character, and then
  654.   //      incremented to an approprate file name character.
  655.   //    The left over 2 bits will be mapped into the seventh file name
  656.   //      character.
  657.   //
  658.   
  659.   int i_letter, i_timechars, i_numtries = 0;
  660.   char ca_time[8];
  661.   time_t this_call = (time_t)0;
  662.   
  663.   //  We have to base the length of our time string on the length
  664.   //    of the incoming prefix....
  665.   //
  666.   i_timechars = 8 - strlen(prefix);
  667.   
  668.   //  Infinite loop until the conditions are satisfied.
  669.   //  There is no danger, unless every possible file name is used.
  670.   //
  671.   while(1)  {
  672.     //    We used to use the time to generate this.
  673.     //    Now, we use some crypto to avoid bug #47027
  674.     RNG_GenerateGlobalRandomBytes((void *)&this_call, sizeof(this_call));
  675.  
  676.     //  Convert the time into a 7 character string.
  677.     //  Strip only the signifigant 5 bits.
  678.     //  We'll want to reverse the string to make it look coherent
  679.     //    in a directory of file names.
  680.     //
  681.     for(i_letter = 0; i_letter < i_timechars; i_letter++) {
  682.       ca_time[i_letter] = (char)((this_call >> (i_letter * 5)) & 0x1F);
  683.       
  684.       //  Convert any numbers to their equivalent ascii code
  685.       //
  686.       if(ca_time[i_letter] <= 9)  {
  687.         ca_time[i_letter] += '0';
  688.       }
  689.       //  Convert the character to it's equivalent ascii code
  690.       //
  691.       else  {
  692.         ca_time[i_letter] += 'A' - 10;
  693.       }
  694.     }
  695.     
  696.     //  End the created time string.
  697.     //
  698.     ca_time[i_letter] = '\0';
  699.     
  700.     //  Reverse the time string.
  701.     //
  702.     _strrev(ca_time);
  703.     
  704.     //  Create the fully qualified path and file name.
  705.     //
  706.     sprintf(file_buf, "%s\\%s%s%s", directory, prefix, ca_time, ext);
  707.  
  708.     //  Determine if the file exists, and mark that we've tried yet
  709.     //    another file name (mark to be used later).
  710.     //  
  711.     //  Use the system call instead of XP_Stat since we already
  712.     //  know the name and we don't want recursion
  713.     //
  714.     status = _stat(file_buf, &statinfo);
  715.     i_numtries++;
  716.     
  717.     //  If it does not exists, we are successful, return the name.
  718.     //
  719.     if(status == -1)  {
  720.       /* don't generate a directory as part of the 
  721.        * cache temp names.  When the cache file name
  722.        * is passed into the other XP_File functions
  723.        * we will append the cache directory to the name
  724.        * to get the complete path.
  725.        * This will allow the cache to be moved around
  726.        * and for netscape to be used to generate external
  727.        * cache FAT's.  :lou
  728.        */
  729.       if(type == xpCache )
  730.           sprintf(file_buf, "%s%s%s", prefix, ca_time, ext);
  731.  
  732. //      TRACE("Temp file name is %s\n", file_buf);
  733.       return(file_buf);
  734.     }
  735.     
  736.     //  If there is no room for additional characters in the time,
  737.     //    we'll have to return NULL here, or we go infinite.
  738.     //    This is a one case scenario where the requested prefix is
  739.     //    actually 8 letters long.
  740.     //  Infinite loops could occur with a 7, 6, 5, etc character prefixes
  741.     //    if available files are all eaten up (rare to impossible), in
  742.     //    which case, we should check at some arbitrary frequency of
  743.     //    tries before we give up instead of attempting to Vulcanize
  744.     //    this code.  Live long and prosper.
  745.     //
  746.     if(i_timechars == 0)  {
  747.       break;
  748.     }
  749.     else if(i_numtries == 0x00FF) {
  750.       break;
  751.     }
  752.   }
  753.   
  754.   //  Requested name is thought to be impossible to generate.
  755.   //
  756.   TRACE("No more temp file names....\n");
  757.   return(NULL);
  758.   
  759. }
  760.  
  761. PUBLIC char *
  762. WH_TempFileName(int type, const char * request_prefix, const char * extension)
  763. {
  764.     static char file_buf[_MAX_PATH];        /* protected by _pr_TempName_lock */
  765.     char* result;
  766. #ifdef NSPR
  767.     XP_ASSERT(_pr_TempName_lock);
  768.     PR_EnterMonitor(_pr_TempName_lock);
  769. #endif
  770.     result = XP_STRDUP(xp_TempFileName(type, request_prefix, extension, file_buf));
  771. #ifdef NSPR
  772.     PR_ExitMonitor(_pr_TempName_lock);
  773. #endif
  774.     return result;
  775. }
  776.  
  777. //
  778. // Return a string that is equal to the NetName string but with the
  779. //  cross-platform characters changed back into DOS characters
  780. // The caller is responsible for XP_FREE()ing the return string
  781. //
  782. MODULE_PRIVATE char * 
  783. XP_NetToDosFileName(const char * NetName)
  784. {
  785.     char *p, *newName;
  786.  
  787.     if(!NetName)
  788.         return NULL;
  789.         
  790.     //  If the name is only '/' or begins '//' keep the
  791.     //    whole name else strip the leading '/'
  792.     BOOL bChopSlash = FALSE;
  793.  
  794.     if(NetName[0] == '/')
  795.         bChopSlash = TRUE;
  796.  
  797.     // save just / as a path
  798.     if(NetName[0] == '/' && NetName[1] == '\0')
  799.         bChopSlash = FALSE;
  800.  
  801.     // spanky Win9X path name
  802.     if(NetName[0] == '/' && NetName[1] == '/')
  803.         bChopSlash = FALSE;
  804.  
  805.     if(bChopSlash)
  806.         newName = XP_STRDUP(&(NetName[1]));
  807.     else
  808.         newName = XP_STRDUP(NetName);
  809.  
  810.     if(!newName)
  811.         return NULL;
  812.  
  813.     if( newName[1] == '|' )
  814.         newName[1] = ':';
  815.  
  816.     for(p = newName; *p; p++){
  817.         if( *p == '/' )
  818.             *p = '\\';
  819.     }
  820.  
  821.     return(newName);
  822.  
  823. }
  824.  
  825. /* implement an lseek using _lseek that
  826.  * writes zero's when extending a file
  827.  * beyond the end.
  828.  * This function attemps to override
  829.  * the standard lseek.
  830.  */
  831. extern "C" long wfe_lseek(int fd, long offset, int origin)
  832. {
  833.      long cur_pos;
  834.     long end_pos;
  835.     long seek_pos;
  836.  
  837.     if(origin == SEEK_CUR)
  838.       {    
  839.           if(offset < 1)                              
  840.             return(_lseek(fd, offset, SEEK_CUR));
  841.  
  842.         cur_pos = _lseek(fd, 0, SEEK_CUR);
  843.  
  844.         if(cur_pos < 0)
  845.             return(cur_pos);
  846.       }
  847.                                          
  848.     end_pos = _lseek(fd, 0, SEEK_END);
  849.     if(end_pos < 0)
  850.         return(end_pos);
  851.  
  852.     if(origin == SEEK_SET)
  853.         seek_pos = offset;
  854.     else if(origin == SEEK_CUR)
  855.         seek_pos = cur_pos + offset;
  856.     else if(origin == SEEK_END)
  857.         seek_pos = end_pos + offset;
  858.      else
  859.       {
  860.           assert(0);
  861.         return(-1);
  862.       }
  863.  
  864.      /* the seek position desired is before the
  865.      * end of the file.  We don't need
  866.      * to do anything special except the seek.
  867.      */
  868.      if(seek_pos <= end_pos)
  869.          return(_lseek(fd, seek_pos, SEEK_SET));
  870.          
  871.      /* the seek position is beyond the end of the
  872.       * file.  Write zero's to the end.
  873.       *
  874.      * we are already at the end of the file so
  875.      * we just need to "write()" zeros for the
  876.      * difference between seek_pos-end_pos and
  877.      * then seek to the position to finish
  878.      * the call
  879.       */
  880.      { 
  881.           char buffer[1024];
  882.            long len = seek_pos-end_pos;
  883.            memset(&buffer, 0, 1024);
  884.            while(len > 0)
  885.           {
  886.             write(fd, &buffer, CASTINT((1024 > len ? len : 1024)));
  887.             len -= 1024L;
  888.           }
  889.         return(_lseek(fd, seek_pos, SEEK_SET));
  890.       }        
  891.  
  892.  }
  893. //
  894. // Returns the absolute name of a file 
  895. // 
  896. // The result of this function can be used with the standard
  897. // open/fopen ansi file functions
  898. // The caller is responsible for XP_FREE()ing the string -*myName
  899. //
  900. PUBLIC char * 
  901. xp_FileName(const char * name, XP_FileType type, char* *myName)
  902. {
  903.     uint16 iFileSystemCSID = CIntlWin::GetSystemLocaleCsid();    // this file system csid, not win_csid
  904.     char * newName = NULL;
  905.     char * netLibName = NULL;
  906.     BOOL   bNeedToRegister = FALSE;   // == do we need to register a new 
  907.                                       //   newshost->file name mapping
  908.     char * prefStr = NULL;
  909.     CString csHostName;
  910.     CString csHost;
  911.     struct _stat sInfo;
  912.     int iDot;
  913.     int iColon;
  914.  
  915.     CString fileName;
  916.     char* tempName = NULL;
  917.  
  918.     switch(type) {
  919.     case xpCacheFAT:
  920.         newName = (char *) XP_ALLOC(_MAX_PATH);
  921.         sprintf(newName, "%s\\fat.db", (const char *)theApp.m_pCacheDir);
  922.         break;
  923.     case xpExtCacheIndex:
  924.         newName = (char *) XP_ALLOC(_MAX_PATH);
  925.         sprintf(newName, "%s\\extcache.fat", (const char *)theApp.m_pCacheDir);
  926.         break;
  927.  
  928.     // larubbio
  929.     case xpSARCacheIndex:
  930.         newName = (char *) XP_ALLOC(_MAX_PATH);
  931.         sprintf(newName, "%s\\archive.fat", theApp.m_pSARCacheDir);
  932.         break;
  933.  
  934.     case xpHTTPCookie:
  935.         newName = (char *) XP_ALLOC(_MAX_PATH);
  936.         //sprintf(newName, "%s\\cookies.txt", theApp.m_pInstallDir->GetCharValue());
  937.         // changed -- jonm to support multi-profile
  938.         sprintf(newName, "%s\\cookies.txt", (const char *)theApp.m_UserDirectory);
  939.         break;
  940. #ifdef MOZ_MAIL_NEWS      
  941.     case xpSNewsRC:
  942.     case xpNewsRC:
  943.         // see if we are asking about the default news host
  944.         // else look up in netlib
  945.         if ( !name || !strlen(name) )
  946.             name = g_MsgPrefs.m_csNewsHost;
  947.  
  948.         netLibName = NET_MapNewsrcHostToFilename((char *)name, 
  949.                                                  (type == xpSNewsRC),
  950.                                                  FALSE);
  951.         
  952.         // if we found something in our map just skip the rest of this stuff
  953.         if(netLibName && *netLibName) {
  954.             newName = XP_STRDUP(netLibName);
  955.             break;
  956.         }
  957.  
  958.         // whatever name we eventually end up with we will need to register it
  959.         //   before we leave the function
  960.         bNeedToRegister = TRUE;
  961.  
  962.         // If we are on the default host see if there is a newsrc file in the
  963.         //   news directory.  If so, that is what we want
  964.         if(!stricmp(name, g_MsgPrefs.m_csNewsHost)) {
  965.             csHostName = g_MsgPrefs.m_csNewsDir;
  966.             csHostName += "\\newsrc";
  967.             if(_stat((const char *) csHostName, &sInfo) == 0) {
  968.                 newName = XP_STRDUP((const char *) csHostName);
  969.                 break;
  970.             }
  971.         }
  972.                         
  973.         // See if we are going to be able to build a file name based 
  974.         //   on the hostname
  975.         csHostName = g_MsgPrefs.m_csNewsDir;
  976.         csHostName += '\\';
  977.  
  978.         // build up '<hostname>.rc' so we can tell how long its going to be
  979.         //   we will use that as the default name to try
  980.         if(type == xpSNewsRC)
  981.             csHost += 's';
  982.         csHost += name;
  983.  
  984.         // if we have a news host news.foo.com we just want to use the "news"
  985.         //   part
  986.         iDot = csHost.Find('.');
  987.         if(iDot != -1)
  988.             csHost = csHost.Left(iDot);
  989.  
  990. #ifdef XP_WIN16
  991.         if(csHost.GetLength() > 8)
  992.             csHost = csHost.Left(8);
  993. #endif
  994.  
  995.         iColon = csHost.Find(':');
  996.         if (iColon != -1) {
  997.             // Windows file system seems to do horrid things if you have
  998.             // a filename with a colon in it.
  999.             csHost = csHost.Left(iColon);
  1000.         }
  1001.  
  1002.         csHost += ".rc";
  1003.  
  1004.         // csHost is now of the form <hostname>.rc and is in 8.3 format
  1005.         //   if we are on a Win16 box
  1006.  
  1007.         csHostName += csHost;
  1008.  
  1009.         // looks like a file with that name already exists -- panic
  1010.         if(_stat((const char *) csHostName, &sInfo) != -1) {
  1011.             
  1012.             char host[5];
  1013.  
  1014.             // else generate a new file in news directory
  1015.             strncpy(host, name, 4);
  1016.             host[4] = '\0';
  1017.  
  1018.             newName = WH_TempFileName(type, host, ".rc");
  1019.             if(!newName)
  1020.                 return(NULL);
  1021.  
  1022.         } else {
  1023.  
  1024.             newName = XP_STRDUP((const char *) csHostName);
  1025.  
  1026.         }
  1027.  
  1028.          break;
  1029.     case xpNewsrcFileMap:
  1030.         // return name of FAT file in news directory
  1031.         newName = (char *) XP_ALLOC(_MAX_PATH);
  1032.         sprintf(newName, "%s\\fat", (const char *)g_MsgPrefs.m_csNewsDir);
  1033.         break;
  1034.     case xpNewsgroups:
  1035.     case xpSNewsgroups:
  1036.         // look up in netlib
  1037.         if ( !name || !strlen(name) )
  1038.             name = g_MsgPrefs.m_csNewsHost;
  1039.  
  1040.         netLibName = NET_MapNewsrcHostToFilename((char *)name, 
  1041.                                                  (type == xpSNewsgroups),
  1042.                                                  TRUE);
  1043.  
  1044.         if(!netLibName) {
  1045.  
  1046.             csHostName = g_MsgPrefs.m_csNewsDir;
  1047.             csHostName += '\\';
  1048.  
  1049.             if(type == xpSNewsgroups)
  1050.                 csHost += 's';
  1051.             csHost += name;
  1052.  
  1053.             // see if we can just use "<hostname>.rcg"
  1054.             // it might be news.foo.com so just take "news"
  1055.             int iDot = csHost.Find('.');
  1056.             if(iDot != -1)
  1057.                 csHost = csHost.Left(iDot);
  1058.  
  1059. #ifdef XP_WIN16
  1060.             if(csHost.GetLength() > 8)
  1061.                 csHost = csHost.Left(8);
  1062. #endif
  1063.  
  1064.             iColon = csHost.Find(':');
  1065.             if (iColon != -1) {
  1066.                 // Windows file system seems to do horrid things if you have
  1067.                 // a filename with a colon in it.
  1068.                 csHost = csHost.Left(iColon);
  1069.             }
  1070.  
  1071.             csHost += ".rcg";
  1072.  
  1073.             // csHost is now of the form <hostname>.rcg
  1074.  
  1075.             csHostName += csHost;
  1076.  
  1077.             // looks like a file with that name already exists -- panic
  1078.             if(_stat((const char *) csHostName, &sInfo) != -1) {
  1079.                 
  1080.                 char host[5];
  1081.  
  1082.                 // else generate a new file in news directory
  1083.                 strncpy(host, name, 4);
  1084.                 host[4] = '\0';
  1085.  
  1086.                 newName = WH_TempFileName(type, host, ".rcg");
  1087.                 if(!newName)
  1088.                     return(NULL);
  1089.  
  1090.             } else {
  1091.  
  1092.                 newName = XP_STRDUP((const char *) csHostName);
  1093.  
  1094.             }
  1095.  
  1096.             if ( !name || !strlen(name))
  1097.                 NET_RegisterNewsrcFile(newName,(char *)(const char *)g_MsgPrefs.m_csNewsHost,
  1098.                     (type == xpSNewsgroups), TRUE );
  1099.             else
  1100.                 NET_RegisterNewsrcFile(newName,(char*)name,(type == xpSNewsgroups), TRUE );
  1101.  
  1102.         } else {
  1103.  
  1104.             newName = XP_STRDUP(netLibName);
  1105.  
  1106.         }
  1107.         break;
  1108.     case xpMimeTypes:
  1109.         name = NULL;
  1110.         break;
  1111. #endif // MOZ_MAIL_NEWS
  1112.     case xpGlobalHistory:
  1113.         newName = (char *) XP_ALLOC(_MAX_PATH);
  1114.         // changed -- jonm to support multi-profile
  1115.         sprintf(newName, "%s\\mozilla.hst", (const char *)theApp.m_UserDirectory);
  1116.         break;
  1117.     case xpGlobalHistoryList:
  1118.         newName = (char *) XP_ALLOC(_MAX_PATH);
  1119.         sprintf( newName, "%s\\ns_hstry.htm" );
  1120.         break;
  1121.     case xpKeyChain:
  1122.         name = NULL;
  1123.         break;
  1124.  
  1125.       /* larubbio */
  1126.       case xpSARCache:
  1127.         if(!name) {
  1128.                       return NULL;
  1129.               }
  1130.               newName = (char *) XP_ALLOC(_MAX_PATH);
  1131.               sprintf(newName, "%s\\%s", theApp.m_pSARCacheDir, name);
  1132.               break;
  1133.  
  1134.     case xpCache:
  1135.         if(!name) {
  1136.             tempName = WH_TempFileName(xpCache, NULL, NULL);
  1137.             if (!tempName) return NULL;
  1138.             name = tempName;
  1139.         }
  1140.         newName = (char *) XP_ALLOC(_MAX_PATH);
  1141.         if ((strchr(name,'|')  || strchr(name,':')))  { // Local File URL if find a |
  1142.             if(name[0] == '/')
  1143.                 strcpy(newName,name+1); // skip past extra slash
  1144.             else
  1145.                 strcpy(newName,name); // absolute path is valid
  1146.         } else {
  1147.             sprintf(newName, "%s\\%s", (const char *)theApp.m_pCacheDir, name);
  1148.         }
  1149.         break;
  1150.     case xpBookmarks:
  1151.     case xpHotlist: 
  1152.         if (!name || !strlen(name)) 
  1153.             name = theApp.m_pBookmarkFile;
  1154.         break;
  1155.     case xpSocksConfig:
  1156.         prefStr = NULL;
  1157.         PREF_CopyCharPref("browser.socksfile_location",&prefStr);
  1158.         name = prefStr;
  1159.         break;        
  1160.     case xpCertDB:
  1161.         newName = (char *) XP_ALLOC(_MAX_PATH);
  1162.         if ( name ) {
  1163.             sprintf(newName, "%s\\cert%s.db", (const char *)theApp.m_UserDirectory, name);
  1164.         } else {
  1165.             sprintf(newName, "%s\\cert.db", (const char *)theApp.m_UserDirectory);
  1166.         }
  1167.         break;
  1168.     case xpCertDBNameIDX:
  1169.         newName = (char *) XP_ALLOC(_MAX_PATH);
  1170.         sprintf(newName, "%s\\certni.db", (const char *)theApp.m_UserDirectory);
  1171.         break;
  1172.     case xpKeyDB:
  1173.         newName = (char *) XP_ALLOC(_MAX_PATH);
  1174.     if ( name ) {
  1175.       sprintf(newName, "%s\\key%s.db", (const char *)theApp.m_UserDirectory, name);
  1176.     } else {
  1177.       sprintf(newName, "%s\\key.db", (const char *)theApp.m_UserDirectory);
  1178.     }
  1179.         break;
  1180.     case xpSecModuleDB:
  1181.         newName = (char *) XP_ALLOC(_MAX_PATH);
  1182.         sprintf(newName, "%s\\secmod.db", (const char *)theApp.m_UserDirectory);
  1183.         break;
  1184.     case xpSignedAppletDB:
  1185.         newName = (char *) XP_ALLOC(_MAX_PATH);
  1186.     if ( name ) {
  1187.       sprintf(newName, "%s\\signed%s.db", (const char *)theApp.m_UserDirectory, name);
  1188.     } else {
  1189.       sprintf(newName, "%s\\signed.db", (const char *)theApp.m_UserDirectory);
  1190.     }
  1191.         break;
  1192. #ifdef MOZ_MAIL_NEWS      
  1193.     case xpAddrBook:
  1194.         {
  1195. #ifdef XP_WIN16
  1196.         if(!name || !strlen(name) )
  1197.             newName = WH_TempName(type, NULL);
  1198. #else
  1199.             newName = (char *) XP_ALLOC(_MAX_PATH);
  1200.             strcpy(newName, name);
  1201.  
  1202.             // strip off the extension
  1203.             char * pEnd = max(strrchr(newName, '\\'), strrchr(newName, '/'));
  1204.             if(!pEnd)
  1205.                 pEnd = newName;
  1206.  
  1207.             pEnd = strchr(pEnd, '.');
  1208.             if(pEnd)
  1209.                 *pEnd = '\0';
  1210.             strcat(newName, ".nab");
  1211. #endif
  1212.         }        
  1213.         break;
  1214.         case xpAddrBookNew:
  1215.         {
  1216.             newName = (char *) XP_ALLOC(_MAX_PATH);
  1217.             sprintf(newName, "%s\\%s", (const char *)theApp.m_UserDirectory, name);
  1218.             break;
  1219.         }        
  1220.         break;
  1221.         case xpVCardFile:
  1222.         {
  1223.             newName = (char *) XP_ALLOC(_MAX_PATH);
  1224.             strcpy(newName, name);
  1225.  
  1226.             // strip off the extension
  1227.             char * pEnd = max(strrchr(newName, '\\'), strrchr(newName, '/'));
  1228.             if(!pEnd)
  1229.                 pEnd = newName;
  1230.  
  1231.             pEnd = strchr(pEnd, '.');
  1232.             if(pEnd)
  1233.                 *pEnd = '\0';
  1234.             strcat(newName, ".vcf");
  1235.         }        
  1236.         break;
  1237.     case xpLDIFFile:
  1238.         {
  1239.             newName = (char *) XP_ALLOC(_MAX_PATH);
  1240.             strcpy(newName, name);
  1241.  
  1242.             // strip off the extension
  1243.             char * pEnd = max(strrchr(newName, '\\'), strrchr(newName, '/'));
  1244.             if(!pEnd)
  1245.                 pEnd = newName;
  1246.  
  1247.             pEnd = strchr(pEnd, '.');
  1248.             if(pEnd)
  1249.                 *pEnd = '\0';
  1250. #ifdef XP_WIN16
  1251.             strcat(newName, ".ldi");
  1252. #else
  1253.             strcat(newName, ".ldif");
  1254. #endif
  1255.         }        
  1256.         break;
  1257.     case xpTemporaryNewsRC:
  1258.         {
  1259.             CString csHostName = g_MsgPrefs.m_csNewsDir;
  1260.             csHostName += "\\news.tmp";
  1261.             newName = XP_STRDUP((const char *) csHostName);
  1262.         }
  1263.         break;
  1264. #endif // MOZ_MAIL_NEWS        
  1265.     case xpPKCS12File:
  1266.         {
  1267.             newName = (char *) XP_ALLOC(_MAX_PATH);
  1268.             strcpy(newName, name);
  1269.  
  1270.             // strip off the extension
  1271.             char * pEnd = max(strrchr(newName, '\\'), strrchr(newName, '/'));
  1272.             if(!pEnd)
  1273.                 pEnd = newName;
  1274.  
  1275.             pEnd = strchr(pEnd, '.');
  1276.             if(pEnd)
  1277.                 *pEnd = '\0';
  1278.             strcat(newName, ".p12");
  1279.         }        
  1280.         break;    
  1281.     case xpTemporary:
  1282.         if(!name || !strlen(name) )
  1283.             newName = WH_TempName(type, NULL);
  1284.         break;
  1285. #ifdef MOZ_MAIL_NEWS        
  1286.     case xpMailFolder:
  1287.         if(!name)
  1288.             name = g_MsgPrefs.m_csMailDir;
  1289.         break;
  1290.     case xpMailFolderSummary:
  1291.         {
  1292.             newName = (char *) XP_ALLOC(_MAX_PATH);
  1293.             strcpy(newName, name);
  1294.  
  1295.             // strip off the extension
  1296.             char * pEnd = max(strrchr(newName, '\\'), strrchr(newName, '/'));
  1297.             if(!pEnd)
  1298.                 pEnd = newName;
  1299.  
  1300. #ifdef XP_WIN16    // backend won't allow '.' in win16 folder names, but just to be safe.
  1301.             pEnd = strchr(pEnd, '.');
  1302.             if(pEnd)
  1303.                 *pEnd = '\0';
  1304. #endif
  1305.             strcat(newName, ".snm");
  1306.         }
  1307.         break;
  1308.     case xpMailSort:
  1309.         newName = (char *) XP_ALLOC(_MAX_PATH);
  1310.         // if name is not null or empty, it's probably the host name for the imap server.
  1311.         // This will need to be extended to support per publc folder filters
  1312.         if (name && strlen(name) > 0)
  1313.             sprintf(newName, "%s\\ImapMail\\%s\\rules.dat", (const char *)theApp.m_UserDirectory, name);
  1314.         else
  1315.             sprintf(newName, "%s\\rules.dat", (const char *)g_MsgPrefs.m_csMailDir);
  1316.         break;
  1317.     case xpNewsSort:
  1318.         newName = (char *) XP_ALLOC(_MAX_PATH);
  1319.         sprintf(newName, "%s\\%s", (const char *)g_MsgPrefs.m_csNewsDir, name);
  1320.         break;
  1321.     case xpMailFilterLog:
  1322.         newName = (char *) XP_ALLOC(_MAX_PATH);
  1323.         sprintf(newName, "%s\\mailfilt.log", (const char *)g_MsgPrefs.m_csMailDir);
  1324.         break;
  1325.     case xpNewsFilterLog:
  1326.         newName = (char *) XP_ALLOC(_MAX_PATH);
  1327.         sprintf(newName, "%s\\newsfilt.log", (const char *)g_MsgPrefs.m_csNewsDir);
  1328.         break;
  1329.     case xpMailPopState:
  1330.         newName = (char *) XP_ALLOC(_MAX_PATH);
  1331.         sprintf(newName, "%s\\popstate.dat", (const char *)g_MsgPrefs.m_csMailDir);
  1332.         break;
  1333.     case xpMailSubdirectory:
  1334.         {
  1335.             newName = (char *) XP_ALLOC(_MAX_PATH);
  1336.             strcpy(newName, name);
  1337.  
  1338.             // strip off the trailing slash if any
  1339.             char * pEnd = max(strrchr(newName, '\\'), strrchr(newName, '/'));
  1340.             if(!pEnd)
  1341.                 pEnd = newName;
  1342.  
  1343.             strcat(newName, ".sbd");
  1344.         }
  1345.         break;
  1346. #endif // MOZ_MAIL_NEWS      
  1347.     // name of global cross-platform registry
  1348.     case xpRegistry:
  1349.         // eventually need to support arbitrary names; this is the default
  1350.         newName = (char *) XP_ALLOC(_MAX_PATH);
  1351.         if ( newName != NULL ) {
  1352.             GetWindowsDirectory(newName, _MAX_PATH);
  1353.             int namelen = strlen(newName);
  1354.             //if ( newName[namelen-1] == '\\' )
  1355.             if( intl_IsEndWithBS( newName, iFileSystemCSID ) )
  1356.                 namelen--;
  1357.             strcpy(newName+namelen, "\\nsreg.dat");
  1358.         }
  1359.         break;
  1360.     // name of news group database 
  1361. #ifdef MOZ_MAIL_NEWS   
  1362.     case xpXoverCache:
  1363.         newName = (char *) XP_ALLOC(_MAX_PATH);
  1364.         sprintf(newName, "%s\\%s", (const char *)g_MsgPrefs.m_csNewsDir, name);
  1365.         break;
  1366. #endif // MOZ_MAIL_NEWS
  1367.     case xpProxyConfig:
  1368.         newName = (char *) XP_ALLOC(_MAX_PATH);
  1369.         //sprintf(newName, "%s\\proxy.cfg", theApp.m_pInstallDir->GetCharValue());
  1370.         sprintf(newName, "%s\\proxy.cfg", (const char *)theApp.m_UserDirectory);
  1371.         break;
  1372.  
  1373.     // add any cases where no modification is necessary here     
  1374.     // The name is fine all by itself, no need to modify it 
  1375.     case xpFileToPost:
  1376.     case xpExtCache:
  1377.     case xpURL:
  1378.         // name is OK as it is
  1379.         break;
  1380. #ifdef MOZ_MAIL_NEWS      
  1381.     case xpNewsHostDatabase:
  1382.         newName = (char *) XP_ALLOC(_MAX_PATH);
  1383.         sprintf(newName, "%s\\news.db", (const char *)g_MsgPrefs.m_csNewsDir);
  1384.         break;
  1385.  
  1386.     case xpImapRootDirectory:
  1387.         newName = PR_smprintf ("%s\\ImapMail", (const char *)theApp.m_UserDirectory);
  1388.         break;
  1389.     case xpImapServerDirectory:
  1390.         {
  1391.             int len = 0;
  1392.             char *tempImapServerDir = XP_STRDUP(name);
  1393.             char *imapServerDir = tempImapServerDir;
  1394. #ifdef XP_WIN16
  1395.             // first, truncate it to 8 characters
  1396.             if ((len = XP_STRLEN(imapServerDir)) > 8) {
  1397.                 imapServerDir = imapServerDir + len - 8;
  1398.             }
  1399.  
  1400.             // Now, replace all illegal characters with '_'
  1401.             const char *illegalChars = "\"/\\[]:;=,|?<>*$. ";
  1402.             for (char *possibleillegal = imapServerDir; *possibleillegal; )
  1403.                 if (XP_STRCHR(illegalChars, *possibleillegal) || ((unsigned char)*possibleillegal < 31) )
  1404.                     *possibleillegal++ = '_';
  1405.                 else
  1406.                     possibleillegal = INTL_NextChar( iFileSystemCSID, possibleillegal );
  1407. #endif
  1408.             newName = PR_smprintf ("%s\\ImapMail\\%s", (const char *)theApp.m_UserDirectory, imapServerDir);
  1409.             if (tempImapServerDir) XP_FREE(tempImapServerDir);
  1410.         }
  1411.     break;
  1412.  
  1413.     case xpJSMailFilters:
  1414.         newName = PR_smprintf("%s\\filters.js", (const char *)g_MsgPrefs.m_csMailDir);
  1415.         break;
  1416. #endif // MOZ_MAIL_NEWS
  1417.     case xpJSHTMLFilters:
  1418.         newName = PR_smprintf("%s\\hook.js", (const char *)theApp.m_UserDirectory);
  1419.         break;
  1420.     case xpFolderCache:
  1421.         newName = PR_smprintf ("%s\\summary.dat", (const char *)theApp.m_UserDirectory);
  1422.         break;
  1423.  
  1424.     case xpCryptoPolicy:
  1425.         newName = (char *) XP_ALLOC(_MAX_PATH);
  1426.         FE_GetProgramDirectory(newName, _MAX_PATH);
  1427.         strcat(newName, "moz40p3");
  1428.         break;
  1429.     
  1430.     case xpJSCookieFilters:
  1431.         newName = PR_smprintf("%s\\cookies.js", (const char *)theApp.m_UserDirectory);
  1432.         break;
  1433.  
  1434.  
  1435.     case xpLIClientDB:
  1436.         newName = (char *) XP_ALLOC(_MAX_PATH);
  1437.         sprintf(newName, "%s\\locindep.dat", (const char *)theApp.m_UserDirectory);
  1438.         break;
  1439.  
  1440.     case xpLIPrefs:
  1441.         newName = (char *) XP_ALLOC(_MAX_PATH);
  1442.         sprintf(newName, "%s\\liprefs.js", (const char *)theApp.m_UserDirectory);
  1443.         break;
  1444.  
  1445.     default:
  1446.         ASSERT(0);  /* all types should be covered */
  1447.         break;
  1448.     }
  1449.  
  1450. #ifdef MOZ_MAIL_NEWS    
  1451.     // make sure we have the correct newsrc file registered for next time
  1452.     if((type == xpSNewsRC || type == xpNewsRC) && bNeedToRegister)
  1453.         NET_RegisterNewsrcFile(newName, (char *)name, (type == xpSNewsRC), FALSE );
  1454. #endif
  1455.  
  1456.     // determine what file we are supposed to load and make sure it looks
  1457.     //   like a DOS pathname and not some unixy punk name
  1458.     if(newName) {
  1459.         *myName = XP_NetToDosFileName((const char*)newName);
  1460.         XP_FREE(newName); 
  1461.     } else {
  1462.         *myName = XP_NetToDosFileName((const char*)name);
  1463.     }
  1464.  
  1465.     if (tempName) XP_FREE(tempName);
  1466.  
  1467.     if (prefStr) XP_FREE(prefStr);        
  1468.     
  1469.     // whee, we're done
  1470.     return(*myName);
  1471. }   
  1472.  
  1473. //
  1474. // Open a file with the given name
  1475. // If a special file type is provided we might need to get the name
  1476. //  out of the preferences list
  1477. //
  1478. PUBLIC XP_File 
  1479. XP_FileOpen(const char * name, XP_FileType type, const XP_FilePerm perm)
  1480. {
  1481.     XP_File fp;
  1482.     char *filename = WH_FileName(name, type);
  1483.  
  1484.     if(!filename || !(*filename))
  1485.         return(NULL);
  1486.         
  1487.      //  THIS MUST BE DONE FIRST TO PLUG WIN OS SECURITY HOLE.
  1488.      //  Do not allow UNC pathnames if the command line stated so.
  1489.      if(xpURL == type && FALSE == theApp.m_bUNC) {
  1490.          //  Make sure we have enough buffer to check.
  1491.          if(filename && filename[0] && filename[1]) {
  1492.              if(
  1493.                  ('\\' == filename[0] && '\\' == filename[1]) ||
  1494.                  ('/' == filename[0] && '/' == filename[1]) ||
  1495.                  ('\\' == filename[0] && '/' == filename[1]) ||
  1496.                  ('/' == filename[0] && '\\' == filename[1])
  1497.              ) {
  1498.                  //  Presumed UNC format (or likely to not open in the first place).
  1499.                  //  Denied.
  1500.                  XP_FREE(filename);
  1501.                  return(NULL);
  1502.              }
  1503.          }
  1504.      }
  1505.  
  1506. #ifdef DEBUG_nobody
  1507.     TRACE("Opening a file type (%d) permissions: %s (%s)\n", type, perm, filename);
  1508. #endif
  1509.  
  1510. #ifdef XP_WIN32
  1511.     if (type == xpURL) {
  1512.         HANDLE    hFile;
  1513.         DWORD    dwType;
  1514.  
  1515.         // Check if we're trying to open a device. We don't allow this
  1516.         hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
  1517.             OPEN_EXISTING, 0, NULL);
  1518.  
  1519.         if (hFile != INVALID_HANDLE_VALUE) {
  1520.             dwType = GetFileType(hFile);
  1521.             CloseHandle(hFile);
  1522.     
  1523.             if (dwType != FILE_TYPE_DISK) {
  1524.                 XP_FREE(filename);
  1525.                 return NULL;
  1526.             }
  1527.         }
  1528.     }
  1529. #endif
  1530.  
  1531. #ifdef XP_WIN16
  1532.     // Windows uses ANSI codepage, DOS uses OEM codepage, fopen takes OEM codepage
  1533.     // That's why we need to do conversion here.
  1534.     CString oembuff = filename;
  1535.     oembuff.AnsiToOem();
  1536.     fp = fopen(oembuff, (char *) perm);
  1537.  
  1538.     if (fp && type == xpURL) {
  1539.         union _REGS    inregs, outregs;
  1540.  
  1541.         // Check if we opened a device. Execute an Interrupt 21h to invoke
  1542.         // MS-DOS system call 44h
  1543.         inregs.x.ax = 0x4400;     // MS-DOS function to get device information
  1544.         inregs.x.bx = _fileno(fp);
  1545.         _int86(0x21, &inregs, &outregs);
  1546.  
  1547.         if (outregs.x.dx & 0x80) {
  1548.             // It's a device. Don't allow any reading/writing
  1549.             fclose(fp);
  1550.             XP_FREE(filename);
  1551.             return NULL;
  1552.         }
  1553.     }
  1554. #else    
  1555.     fp = fopen(filename, (char *) perm);
  1556. #endif
  1557.     XP_FREE(filename);
  1558.     return(fp);
  1559. }
  1560.  
  1561.  
  1562. //
  1563. // Rename tmpname to fname 
  1564. //
  1565. int XP_FileRename(const char *tmpname, XP_FileType tmptype, const char *fname, XP_FileType ftype)    
  1566. {
  1567.     char * pOldName = WH_FileName(tmpname, tmptype);
  1568.     char * pNewName = WH_FileName(fname, ftype);
  1569.  
  1570.     if(!pOldName || !pNewName)
  1571.         return(-1);
  1572.  
  1573. #ifdef XP_WIN32
  1574.     // try using win32 system call. If that fails, do what the old code did.
  1575.     if (MoveFileEx(pOldName, pNewName, MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING))
  1576.     {
  1577.         XP_FREE(pOldName);
  1578.         XP_FREE(pNewName);
  1579.         return 0;
  1580.     }
  1581. #endif
  1582.     // lets try ANSI first
  1583.     int status = rename(pOldName, pNewName);
  1584.  
  1585.     // if rename failed try to just copy
  1586.     if(status == -1)
  1587.     {
  1588.         if(WFE_CopyFile(pOldName, pNewName))    
  1589.         {
  1590.             // we were at least able to copy the file so return the correct
  1591.             //   status and get rid of the old file
  1592.             status = 0;
  1593.             remove(pOldName);
  1594.         }
  1595.     }
  1596.  
  1597.     // clean up
  1598.     XP_FREE(pOldName);
  1599.     XP_FREE(pNewName);
  1600.  
  1601.     return(status);
  1602. }
  1603.  
  1604. //
  1605. // Make a directory with the given name (may need WH_FileName munging first)
  1606. //
  1607. int XP_MakeDirectory(const char* name, XP_FileType type)    
  1608. {
  1609.     char * pName = WH_FileName(name, type);
  1610.     if(pName) {
  1611.             int dir;
  1612.         dir = mkdir(pName);
  1613.         XP_FREE(pName);
  1614.         return(dir);
  1615.     }
  1616.     else
  1617.         return(-1);
  1618. }
  1619.  
  1620. //
  1621. // Remove a directory with the given name
  1622. //
  1623. int XP_RemoveDirectory (const char *name, XP_FileType type)
  1624. {
  1625.     int ret = -1;
  1626.     char *pName = WH_FileName (name, type);
  1627.     if (pName)    {
  1628.         ret = rmdir (pName);
  1629.         XP_FREE(pName);
  1630.     }
  1631.     return ret;
  1632. }
  1633.  
  1634. /****************************************************************************
  1635. *
  1636. *    XP_FileTruncate
  1637. *
  1638. *    PARAMETERS:
  1639. *        name    - filename to be truncated
  1640. *        length    - desired size (in bytes) for the truncated file
  1641. *
  1642. *    RETURNS:
  1643. *        Non-negative if successful, -1 if an exception occurs
  1644. *
  1645. *    DESCRIPTION:
  1646. *        This function is called to truncate (or extend) a given file.
  1647. *
  1648. ****************************************************************************/
  1649.  
  1650. int XP_FileTruncate(const char * name, XP_FileType type, int32 length)
  1651. {
  1652.     int nRtn = 0;
  1653.     
  1654.     char * szFileName = WH_FileName(name, type);
  1655.     if (szFileName != NULL)
  1656.     {
  1657.         TRY
  1658.         {
  1659.             CFile file(szFileName, CFile::modeReadWrite);
  1660.             file.SetLength((DWORD)length);
  1661.             file.Close();
  1662.         }
  1663.         CATCH(CFileException, e)
  1664.         {
  1665.             nRtn = -1;
  1666.             
  1667.             #ifdef _DEBUG
  1668.                 afxDump << "File exception: " << e->m_cause << "\n";
  1669.             #endif
  1670.         }
  1671.         END_CATCH
  1672.         XP_FREE(szFileName);
  1673.     }  /* end if */
  1674.     else
  1675.     {
  1676.         nRtn = -1;
  1677.     }  /* end else */
  1678.  
  1679.     return(nRtn);
  1680.     
  1681. } // END OF    FUNCTION XP_FileTruncate()
  1682.  
  1683. //
  1684. // Mimic unix stat call
  1685. // Return -1 on error
  1686. //
  1687. PUBLIC int 
  1688. XP_Stat(const char * name, XP_StatStruct * info, XP_FileType type)
  1689. {
  1690.     char * filename = WH_FileName(name, type);
  1691.     int res;
  1692.  
  1693.     if(!info || !filename)
  1694.         return(-1);
  1695.  
  1696.     //  THIS MUST BE DONE FIRST TO PLUG WIN OS SECURITY HOLE.    
  1697.     //  Do not allow UNC pathnames if the command line stated so.
  1698.     if(xpURL == type && FALSE == theApp.m_bUNC) {
  1699.         //  Make sure we have enough buffer to check.
  1700.         if(filename && filename[0] && filename[1]) {
  1701.             if(
  1702.                 ('\\' == filename[0] && '\\' == filename[1]) ||
  1703.                 ('/' == filename[0] && '/' == filename[1]) ||
  1704.                 ('\\' == filename[0] && '/' == filename[1]) ||
  1705.                 ('/' == filename[0] && '\\' == filename[1])
  1706.             ) {
  1707.                 //  Presumed UNC format (or likely to not open in the first place).
  1708.                 //  Denied.
  1709.                 XP_FREE(filename);
  1710.                 return(-1);
  1711.             }
  1712.         }
  1713.     }    
  1714.     
  1715.     // Strip off final slash on directory names 
  1716.     // BUT we will need to make sure we have c:\ NOT c:   
  1717.     int len = XP_STRLEN(filename) - 1;
  1718.     if(len > 1 && filename[len] == '\\' && filename[len -1] != ':'){
  1719.         uint16 iFileSystemCSID = CIntlWin::GetSystemLocaleCsid();    // this file system csid, not win_csid
  1720.         if( intl_IsEndWithBS( filename, iFileSystemCSID ) )
  1721.             filename[len] = '\0';
  1722.     }
  1723.  
  1724. #ifdef XP_WIN16        
  1725.     //  Also, if we are looking at something like "c:", we won't call stat at 
  1726.     //      all, as we never know if they have a diskette in drive A or such 
  1727.     //      and don't want to stall waiting.
  1728.     //  Be very strict on what we let into this statement, though.
  1729.     if(len == 1 && filename[len] == ':')  {
  1730.       //  Set the stat info ourselves.  The numbers were generic, taken 
  1731.       //    from a _stat call to "c:\"
  1732.       //  Is this a hack, or what?
  1733.       info->st_atime =
  1734.       info->st_ctime =
  1735.       info->st_mtime = 315561600L;
  1736.       info->st_uid = 0;
  1737.       info->st_gid = 0;
  1738.       info->st_size = (_off_t) 0;
  1739.       info->st_rdev =
  1740.       info->st_dev = filename[len - 1] - 'A';
  1741.       info->st_mode = 16895;
  1742.       info->st_nlink = 1;
  1743.       res = 0;
  1744.     }
  1745.     else  {
  1746.       // Windows uses ANSI codepage, DOS uses OEM codepage, _stat takes OEM codepage
  1747.       // That's why we need to do conversion here.
  1748.       CString oembuff = filename;
  1749.       oembuff.AnsiToOem();
  1750.       res = _stat(oembuff, info);
  1751.     }
  1752. #else // XP_WIN16
  1753.       //  Normal file or directory.
  1754.       res = _stat(filename, info);
  1755. #endif
  1756.     XP_FREE(filename);
  1757.     return(res);
  1758. }
  1759.                              
  1760.                              
  1761. PUBLIC XP_Dir 
  1762. XP_OpenDir(const char * name, XP_FileType type)
  1763. {
  1764.     XP_Dir dir;
  1765.     char * filename = WH_FileName(name, type);
  1766.     uint16 iFileSystemCSID = CIntlWin::GetSystemLocaleCsid();    // this file system csid, not win_csid
  1767.     CString foo;
  1768.                                               
  1769.     if(!filename)
  1770.         return NULL;
  1771.  
  1772.     //  THIS MUST BE DONE FIRST TO PLUG WIN OS SECURITY HOLE.    
  1773.     //  Do not allow UNC pathnames if the command line stated so.
  1774.     if(xpURL == type && FALSE == theApp.m_bUNC) {
  1775.         //  Make sure we have enough buffer to check.
  1776.         if(filename && filename[0] && filename[1]) {
  1777.             if(
  1778.                 ('\\' == filename[0] && '\\' == filename[1]) ||
  1779.                 ('/' == filename[0] && '/' == filename[1]) ||
  1780.                 ('\\' == filename[0] && '/' == filename[1]) ||
  1781.                 ('/' == filename[0] && '\\' == filename[1])
  1782.             ) {
  1783.                 //  Presumed UNC format (or likely to not open in the first place).
  1784.                 //  Denied.
  1785.                 XP_FREE(filename);
  1786.                 return(NULL);
  1787.             }
  1788.         }
  1789.     }    
  1790.     
  1791.     dir = (XP_Dir) new DIR;
  1792.  
  1793.     // For directory names we need \*.* at the end, if and only if there is an actual name specified.
  1794.     foo += filename;
  1795.     //if(filename[XP_STRLEN(filename) - 1] != '\\')
  1796.     if( !intl_IsEndWithBS( filename, iFileSystemCSID ) )
  1797.         foo += '\\';
  1798.     foo += "*.*";
  1799.  
  1800.     dir->directoryPtr = FindFirstFile((const char *) foo, &(dir->data));
  1801.     XP_FREE(filename);
  1802.     if(dir->directoryPtr == INVALID_HANDLE_VALUE) {
  1803.         delete dir;
  1804.         return(NULL);
  1805.     } else {
  1806.         return(dir);
  1807.     }
  1808. }
  1809.  
  1810.  
  1811. //
  1812. // HACK:- use a static location cuz unix does it that way even
  1813. //  though it makes for non-reentrant code
  1814. //
  1815. PUBLIC XP_DirEntryStruct * 
  1816. XP_ReadDir(XP_Dir dir)
  1817. {                                         
  1818.     static XP_DirEntryStruct dirEntry;
  1819.  
  1820.     if(dir && dir->directoryPtr) {
  1821. #ifdef XP_WIN16
  1822.         XP_STRCPY(dirEntry.d_name, dir->data.file_data.name);
  1823. #else
  1824.         XP_STRCPY(dirEntry.d_name, dir->data.cFileName);
  1825. #endif
  1826.         if(FindNextFile(dir->directoryPtr, &(dir->data)) == FALSE) {
  1827.             FindClose(dir->directoryPtr);
  1828.             dir->directoryPtr = NULL;
  1829.         }
  1830.         return(&dirEntry);
  1831.     } else {
  1832.         return(NULL);
  1833.     }
  1834. }
  1835.  
  1836.  
  1837. //
  1838. // Close the directory
  1839. //
  1840. PUBLIC void 
  1841. XP_CloseDir(XP_Dir dir)
  1842. {
  1843.     if (dir)
  1844.     {
  1845.         if (dir->directoryPtr)
  1846.             FindClose (dir->directoryPtr);
  1847.         delete dir;
  1848.     }
  1849.  
  1850. //
  1851. // Return 0 on success, -1 on failure.  Silly unix weenies
  1852. //
  1853. PUBLIC int 
  1854. XP_FileRemove(const char * name, XP_FileType type)
  1855. {           
  1856.     char *filename = WH_FileName(name, type);
  1857.  
  1858.     if(!filename)
  1859.         return(-1);
  1860.  
  1861. #ifdef MOZ_MAIL_NEWS    
  1862.     if(type == xpNewsRC || type == xpNewsgroups)
  1863.         NET_UnregisterNewsHost( name, FALSE);
  1864.     else if(type == xpSNewsRC || type == xpSNewsgroups)
  1865.         NET_UnregisterNewsHost(name, TRUE);
  1866. #endif // MOZ_MAIL_NEWS
  1867.  
  1868.     int status = remove(filename);
  1869.     XP_FREE(filename);
  1870.     return(status);
  1871. }
  1872.  
  1873. BOOL XP_RemoveDirectoryRecursive(const char *name, XP_FileType type)
  1874. {
  1875.     XP_DirEntryStruct *entry;
  1876.     XP_StatStruct     statbuf;
  1877.     BOOL          ret = TRUE;
  1878.     CString       dot    = ".";
  1879.     CString       dotdot = "..";
  1880.     int            status;
  1881.  
  1882.     XP_Dir dir = XP_OpenDir(name, type);  
  1883.     if (!dir) return FALSE;
  1884.  
  1885.     // Go through the directory entries and delete appropriately
  1886.     while ((entry = XP_ReadDir(dir)))
  1887.     {
  1888.         CString child;
  1889.         child = name;
  1890.         child += "\\";
  1891.         child += entry->d_name;
  1892.         if (!(status = XP_Stat(child, &statbuf, type)))
  1893.             if (entry->d_name == dot || entry->d_name == dotdot)
  1894.             {
  1895.                 // Do nothing, rmdir will clean these up
  1896.             }
  1897.             else if ((statbuf.st_mode & _S_IFMT) == _S_IFDIR) // _S_ISDIR() isn't on Win16
  1898.             {
  1899.                 // Recursive call to clean out subdirectory 
  1900.                 if (!XP_RemoveDirectoryRecursive(child, type))
  1901.                     ret = FALSE;
  1902.             }
  1903.             else
  1904.             {
  1905.                 // Everything that's not a directory is a file!
  1906.                 if (XP_FileRemove(child, type) != 0)
  1907.                     ret = FALSE;
  1908.             }
  1909.     }
  1910.  
  1911.     // OK, remove the top-level directory if we can
  1912.     if (XP_RemoveDirectory(name, type) != 0)
  1913.         ret = FALSE;
  1914.     
  1915.     XP_CloseDir(dir);
  1916.  
  1917.     return ret;
  1918. }
  1919.  
  1920.  
  1921. //  Should be self-explanitory --- return TRUE on success FALSE on failure
  1922. BOOL 
  1923. WFE_MoveFile(const char *cpSrc, const char *cpTarg)  
  1924. {
  1925. #ifdef XP_WIN32
  1926.     return MoveFile(cpSrc, cpTarg);  // overwrite existing target file
  1927. #else
  1928.     // lets try ANSI first
  1929.     int status = rename(cpSrc, cpTarg);
  1930.  
  1931.     // if rename failed try to just copy
  1932.     if(status !=0)
  1933.     {
  1934.         if(WFE_CopyFile(cpSrc, cpTarg))    
  1935.         {
  1936.             // we were at least able to copy the file so return the correct
  1937.             //   status and get rid of the old file
  1938.             status = 0;
  1939.             remove(cpSrc);
  1940.             return TRUE;
  1941.         }
  1942.         else return FALSE;
  1943.     }
  1944.     else return TRUE;
  1945. #endif
  1946. }
  1947.  
  1948. //  Should be self-explanitory --- return TRUE on success FALSE on failure
  1949. BOOL 
  1950. WFE_CopyFile(const char *cpSrc, const char *cpTarg)  
  1951. {
  1952. #ifdef XP_WIN32
  1953.     return CopyFile(cpSrc, cpTarg, FALSE);  // overwrite existing target file
  1954. #else
  1955.   CFile cfSource;
  1956.   CFile cfTarget;
  1957.   
  1958.   TRY {
  1959.     Bool fail;
  1960.     /* Open returns 0 on failure */
  1961.     fail = cfSource.Open(cpSrc, CFile::modeRead | CFile::shareExclusive);
  1962.     if (fail == 0)
  1963.         return (FALSE);
  1964.     fail = cfTarget.Open(cpTarg, CFile::modeWrite | CFile::modeCreate | CFile::shareExclusive);
  1965.     if (fail == 0)
  1966.         return (FALSE);
  1967.   }
  1968.   CATCH(CFileException, e)  {
  1969.     //  Couldn't do it, just return.
  1970.     return(FALSE);
  1971.   }
  1972.   END_CATCH
  1973.   
  1974.   //  Copy the thing.
  1975.   char *pBuffer = new char[8192];
  1976.   UINT uAmount;
  1977.   
  1978.   do  {
  1979.     uAmount = 8192;
  1980.     TRY {
  1981.       uAmount = cfSource.Read((void *)pBuffer, uAmount);
  1982.       cfTarget.Write((void *)pBuffer, uAmount);
  1983.     }
  1984.     CATCH(CFileException, e)  {
  1985.       //  don't know why we failed, but assume we're done.
  1986.       //  perhaps end of file.
  1987.       break;
  1988.     }
  1989.     END_CATCH
  1990.   }
  1991.   while(uAmount != 0);
  1992.   
  1993.   //  Clean up the buffer.
  1994.   //  Files close up automagically.
  1995.   delete []pBuffer;
  1996.   return(TRUE);
  1997. #endif
  1998. }
  1999.  
  2000. /* copy the file specified by the first argument
  2001.  * over the newsrc file.  The second argument specifies
  2002.  * the hostname for this newsrc or "" if it is the default
  2003.  * host.
  2004.  *
  2005.  * The first filename argument was generated by a call to WH_TempName
  2006.  * with an enum of "xpTemporaryNewsRC" 
  2007.  *
  2008.  * Should return TRUE on success or FALSE on failure.
  2009.  */
  2010. extern "C" Bool XP_File_CopyOverNewsRC(const char *newfile, 
  2011.                                        const char *news_hostname,
  2012.                                        Bool        is_secure)  
  2013. {
  2014. #ifdef MOZ_MAIL_NEWS
  2015.     char *pRCName = NET_MapNewsrcHostToFilename((char *)news_hostname, 
  2016.                                                 is_secure,
  2017.                                                 FALSE);
  2018.  
  2019.     //  Is the current rc valid?
  2020.     if(pRCName == NULL) {
  2021.         return(FALSE);
  2022.     }
  2023.  
  2024.     //  Are we getting a valid filename?
  2025.     if(newfile == NULL) {
  2026.         return(FALSE);
  2027.     }
  2028.  
  2029.     //  Does the new one exist?
  2030.     CFileStatus rStatus;
  2031.     if(CFile::GetStatus(newfile, rStatus) == 0) {
  2032.         return(FALSE);
  2033.     }
  2034.  
  2035.     //  Does the old one exist?
  2036.     //  If so, we should remove it.
  2037.     if(CFile::GetStatus(pRCName, rStatus) != 0) {
  2038.         //  Attempt to remove.
  2039.         TRY {
  2040.             CFile::Remove(pRCName);
  2041.         }
  2042.         CATCH(CFileException, e)  {
  2043.             return(FALSE);
  2044.         }
  2045.         END_CATCH     
  2046.     }
  2047.  
  2048.     TRY {
  2049.         //  Attempt a speedy rename.
  2050.         CFile::Rename(newfile, pRCName);
  2051.     }
  2052.     CATCH(CFileException, e)  {
  2053.         //  Rename didn't work, attempt to copy, as fast as possible.
  2054.         if(FALSE == WFE_CopyFile(newfile, pRCName)) {
  2055.             //  Uh, like we lost the newsrc file permanently here!!!!!!!!!!
  2056.             ASSERT(0);
  2057.             return(FALSE);
  2058.         }
  2059.  
  2060.         //  Should remove the temp file now, as it is expected to go away.
  2061.         TRY {
  2062.             CFile::Remove(newfile);
  2063.         }
  2064.         CATCH(CFileException, e)  {
  2065.             //  Leave it lying around, not much we can do.
  2066.             return(TRUE);
  2067.         }
  2068.         END_CATCH
  2069.     }
  2070.     END_CATCH
  2071. #endif // MOZ_MAIL_NEWS
  2072.     return(TRUE);
  2073. }
  2074.  
  2075. extern "C" XP_Bool XP_FileNameContainsBadChars (const char *name)
  2076. {
  2077. #ifdef XP_WIN16
  2078.     char *badChars = "\\/:*?\"<>| ,+";
  2079. #else
  2080.     char *badChars = "\\/:*?\"<>|";
  2081. #endif
  2082.     XP_ASSERT( name != NULL );
  2083.     uint len = XP_STRLEN(badChars);
  2084.     if( len < 1 )
  2085.         return FALSE;
  2086.  
  2087.     uint16 iFileSystemCSID = CIntlWin::GetSystemLocaleCsid();    // this file system csid, not win_csid
  2088.     while( *name != NULL ){
  2089.         for (uint j = 0; j < len; j++)
  2090.             if (*name == badChars[j])
  2091.                 return TRUE;
  2092.         name = INTL_NextChar( iFileSystemCSID, (char*)name );
  2093.     }
  2094.     return FALSE;
  2095. }
  2096.  
  2097. // Print a trace message to the console
  2098. //
  2099. #ifdef DEBUG
  2100. PUBLIC void 
  2101. FE_Trace(const char * msg)
  2102. {
  2103.     /* This used to be just TRACE(msg), but that's a mistake -- 
  2104.      * if msg happens to have a '%' in it, TRACE will
  2105.      * interpret the '%' as the beginning of an argument to be
  2106.      * printf'd and look up the stack and try to
  2107.      * interpret random data as the argument. At a minimum this
  2108.      * leads to corrupt trace info. Usually it causes bus errors.
  2109.      */
  2110.     TRACE("%s", msg);
  2111. }
  2112. #endif
  2113.  
  2114. PUBLIC void 
  2115. FE_ConnectToRemoteHost(MWContext * context, int url_type, char *
  2116.     hostname, char * port, char * username) 
  2117. {
  2118.     LPSTR   lpszCommand;
  2119.     UINT    iRet;
  2120.  
  2121.     ASSERT(url_type == FE_TN3270_URL_TYPE ||
  2122.            url_type == FE_TELNET_URL_TYPE ||
  2123.            url_type == FE_RLOGIN_URL_TYPE);
  2124.  
  2125. #ifdef _WIN32
  2126.     BOOL checkRegistry = TRUE;
  2127.     CInternetShortcut InternetShortcut;
  2128.     if (InternetShortcut.ShellSupport() && !theApp.m_bParseTelnetURLs)
  2129.     {
  2130.       SHELLEXECUTEINFO    sei;
  2131.       
  2132.       // Build the command string
  2133.       if (port)
  2134.         lpszCommand = PR_smprintf("%s://%s:%s", url_type == FE_TN3270_URL_TYPE ?
  2135.             "tn3270" : "telnet", hostname, port);
  2136.       else
  2137.         lpszCommand = PR_smprintf("%s://%s", url_type == FE_TN3270_URL_TYPE ?
  2138.             "tn3270" : "telnet", hostname);
  2139.  
  2140.       // Use ShellExecuteEx to launch
  2141.       sei.cbSize = sizeof(sei);
  2142.       sei.fMask = SEE_MASK_FLAG_NO_UI | SEE_MASK_NOCLOSEPROCESS;
  2143.       sei.hwnd = NULL;
  2144.       sei.lpVerb = NULL;  // default to Open
  2145.       sei.lpFile = lpszCommand;
  2146.       sei.lpParameters = NULL;
  2147.       sei.lpDirectory = NULL;
  2148.       sei.nShow = SW_SHOW;
  2149.       ShellExecuteEx(&sei);
  2150.       iRet = (UINT)sei.hInstApp;
  2151.       
  2152.       XP_FREE(lpszCommand);
  2153.  
  2154.       checkRegistry = iRet < 32;
  2155.     }
  2156.     
  2157.     if (checkRegistry)
  2158.     {
  2159. #endif // _WIN32
  2160.     char    szBuf[_MAX_PATH];
  2161.     LONG    lResult;
  2162.     LONG    cbData;
  2163.     HKEY    hKey;
  2164.  
  2165.     // Build the shell\open key for the file type class
  2166.     PR_snprintf(szBuf, sizeof(szBuf), "%s\\shell\\open",
  2167.         url_type == FE_TN3270_URL_TYPE ? "tn3270" : "telnet");
  2168.     
  2169.     // Open the key
  2170.     lResult = RegOpenKey(HKEY_CLASSES_ROOT, szBuf, &hKey);
  2171.     if (lResult != ERROR_SUCCESS) {
  2172.         // Nothing registered for the file type class
  2173.         FE_Alert(context, szLoadString(IDS_NO_VIEWER_CONFIGD));
  2174.         return;
  2175.     }
  2176.  
  2177.     // Get the Open command string
  2178.     cbData = sizeof(szBuf);
  2179.     lResult = RegQueryValue(hKey, "command", szBuf, &cbData);
  2180.     RegCloseKey(hKey);
  2181.  
  2182.     if (lResult == ERROR_SUCCESS) {
  2183.         LPSTR   lpszApp = szBuf;
  2184.         LPSTR   lpszArg;
  2185.  
  2186.         // Strip off any command line options
  2187.         lpszArg = strstr(lpszApp, "%1");
  2188.         if (lpszArg)
  2189.             *lpszArg = '\0';  // null terminate the string here
  2190.  
  2191.         // Build the WinExec command line
  2192.         if (port)
  2193.             lpszCommand = PR_smprintf("%s %s %s", lpszApp, hostname, port);
  2194.         else
  2195.             lpszCommand = PR_smprintf("%s %s", lpszApp, hostname);
  2196.     
  2197.         // Run it
  2198.         iRet = (UINT)WinExec(lpszCommand, SW_SHOW);
  2199.         XP_FREE(lpszCommand);
  2200.     
  2201.         // If the error is file not found or path not found report it here; otherwise
  2202.         // report it below
  2203.         if (iRet == 2 || iRet == 3) {
  2204.             LPSTR   lpszMsg;
  2205.     
  2206.             lpszMsg = PR_smprintf(szLoadString(IDS_UNABLE_FIND_APP), lpszApp);
  2207.             if (lpszMsg) {
  2208.                 FE_Alert(context, lpszMsg);
  2209.                 XP_FREE(lpszMsg);
  2210.             }
  2211.     
  2212.             return;
  2213.         }
  2214.     }
  2215. #ifdef _WIN32
  2216.     }
  2217. #endif // _WIN32
  2218.  
  2219.     // See if it worked
  2220.     if (iRet < 32) {
  2221.         LPSTR   lpszMsg;
  2222.  
  2223.         lpszMsg = PR_smprintf(szLoadString(IDS_UNABLE_TO_LAUNCH_APP), iRet);
  2224.         if (lpszMsg) {
  2225.             FE_Alert(context, lpszMsg);
  2226.             XP_FREE(lpszMsg);
  2227.         }
  2228.  
  2229.     } else {
  2230.         FE_Progress(context, szLoadString(IDS_SPAWNING_APP));
  2231.  
  2232.         if (username) {
  2233.             LPSTR   lpszMsg;
  2234.  
  2235.             lpszMsg = PR_smprintf(szLoadString(IDS_LOGIN_AS), username);
  2236.             if (lpszMsg) {
  2237.                 FE_Alert(context, lpszMsg);
  2238.                 XP_FREE(lpszMsg);
  2239.             }
  2240.         }
  2241.     }
  2242. }
  2243.  
  2244.  
  2245. PUBLIC void *FE_AboutData (const char *which, char **data_ret, int32 *length_ret, char **content_type_ret)
  2246. {
  2247.   char *loc = (char*)strchr (which, '?');
  2248.   char *which2;
  2249.   char *tmp;
  2250.   
  2251.   if (loc)
  2252.     *loc++ = 0;
  2253.  
  2254.     BOOL bHandled = FALSE;
  2255.     if(FALSE == bHandled) {
  2256.         char *pCompare = strdup(which);
  2257.         if(pCompare) {
  2258.             char *pReplace = strchr(pCompare, '.');
  2259.             if(pReplace) {
  2260.                 *pReplace = '_';
  2261.             }
  2262.             HINSTANCE hInst = AfxGetResourceHandle();
  2263.             if(hInst) {
  2264.                 HRSRC hFound = FindResource(hInst, pCompare, RT_RCDATA);
  2265.                 free(pCompare);
  2266.                 pCompare = NULL;
  2267.                 if(hFound) {
  2268.                     HGLOBAL hRes = LoadResource(hInst, hFound);
  2269.                     hFound = NULL;
  2270.                     if(hRes) {
  2271.                         char *pBytes = (char *)LockResource(hRes);
  2272.                         if(pBytes) {
  2273.                             //  Check for identifying bin2rc string.
  2274.                             if(!strcmp(pBytes, "bin2rc generated resource")) {
  2275.                                 pBytes += 26; // length + 1
  2276.  
  2277.                                 //  Next is a content-type.
  2278.                                 //  The mime type should be something we recognize.
  2279.                                 //  Assign in a constant string only.
  2280.                                 if(!stricmp(pBytes, IMAGE_GIF))   {
  2281.                                     *content_type_ret = IMAGE_GIF;
  2282.                                 }
  2283.                                 else if(!stricmp(pBytes, IMAGE_JPG))    {
  2284.                                     *content_type_ret = IMAGE_JPG;
  2285.                                 }
  2286.                                 pBytes += strlen(pBytes) + 1;  // length + 1
  2287.  
  2288.                                 //  Next is the size of the data if we are willing.
  2289.                                 if(*content_type_ret)   {
  2290.                                     *length_ret =  strtol(pBytes, NULL, 10);
  2291.                                 }
  2292.                                 pBytes += strlen(pBytes) + 1; // length + 1
  2293.  
  2294.                                 //  Next is the data if any.
  2295.                                 if(*length_ret)  {
  2296.                                     *data_ret = (char *)malloc(*length_ret);
  2297.                                     if(*data_ret) {
  2298.                                         memcpy(*data_ret, pBytes, *length_ret);
  2299.                                         bHandled = TRUE;
  2300.                                     }
  2301.                                     else    {
  2302.                                         //  Unable to alloc.
  2303.                                         //  Clear out.
  2304.                                         *content_type_ret = NULL;
  2305.                                         *length_ret = 0;
  2306.                                     }
  2307.                                 }
  2308.                             }
  2309.                             pBytes = NULL;
  2310.                         }
  2311.                         UnlockResource(hRes);
  2312.                         FreeResource(hRes);
  2313.                         hRes = NULL;
  2314.                     }
  2315.                 }
  2316.             }
  2317.         }
  2318.     }
  2319.  
  2320.     if(FALSE == bHandled)    {
  2321.       which2 = strdup (which);
  2322.       for (tmp = which2; *tmp; tmp++)
  2323.           *tmp += 69;
  2324.  
  2325.         char *a = NULL;
  2326.         if (!strcmp (which2, ""))   {                 // about:
  2327.             CString csVersion, csBuildNumber;
  2328.             char *tmpversionBuf;
  2329.  
  2330.             csVersion = XP_AppVersion;
  2331.             csVersion = csVersion.Left(csVersion.Find("]") + 1);
  2332.             tmpversionBuf = (char *)XP_ALLOC(15);
  2333.             //Loading from netscape.exe instead of resdll.dll since the string has been moved #109455
  2334.             LoadString(::AfxGetInstanceHandle(), IDS_APP_BUILD_NUMBER, tmpversionBuf, 15);
  2335.             csBuildNumber = tmpversionBuf;
  2336.             if (tmpversionBuf) XP_FREE(tmpversionBuf);
  2337.             csVersion+=csBuildNumber;
  2338.  
  2339.  
  2340.             char *pSSLVersion;
  2341.             char *pSSLCapability = XP_SecurityCapabilities();
  2342.             pSSLVersion = strdup(XP_SecurityVersion(1));
  2343.             char *pSSLString = (char *)malloc(strlen(pSSLVersion) + strlen(pSSLCapability) + 48*2);
  2344.             sprintf(pSSLString, szLoadString(IDS_ABOUT_SECURITY), pSSLVersion, pSSLCapability);
  2345.             free(pSSLCapability);
  2346.  
  2347.             char *pSp = szLoadString(IDS_ABOUT_0);
  2348.             a = (char *)malloc(strlen(pSp) + strlen(pSSLString) + strlen(csVersion) * 2 + 48);
  2349.             sprintf(a, pSp, (const char *)csVersion, (const char *)csVersion, pSSLString);
  2350.         
  2351.             free(pSSLString);
  2352.             free(pSSLVersion);
  2353.         }
  2354.         else if (!strcmp (which, "mailintro"))
  2355.           a = strdup(szLoadString(IDS_MAIL_0)); 
  2356.         else if (!strcmp (which, "license"))
  2357.           a = wfe_LoadResourceString("license");      
  2358.         else if (!strcmp (which, "mozilla"))
  2359.           a = strdup (szLoadString(IDS_MOZILLA_0));
  2360.         else if (!strcmp (which2, "\250\264\265\276\267\256\254\255\271"))
  2361.           a = strdup(szLoadString(IDS_COPYRIGHT_0));
  2362.         else if (!strcmp (which2, "\247\261\246\263\260"))
  2363.           a = strdup ("");                                           
  2364. #ifdef EDITOR
  2365.         else if (!strcmp (which, "editfilenew"))
  2366.           a = strdup (EDT_GetEmptyDocumentString());
  2367. #endif // EDITOR
  2368.         else if (!strcmp(which, "plugins"))
  2369.           a = wfe_LoadResourceString("aboutplg");      
  2370.         else
  2371.           a = strdup(which);
  2372.  
  2373.     
  2374.         if (a)
  2375.         {
  2376.         //          for (tmp = a; *tmp; tmp++) *tmp -= 69;
  2377.           *data_ret = a;
  2378.           *length_ret = strlen (*data_ret);
  2379.           *content_type_ret = TEXT_MDL; 
  2380.       
  2381.           if(!strcmp (which, "license"))
  2382.             *content_type_ret = TEXT_PLAIN;
  2383.  
  2384. #ifdef DEBUG
  2385.           //    Produce some hard to debug situations here manually.
  2386.           if(!stricmp(which, "WM_ENDSESSION"))   {
  2387.               //    Shutdown of the system case.
  2388.               FEU_FrameBroadcast(TRUE, WM_QUERYENDSESSION, 1, 0);
  2389.               FEU_FrameBroadcast(FALSE, WM_ENDSESSION, 1, 0);
  2390.           }
  2391.           else if(!stricmp(which, "debug")) {
  2392.             DebugBreak();
  2393.           }
  2394.           else if(!stricmp(which, "PostQuitMessage"))   {
  2395.             PostQuitMessage(0);
  2396.           }
  2397. #endif
  2398.         }
  2399.         else
  2400.         {
  2401.           *data_ret = 0;
  2402.           *length_ret = 0;
  2403.           *content_type_ret = 0;
  2404.         }
  2405.         free (which2);
  2406.     }
  2407.  
  2408.     return(*data_ret);
  2409. }
  2410.  
  2411. /*****/
  2412.  
  2413. PUBLIC void FE_FreeAboutData(void *data, const char *which2)
  2414. {
  2415.     if(data)   {
  2416.         free(data);
  2417.         data = NULL;
  2418.     }
  2419. }
  2420.  
  2421. char *XP_PlatformPartialPathToXPPartialPath (const char *platformName)
  2422. {
  2423.     return XP_STRDUP(platformName);
  2424. }
  2425.  
  2426.  
  2427. char *XP_PlatformFileToURL (const char *platformName)
  2428. {
  2429.     CString csXPName;
  2430.     WFE_ConvertFile2Url (csXPName, platformName);
  2431.     return XP_STRDUP(csXPName);
  2432. }
  2433. void WFE_ConvertFile2Url(CString& csUrl, const char *pLocalFileName)
  2434. {
  2435.     uint16 iFileSystemCSID = CIntlWin::GetSystemLocaleCsid();    // this file system csid, not win_csid
  2436.     //    First empty the returning url, in case it has something in it.
  2437.     csUrl.Empty();
  2438.  
  2439.     //    If there's nothing to convert, return now.
  2440.     if(pLocalFileName == NULL || *pLocalFileName == '\0')    {
  2441.         return;
  2442.     }
  2443.  
  2444.     //    A CString we can muck with.
  2445.     CString csLocal = pLocalFileName;
  2446.  
  2447.     if (csLocal.GetLength() > 4) {        
  2448.  
  2449.         if ( !strnicmp(&pLocalFileName[strlen(pLocalFileName)-4],".lnk",4)) {
  2450.             char szName[_MAX_PATH];
  2451.             HRESULT hRes = ::ResolveShortCut(NULL, pLocalFileName, szName);
  2452.             if (SUCCEEDED(hRes)) {
  2453.                 csLocal = szName;
  2454.             }
  2455.         }
  2456.         else if (!strnicmp(&pLocalFileName[strlen(pLocalFileName)-4],".url",4)) {
  2457.             CInternetShortcut InternetShortcut;
  2458.               if (InternetShortcut.ShellSupport()) {
  2459.                 // got a valid .URL internet shortcut file
  2460.                 char szNew[_MAX_PATH];
  2461.                 CInternetShortcut Shortcut (pLocalFileName);
  2462.                 Shortcut.GetURL(szNew,sizeof(szNew));
  2463.                 csUrl = szNew;
  2464.                 return;
  2465.             }
  2466.         }
  2467.     }
  2468.  
  2469.  
  2470.     //    Convert $ROOT to the directory of the executable.
  2471.     if(csLocal.Left(5) == "$ROOT")    {
  2472.         char aPath[_MAX_PATH];
  2473.         ::GetModuleFileName(theApp.m_hInstance, aPath, _MAX_PATH);
  2474.  
  2475.         //    Find the trailing slash.
  2476.         char *pSlash = intl_strrchr(aPath, '\\', iFileSystemCSID);
  2477.         if(pSlash)    {
  2478.             *pSlash = '\0';
  2479.         }
  2480.         else    {
  2481.             aPath[0] = '\0';
  2482.         }
  2483.  
  2484.         csLocal = aPath + csLocal.Right(csLocal.GetLength() - 5);
  2485.     }
  2486.     
  2487.     //    Convert local file paths which have a drive letter to an appropriate URL.
  2488.     //    This means we must always have a fully qualified file path in order to convert
  2489.     //        these correctly.
  2490.     const char* src = csLocal.GetBuffer( csLocal.GetLength() ) + 2;
  2491.     const char* end = src + csLocal.GetLength() - 2;
  2492.     if(csLocal.GetLength() >= 2 && csLocal[1] == ':')    {
  2493.         csUrl += "file:///";
  2494.         csUrl += csLocal[0];
  2495.         csUrl += '|';
  2496. #ifdef BUG93660_4_05_FIX
  2497.         for(int iTraverse = 2; iTraverse < csLocal.GetLength();
  2498.             iTraverse++)    
  2499.         {
  2500.             if(csLocal[iTraverse] == '\\')
  2501.             {
  2502.                 // bug 93660 -- double byte file name gets truncated
  2503.                 // We don't want to replace the backslash with
  2504.                 // forwardslash in case of the double byte file name
  2505.                 // iTraverse starts with 2; iTraverse - 1 will not go
  2506.                 // negative 
  2507.                 if (CIntlWin::GetSystemLocaleCsid() & MULTIBYTE &&
  2508.                     INTL_IsLeadByte(CIntlWin::GetSystemLocaleCsid(), 
  2509.                                     csLocal[iTraverse-1]))
  2510.                 {
  2511.                     csUrl += csLocal[iTraverse];
  2512.                 }
  2513.                 else
  2514.                 {
  2515.                     csUrl += '/';
  2516.                 }
  2517.             }
  2518.             else
  2519.             {
  2520.                 csUrl += csLocal[iTraverse];
  2521.             }
  2522.         }
  2523. #endif
  2524.     }
  2525.     //    Convert microsoft network paths.
  2526.     else if(csLocal.Left(2) == "\\\\" || csLocal.Left(2) == "//")    {
  2527.         csUrl += "file:////";
  2528.     }
  2529.     else    {
  2530.         //    This was a normal URL.
  2531.         //    Don't corrupt it.
  2532.         csUrl = pLocalFileName;
  2533.         src = end = NULL;
  2534.     }
  2535.  
  2536.     if( src != NULL ){
  2537.         while( src < end ){
  2538.               if( *src == '\\'){
  2539.                   csUrl += '/';
  2540.                 src++;
  2541.  
  2542.               } else {
  2543.                 const char* next = INTL_NextChar( iFileSystemCSID, (char*)src );
  2544.                 ASSERT( next <= end );
  2545.                 while( src < next )
  2546.                     csUrl += *src++;
  2547.               }
  2548.         }
  2549.          csLocal.ReleaseBuffer();
  2550.     }
  2551.  
  2552.  
  2553.  
  2554.  
  2555.     // This seems to be missing cases such as "..\foo"
  2556.     // Replace all "\" with "/" Note: only do this for the file: protocol or if there is no
  2557.     // specified protocol type; this way we won't munge things like mocha: and mailbox:
  2558.     int    nUrlType = NET_URL_Type(csUrl);
  2559.  
  2560.     if (nUrlType == FILE_TYPE_URL || nUrlType == 0) {
  2561.          char* src = csUrl.GetBuffer( csUrl.GetLength() );
  2562.          while( *src != NULL ){
  2563.              if( *src == '\\' )
  2564.                  *src++ = '/';
  2565.              else
  2566.                  src = INTL_NextChar( iFileSystemCSID, src );
  2567.         }
  2568.          csUrl.ReleaseBuffer();
  2569.     }
  2570.  
  2571.     //    Check for a file url with an extra slash.
  2572.     //    This is special case code to make sure an arbitrary number
  2573.     //        of slashes sends the file URL as a microsoft network
  2574.     //        path.
  2575.     //    Go recursive, minus one slash.
  2576.     if(csUrl.Left(10) == "file://///")    {
  2577.         CString csLeft = csUrl.Left(9);
  2578.         CString csRight = csUrl.Right(csUrl.GetLength() - 10);
  2579.         WFE_ConvertFile2Url(csUrl, (const char *)(csLeft + csRight));
  2580.     }
  2581. }
  2582.  
  2583. extern CString WFE_EscapeURL(const char* url)
  2584. {
  2585.     CString urlStr(url);
  2586.     CString encoded;
  2587.     int l = urlStr.GetLength();
  2588.     for (int i = 0; i < l; i++)
  2589.     {
  2590.         char c = urlStr[i];
  2591.         if (c == ' ')
  2592.             encoded += "%20";
  2593.         else encoded += c;
  2594.     }
  2595.  
  2596.     return encoded;
  2597. }
  2598.  
  2599. extern void FE_SetRefreshURLTimer(MWContext *pContext, uint32 ulSeconds, char *pRefreshUrl) {
  2600. //    Purpose:    Set a delayed load timer for a window for a particular URL.
  2601. //    Arguments:  pContext    The context that we're in.  We are only interested on wether or not there appears to be a Frame/hence document.
  2602. //              ulSeconds   The number of seconds that will pass before we attempt the reload.
  2603. //    Returns:    void
  2604. //    Comments:
  2605. //    Revision History:
  2606. //      02-17-95    created GAB
  2607. //        07-22-95    modified to use new context.
  2608. //      05-03-96    modified to use new API outside of idle loop.
  2609. //
  2610.  
  2611.     //  Only do this if it is a window context from the back end.
  2612.     if(ABSTRACTCX(pContext) && ABSTRACTCX(pContext)->IsWindowContext()) {
  2613.         FEU_ClientPull(pContext, ulSeconds * 1000, NET_CreateURLStruct(pRefreshUrl, NET_NORMAL_RELOAD), FO_CACHE_AND_PRESENT, FALSE);
  2614.     }
  2615. }
  2616.  
  2617. #if defined XP_WIN16 && defined DEBUG
  2618. void AfxDebugBreak()    {
  2619.     _asm { int 3 };
  2620. }
  2621. #endif
  2622.  
  2623. extern "C" void XP_Assert(int stuff)    {
  2624.     ASSERT(stuff);
  2625. }
  2626.  
  2627. extern "C" void fe__assert(void *, void *, unsigned)    {
  2628. #ifdef DEBUG
  2629.     TRACE("lowest level Assertion failure!\n");
  2630.     AfxDebugBreak(); 
  2631. #endif
  2632. }
  2633. extern "C" void fe_abort(void)    {
  2634. #ifdef DEBUG
  2635.     TRACE("lowest level Abortion called!\n");
  2636.     AfxDebugBreak();
  2637. #endif
  2638. }
  2639.  
  2640. extern "C" void XP_AssertAtLine( char *pFileName, int iLine ){
  2641. #ifdef DEBUG
  2642. #ifdef XP_WIN32
  2643.     if( AfxAssertFailedLine( pFileName, iLine) )
  2644. #endif
  2645.     {
  2646.         AfxDebugBreak();
  2647.     }
  2648. #endif
  2649. }
  2650.  
  2651. // Draws a 3D button exactly as Windows95 style
  2652. void WFE_DrawWindowsButtonRect(HDC hDC, LPRECT lpRect, BOOL bPushed)
  2653. {
  2654.     
  2655.     HPEN penHighlight = ::CreatePen(PS_SOLID, 1, bPushed ? sysInfo.m_clrBtnShadow : sysInfo.m_clrBtnHilite);
  2656.     HPEN penShadow = ::CreatePen(PS_SOLID, 1, bPushed ? sysInfo.m_clrBtnHilite : sysInfo.m_clrBtnShadow);
  2657.     HPEN penBlack = ::CreatePen(PS_SOLID, 1, RGB(0,0,0));
  2658.  
  2659.     // Top and left
  2660.     HPEN penOld = (HPEN)::SelectObject(hDC, bPushed ? penBlack : penHighlight);
  2661.     ::MoveToEx(hDC, lpRect->left, lpRect->bottom, NULL);
  2662.     ::LineTo(hDC, lpRect->left, lpRect->top);
  2663.     ::LineTo(hDC, lpRect->right+1, lpRect->top);
  2664.  
  2665.     // Bottom and right
  2666.     ::SelectObject(hDC, bPushed ? penHighlight : penBlack);
  2667.     ::MoveToEx(hDC, lpRect->left+1, lpRect->bottom, NULL);
  2668.     ::LineTo(hDC, lpRect->right, lpRect->bottom);
  2669.     ::LineTo(hDC, lpRect->right, lpRect->top);
  2670.  
  2671.     // Shadow color line inside to black line
  2672.     ::SelectObject(hDC, penShadow);
  2673.    ::MoveToEx(hDC, lpRect->left+1, lpRect->bottom-1, NULL);
  2674.     if( bPushed )
  2675.     {
  2676.         ::LineTo(hDC, lpRect->left+1, lpRect->top-1);
  2677.         ::LineTo(hDC, lpRect->right-1, lpRect->top-1);
  2678.     } else {
  2679.         ::LineTo(hDC, lpRect->right-1, lpRect->bottom-1);
  2680.         ::LineTo(hDC, lpRect->right-1, lpRect->top+1);
  2681.     }
  2682.  
  2683.     // Cleanup
  2684.     ::SelectObject(hDC, penOld);
  2685.     ::DeleteObject(penShadow);
  2686.     ::DeleteObject(penHighlight);
  2687.     ::DeleteObject(penBlack);
  2688.  
  2689. }
  2690.  
  2691. //============================================================= DrawHighlight
  2692. // Draw the highlight around the area
  2693.  void WFE_DrawHighlight( HDC hDC, LPRECT lpRect, COLORREF clrTopLeft, COLORREF clrBottomRight )
  2694. {
  2695.     HPEN hpenTopLeft = ::CreatePen( PS_SOLID, 0, clrTopLeft );
  2696.     HPEN hpenBottomRight = ::CreatePen( PS_SOLID, 0, clrBottomRight );
  2697.     HPEN hpenOld = (HPEN) ::SelectObject( hDC, hpenTopLeft );
  2698.  
  2699.     ::MoveToEx( hDC, lpRect->left, lpRect->bottom, NULL );
  2700.     ::LineTo( hDC, lpRect->left, lpRect->top );
  2701.     ::LineTo( hDC, lpRect->right - 1, lpRect->top );
  2702.  
  2703.     ::SelectObject( hDC, hpenBottomRight );
  2704.     ::LineTo( hDC, lpRect->right - 1, lpRect->bottom - 1);
  2705.     ::LineTo( hDC, lpRect->left, lpRect->bottom - 1);
  2706.  
  2707.     ::SelectObject( hDC, hpenOld );
  2708.  
  2709.     VERIFY(::DeleteObject( hpenTopLeft ));
  2710.     VERIFY(::DeleteObject( hpenBottomRight ));
  2711. }
  2712.  
  2713.  
  2714. //============================================================ DrawRaisedRect
  2715. void WFE_DrawRaisedRect( HDC hDC, LPRECT lpRect )
  2716. {
  2717.     RECT rcTmp = *lpRect;
  2718.     ::InflateRect( &rcTmp, -1, -1 );
  2719. #ifdef _WIN32
  2720.     WFE_DrawHighlight( hDC, &rcTmp, 
  2721.                    GetSysColor( COLOR_3DLIGHT ), 
  2722.                    GetSysColor( COLOR_3DSHADOW ) );
  2723.     WFE_DrawHighlight( hDC, lpRect, 
  2724.                    GetSysColor( COLOR_3DHILIGHT ), 
  2725.                    GetSysColor( COLOR_3DDKSHADOW ) );
  2726. #else
  2727.     WFE_DrawHighlight( hDC, lpRect, 
  2728.                    GetSysColor( COLOR_BTNHIGHLIGHT ), 
  2729.                    GetSysColor( COLOR_BTNSHADOW ) );
  2730.     WFE_DrawHighlight( hDC, &rcTmp, 
  2731.                    GetSysColor( COLOR_BTNHIGHLIGHT ), 
  2732.                    GetSysColor( COLOR_BTNSHADOW ) );
  2733. #endif
  2734. }
  2735.  
  2736.  
  2737. //=========================================================== DrawLoweredRect
  2738. void WFE_DrawLoweredRect( HDC hDC, LPRECT lpRect )
  2739. {
  2740.     RECT rcTmp = *lpRect;
  2741.     ::InflateRect( &rcTmp, -1, -1 );
  2742. #ifdef _WIN32
  2743.     WFE_DrawHighlight( hDC, &rcTmp, 
  2744.                    GetSysColor( COLOR_3DSHADOW ), 
  2745.                    GetSysColor( COLOR_3DLIGHT ) );
  2746.     WFE_DrawHighlight( hDC, lpRect, 
  2747.                    GetSysColor( COLOR_3DDKSHADOW ), 
  2748.                    GetSysColor( COLOR_3DHILIGHT) );
  2749. #else
  2750.     WFE_DrawHighlight( hDC, &rcTmp, 
  2751.                    GetSysColor( COLOR_BTNSHADOW ), 
  2752.                    GetSysColor( COLOR_BTNHIGHLIGHT ) );
  2753.     WFE_DrawHighlight( hDC, lpRect, 
  2754.                    GetSysColor( COLOR_BTNSHADOW ), 
  2755.                    GetSysColor( COLOR_BTNHIGHLIGHT ) );
  2756. #endif
  2757. }
  2758.  
  2759. void WFE_Draw3DButtonRect( HDC hDC, LPRECT lpRect, BOOL bPushed )
  2760. {
  2761.     if ( bPushed ) {
  2762.         WFE_DrawLoweredRect( hDC, lpRect );
  2763.     } else {
  2764.         WFE_DrawRaisedRect( hDC, lpRect );
  2765.     }
  2766. }
  2767.  
  2768. void WFE_MakeTransparentBitmap( HDC hDC, HBITMAP hBitmap )
  2769. {
  2770.     BITMAP bm;
  2771.     COLORREF cColor;
  2772.     HBITMAP bmAndBack, bmAndObject, bmAndMem;
  2773.     HGDIOBJ bmBackOld, bmObjectOld, bmMemOld;
  2774.     HDC hdcTemp, hdcMem, hdcBack, hdcObject;
  2775.  
  2776.     VERIFY( ::GetObject( hBitmap, sizeof(BITMAP), (LPSTR)&bm ) );
  2777.  
  2778.     // Create some DCs to hold temporary data.
  2779.     hdcTemp   = CreateCompatibleDC(hDC);
  2780.     hdcBack   = CreateCompatibleDC(hDC);
  2781.     hdcObject = CreateCompatibleDC(hDC);
  2782.     hdcMem    = CreateCompatibleDC(hDC);
  2783.  
  2784.     SelectObject( hdcTemp, hBitmap );
  2785.  
  2786.     // Monochrome DC
  2787.     bmAndBack   = CreateBitmap(bm.bmWidth, bm.bmHeight, 1, 1, NULL);
  2788.  
  2789.     // Monochrome DC
  2790.     bmAndObject = CreateBitmap(bm.bmWidth, bm.bmHeight, 1, 1, NULL);
  2791.  
  2792.     bmAndMem    = CreateCompatibleBitmap(hDC, bm.bmWidth, bm.bmHeight);
  2793.  
  2794.     // Each DC must select a bitmap object to store pixel data.
  2795.     bmBackOld   = ::SelectObject(hdcBack, bmAndBack);
  2796.     bmObjectOld = ::SelectObject(hdcObject, bmAndObject);
  2797.     bmMemOld    = ::SelectObject(hdcMem, bmAndMem);
  2798.  
  2799.     // Set the background color of the source DC to the color
  2800.     // contained in the parts of the bitmap that should be transparent
  2801.     cColor = SetBkColor(hdcTemp, RGB_TRANSPARENT );
  2802.  
  2803.     // Create the object mask for the bitmap by performing a BitBlt
  2804.     // from the source bitmap to a monochrome bitmap.
  2805.     BitBlt(hdcObject, 0, 0, bm.bmWidth, bm.bmHeight, hdcTemp, 0, 0, SRCCOPY);
  2806.  
  2807.     // Set the background color of the source DC back to the original
  2808.     // color.
  2809.     SetBkColor(hdcTemp, cColor);
  2810.  
  2811.     // Create the inverse of the object mask.
  2812.     BitBlt(hdcBack, 0, 0, bm.bmWidth, bm.bmHeight, hdcObject, 0, 0, NOTSRCCOPY);
  2813.  
  2814.     // Fill the background of the mem DC with the system background color.
  2815.     FillRect( hdcMem, CRect( 0, 0, bm.bmWidth, bm.bmHeight ), CreateSolidBrush( GetSysColor( COLOR_BTNFACE ) ) );
  2816.  
  2817.     // Mask out the places where the bitmap will be placed.
  2818.     BitBlt(hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, hdcObject, 0, 0, SRCAND);
  2819.  
  2820.     // Mask out the transparent colored pixels on the bitmap.
  2821.     BitBlt(hdcTemp, 0, 0, bm.bmWidth, bm.bmHeight, hdcBack, 0, 0, SRCAND);
  2822.  
  2823.     // XOR the bitmap with the background on the destination DC.
  2824.     BitBlt(hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, hdcTemp, 0, 0, SRCPAINT);
  2825.  
  2826.     // Copy the results back to the source bitmap.
  2827.     BitBlt(hdcTemp, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
  2828.  
  2829.     // Delete the memory bitmaps.
  2830.     VERIFY(DeleteObject(SelectObject(hdcBack, bmBackOld)));
  2831.     VERIFY(DeleteObject(SelectObject(hdcObject, bmObjectOld)));
  2832.     VERIFY(DeleteObject(SelectObject(hdcMem, bmMemOld)));
  2833.  
  2834.     // Delete the memory DCs.
  2835.     VERIFY(DeleteDC(hdcMem));
  2836.     VERIFY(DeleteDC(hdcBack));
  2837.     VERIFY(DeleteDC(hdcObject));
  2838.     VERIFY(DeleteDC(hdcTemp));
  2839. }
  2840.  
  2841. #define RGB_TO_RGBQUAD(r,g,b)   (RGB(b,g,r))
  2842. #define CLR_TO_RGBQUAD(clr)     (RGB(GetBValue(clr), GetGValue(clr), GetRValue(clr)))
  2843.  
  2844. HBITMAP WFE_LoadSysColorBitmap( HINSTANCE hInst, LPCSTR lpszResourceName )
  2845. {
  2846.     struct COLORMAP
  2847.     {
  2848.         // use DWORD instead of RGBQUAD so we can compare two RGBQUADs easily
  2849.         DWORD rgbqFrom;
  2850.         int iSysColorTo;
  2851.     };
  2852.     static const COLORMAP sysColorMap[] =
  2853.     {
  2854.         // mapping from color in DIB to system color
  2855.         { RGB_TO_RGBQUAD(0x00, 0x00, 0x00),  COLOR_BTNTEXT },       // black
  2856.         { RGB_TO_RGBQUAD(0x80, 0x80, 0x80),  COLOR_BTNSHADOW },     // dark grey
  2857.         { RGB_TO_RGBQUAD(0xC0, 0xC0, 0xC0),  COLOR_BTNFACE },       // bright grey
  2858.         { RGB_TO_RGBQUAD(0xFF, 0xFF, 0xFF),  COLOR_BTNHIGHLIGHT },   // white
  2859.         { RGB_TO_RGBQUAD(0xFF, 0x00, 0xFF),  COLOR_BTNFACE }   // hot pink
  2860.     };
  2861.     const int nMaps = 5;
  2862.  
  2863.     HRSRC hRsrc = ::FindResource(hInst, lpszResourceName, RT_BITMAP);
  2864.  
  2865.     HGLOBAL hglb;
  2866.     if ((hglb = LoadResource(hInst, hRsrc)) == NULL)
  2867.         return NULL;
  2868.  
  2869.     LPBITMAPINFOHEADER lpBitmap = (LPBITMAPINFOHEADER)LockResource(hglb);
  2870.     if (lpBitmap == NULL)
  2871.         return NULL;
  2872.  
  2873.     // make copy of BITMAPINFOHEADER so we can modify the color table
  2874.     int nColorTableSize = 1 << lpBitmap->biBitCount;
  2875.     UINT nSize = CASTUINT(lpBitmap->biSize + nColorTableSize * sizeof(RGBQUAD));
  2876.     LPBITMAPINFOHEADER lpBitmapInfo = (LPBITMAPINFOHEADER)::malloc(nSize);
  2877.     if (lpBitmapInfo == NULL)
  2878.         return NULL;
  2879.     memcpy(lpBitmapInfo, lpBitmap, nSize);
  2880.  
  2881.     // color table is in RGBQUAD DIB format
  2882.     DWORD* pColorTable =
  2883.         (DWORD*)(((LPBYTE)lpBitmapInfo) + (UINT)lpBitmapInfo->biSize);
  2884.  
  2885.     for (int iColor = 0; iColor < nColorTableSize; iColor++)
  2886.     {
  2887.         // look for matching RGBQUAD color in original
  2888.         for (int i = 0; i < nMaps; i++)
  2889.         {
  2890.             if (pColorTable[iColor] == sysColorMap[i].rgbqFrom)
  2891.             {
  2892.                 pColorTable[iColor] =
  2893.                     CLR_TO_RGBQUAD(::GetSysColor(sysColorMap[i].iSysColorTo));
  2894.                 break;
  2895.             }
  2896.         }
  2897.     }
  2898.  
  2899.     int nWidth = (int)lpBitmapInfo->biWidth;
  2900.     int nHeight = (int)lpBitmapInfo->biHeight;
  2901.     HDC hDCScreen = ::GetDC(NULL);
  2902.     HBITMAP hbm = ::CreateCompatibleBitmap(hDCScreen, nWidth, nHeight);
  2903.  
  2904.     if (hbm != NULL)
  2905.     {
  2906.         HDC hDCGlyphs = ::CreateCompatibleDC(hDCScreen);
  2907.         HBITMAP hbmOld = (HBITMAP)::SelectObject(hDCGlyphs, hbm);
  2908.  
  2909.         LPBYTE lpBits;
  2910.         lpBits = (LPBYTE)(lpBitmap + 1);
  2911.         lpBits += (1 << (lpBitmapInfo->biBitCount)) * sizeof(RGBQUAD);
  2912.  
  2913.         StretchDIBits(hDCGlyphs, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,
  2914.             lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS, SRCCOPY);
  2915.         SelectObject(hDCGlyphs, hbmOld);
  2916.  
  2917.         ::DeleteDC(hDCGlyphs);
  2918.     }
  2919.     ::ReleaseDC(NULL, hDCScreen);
  2920.  
  2921.     // free copy of bitmap info struct and resource itself
  2922.     ::free(lpBitmapInfo);
  2923.     ::FreeResource(hglb);
  2924.  
  2925.     return hbm;
  2926. }
  2927.  
  2928. /////////////////////////////////////////////////////////////////////////////
  2929. // equivalent to LoadBitmap(), except uses pDC for
  2930. // correct color mapping of BMP into pDC's palette.
  2931. HBITMAP wfe_LoadBitmap(HINSTANCE hInst, HDC hDC, LPCSTR pszBmName ) 
  2932. {
  2933.     int iFrames;
  2934.  
  2935.     if ((pszBmName == MAKEINTRESOURCE(IDB_ANIM_0)) && (CUST_IsCustomAnimation(&iFrames))) {
  2936.         char *pFile=NULL,*pUrl=NULL;
  2937.         HBITMAP hCust = NULL;
  2938.         CString csProfileFile;
  2939.  
  2940.         PREF_CopyConfigString("toolbar.logo.win_large_file",&pFile);
  2941.  
  2942.         // we need to first check the profile for the file (for PE) and then resort to the default of the EXE dir
  2943.         csProfileFile = theApp.m_UserDirectory;
  2944.         csProfileFile += "\\";
  2945.         csProfileFile += pFile;
  2946.         hCust = WFE_LoadBitmapFromFile(csProfileFile);
  2947.         
  2948.         if (!hCust)  // try the default place
  2949.             hCust = WFE_LoadBitmapFromFile(pFile);    
  2950.         if (pFile) XP_FREE(pFile);
  2951.         if (hCust) return hCust;
  2952.     }
  2953.  
  2954.     if ((pszBmName == MAKEINTRESOURCE(IDB_ANIMSMALL_0)) && (CUST_IsCustomAnimation(&iFrames))) {
  2955.         char *pFile=NULL,*pUrl=NULL;
  2956.         HBITMAP hCust = NULL;
  2957.         CString csProfileFile;
  2958.  
  2959.         PREF_CopyConfigString("toolbar.logo.win_small_file",&pFile);
  2960.  
  2961.         // we need to first check the profile for the file (for PE) and then resort to the default of the EXE dir
  2962.         csProfileFile = theApp.m_UserDirectory;
  2963.         csProfileFile += "\\";
  2964.         csProfileFile += pFile;
  2965.         hCust = WFE_LoadBitmapFromFile(csProfileFile);
  2966.         
  2967.         if (!hCust)  // try the default place
  2968.             hCust = WFE_LoadBitmapFromFile(pFile);
  2969.         if (pFile) XP_FREE(pFile);
  2970.         if (hCust) return hCust;
  2971.     }
  2972.  
  2973.     // get the resource from the file
  2974.     HBITMAP hBmp = (HBITMAP)FindResource(hInst, pszBmName, RT_BITMAP);
  2975.     ASSERT(hBmp != NULL);
  2976.     if(!hBmp)
  2977.         return NULL;
  2978.     HGLOBAL hRes = LoadResource(hInst, (HRSRC)hBmp);
  2979.     ASSERT(hRes != NULL);
  2980.     if(!hRes)
  2981.         return NULL;
  2982.     LPBITMAPINFO pPackedDib = (LPBITMAPINFO)(LockResource(hRes));
  2983.     ASSERT(pPackedDib != NULL);
  2984.     if(!pPackedDib)
  2985.         return NULL;
  2986.         
  2987.     // build a DDB header for  pDC
  2988.  
  2989.     BITMAPINFOHEADER bmihDDB;
  2990.     memcpy(&bmihDDB, pPackedDib, sizeof(BITMAPINFOHEADER));
  2991.     bmihDDB.biBitCount = GetDeviceCaps( hDC, BITSPIXEL);
  2992.     bmihDDB.biClrUsed = 0;
  2993.     bmihDDB.biClrImportant = 0;
  2994.  
  2995.     
  2996.     // create the DDB
  2997.     int iColorTableSize =
  2998.         (1 << pPackedDib->bmiHeader.biBitCount) * sizeof(RGBQUAD);
  2999.     void* pBits =
  3000.         ((char*)pPackedDib) + pPackedDib->bmiHeader.biSize + iColorTableSize;
  3001.     HBITMAP hDDB = CreateDIBitmap(hDC,
  3002.                                 &bmihDDB,
  3003.                                 CBM_INIT,
  3004.                                 pBits,
  3005.                                 pPackedDib,
  3006.                                 DIB_RGB_COLORS);
  3007.     
  3008.     // done, clean up
  3009.     UnlockResource(hRes);
  3010.     BOOL bResult = FreeResource(hRes);
  3011.     
  3012.     return hDDB;
  3013. }
  3014.  
  3015. static int FindColorIndex(LPRGBQUAD pColors, int nNumColors, COLORREF color)
  3016. {
  3017.     for(int i = 0; i < nNumColors; i++)
  3018.     {
  3019.         if(pColors[i].rgbRed == GetRValue(color) &&
  3020.            pColors[i].rgbGreen == GetGValue(color) &&
  3021.            pColors[i].rgbBlue == GetBValue(color)) {
  3022.                 return i;
  3023.         }
  3024.     }
  3025.     return -1;
  3026. }
  3027.  
  3028. // Loads a bitmap and returns the handle. Retrieves the color of the
  3029. // first pixel in the image and replaces that entry in the color table
  3030. // with clrBackground
  3031. HBITMAP WFE_LoadTransparentBitmap(HINSTANCE hInstance, HDC hDC, COLORREF clrBackground, COLORREF clrTransparent,
  3032.                                   HPALETTE hPalette, UINT nResID)
  3033. {
  3034.     // Find the resource
  3035.     HRSRC    hrsrc = FindResource(hInstance, MAKEINTRESOURCE(nResID), RT_BITMAP);
  3036.  
  3037.     assert(hrsrc);
  3038.     if (!hrsrc)
  3039.         return NULL;
  3040.  
  3041.     // Get a handle for the resource
  3042.     HGLOBAL    hglb = LoadResource(hInstance, hrsrc);
  3043.     if (!hglb)
  3044.         return NULL;
  3045.  
  3046.     // Get a pointer to the BITMAPINFOHEADER
  3047.     LPBITMAPINFOHEADER    lpbi = (LPBITMAPINFOHEADER)LockResource(hglb);
  3048.  
  3049.     // We expect a 4-bpp or 8-bpp image only
  3050.     assert(lpbi->biBitCount == 4 || lpbi->biBitCount == 8);
  3051.     if (lpbi->biBitCount != 4 && lpbi->biBitCount != 8) {
  3052.         UnlockResource(hglb);
  3053.         FreeResource(hglb);
  3054.         return NULL;
  3055.     }
  3056.  
  3057. #ifdef XP_WIN32
  3058.     // make copy of BITMAPINFOHEADER so we can modify the color table
  3059.     int nColorTableSize = 1 << lpbi->biBitCount;
  3060.     UINT nSize = CASTUINT(lpbi->biSize + nColorTableSize * sizeof(RGBQUAD));
  3061.  
  3062.     LPBITMAPINFOHEADER lpBitmapInfo = (LPBITMAPINFOHEADER)::malloc(nSize);
  3063.     if (lpBitmapInfo == NULL)
  3064.         return NULL;
  3065.     memcpy(lpBitmapInfo, lpbi, nSize);
  3066.  
  3067.     // color table is in RGBQUAD DIB format
  3068.     LPRGBQUAD pColors =
  3069.         (LPRGBQUAD)((LPSTR)lpBitmapInfo + lpBitmapInfo->biSize);
  3070.  
  3071.     LPRGBQUAD pOldColors =
  3072.         (LPRGBQUAD)((LPSTR)lpbi + lpbi->biSize);
  3073.  
  3074.     UINT    nClrUsed = lpbi->biClrUsed == 0 ? 1 << lpbi->biBitCount : (UINT)lpbi->biClrUsed;
  3075.     LPBYTE    lpBits = (LPBYTE)(pOldColors + nClrUsed);
  3076.  
  3077.  
  3078. #else
  3079.     LPRGBQUAD    pColors = (LPRGBQUAD)((LPSTR)lpbi + (WORD)lpbi->biSize);
  3080.     UINT    nClrUsed = lpbi->biClrUsed == 0 ? 1 << lpbi->biBitCount : (UINT)lpbi->biClrUsed;
  3081.     LPBYTE    lpBits = (LPBYTE)(pColors + nClrUsed);
  3082. #endif
  3083.  
  3084.  
  3085.     // Munge the color table entry
  3086. //    int    nIndex = lpbi->biBitCount == 8 ? *lpBits : *lpBits & 0xF;
  3087.     int nIndex = FindColorIndex(pColors, nClrUsed, clrTransparent);
  3088.  
  3089.     pColors[nIndex].rgbGreen = GetGValue(clrBackground);
  3090.     pColors[nIndex].rgbRed = GetRValue(clrBackground);
  3091.     pColors[nIndex].rgbBlue = GetBValue(clrBackground);
  3092.  
  3093.     // Create the DDB
  3094.     HBITMAP        hBitmap;
  3095.     HPALETTE hOldPalette = SelectPalette(hDC, hPalette, FALSE);
  3096.  
  3097.  
  3098. #ifdef XP_WIN32
  3099.     hBitmap = CreateDIBitmap(hDC, lpBitmapInfo, CBM_INIT, lpBits,
  3100.         (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS);
  3101.  
  3102.     ::free(lpBitmapInfo);
  3103. #else
  3104.     hBitmap = CreateDIBitmap(hDC, lpbi, CBM_INIT, lpBits,
  3105.         (LPBITMAPINFO)lpbi, DIB_RGB_COLORS);
  3106.  
  3107.     //Restore the bitmap in case we want to go through this process again
  3108.     pColors[nIndex].rgbRed = GetRValue(clrTransparent);
  3109.     pColors[nIndex].rgbGreen = GetGValue(clrTransparent);
  3110.     pColors[nIndex].rgbBlue = GetBValue(clrTransparent);
  3111. #endif
  3112.     // The parent should unselect the palette when they got destroy.
  3113.         SelectPalette(hDC, hOldPalette, TRUE);
  3114.     // Release the resource
  3115.     UnlockResource(hglb);
  3116.     FreeResource(hglb);
  3117.  
  3118.     return hBitmap;
  3119. }
  3120.  
  3121. void WFE_InitializeUIPalette(HDC hDC)
  3122. {
  3123.     IL_IRGB transparentColor;
  3124.     transparentColor.index = 0;
  3125.     transparentColor.red = 255;
  3126.     transparentColor.green = 0;
  3127.     transparentColor.blue = 255;
  3128.     if(ghPalette == NULL) {
  3129.         ghPalette = CDCCX::CreateColorPalette(hDC, transparentColor, 8);
  3130.  
  3131.     }
  3132. }
  3133.  
  3134. BOOL WFE_IsGlobalPalette(HPALETTE hPal)
  3135. {
  3136.  
  3137.     return (hPal == ghPalette);
  3138. }
  3139.  
  3140. HPALETTE WFE_GetUIPalette(CWnd* parent)
  3141. {
  3142.     // for normal case.
  3143.     if (!parent)
  3144.         return ghPalette;
  3145.     else if (parent->IsKindOf(RUNTIME_CLASS(CGenericFrame))) {
  3146.         CWinCX* pcxWin = ((CGenericFrame*)parent)->GetMainWinContext();
  3147.         if (pcxWin) {
  3148.             HPALETTE hPalette = pcxWin->GetPalette();
  3149.             if (hPalette) return hPalette;
  3150.             else return    ghPalette;
  3151.         }
  3152.         else return ghPalette;
  3153.     }
  3154.     else if (parent->IsKindOf(RUNTIME_CLASS(CInPlaceFrame))) {     // for OLE
  3155.         // XXX write me.
  3156.         CWinCX *pWinCX = (CWinCX*)FEU_GetLastActiveFrameContext();
  3157.         if (pWinCX) {
  3158.             HPALETTE hPalette = pWinCX->GetPalette();
  3159.             if (hPalette) return hPalette;
  3160.             else return    ghPalette;
  3161.         }
  3162.         else return    ghPalette;
  3163.  
  3164.     }
  3165.     else // for other case. 
  3166.         return ghPalette;
  3167. }
  3168.  
  3169. void WFE_DestroyUIPalette(void)
  3170. {
  3171.     if(ghPalette)
  3172.         DeleteObject(ghPalette);
  3173. }
  3174.  
  3175. typedef struct {
  3176.     COLORREF clrBackground;
  3177.     HBITMAP bitmap;
  3178. } BitmapMapEntry;
  3179.  
  3180. // if bTransparent is FALSE then clrBackground and clrTransparent are ignored
  3181. HBITMAP WFE_LookupLoadAndEnterBitmap(HDC hDC, UINT nID, BOOL bTransparent, HPALETTE hPalette, 
  3182.                                      COLORREF clrBackground, COLORREF clrTransparent)
  3183. {
  3184.  
  3185.     HINSTANCE hInst = AfxGetResourceHandle();
  3186.     HBITMAP hBitmap;
  3187.     BitmapMapEntry *pEntry = NULL;
  3188.  
  3189.     if(!gBitmapMap.Lookup(nID, (void*&)pEntry) || pEntry->clrBackground != clrBackground)
  3190.     {
  3191.         HPALETTE hOldPalette = SelectPalette(hDC, hPalette, FALSE);
  3192.  
  3193.         if(bTransparent)
  3194.             hBitmap = WFE_LoadTransparentBitmap(hInst, hDC, clrBackground, clrTransparent,
  3195.                                                 hPalette, nID);
  3196.         else
  3197.         {
  3198.             hBitmap = wfe_LoadBitmap(hInst, hDC, MAKEINTRESOURCE(nID));
  3199.         }
  3200.         if(!pEntry)
  3201.             pEntry = new BitmapMapEntry;
  3202.         pEntry->clrBackground = clrBackground;
  3203.         pEntry->bitmap = hBitmap;
  3204.         gBitmapMap.SetAt(nID, (void*&)pEntry);
  3205.         ::SelectPalette(hDC, hOldPalette, TRUE);
  3206.     }
  3207.  
  3208.     return pEntry->bitmap;
  3209. }
  3210.  
  3211. void WFE_RemoveBitmapFromMap(UINT nID)
  3212. {
  3213.     BitmapMapEntry *pEntry = NULL;
  3214.  
  3215.     if(gBitmapMap.Lookup(nID, (void*&)pEntry))
  3216.     {
  3217.         ::DeleteObject(pEntry->bitmap);
  3218.         delete pEntry;
  3219.         gBitmapMap.RemoveKey(nID);
  3220.     }
  3221. }
  3222.  
  3223. void WFE_DestroyBitmapMap(void)
  3224. {
  3225.     POSITION pos;
  3226.     WORD dwKey;
  3227.     BitmapMapEntry *pEntry = NULL;
  3228.  
  3229.     // also destroy bitmaps;
  3230.     pos = gBitmapMap.GetStartPosition();
  3231.  
  3232.     while(pos)
  3233.     {
  3234.         gBitmapMap.GetNextAssoc(pos, dwKey,(void *&)pEntry);
  3235.         DeleteObject(pEntry->bitmap);
  3236.         delete pEntry;
  3237.     }
  3238.  
  3239.     gBitmapMap.RemoveAll();
  3240.  
  3241.  
  3242. }
  3243.  
  3244. HFONT WFE_GetUIFont(HDC hDC)
  3245. {
  3246. #ifdef XP_WIN32
  3247.         if (sysInfo.m_bWin4 == TRUE)
  3248.             ghFont = (HFONT) GetStockObject(DEFAULT_GUI_FONT);
  3249.         else 
  3250. #endif
  3251.         if (sysInfo.m_bDBCS == FALSE)
  3252.             ghFont = (HFONT) GetStockObject(ANSI_VAR_FONT);
  3253.         else {
  3254.             if (ghFont == NULL) {
  3255.                 LOGFONT lf;
  3256.                 XP_MEMSET(&lf,0,sizeof(LOGFONT));
  3257.                 lf.lfPitchAndFamily = FF_SWISS;
  3258.                 lf.lfCharSet = IntlGetLfCharset(0);
  3259.                    lf.lfHeight = -MulDiv(8, GetDeviceCaps(hDC, LOGPIXELSY), 72);
  3260.                 strcpy(lf.lfFaceName, IntlGetUIPropFaceName(0));
  3261.                 lf.lfWeight = 400;
  3262.                 ghFont = theApp.CreateAppFont( lf );
  3263.             }
  3264.         }
  3265.     return ghFont;
  3266. }
  3267.  
  3268. void WFE_DestroyUIFont(void)
  3269. {
  3270. }
  3271.  
  3272. CFrameWnd *WFE_GetOwnerFrame(CWnd *pWnd)
  3273. {
  3274.     return pWnd->GetTopLevelFrame();
  3275. }
  3276.  
  3277. int WFE_FindMenu(CMenu *pMenu, CString& menuItemName)
  3278. {
  3279.     if (!pMenu)
  3280.         return -1;
  3281.  
  3282.     int nCount = pMenu->GetMenuItemCount();
  3283.     
  3284.     for(int i = 0; i < nCount; i++)
  3285.     {
  3286.         char lpszMenuString[64];
  3287.  
  3288.         pMenu->GetMenuString(i, lpszMenuString, 64, MF_BYPOSITION);
  3289.  
  3290.         if(strcmp( lpszMenuString, menuItemName) == 0)
  3291.             return i;
  3292.  
  3293.     }
  3294.  
  3295.     return -1;
  3296.  
  3297. }
  3298.  
  3299. int WFE_FindMenuItem(CMenu *pMenu, UINT nCommand)
  3300. {
  3301.     if (!pMenu)
  3302.         return -1;
  3303.  
  3304.     int nCount = pMenu->GetMenuItemCount();
  3305.     
  3306.     for(int i = 0; i < nCount; i++)
  3307.     {
  3308.  
  3309.         UINT nID = pMenu->GetMenuItemID(i);
  3310.  
  3311.         if(nID == nCommand)
  3312.             return i;
  3313.  
  3314.     }
  3315.  
  3316.     return -1;
  3317. }
  3318.  
  3319. #ifdef FEATURE_LOAD_BITMAP_FILES
  3320. #include "loadbmps.i00"
  3321. #endif
  3322.  
  3323. HBITMAP WFE_LoadBitmapFromFile (const char* szFileName)
  3324. {
  3325.     HBITMAP hRetval = NULL;
  3326.     
  3327. #ifdef FEATURE_LOAD_BITMAP_FILES
  3328.     hRetval = wfe_loadbitmapfromfile(szFileName);
  3329. #else
  3330. #ifdef _WIN32
  3331.     //  This only works on >= 95 and NT4.
  3332.     hRetval = (HBITMAP)LoadImage(NULL, szFileName, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE);
  3333. #endif
  3334. #endif
  3335.     
  3336.     return(hRetval);
  3337. }
  3338.  
  3339. void WFE_FillSolidRect(CDC *pDC, CRect crRect, COLORREF rgbFill)    {
  3340. #ifdef XP_WIN32
  3341.     pDC->FillSolidRect(crRect, rgbFill);
  3342. #else
  3343.     ::SetBkColor(pDC->m_hDC, rgbFill);
  3344.     ::ExtTextOut(pDC->m_hDC, 0, 0, ETO_OPAQUE, crRect, NULL, 0, NULL);
  3345. #endif
  3346. }
  3347.  
  3348. #define STRING_ELLIPSES _T("...")
  3349.  
  3350. int WFE_DrawTextEx( int iCSID, HDC hdc, LPTSTR lpchText, int cchText, LPRECT lprc, UINT dwDTFormat,
  3351.                     UINT dwMoreFormat )
  3352. {
  3353.     if (cchText < 0)
  3354.         cchText = _tcslen(lpchText);
  3355.  
  3356. #ifdef XP_WIN32
  3357.     if ((dwMoreFormat == WFE_DT_CROPRIGHT) && sysInfo.m_bWin4) {
  3358.         dwDTFormat |= DT_END_ELLIPSIS;
  3359.         return CIntlWin::DrawTextEx(iCSID, hdc, (LPTSTR) lpchText, cchText, lprc,
  3360.                                     dwDTFormat, NULL);
  3361.     }
  3362. #endif
  3363.  
  3364.     LPTSTR pString = NULL;
  3365.     CSize cs = CIntlWin::GetTextExtent( iCSID, hdc, lpchText, cchText);
  3366.  
  3367.     if (cs.cx > (lprc->right - lprc->left) ) {
  3368.         int iNumToRemove = 0;
  3369.         int iEllipsesLength = _tcslen(STRING_ELLIPSES);
  3370.  
  3371.         pString = new _TCHAR[cchText + iEllipsesLength + 2];
  3372.         if (!pString) {
  3373.             ASSERT(0);
  3374.             return 0;
  3375.         }
  3376.         _tcscpy(pString,lpchText);
  3377.         while ( cs.cx > (lprc->right - lprc->left) ) {
  3378.             if (++iNumToRemove >= cchText) {
  3379.                 delete [] pString;
  3380.                 return cs.cy;
  3381.             }
  3382.             switch (dwMoreFormat) {
  3383.                 case WFE_DT_CROPRIGHT:
  3384.                     _tcscpy(&pString[cchText - iNumToRemove], STRING_ELLIPSES);
  3385.                     break;
  3386.                 case WFE_DT_CROPCENTER:
  3387.                     {
  3388.                         int iLeft = (cchText - iNumToRemove) / 2;
  3389.                         int iRight = iLeft + ((cchText - iNumToRemove)%2);
  3390.                         _tcscpy(&pString[iLeft], STRING_ELLIPSES);
  3391.                         _tcscpy(&pString[iLeft+iEllipsesLength],
  3392.                                 &lpchText[cchText-iRight]);
  3393.                     }
  3394.                     break;
  3395.                 case WFE_DT_CROPLEFT:
  3396.                         _tcscpy(pString, STRING_ELLIPSES);
  3397.                         _tcscpy(&pString[iEllipsesLength],
  3398.                                 &lpchText[iNumToRemove]);
  3399.                     break;
  3400.             }
  3401.             cs = CIntlWin::GetTextExtent( iCSID, hdc, pString, strlen(pString));
  3402.         }
  3403.         lpchText = pString;
  3404.     }
  3405.  
  3406.     int res = CIntlWin::DrawText( iCSID, hdc, (LPTSTR) lpchText, -1,  lprc, dwDTFormat );
  3407.  
  3408.     if (pString)
  3409.         delete [] pString;
  3410.     
  3411.     return res;
  3412.     
  3413. }
  3414.  
  3415. #ifdef __BORLANDC__
  3416.     #define    _S_IFREG    S_IFREG
  3417. #endif
  3418.  
  3419. // If pszLocalName is not NULL, we return the full pathname
  3420. //   in local platform syntax, even if file is not found.
  3421. //   Caller must free this string.
  3422. // Returns TRUE if file already exists
  3423. //
  3424. MODULE_PRIVATE Bool
  3425. XP_ConvertUrlToLocalFile( const char * szURL, char **pszLocalName)
  3426. {
  3427.     BOOL bFileFound = FALSE;
  3428.     // Default assumes no file found - no local filename
  3429.     if ( pszLocalName ) {
  3430.         *pszLocalName = NULL;
  3431.     }
  3432.  
  3433.     // Must have "file:" URL type and at least 1 character after "///"
  3434.     if ( szURL == NULL || !NET_IsLocalFileURL((char*)szURL) || XP_STRLEN(szURL) <= 8 ) {
  3435.         return FALSE;
  3436.     }
  3437.  
  3438.     // Extract file path from URL: e.g. "/c|/foo/file.html"
  3439.     char *szPath = NET_ParseURL( szURL, GET_PATH_PART);
  3440.     if ( szPath == NULL ) {
  3441.         return FALSE;
  3442.     }
  3443.  
  3444.       // Get filename - skip over initial "/"
  3445.     char *szFileName;
  3446.     if (szPath[0] == '/' && szPath[1] == '/') {
  3447.       // bug 35222, if url is a shared Windows (NT or Win95) directory using UNC name,
  3448.       // don't skip over the first slash, WH_FileName will do the right thing.
  3449.       // I have the suspicion that we should never be skipping the first slash, that
  3450.       // WH_FileName knows what to do, but I don't want to make a risky change now.
  3451.       szFileName = WH_FileName(szPath, xpURL);
  3452.     }
  3453.     else {
  3454.       szFileName = WH_FileName(szPath+1, xpURL);
  3455.     }
  3456.     XP_FREE(szPath);
  3457.  
  3458.     // Test if file exists
  3459.     XP_StatStruct statinfo; 
  3460.     if ( -1 != XP_Stat(szFileName, &statinfo, xpURL) &&
  3461.         statinfo.st_mode & _S_IFREG ) {
  3462.         bFileFound = TRUE;
  3463.     }
  3464.  
  3465.     if ( pszLocalName ) {
  3466.         // Pass string to caller
  3467.         // (we didn't change it, so there's no need to XP_STRDUP)
  3468.         *pszLocalName = szFileName;
  3469.     }
  3470.     return bFileFound;
  3471. }
  3472.  
  3473.  
  3474. // Create a backup filename for renaming current file before saving data
  3475. //    Input should be be URL file type "file:///..."
  3476. //    Caller must free the string with XP_FREE
  3477. //
  3478. MODULE_PRIVATE char *
  3479. XP_BackupFileName( const char * szURL )
  3480. {
  3481.     char * szFileName;
  3482.     // Must have "file:" URL type and at least 1 character after "///"
  3483.     if ( szURL == NULL || !NET_IsLocalFileURL((char*)szURL) || XP_STRLEN(szURL) <= 8 ) {
  3484.         return NULL;
  3485.     }
  3486.     // Add extra space for 8+3 temp filename, but subtract for "file:///"
  3487.     szFileName = (char *) XP_ALLOC((XP_STRLEN(szURL)+5)*sizeof(char));
  3488.     if ( szFileName == NULL ) {
  3489.         return NULL;
  3490.     }
  3491.     // Get filename but ignore "file:///"
  3492.     {
  3493.     char* filename;
  3494.   if (szURL[8] == '/') {
  3495.     // bug 35222, if url is a shared Windows (NT or Win95) directory using UNC name,
  3496.     // don't skip over the first slash, WH_FileName will do the right thing.
  3497.     // I have the suspicion that we should never be skipping the first slash, that
  3498.     // WH_FileName knows what to do, but I don't want to make a risky change now.
  3499.     filename = WH_FileName(szURL+7, xpURL);
  3500.   }
  3501.   else {
  3502.     filename = WH_FileName(szURL+8, xpURL);
  3503.   }
  3504.     if (!filename) return NULL;
  3505.     XP_STRCPY(szFileName,filename);
  3506.     XP_FREE(filename);
  3507.     }
  3508.  
  3509. #ifdef XP_WIN16
  3510.     char * pEnd = szFileName + XP_STRLEN( szFileName );
  3511.     while ( *pEnd != '\\' && pEnd != szFileName ) {
  3512.         if ( *pEnd == '.' ) {
  3513.             // Truncate at current extension
  3514.             *pEnd = '\0';
  3515.         }
  3516.         pEnd--;
  3517.     }
  3518. #endif
  3519.     // Add extension to the filename
  3520.     XP_STRCAT( szFileName, ".BAK" );
  3521.     return szFileName;
  3522. }
  3523.  
  3524. // Copy file routine for Editor - ask user permission
  3525. //  to overwrite existing file.
  3526. // Params may be local file format or "file://" URL format,
  3527. //   and assumes full pathnames
  3528. BOOL FE_CopyFile(const char *cpSrc, const char *cpTarg)
  3529. {
  3530.     char * szSrc = NULL;
  3531.     char * szTarg = NULL;
  3532.     BOOL bFreeSrc = FALSE;
  3533.     BOOL bFreeTarg = FALSE;
  3534.     BOOL bSrcExists = TRUE;
  3535.     BOOL bTargExists = FALSE;
  3536.     XP_StatStruct statinfo; 
  3537.     CString csMsg;
  3538.     BOOL bResult = FALSE;
  3539.  
  3540.     if ( NET_IsLocalFileURL((char*)cpSrc) ){
  3541.         bSrcExists = XP_ConvertUrlToLocalFile(cpSrc, &szSrc);        
  3542.         bFreeSrc = (szSrc != NULL);
  3543.     } else {
  3544.         // Use supplied name - assume its a file
  3545.         szSrc = (char*)cpSrc;
  3546.         bSrcExists = (-1 != XP_Stat(cpSrc, &statinfo, xpURL)) &&
  3547.                      (statinfo.st_mode & _S_IFREG);
  3548.     }
  3549.  
  3550.     if ( bSrcExists ){
  3551.         if ( NET_IsLocalFileURL((char*)cpTarg) ){
  3552.             bTargExists = XP_ConvertUrlToLocalFile(cpTarg, &szTarg);
  3553.             bFreeTarg = (szTarg != NULL);
  3554.         } else {
  3555.             bTargExists = (-1 != XP_Stat(cpTarg, &statinfo, xpURL)) &&
  3556.                           (statinfo.st_mode & _S_IFREG);
  3557.             // Use supplied name - assume its a file
  3558.             szTarg = (char*)cpTarg;
  3559.         }
  3560.         if ( bTargExists ) {
  3561.             AfxFormatString1(csMsg, IDS_WARN_REPLACE_FILE, szTarg);  
  3562.             if ( IDYES == MessageBox( NULL, csMsg, szLoadString(IDS_COPY_FILE), 
  3563.                                       MB_YESNO | MB_ICONQUESTION) ) {
  3564.                 bResult = WFE_CopyFile(szSrc, szTarg);
  3565.             }
  3566.         } else {
  3567.             bResult = WFE_CopyFile(szSrc, szTarg);
  3568.         }
  3569.         if ( !bResult ) {
  3570.             AfxFormatString1(csMsg, IDS_ERR_COPY_FILE, szSrc);  
  3571.             MessageBox( NULL, csMsg, szLoadString(IDS_COPY_FILE), MB_OK | MB_ICONSTOP);
  3572.         }
  3573.     }
  3574.     else {
  3575.         // Can't copy if no source!
  3576.         AfxFormatString1(csMsg, IDS_ERR_SRC_NOT_FOUND, szSrc);  
  3577.         MessageBox( NULL, csMsg, szLoadString(IDS_COPY_FILE), MB_OK | MB_ICONSTOP);
  3578.     }
  3579.  
  3580.     if ( bFreeSrc ) {
  3581.         XP_FREE(szSrc);
  3582.     }
  3583.     if ( bFreeTarg ) {
  3584.         XP_FREE(szTarg);
  3585.     }
  3586.     return bResult;
  3587. }
  3588.  
  3589. // CLM: Some simple functions to aid in COLORREF to LO_Color conversions
  3590.  
  3591. // Fill a LoColor structure
  3592. void WFE_SetLO_Color( COLORREF crColor, LO_Color *pLoColor )
  3593. {
  3594.     if ( pLoColor ) {
  3595.         pLoColor->red = GetRValue(crColor);
  3596.         pLoColor->green = GetGValue(crColor);
  3597.         pLoColor->blue = GetBValue(crColor);
  3598.     }
  3599. }
  3600.  
  3601. // This allocates a new LoColor structure if it
  3602. //   does not exist
  3603. void WFE_SetLO_ColorPtr( COLORREF crColor, LO_Color **ppLoColor )
  3604. {
  3605.     if ( ppLoColor == NULL ) {
  3606.         return;
  3607.     }
  3608.     if ( *ppLoColor == NULL ) {
  3609.         *ppLoColor = XP_NEW( LO_Color );
  3610.     }
  3611.     (*ppLoColor)->red = GetRValue(crColor);
  3612.     (*ppLoColor)->green = GetGValue(crColor);
  3613.     (*ppLoColor)->blue = GetBValue(crColor);
  3614. }
  3615.  
  3616. // Convert a LO_Color structure or get the default
  3617. //  default document colors
  3618. COLORREF WFE_LO2COLORREF( LO_Color * pLoColor, int iColorIndex )
  3619. {
  3620.     COLORREF crColor = 0;
  3621.     if ( pLoColor ) {
  3622.         crColor = RGB( pLoColor->red, pLoColor->green, pLoColor->blue);
  3623.     } 
  3624.     else {
  3625.         crColor = RGB(lo_master_colors[iColorIndex].red,
  3626.                       lo_master_colors[iColorIndex].green,
  3627.                       lo_master_colors[iColorIndex].blue);
  3628.     }
  3629.     return crColor;
  3630. }
  3631.  
  3632. // Parse a "#FFEEAA" style color string into colors make a COLORREF
  3633. BOOL WFE_ParseColor(char *pRGB, COLORREF * pCRef )
  3634. {
  3635.     uint8 red, green, blue;
  3636.     BOOL bColorsFound = LO_ParseRGB(pRGB, &red, &green, &blue);
  3637.     if ( bColorsFound ) {
  3638.         *pCRef = RGB( red, green, blue);
  3639.     }
  3640.     return bColorsFound;
  3641. }
  3642.  
  3643. // Helper to clear data
  3644. void WFE_FreeLO_Color(LO_Color_struct **ppLo)
  3645. {
  3646.     if ( *ppLo ) {
  3647.         XP_FREE( *ppLo );
  3648.         *ppLo = NULL;
  3649.     }
  3650. }
  3651.  
  3652. #ifdef EDITOR
  3653. // Get current color at caret or within a selection
  3654. COLORREF WFE_GetCurrentFontColor(MWContext * pMWContext)
  3655. {
  3656.     COLORREF crColor = DEFAULT_COLORREF;
  3657.  
  3658.     EDT_CharacterData *pCharData = EDT_GetCharacterData(pMWContext);
  3659.  
  3660.     if( !pMWContext ){
  3661.         return crColor;
  3662.     }
  3663.  
  3664.     if( pCharData && 0 != (pCharData->mask & TF_FONT_COLOR) ){
  3665.         // We are sure about the color
  3666.         if( pCharData->pColor ){
  3667.             // If we have a LO_Color struct, then use its color
  3668.             crColor = WFE_LO2COLORREF( pCharData->pColor, LO_COLOR_FG );
  3669.         }
  3670.     } else {
  3671.         // We are not sure of color
  3672.         crColor = MIXED_COLORREF;
  3673.     }
  3674.     if(pCharData) EDT_FreeCharacterData(pCharData);
  3675.     return crColor;
  3676. }
  3677. #endif // EDITOR
  3678.  
  3679. /******************************************************************************/
  3680. /* Thread-safe entry points: */
  3681.  
  3682. extern PRMonitor* _pr_TempName_lock;
  3683.  
  3684. char *
  3685. WH_TempName(XP_FileType type, const char * prefix)
  3686. {
  3687.     static char buf[_MAX_PATH];    /* protected by _pr_TempName_lock */
  3688.     char* result;
  3689. #ifdef NSPR
  3690.     XP_ASSERT(_pr_TempName_lock);
  3691.     PR_EnterMonitor(_pr_TempName_lock);
  3692. #endif
  3693.     result = XP_STRDUP(xp_TempFileName(type, prefix, NULL, buf));
  3694. #ifdef NSPR
  3695.     PR_ExitMonitor(_pr_TempName_lock);
  3696. #endif
  3697.     return result;
  3698. }
  3699.  
  3700. // The caller is responsible for XP_FREE()ing the return string
  3701. PUBLIC char *
  3702. WH_FileName (const char *name, XP_FileType type)
  3703. {
  3704.     char* myName;
  3705.     char* result;
  3706.     /*
  3707.     ** I'm not sure this lock is really needed by windows, but just
  3708.     ** to be safe:
  3709.     */
  3710. #ifdef NSPR
  3711.     //    XP_ASSERT(_pr_TempName_lock);
  3712.     //    PR_EnterMonitor(_pr_TempName_lock);
  3713. #endif
  3714.     result = xp_FileName(name, type, &myName);
  3715. #ifdef NSPR
  3716.     //    PR_ExitMonitor(_pr_TempName_lock);
  3717. #endif
  3718.     return myName;
  3719. }
  3720.  
  3721. int32 FE_LPtoDPoint(MWContext *pContext, int32 logicalPoint)    
  3722. {
  3723.       int32 iRetval = logicalPoint;
  3724.  
  3725.       CAbstractCX *pAbstract = ABSTRACTCX(pContext);
  3726.       if(pAbstract && pAbstract->IsDCContext())       {
  3727.               CDCCX *pCx = CXDC(pContext);
  3728.               HDC hDC = pCx->GetContextDC();
  3729.               if(hDC) {
  3730.                       POINT tempPoint;
  3731.                       tempPoint.x = 1;
  3732.                       tempPoint.y = logicalPoint;
  3733.                       // it is printing, convert them from device point to logical point for printers
  3734.                       if( TRUE == ::LPtoDP(hDC, &tempPoint, 1) )
  3735.                               iRetval = tempPoint.y;
  3736.               }
  3737.       }
  3738.  
  3739.       return(iRetval);
  3740. }
  3741.  
  3742. /******************************************************************************/
  3743.  
  3744. #ifdef XP_WIN16
  3745. static UINT PASCAL DirOpenHookProc(
  3746.         HWND hDlg,                /* window handle of the dialog box */
  3747.         UINT message,             /* type of message                 */
  3748.         UINT wParam,            /* message-specific information    */
  3749.         LONG lParam)
  3750. #else
  3751. static BOOL APIENTRY DirOpenHookProc(
  3752.         HWND hDlg,                /* window handle of the dialog box */
  3753.         UINT message,             /* type of message                 */
  3754.         UINT wParam,            /* message-specific information    */
  3755.         LONG lParam)
  3756. #endif
  3757. {
  3758.     switch (message)
  3759.     {
  3760.         case WM_INITDIALOG:
  3761.         //We must put something in this field, even though it is hidden.  This is
  3762.         //because if this field is empty, or has something like "*.txt" in it,
  3763.         //and the user hits OK, the dlg will NOT close.  We'll jam something in
  3764.         //there (like "k5bg") so when the user hits OK, the dlg terminates.
  3765.         //Note that we'll deal with the "k5bg" during return processing (see below)
  3766.             SetDlgItemText(hDlg, edt1, "k5bg");
  3767.         break;
  3768.     }
  3769.     return (FALSE);
  3770. }
  3771.  
  3772. /////////////////////////////////////////////////////////////////////////////
  3773. // CDirDialog           
  3774. CDirDialog::CDirDialog(CWnd* pParent, LPCTSTR pInitDir)
  3775.     : CFileDialog(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, NULL, pParent)
  3776. {
  3777.     m_szIniFile[0] = '\0';
  3778.  
  3779.     m_ofn.lStructSize        = sizeof(OPENFILENAME);
  3780.     m_ofn.hwndOwner            = pParent->GetSafeHwnd();
  3781.     m_ofn.hInstance            = AfxGetResourceHandle();
  3782.     m_ofn.lpstrFile            = m_szIniFile;
  3783.     m_ofn.nMaxFile            = 132;
  3784.     m_ofn.lpstrFilter        = NULL; 
  3785.     m_ofn.lpstrCustomFilter = NULL;
  3786.     m_ofn.lpstrInitialDir    = pInitDir; 
  3787.     m_ofn.lpstrFileTitle    = NULL;
  3788.     m_ofn.nMaxFileTitle        = 132;
  3789.     m_ofn.lpstrDefExt        = (LPSTR)NULL;
  3790.     m_ofn.lpstrDefExt        = "";
  3791. #ifdef XP_WIN32
  3792.     m_ofn.Flags = OFN_NOCHANGEDIR | OFN_ENABLETEMPLATE | OFN_ENABLEHOOK |OFN_NONETWORKBUTTON |OFN_LONGNAMES; 
  3793.     m_ofn.lpfnHook = (LPOFNHOOKPROC)DirOpenHookProc;
  3794. #else
  3795.     m_ofn.Flags = OFN_NOCHANGEDIR | OFN_ENABLETEMPLATE | OFN_ENABLEHOOK; 
  3796.     m_ofn.lpfnHook = &DirOpenHookProc;
  3797. #endif
  3798.     m_ofn.lpTemplateName = (LPTSTR)MAKEINTRESOURCE(FILEOPENORD);
  3799.  
  3800. }
  3801.  
  3802. void CDirDialog::DoDataExchange(CDataExchange* pDX)
  3803. {
  3804.     CFileDialog::DoDataExchange(pDX);
  3805. }
  3806.  
  3807. BEGIN_MESSAGE_MAP(CDirDialog, CFileDialog)
  3808. END_MESSAGE_MAP()
  3809.  
  3810. void FE_PokeLibSecOnIdle()
  3811. {
  3812.     long    lVal;
  3813.     DWORD    dwVal;
  3814.     HWND    hWnd;
  3815.     BYTE    buf[20];
  3816.     int        nBytes;
  3817.  
  3818.     nBytes = RNG_GetNoise(buf, sizeof(buf));
  3819.     RNG_RandomUpdate(buf, nBytes);
  3820.  
  3821.     dwVal = GetMessagePos();            // mouse position based
  3822.     RNG_RandomUpdate(&dwVal, sizeof(dwVal));
  3823.  
  3824.     lVal = GetMessageTime();            // time from startup to last message
  3825.     RNG_RandomUpdate(&lVal, sizeof(lVal));
  3826.  
  3827.     lVal = GetTickCount();            // we are about to go idle so this is probably
  3828.     RNG_RandomUpdate(&lVal, sizeof(lVal));    //   different from the one above
  3829.  
  3830.     hWnd = GetClipboardOwner();         // 2 or 4 bytes
  3831.     RNG_RandomUpdate((void *)&hWnd, sizeof(HWND));
  3832. }
  3833.  
  3834.  
  3835. void WFE_DrawDragRect(CDC* pdc, LPCRECT lpRect, SIZE size,
  3836.     LPCRECT lpRectLast, SIZE sizeLast, CBrush* pBrush, CBrush* pBrushLast)
  3837. {
  3838. #ifdef XP_WIN32
  3839.     pdc->DrawDragRect(lpRect, size, lpRectLast, sizeLast, pBrush, pBrushLast);
  3840. #endif
  3841. }
  3842.  
  3843. void FE_GetDocAndWindowPosition(MWContext * context, int32 *pX, int32 *pY, 
  3844.     int32 *pWidth, int32 *pHeight )
  3845. {
  3846.     if(context && ABSTRACTCX(context) &&
  3847.         ABSTRACTCX(context)->IsWindowContext() == TRUE)    {
  3848.         CPaneCX *pPaneCX = VOID2CX(context->fe.cx, CPaneCX);
  3849.  
  3850.         *pX = pPaneCX->GetOriginX(); 
  3851.         *pY = pPaneCX->GetOriginY();                             
  3852.  
  3853.         //    When we report the size to layout, we must always take care to subtract
  3854.         //        for the size of the scrollbars if we have dynamic or always on
  3855.         //        scrollers.
  3856.         if(pPaneCX->DynamicScrollBars() == FALSE 
  3857.                 && pPaneCX->IsHScrollBarOn() == FALSE 
  3858.                 && pPaneCX->IsVScrollBarOn() == FALSE)    {
  3859.             *pWidth = pPaneCX->GetWidth();
  3860.             *pHeight = pPaneCX->GetHeight();
  3861.         }
  3862.         else    {
  3863.             *pWidth = pPaneCX->GetWidth() - sysInfo.m_iScrollWidth;
  3864.             *pHeight = pPaneCX->GetHeight() - sysInfo.m_iScrollHeight;
  3865.         }
  3866.     }
  3867.     else    {
  3868.         //    No window here....
  3869.         ASSERT(0);
  3870.         *pX = *pY = *pHeight = *pWidth = 0;
  3871.     }
  3872. }
  3873.