2041 lines
64 KiB
C++
2041 lines
64 KiB
C++
//
|
|
// IMPEXP.CPP - Browser Import and Export Code
|
|
//
|
|
// Imports and Exports Favorites in various formats
|
|
//
|
|
// julianj 2/16/98
|
|
//
|
|
|
|
//
|
|
// *** IMPORT FAVORITES CODE ***
|
|
//
|
|
|
|
/************************************************************\
|
|
FILE: impext.cpp
|
|
|
|
DATE: April 1, 1996
|
|
|
|
AUTHOR(S): Bryan Starbuck (bryanst)
|
|
|
|
DESCRIPTION:
|
|
This file contains functions that can be used to upgrade
|
|
settings from the Microsoft Internet Explorer v2.0 to v3.0,
|
|
and some features to import Netscape features into Internet
|
|
Explorer.
|
|
|
|
This file will handle the logic to convert Netscape
|
|
bookmarks to Microsoft Internet Explorer favorites. This
|
|
will happen by finding the location of the Netscape bookmarks
|
|
file and the Microsoft Internet Explorer favorites directory
|
|
from the registry. Then it will parse the bookmarks file to
|
|
extract the URLs, which will finally be added to the favorites
|
|
directory.
|
|
|
|
USAGE:
|
|
This code is designed to be called when the user may
|
|
want Netscape bookmarks imported into system level Favorites
|
|
usable by programs such as Internet Explorer. External
|
|
users should call ImportBookmarks(). If this is done during
|
|
setup, it should be done after setup specifies the Favorites
|
|
registry entry and directory. If Netscape is not installed,
|
|
then the ImportBookmarks() is just a big no-op.
|
|
|
|
NOTE:
|
|
If this file is being compiled into something other
|
|
than infnist.exe, it will be necessary to include the
|
|
following String Resource:
|
|
|
|
#define IDS_NS_BOOKMARKS_DIR 137
|
|
STRINGTABLE DISCARDABLE
|
|
BEGIN
|
|
...
|
|
IDS_NS_BOOKMARKS_DIR "\\Imported Bookmarks"
|
|
END
|
|
|
|
|
|
UPDATES: I adopted this file to allow IE4.0 having the abilities
|
|
to upgrade from NetScape's setting. Two CustomActions will be added
|
|
to call in functions in this file. (inateeg)
|
|
|
|
8/14/98: added functions to import or export via an URL,
|
|
8/19/98: added UI to allow user to import/export via browser's File
|
|
menu/"Import and Exporting..."
|
|
\************************************************************/
|
|
#include "priv.h"
|
|
#include "impexp.h"
|
|
#include <regstr.h>
|
|
#include "resource.h"
|
|
|
|
#include <mluisupp.h>
|
|
|
|
//
|
|
// Information about the Netscape Bookmark file format that is shared between
|
|
// the import and export code
|
|
//
|
|
|
|
#define BEGIN_DIR_TOKEN "<DT><H"
|
|
#ifdef UNIX
|
|
#define MID_DIR_TOKEN0 "3>"
|
|
#endif
|
|
#define MID_DIR_TOKEN "\">"
|
|
#define END_DIR_TOKEN "</H"
|
|
#define BEGIN_EXITDIR_TOKEN "</DL><p>"
|
|
#define BEGIN_URL_TOKEN "<DT><A HREF=\""
|
|
#define END_URL_TOKEN "\" A"
|
|
#ifdef UNIX
|
|
#define END_URL_TOKEN2 "\">"
|
|
#endif
|
|
#define BEGIN_BOOKMARK_TOKEN ">"
|
|
#define END_BOOKMARK_TOKEN "</A>"
|
|
|
|
#define VALIDATION_STR "<!DOCTYPE NETSCAPE-Bookmark-file-"
|
|
|
|
//
|
|
// Use by export code
|
|
//
|
|
#define COMMENT_STR "<!-- This is an automatically generated file.\r\nIt will be read and overwritten.\r\nDo Not Edit! -->"
|
|
#define TITLE "<TITLE>Bookmarks</TITLE>\r\n<H1>Bookmarks</H1>"
|
|
|
|
// ItemType is going to be the type of entry found in the bookmarks
|
|
// file.
|
|
typedef enum MYENTRYTYPE
|
|
{
|
|
ET_OPEN_DIR = 531, // New level in heirarchy
|
|
ET_CLOSE_DIR, // Close level in heirarchy
|
|
ET_BOOKMARK, // Bookmark entry.
|
|
ET_NONE, // End of File
|
|
ET_ERROR // Bail, we encountered an error
|
|
} MyEntryType;
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
// Internal Functions
|
|
//////////////////////////////////////////////////////////////////
|
|
BOOL ImportNetscapeProxy(void); // Import Netscape Proxy Setting
|
|
BOOL UpdateHomePage(void); // Upgrade IE v1.0 Home URL to v3.0
|
|
BOOL ImportBookmarks(TCHAR *pszPathToFavorites, TCHAR *pszPathToBookmarks, HWND hwnd); // Import Netscape Bookmarks to IE Favorites
|
|
BOOL ExportFavorites(TCHAR *pszPathToFavorites, TCHAR *pszPathToBookmarks, HWND hwnd); // Export IE Favorites to Netscape Bookmarks
|
|
BOOL RegStrValueEmpty(HKEY hTheKey, char * szPath, char * szKey);
|
|
BOOL GetNSProxyValue(char * szProxyValue, DWORD * pdwSize);
|
|
|
|
BOOL VerifyBookmarksFile(HANDLE hFile);
|
|
BOOL ConvertBookmarks(TCHAR * szFavoritesDir, HANDLE hFile);
|
|
MyEntryType NextFileEntry(char ** ppStr, char ** ppToken);
|
|
BOOL GetData(char ** ppData, HANDLE hFile);
|
|
void RemoveInvalidFileNameChars(char * pBuf);
|
|
BOOL CreateDir(char *pDirName);
|
|
BOOL CloseDir(void);
|
|
BOOL CreateBookmark(char *pBookmarkName);
|
|
BOOL GetPathFromRegistry(LPTSTR szPath, UINT cbPath, HKEY theHKEY, LPTSTR szKey, LPTSTR szVName);
|
|
BOOL GetNavBkMkDir( LPTSTR lpszDir, int isize);
|
|
BOOL GetTargetFavoritesPath(LPTSTR szPath, UINT cbPath);
|
|
|
|
BOOL PostFavorites(TCHAR *pszPathToBookmarks, TCHAR* pszPathToPost);
|
|
void CALLBACK StatusCallback(HINTERNET hInternet, DWORD_PTR dwContext, DWORD dwStatus,
|
|
LPVOID lpvInfo, DWORD dwInfoLength);
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
// TYPES:
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
//typedef enum MYENTRYTYPE MyEntryType;
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
// Constants:
|
|
//////////////////////////////////////////////////////////////////
|
|
#define MAX_URL 2048
|
|
#define FILE_EXT 4 // For ".url" at the end of favorite filenames
|
|
#define REASONABLE_NAME_LEN 100
|
|
|
|
|
|
#define ANSIStrStr(p, q) StrStrIA(p, q)
|
|
#define ANSIStrChr(p, q) StrChrIA(p, q)
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
// GLOBALS:
|
|
//////////////////////////////////////////////////////////////////
|
|
#ifndef UNIX
|
|
TCHAR * szNetscapeBMRegSub = TEXT("SOFTWARE\\Netscape\\Netscape Navigator\\Bookmark List");
|
|
#else
|
|
TCHAR * szNetscapeBMRegSub = TEXT("SOFTWARE\\Microsoft\\Internet Explorer\\unix\\nsbookmarks");
|
|
#endif
|
|
|
|
TCHAR * szNetscapeBMRegKey = TEXT("File Location");
|
|
TCHAR * szIEFavoritesRegSub = TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders");
|
|
TCHAR * szIEFavoritesRegKey = TEXT("Favorites");
|
|
char * szInvalidFolderCharacters = "\\/:*?\"<>|";
|
|
|
|
BOOL gfValidNetscapeFile = FALSE;
|
|
BOOL gfValidIEDirFile = FALSE;
|
|
|
|
// Returns the location of the favorites folder in which to import the netscape favorites
|
|
BOOL GetTargetFavoritesPath(LPTSTR szPath, UINT cbPath)
|
|
{
|
|
if (GetPathFromRegistry(szPath, cbPath, HKEY_CURRENT_USER, szIEFavoritesRegSub, szIEFavoritesRegKey))
|
|
{
|
|
//MLLoadString(IDS_NS_BOOKMARKS_DIR, szSubDir, sizeof(szSubDir))
|
|
//lstrcat(szPath, "\\Imported Netscape Favorites");
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////
|
|
// Import Netscape Bookmarks to Microsoft
|
|
// Internet Explorer's Favorites
|
|
///////////////////////////////////////////////////////
|
|
|
|
/************************************************************\
|
|
FUNCTION: ImportBookmarks
|
|
|
|
PARAMETERS:
|
|
HINSTANCE hInstWithStr - Location of String Resources.
|
|
BOOL return - If an error occurs importing the bookmarks, FALSE is returned.
|
|
|
|
DESCRIPTION:
|
|
This function will see if it can find a IE Favorite's
|
|
registry entry and a Netscape bookmarks registry entry. If
|
|
both are found, then the conversion can happen. It will
|
|
attempt to open the verify that the bookmarks file is
|
|
valid and then convert the entries to favorite entries.
|
|
If an error occures, ImportBookmarks() will return FALSE,
|
|
otherwise it will return TRUE.
|
|
\*************************************************************/
|
|
|
|
BOOL ImportBookmarks(TCHAR *pszPathToFavorites, TCHAR *pszPathToBookmarks, HWND hwnd)
|
|
{
|
|
HANDLE hBookmarksFile = INVALID_HANDLE_VALUE;
|
|
BOOL fSuccess = FALSE;
|
|
|
|
// Prompt the user to insert floppy, format floppy or drive, remount mapped partition,
|
|
// or any create sub directories so pszPathToBookmarks becomes valid.
|
|
if (FAILED(SHPathPrepareForWriteWrap(hwnd, NULL, pszPathToBookmarks, FO_COPY, (SHPPFW_DEFAULT | SHPPFW_IGNOREFILENAME))))
|
|
return FALSE;
|
|
|
|
if (pszPathToFavorites==NULL || *pszPathToFavorites == TEXT('\0') ||
|
|
pszPathToBookmarks==NULL || *pszPathToBookmarks == TEXT('\0'))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
hBookmarksFile = CreateFile(pszPathToBookmarks, GENERIC_READ, FILE_SHARE_READ, NULL,
|
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
|
|
|
|
if ( hBookmarksFile != INVALID_HANDLE_VALUE )
|
|
{
|
|
//
|
|
// Verify it's a valid Bookmarks file
|
|
//
|
|
if (VerifyBookmarksFile( hBookmarksFile ))
|
|
{
|
|
//
|
|
// Do the importing...
|
|
//
|
|
fSuccess = ConvertBookmarks(pszPathToFavorites, hBookmarksFile);
|
|
|
|
if (hwnd && !fSuccess)
|
|
{
|
|
MLShellMessageBox(
|
|
hwnd,
|
|
MAKEINTRESOURCE(IDS_IMPORTCONVERTERROR),
|
|
MAKEINTRESOURCE(IDS_CONFIRM_IMPTTL_FAV),
|
|
MB_OK);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (hwnd)
|
|
{
|
|
MLShellMessageBox(
|
|
hwnd,
|
|
MAKEINTRESOURCE(IDS_NOTVALIDBOOKMARKS),
|
|
MAKEINTRESOURCE(IDS_CONFIRM_IMPTTL_FAV),
|
|
MB_OK);
|
|
}
|
|
}
|
|
CloseHandle(hBookmarksFile);
|
|
}
|
|
else
|
|
{
|
|
if (hwnd)
|
|
{
|
|
MLShellMessageBox(
|
|
hwnd,
|
|
MAKEINTRESOURCE(IDS_COULDNTOPENBOOKMARKS),
|
|
MAKEINTRESOURCE(IDS_CONFIRM_IMPTTL_FAV),
|
|
MB_OK);
|
|
}
|
|
}
|
|
return(fSuccess);
|
|
}
|
|
|
|
|
|
/************************************************************\
|
|
FUNCTION: ConvertBookmarks
|
|
|
|
PARAMETERS:
|
|
char * szFavoritesDir - String containing the path to
|
|
the IE Favorites directory
|
|
BOOL return - If an error occurs importing the bookmarks, FALSE is returned.
|
|
|
|
DESCRIPTION:
|
|
This function will continue in a loop converting each
|
|
entry in the bookmark file. There are three types of
|
|
entries in the bookmark file, 1) a bookmark, 2) start of
|
|
new level in heirarchy, 3) end of current level in heirarchy.
|
|
The function NextFileEntry() will return these values until
|
|
the file is empty, at which point, this function will end.
|
|
|
|
NOTE:
|
|
In order to prevent an infinite loop, it's assumed
|
|
that NextFileEntry() will eventually return ET_NONE or ET_ERROR.
|
|
\************************************************************/
|
|
|
|
BOOL ConvertBookmarks(TCHAR * szFavoritesDir, HANDLE hFile)
|
|
{
|
|
BOOL fDone = FALSE;
|
|
BOOL fSuccess = TRUE;
|
|
BOOL fIsEmpty = TRUE;
|
|
char * szData = NULL;
|
|
char * szCurrent = NULL;
|
|
char * szToken = NULL;
|
|
|
|
fSuccess = GetData(&szData, hFile);
|
|
if (NULL == szData)
|
|
fSuccess = FALSE;
|
|
|
|
szCurrent = szData;
|
|
|
|
// Verify directory exists or that we can make it.
|
|
if ((TRUE == fSuccess) && ( !SetCurrentDirectory(szFavoritesDir)))
|
|
{
|
|
// If the directory doesn't exist, make it...
|
|
if ( !CreateDirectory(szFavoritesDir, NULL))
|
|
fSuccess = FALSE;
|
|
else
|
|
if (!SetCurrentDirectory(szFavoritesDir))
|
|
fSuccess = FALSE;
|
|
}
|
|
|
|
|
|
while ((FALSE == fDone) && (TRUE == fSuccess))
|
|
{
|
|
switch(NextFileEntry(&szCurrent, &szToken))
|
|
{
|
|
case ET_OPEN_DIR:
|
|
fSuccess = CreateDir(szToken);
|
|
break;
|
|
case ET_CLOSE_DIR:
|
|
fSuccess = CloseDir();
|
|
break;
|
|
case ET_BOOKMARK:
|
|
fSuccess = CreateBookmark(szToken);
|
|
fIsEmpty = FALSE;
|
|
break;
|
|
case ET_ERROR:
|
|
fSuccess = FALSE;
|
|
break;
|
|
case ET_NONE:
|
|
default:
|
|
fDone = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( fIsEmpty )
|
|
{
|
|
// nothing to import, delete the dir created earlier
|
|
RemoveDirectory(szFavoritesDir);
|
|
}
|
|
|
|
if (NULL != szData)
|
|
{
|
|
LocalFree(szData);
|
|
szData = NULL;
|
|
szCurrent = NULL; // szCurrent no longer points to valid data.
|
|
szToken = NULL; // szCurrent no longer points to valid data.
|
|
}
|
|
|
|
return(fSuccess);
|
|
}
|
|
|
|
/************************************************************\
|
|
FUNCTION: NextFileEntry
|
|
|
|
PARAMETERS:
|
|
char ** ppStr - The data to parse.
|
|
char ** ppToken - The token pointer.
|
|
EntryType return- See below.
|
|
|
|
DESCRIPTION:
|
|
This function will look for the next entry in the
|
|
bookmark file to create or act on. The return value
|
|
will indicate this response:
|
|
ET_OPEN_DIR Create a new level in heirarchy
|
|
ET_CLOSE_DIR, Close level in heirarchy
|
|
ET_BOOKMARK, Create Bookmark entry.
|
|
ET_NONE, End of File
|
|
ET_ERROR Error encountered
|
|
|
|
Errors will be detected by finding the start of a token,
|
|
but in not finding other parts of the token that are needed
|
|
to parse the data.
|
|
\************************************************************/
|
|
|
|
MyEntryType NextFileEntry(char ** ppStr, char ** ppToken)
|
|
{
|
|
MyEntryType returnVal = ET_NONE;
|
|
char * pCurrentToken = NULL; // The current token to check if valid.
|
|
char * pTheToken = NULL; // The next valid token.
|
|
char * pszTemp = NULL;
|
|
#ifdef UNIX
|
|
char szMidDirToken[8];
|
|
#endif
|
|
|
|
//ASSERTSZ(NULL != ppStr, "It's an error to pass NULL for ppStr");
|
|
//ASSERTSZ(NULL != *ppStr, "It's an error to pass NULL for *ppStr");
|
|
//ASSERTSZ(NULL != ppToken, "It's an error to pass NULL for ppToken");
|
|
|
|
if ((NULL != ppStr) && (NULL != *ppStr) && (NULL != ppToken))
|
|
{
|
|
// Check for begin dir token
|
|
if (NULL != (pCurrentToken = ANSIStrStr(*ppStr, BEGIN_DIR_TOKEN)))
|
|
{
|
|
// Begin dir token found
|
|
// Verify that other needed tokens exist or it's an error
|
|
#ifndef UNIX
|
|
if ((NULL == (pszTemp = ANSIStrStr(pCurrentToken, MID_DIR_TOKEN))) ||
|
|
#else
|
|
if (pCurrentToken[7] == ' ')
|
|
StrCpyNA(szMidDirToken, MID_DIR_TOKEN, ARRAYSIZE(szMidDirToken));
|
|
else
|
|
StrCpyNA(szMidDirToken, MID_DIR_TOKEN0, ARRAYSIZE(szMidDirToken));
|
|
if ((NULL == (pszTemp = ANSIStrStr(pCurrentToken, szMidDirToken))) ||
|
|
#endif
|
|
(NULL == ANSIStrStr(pszTemp, END_DIR_TOKEN)))
|
|
{
|
|
returnVal = ET_ERROR; // We can't find all the tokens needed.
|
|
}
|
|
else
|
|
{
|
|
// This function has to set *ppToken to the name of the directory to create
|
|
#ifndef UNIX
|
|
*ppToken = ANSIStrStr(pCurrentToken, MID_DIR_TOKEN) + sizeof(MID_DIR_TOKEN)-1;
|
|
#else
|
|
*ppToken = ANSIStrStr(pCurrentToken, szMidDirToken) + lstrlenA(szMidDirToken);
|
|
#endif
|
|
pTheToken = pCurrentToken;
|
|
returnVal = ET_OPEN_DIR;
|
|
}
|
|
}
|
|
// Check for exit dir token
|
|
if ((ET_ERROR != returnVal) &&
|
|
(NULL != (pCurrentToken = ANSIStrStr(*ppStr, BEGIN_EXITDIR_TOKEN))))
|
|
{
|
|
// Exit dir token found
|
|
// See if this token comes before TheToken.
|
|
if ((NULL == pTheToken) || (pCurrentToken < pTheToken))
|
|
{
|
|
// ppToken is not used for Exit Dir
|
|
*ppToken = NULL;
|
|
pTheToken = pCurrentToken;
|
|
returnVal = ET_CLOSE_DIR;
|
|
}
|
|
}
|
|
// Check for begin url token
|
|
if ((ET_ERROR != returnVal) &&
|
|
(NULL != (pCurrentToken = ANSIStrStr(*ppStr, BEGIN_URL_TOKEN))))
|
|
{
|
|
// Bookmark token found
|
|
// Verify that other needed tokens exist or it's an error
|
|
#ifndef UNIX
|
|
if ((NULL == (pszTemp = ANSIStrStr(pCurrentToken, END_URL_TOKEN))) ||
|
|
#else
|
|
if (((NULL == (pszTemp = ANSIStrStr(pCurrentToken, END_URL_TOKEN))) &&
|
|
(NULL == (pszTemp = ANSIStrStr(pCurrentToken, END_URL_TOKEN2)))) ||
|
|
#endif
|
|
(NULL == (pszTemp = ANSIStrStr(pszTemp, BEGIN_BOOKMARK_TOKEN))) ||
|
|
(NULL == ANSIStrStr(pszTemp, END_BOOKMARK_TOKEN)))
|
|
{
|
|
returnVal = ET_ERROR; // We can't find all the tokens needed.
|
|
}
|
|
else
|
|
{
|
|
// See if this token comes before TheToken.
|
|
if ((NULL == pTheToken) || (pCurrentToken < pTheToken))
|
|
{
|
|
// This function has to set *ppToken to the name of the bookmark
|
|
*ppToken = pCurrentToken + sizeof(BEGIN_URL_TOKEN)-1;
|
|
pTheToken = pCurrentToken;
|
|
returnVal = ET_BOOKMARK;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
returnVal = ET_ERROR; // We should never get here.
|
|
|
|
if (NULL == pTheToken)
|
|
returnVal = ET_NONE;
|
|
else
|
|
{
|
|
// Next time we will start parsing where we left off.
|
|
switch(returnVal)
|
|
{
|
|
case ET_OPEN_DIR:
|
|
#ifndef UNIX
|
|
*ppStr = ANSIStrStr(pTheToken, MID_DIR_TOKEN) + sizeof(MID_DIR_TOKEN);
|
|
#else
|
|
*ppStr = ANSIStrStr(pTheToken, szMidDirToken) + lstrlenA(szMidDirToken) + 1;
|
|
#endif
|
|
break;
|
|
case ET_CLOSE_DIR:
|
|
*ppStr = pTheToken + sizeof(BEGIN_EXITDIR_TOKEN);
|
|
break;
|
|
case ET_BOOKMARK:
|
|
*ppStr = ANSIStrStr(pTheToken, END_BOOKMARK_TOKEN) + sizeof(END_BOOKMARK_TOKEN);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return(returnVal);
|
|
}
|
|
|
|
|
|
/************************************************************\
|
|
FUNCTION: GetPathFromRegistry
|
|
|
|
PARAMETERS:
|
|
LPSTR szPath - The value found in the registry. (Result of function)
|
|
UINT cbPath - Size of szPath.
|
|
HKEY theHKEY - The HKEY to look into (HKEY_CURRENT_USER)
|
|
LPSTR szKey - Path in Registry (Software\...\Explore\Shell Folders)
|
|
LPSTR szVName - Value to query (Favorites)
|
|
BOOL return - TRUE if succeeded, FALSE if Error.
|
|
EXAMPLE:
|
|
HKEY_CURRENT_USER\Software\Microsoft\CurrentVersion\Explore\Shell Folders
|
|
Favorites = "C:\WINDOWS\Favorites"
|
|
|
|
DESCRIPTION:
|
|
This function will look in the registry for the value
|
|
to look up. The caller specifies the HKEY, subkey (szKey),
|
|
value to query (szVName). The caller also sets a side memory
|
|
for the result and passes a pointer to that memory in szPath
|
|
with it's size in cbPath. The BOOL return value will indicate
|
|
success or failure of this function.
|
|
\************************************************************/
|
|
|
|
BOOL GetPathFromRegistry(LPTSTR szPath, UINT cbPath, HKEY theHKEY,
|
|
LPTSTR szKey, LPTSTR szVName)
|
|
{
|
|
DWORD dwType;
|
|
DWORD dwSize;
|
|
|
|
/*
|
|
* Get Path to program
|
|
* from the registry
|
|
*/
|
|
dwSize = cbPath;
|
|
return (ERROR_SUCCESS == SHGetValue(theHKEY, szKey, szVName, &dwType, (LPBYTE) szPath, &dwSize)
|
|
&& (dwType == REG_EXPAND_SZ || dwType == REG_SZ));
|
|
}
|
|
|
|
|
|
/************************************************************\
|
|
FUNCTION: RemoveInvalidFileNameChars
|
|
|
|
PARAMETERS:
|
|
char * pBuf - The data to search.
|
|
|
|
DESCRIPTION:
|
|
This function will search pBuf until it encounters
|
|
a character that is not allowed in a file name. It will
|
|
then replace that character with a SPACE and continue looking
|
|
for more invalid chars until they have all been removed.
|
|
\************************************************************/
|
|
|
|
void RemoveInvalidFileNameChars(char * pBuf)
|
|
{
|
|
//ASSERTSZ(NULL != pBuf, "Invalid function parameter");
|
|
|
|
// Go through the array of chars, replacing offending characters with a space
|
|
if (NULL != pBuf)
|
|
{
|
|
if (REASONABLE_NAME_LEN < strlen(pBuf))
|
|
pBuf[REASONABLE_NAME_LEN] = '\0'; // String too long. Terminate it.
|
|
|
|
while ('\0' != *pBuf)
|
|
{
|
|
// Check if the character is invalid
|
|
if (!IsDBCSLeadByte(*pBuf))
|
|
{
|
|
if (ANSIStrChr(szInvalidFolderCharacters, *pBuf) != NULL)
|
|
*pBuf = '_';
|
|
}
|
|
pBuf = CharNextA(pBuf);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/************************************************************\
|
|
FUNCTION: CreateBookmark
|
|
|
|
PARAMETERS:
|
|
char * pBookmarkName- This is a pointer that contains
|
|
the name of the bookmark to create.
|
|
Note that it is not NULL terminated.
|
|
BOOL return - Return TRUE if successful.
|
|
|
|
DESCRIPTION:
|
|
This function will take the data that is passed to
|
|
it and extract the name of the bookmark and it's value to create.
|
|
If the name is too long, it will be truncated. Then,
|
|
the directory will be created. Any errors encountered
|
|
will cause the function to return FALSE to indicate
|
|
failure.
|
|
\************************************************************/
|
|
|
|
BOOL CreateBookmark(char *pBookmarkName)
|
|
{
|
|
BOOL fSuccess = FALSE;
|
|
char szNameOfBM[REASONABLE_NAME_LEN];
|
|
char szURL[MAX_URL];
|
|
char * pstrEndOfStr = NULL;
|
|
char * pstrBeginOfName = NULL;
|
|
long lStrLen = 0;
|
|
HANDLE hFile = NULL;
|
|
DWORD dwSize;
|
|
char szBuf[MAX_URL];
|
|
|
|
//ASSERTSZ(NULL != pBookmarkName, "Bad input parameter");
|
|
if (NULL != pBookmarkName)
|
|
{
|
|
|
|
pstrEndOfStr = ANSIStrStr(pBookmarkName, END_URL_TOKEN);
|
|
#ifdef UNIX
|
|
if (!pstrEndOfStr)
|
|
pstrEndOfStr = ANSIStrStr(pBookmarkName, END_URL_TOKEN2);
|
|
#endif
|
|
if (NULL != pstrEndOfStr)
|
|
{
|
|
lStrLen = (int) (pstrEndOfStr-pBookmarkName);
|
|
if (MAX_URL < lStrLen)
|
|
lStrLen = MAX_URL-1;
|
|
|
|
// Create the name of the Bookmark
|
|
StrCpyNA(szURL, pBookmarkName, ARRAYSIZE(szURL));
|
|
szURL[lStrLen] = '\0';
|
|
|
|
// filter out file links, we won't create a bookmark to a file link
|
|
// but remove the link silently and continue
|
|
if (IsFileUrl(szURL))
|
|
return TRUE;
|
|
|
|
pstrBeginOfName = ANSIStrStr(pstrEndOfStr, BEGIN_BOOKMARK_TOKEN);
|
|
if (NULL != pstrBeginOfName)
|
|
{
|
|
pstrBeginOfName += sizeof(BEGIN_BOOKMARK_TOKEN) - 1; // Start at beginning of Name
|
|
|
|
pstrEndOfStr = ANSIStrStr(pstrBeginOfName, END_BOOKMARK_TOKEN); // Find end of name
|
|
if (NULL != pstrEndOfStr)
|
|
{
|
|
lStrLen = (int) (pstrEndOfStr-pstrBeginOfName);
|
|
if (REASONABLE_NAME_LEN-FILE_EXT-1 < lStrLen)
|
|
lStrLen = REASONABLE_NAME_LEN-FILE_EXT-1;
|
|
|
|
// Generate the URL
|
|
StrCpyNA(szNameOfBM, pstrBeginOfName, lStrLen+1);
|
|
//szNameOfBM[lStrLen] = '\0';
|
|
StrCatBuffA(szNameOfBM, ".url", ARRAYSIZE(szNameOfBM));
|
|
RemoveInvalidFileNameChars(szNameOfBM);
|
|
|
|
// Check to see if Favorite w/same name exists
|
|
if (INVALID_HANDLE_VALUE != (hFile = CreateFileA(szNameOfBM, GENERIC_WRITE, FILE_SHARE_READ, NULL,
|
|
CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL )))
|
|
{
|
|
WriteFile(hFile, "[InternetShortcut]\n", lstrlenA( "[InternetShortcut]\n" ), &dwSize, NULL);
|
|
wnsprintfA( szBuf, ARRAYSIZE(szBuf), "URL=%s\n", szURL);
|
|
WriteFile(hFile, szBuf, lstrlenA(szBuf), &dwSize, NULL );
|
|
fSuccess = TRUE;
|
|
}
|
|
else
|
|
{
|
|
fSuccess = TRUE;
|
|
}
|
|
|
|
if (NULL != hFile)
|
|
{
|
|
CloseHandle( hFile );
|
|
hFile = NULL;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return(fSuccess);
|
|
}
|
|
|
|
|
|
/************************************************************\
|
|
FUNCTION: CreateDir
|
|
|
|
PARAMETERS:
|
|
char * pDirName - This is a pointer that contains
|
|
the name of the directory to create.
|
|
Note that it is not NULL terminated.
|
|
BOOL return - Return TRUE if successful.
|
|
|
|
DESCRIPTION:
|
|
This function will take the data that is passed to
|
|
it and extract the name of the directory to create.
|
|
If the name is too long, it will be truncated. Then,
|
|
the directory will be created. Any errors encountered
|
|
will cause the function to return FALSE to indicate
|
|
failure.
|
|
\************************************************************/
|
|
BOOL CreateDir(char *pDirName)
|
|
{
|
|
BOOL fSuccess = FALSE;
|
|
char szNameOfDir[REASONABLE_NAME_LEN];
|
|
char * pstrEndOfName = NULL;
|
|
long lStrLen = 0;
|
|
|
|
//ASSERTSZ(NULL != pDirName, "Bad input parameter");
|
|
if (NULL != pDirName)
|
|
{
|
|
pstrEndOfName = ANSIStrStr(pDirName, END_DIR_TOKEN);
|
|
if (NULL != pstrEndOfName)
|
|
{
|
|
lStrLen = (int) (pstrEndOfName-pDirName);
|
|
if (REASONABLE_NAME_LEN-1 < lStrLen)
|
|
lStrLen = REASONABLE_NAME_LEN-1;
|
|
|
|
StrCpyNA(szNameOfDir, pDirName, lStrLen+1);
|
|
//szNameOfDir[lStrLen] = '\0';
|
|
RemoveInvalidFileNameChars(szNameOfDir);
|
|
|
|
if ( !SetCurrentDirectoryA(szNameOfDir) )
|
|
{
|
|
if ( CreateDirectoryA(szNameOfDir, NULL) )
|
|
{
|
|
if ( SetCurrentDirectoryA(szNameOfDir) )
|
|
{
|
|
fSuccess = TRUE;// It didn't exist, but now it does.
|
|
}
|
|
}
|
|
}
|
|
else
|
|
fSuccess = TRUE; // It exists already.
|
|
}
|
|
}
|
|
|
|
return(fSuccess);
|
|
}
|
|
|
|
|
|
/************************************************************\
|
|
FUNCTION: CloseDir
|
|
|
|
PARAMETERS:
|
|
BOOL return - Return TRUE if successful.
|
|
|
|
DESCRIPTION:
|
|
This function will back out of the current directory.
|
|
\************************************************************/
|
|
BOOL CloseDir(void)
|
|
{
|
|
return( SetCurrentDirectoryA("..") );
|
|
}
|
|
|
|
|
|
/************************************************************\
|
|
FUNCTION: VerifyBookmarksFile
|
|
|
|
PARAMETERS:
|
|
FILE * pFile - Pointer to Netscape Bookmarks file.
|
|
BOOL return - TRUE if No Error and Valid Bookmark file
|
|
|
|
DESCRIPTION:
|
|
This function needs to be passed with a valid pointer
|
|
that points to an open file. Upon return, the file will
|
|
still be open and is guarenteed to have the file pointer
|
|
point to the beginning of the file.
|
|
This function will return TRUE if the file contains
|
|
text that indicates it's a valid Netscape bookmarks file.
|
|
\************************************************************/
|
|
|
|
BOOL VerifyBookmarksFile(HANDLE hFile)
|
|
{
|
|
BOOL fSuccess = FALSE;
|
|
char szFileHeader[sizeof(VALIDATION_STR)+1] = "";
|
|
DWORD dwSize;
|
|
|
|
//ASSERTSZ(NULL != pFile, "You can't pass me a NULL File Pointer");
|
|
if (INVALID_HANDLE_VALUE == hFile)
|
|
return(FALSE);
|
|
|
|
// Reading the first part of the file. If the file isn't this long, then
|
|
// it can't possibly be a Bookmarks file.
|
|
if ( ReadFile( hFile, szFileHeader, sizeof(VALIDATION_STR)-1, &dwSize, NULL ) && (dwSize == sizeof(VALIDATION_STR)-1) )
|
|
{
|
|
#ifndef UNIX
|
|
szFileHeader[sizeof(VALIDATION_STR)] = '\0'; // Terminate String.
|
|
#else
|
|
// The above statement doesn;t serve the purpose on UNIX.
|
|
// I think we should change for NT also.
|
|
// IEUNIX : NULL character after the buffer read
|
|
szFileHeader[sizeof(VALIDATION_STR)-1] = '\0'; // Terminate String.
|
|
#endif
|
|
|
|
if (0 == StrCmpA(szFileHeader, VALIDATION_STR)) // See if header is the same as the Validation string.
|
|
fSuccess = TRUE;
|
|
}
|
|
|
|
// Reset the point to point to the beginning of the file.
|
|
dwSize = SetFilePointer( hFile, 0, NULL, FILE_BEGIN );
|
|
if ( dwSize == 0xFFFFFFFF )
|
|
fSuccess = FALSE;
|
|
|
|
return(fSuccess);
|
|
}
|
|
|
|
|
|
|
|
/************************************************************\
|
|
FUNCTION: GetData
|
|
|
|
PARAMETERS:
|
|
char ** ppData - Where to put the data
|
|
FILE * pFile - Pointer to Netscape Bookmarks file.
|
|
BOOL return - Return TRUE is successful.
|
|
|
|
DESCRIPTION:
|
|
This function will find the size of the bookmarks file,
|
|
malloc that much memory, and put the file's contents in
|
|
that buffer. ppData will be invalid when the function
|
|
is called and will return with malloced memory that
|
|
needs to be freed by the falling function.
|
|
\************************************************************/
|
|
|
|
BOOL GetData(char ** ppData, HANDLE hFile)
|
|
{
|
|
DWORD dwlength, dwRead;
|
|
BOOL fSuccess = FALSE;
|
|
|
|
//ASSERTSZ(NULL != ppData, "Invalid input parameter");
|
|
|
|
if (NULL != ppData)
|
|
{
|
|
*ppData = NULL;
|
|
|
|
// Find the size of the data
|
|
if ( dwlength = GetFileSize(hFile, NULL))
|
|
{
|
|
*ppData = (PSTR)LocalAlloc(LPTR, dwlength+1 );
|
|
if (NULL != *ppData)
|
|
{
|
|
if ( ReadFile( hFile, *ppData, dwlength+1, &dwRead, NULL ) &&
|
|
( dwlength == dwRead ) )
|
|
{
|
|
fSuccess = TRUE;
|
|
}
|
|
|
|
(*ppData)[dwlength] = '\0';
|
|
}
|
|
}
|
|
}
|
|
|
|
return(fSuccess);
|
|
}
|
|
|
|
//
|
|
// AddPath - added by julianj when porting from setup code to stand alone
|
|
//
|
|
void PASCAL AddPath(LPTSTR pszPath, LPCTSTR pszName, int cchPath )
|
|
{
|
|
LPTSTR pszTmp;
|
|
int cchTmp;
|
|
|
|
// Find end of the string
|
|
cchTmp = lstrlen(pszPath);
|
|
pszTmp = pszPath + cchTmp;
|
|
cchTmp = cchPath - cchTmp;
|
|
|
|
// If no trailing backslash then add one
|
|
if ( pszTmp > pszPath && *(CharPrev( pszPath, pszTmp )) != FILENAME_SEPARATOR )
|
|
{
|
|
*(pszTmp++) = FILENAME_SEPARATOR;
|
|
cchTmp--;
|
|
}
|
|
|
|
// Add new name to existing path string
|
|
while ( *pszName == TEXT(' ') ) pszName++;
|
|
StrCpyN( pszTmp, pszName, cchTmp );
|
|
}
|
|
|
|
//
|
|
// GetVersionFromFile - added by julianj when porting from setup code to stand alone
|
|
//
|
|
BOOL GetVersionFromFile(PTSTR pszFileName, PDWORD pdwMSVer, PDWORD pdwLSVer)
|
|
{
|
|
DWORD dwVerInfoSize, dwHandle;
|
|
LPVOID lpVerInfo;
|
|
VS_FIXEDFILEINFO *pvsVSFixedFileInfo;
|
|
UINT uSize;
|
|
|
|
HRESULT hr = E_FAIL;
|
|
|
|
*pdwMSVer = *pdwLSVer = 0;
|
|
|
|
if ((dwVerInfoSize = GetFileVersionInfoSize(pszFileName, &dwHandle)))
|
|
{
|
|
if ((lpVerInfo = (LPVOID) LocalAlloc(LPTR, dwVerInfoSize)) != NULL)
|
|
{
|
|
if (GetFileVersionInfo(pszFileName, dwHandle, dwVerInfoSize, lpVerInfo))
|
|
{
|
|
if (VerQueryValue(lpVerInfo, TEXT("\\"), (LPVOID *) &pvsVSFixedFileInfo, &uSize))
|
|
{
|
|
*pdwMSVer = pvsVSFixedFileInfo->dwFileVersionMS;
|
|
*pdwLSVer = pvsVSFixedFileInfo->dwFileVersionLS;
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
LocalFree(lpVerInfo);
|
|
lpVerInfo = NULL;
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
BOOL GetNavBkMkDir( LPTSTR lpszDir, int isize)
|
|
{
|
|
BOOL bDirFound = FALSE;
|
|
#ifndef UNIX
|
|
TCHAR szDir[MAX_PATH];
|
|
HKEY hKey;
|
|
HKEY hKeyUser;
|
|
TCHAR szUser[MAX_PATH];
|
|
DWORD dwSize;
|
|
|
|
StrCpyN( szUser, REGSTR_PATH_APPPATHS, ARRAYSIZE(szUser) );
|
|
AddPath( szUser, TEXT("NetScape.exe"), ARRAYSIZE(szUser) );
|
|
if ( GetPathFromRegistry( szDir, ARRAYSIZE(szDir), HKEY_LOCAL_MACHINE, szUser, TEXT("") ) &&
|
|
lstrlen(szDir) )
|
|
{
|
|
DWORD dwMV, dwLV;
|
|
|
|
if ( SUCCEEDED(GetVersionFromFile( szDir, &dwMV, &dwLV )) )
|
|
{
|
|
if ( dwMV < 0x00040000 )
|
|
bDirFound = GetPathFromRegistry( lpszDir, isize, HKEY_CURRENT_USER,
|
|
szNetscapeBMRegSub, szNetscapeBMRegKey);
|
|
else
|
|
{
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Netscape\\Netscape Navigator\\Users"), 0, KEY_READ, &hKey) == ERROR_SUCCESS)
|
|
{
|
|
dwSize = sizeof(szUser);
|
|
if (RegQueryValueEx(hKey, TEXT("CurrentUser"), NULL, NULL, (LPBYTE)szUser, &dwSize) == ERROR_SUCCESS)
|
|
{
|
|
if (RegOpenKeyEx(hKey, szUser, 0, KEY_READ, &hKeyUser) == ERROR_SUCCESS)
|
|
{
|
|
dwSize = sizeof(szDir);
|
|
if (RegQueryValueEx(hKeyUser, TEXT("DirRoot"), NULL, NULL, (LPBYTE)szDir, &dwSize) == ERROR_SUCCESS)
|
|
{
|
|
// Found the directory for the current user.
|
|
StrCpyN( lpszDir, szDir, isize);
|
|
AddPath( lpszDir, TEXT("bookmark.htm"), isize );
|
|
bDirFound = TRUE;
|
|
}
|
|
RegCloseKey(hKeyUser);
|
|
}
|
|
}
|
|
RegCloseKey(hKey);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
bDirFound = GetPathFromRegistry( lpszDir, isize, HKEY_CURRENT_USER,
|
|
szNetscapeBMRegSub, szNetscapeBMRegKey);
|
|
|
|
return bDirFound;
|
|
}
|
|
|
|
|
|
//
|
|
// *** EXPORT FAVORITES CODE ***
|
|
//
|
|
|
|
// REVIEW REMOVE THESE
|
|
#include <windows.h>
|
|
//#include <stdio.h>
|
|
#include <shlobj.h>
|
|
#include <shlwapi.h>
|
|
|
|
//
|
|
// Generate HTML from favorites
|
|
//
|
|
|
|
#define INDENT_AMOUNT 4
|
|
|
|
int Indent = 0;
|
|
|
|
HANDLE g_hOutputStream = INVALID_HANDLE_VALUE;
|
|
|
|
void Output(const char *format, ...)
|
|
{
|
|
DWORD dwSize;
|
|
char buf[MAX_URL];
|
|
|
|
va_list argptr;
|
|
|
|
va_start(argptr, format);
|
|
|
|
for (int i=0; i<Indent*INDENT_AMOUNT; i++)
|
|
{
|
|
WriteFile(g_hOutputStream, " ", 1, &dwSize, NULL);
|
|
}
|
|
|
|
wvnsprintfA(buf, ARRAYSIZE(buf), format, argptr);
|
|
WriteFile(g_hOutputStream, buf, lstrlenA(buf), &dwSize, NULL);
|
|
}
|
|
|
|
void OutputLn(const char *format, ...)
|
|
{
|
|
DWORD dwSize;
|
|
char buf[MAX_URL];
|
|
|
|
va_list argptr;
|
|
|
|
va_start(argptr, format);
|
|
|
|
for (int i=0; i<Indent*INDENT_AMOUNT; i++)
|
|
{
|
|
WriteFile(g_hOutputStream, " ", 1, &dwSize, NULL);
|
|
}
|
|
|
|
wvnsprintfA(buf, ARRAYSIZE(buf), format, argptr);
|
|
WriteFile(g_hOutputStream, buf, lstrlenA(buf), &dwSize, NULL);
|
|
WriteFile(g_hOutputStream, "\r\n", 2, &dwSize, NULL);
|
|
}
|
|
|
|
#define CREATION_TIME 0
|
|
#define ACCESS_TIME 1
|
|
#define MODIFY_TIME 2
|
|
|
|
//
|
|
// This nasty looking macro converts a FILETIME structure
|
|
// (100-nanosecond intervals since Jan 1st 1601) to a
|
|
// unix time_t value (seconds since Jan 1st 1970).
|
|
//
|
|
// The numbers come from knowledgebase article Q167296
|
|
//
|
|
#define FILETIME_TO_UNIXTIME(ft) (UINT)((*(LONGLONG*)&ft-116444736000000000)/10000000)
|
|
|
|
UINT GetUnixFileTime(LPTSTR pszFileName, int mode)
|
|
{
|
|
|
|
WIN32_FIND_DATA wfd;
|
|
HANDLE hFind;
|
|
|
|
hFind = FindFirstFile(pszFileName,&wfd);
|
|
|
|
if (hFind == INVALID_HANDLE_VALUE)
|
|
return 0;
|
|
|
|
FindClose(hFind);
|
|
|
|
switch (mode)
|
|
{
|
|
|
|
case CREATION_TIME:
|
|
return FILETIME_TO_UNIXTIME(wfd.ftCreationTime);
|
|
|
|
case ACCESS_TIME:
|
|
return FILETIME_TO_UNIXTIME(wfd.ftLastAccessTime);
|
|
|
|
case MODIFY_TIME:
|
|
return FILETIME_TO_UNIXTIME(wfd.ftLastWriteTime);
|
|
|
|
default:
|
|
ASSERT(0);
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void WalkTree(TCHAR * szDir)
|
|
{
|
|
WIN32_FIND_DATA findFileData;
|
|
TCHAR buf[MAX_PATH];
|
|
HANDLE hFind;
|
|
|
|
Indent++;
|
|
|
|
//
|
|
// First iterate through all directories
|
|
//
|
|
wnsprintf(buf, ARRAYSIZE(buf), TEXT("%s") TEXT(FILENAME_SEPARATOR_STR) TEXT("*"), szDir);
|
|
hFind = FindFirstFile(buf, &findFileData);
|
|
if (INVALID_HANDLE_VALUE != hFind)
|
|
{
|
|
do
|
|
{
|
|
if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
{
|
|
if ((StrCmp(findFileData.cFileName, TEXT(".")) != 0 &&
|
|
StrCmp(findFileData.cFileName, TEXT("..")) != 0 &&
|
|
StrCmp(findFileData.cFileName, TEXT("History")) != 0 && // REVIEW just for JJ. Should check for system bit on folders
|
|
StrCmp(findFileData.cFileName, TEXT("Software Updates")) != 0 && // don't export software updates
|
|
StrCmp(findFileData.cFileName, TEXT("Channels")) != 0)) // don't export channels for now!
|
|
{
|
|
char thisFile[MAX_PATH];
|
|
wnsprintf(buf, ARRAYSIZE(buf), TEXT("%s") TEXT(FILENAME_SEPARATOR_STR) TEXT("%s"), szDir, findFileData.cFileName);
|
|
|
|
if (!(GetFileAttributes(buf)&FILE_ATTRIBUTE_SYSTEM))
|
|
{
|
|
SHTCharToAnsi(findFileData.cFileName, thisFile, MAX_PATH);
|
|
OutputLn("<DT><H3 FOLDED ADD_DATE=\"%u\">%s</H3>", GetUnixFileTime(buf,CREATION_TIME), thisFile);
|
|
OutputLn("<DL><p>");
|
|
WalkTree(buf);
|
|
OutputLn(BEGIN_EXITDIR_TOKEN);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
; // ignore . and ..
|
|
}
|
|
}
|
|
} while (FindNextFile(hFind, &findFileData));
|
|
|
|
FindClose(hFind);
|
|
}
|
|
|
|
//
|
|
// Next iterate through all files
|
|
//
|
|
wnsprintf(buf, ARRAYSIZE(buf), TEXT("%s") TEXT(FILENAME_SEPARATOR_STR) TEXT("*"), szDir);
|
|
hFind = FindFirstFile(buf, &findFileData);
|
|
if (INVALID_HANDLE_VALUE != hFind)
|
|
{
|
|
do
|
|
{
|
|
if (!(findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
|
{
|
|
wnsprintf(buf, ARRAYSIZE(buf), TEXT("%s") TEXT(FILENAME_SEPARATOR_STR) TEXT("%s"), szDir, findFileData.cFileName);
|
|
|
|
//
|
|
// Read the url from the .url file
|
|
//
|
|
TCHAR szUrl[MAX_PATH];
|
|
|
|
SHGetIniString(
|
|
TEXT("InternetShortcut"),
|
|
TEXT("URL"),
|
|
szUrl, // returns url
|
|
MAX_PATH,
|
|
buf); // full path to .url file
|
|
|
|
if (*szUrl != 0)
|
|
{
|
|
//
|
|
// create a copy of the filename without the extension
|
|
// note PathFindExtension returns a ptr to the NULL at
|
|
// end if '.' not found so its ok to just blast *pch with 0
|
|
//
|
|
TCHAR szFileName[MAX_PATH];
|
|
StrCpyN(szFileName, findFileData.cFileName, ARRAYSIZE(szFileName));
|
|
TCHAR *pch = PathFindExtension(szFileName);
|
|
*pch = TEXT('\0'); //
|
|
char szUrlAnsi[MAX_PATH], szFileNameAnsi[MAX_PATH];
|
|
SHTCharToAnsi(szUrl, szUrlAnsi, MAX_PATH);
|
|
SHTCharToAnsi(szFileName, szFileNameAnsi, MAX_PATH);
|
|
OutputLn("<DT><A HREF=\"%s\" ADD_DATE=\"%u\" LAST_VISIT=\"%u\" LAST_MODIFIED=\"%u\">%s</A>",
|
|
szUrlAnsi,
|
|
GetUnixFileTime(buf,CREATION_TIME),
|
|
GetUnixFileTime(buf,ACCESS_TIME),
|
|
GetUnixFileTime(buf,MODIFY_TIME),
|
|
szFileNameAnsi);
|
|
}
|
|
}
|
|
} while (FindNextFile(hFind, &findFileData));
|
|
|
|
FindClose(hFind);
|
|
}
|
|
|
|
Indent--;
|
|
}
|
|
|
|
BOOL ExportFavorites(TCHAR * pszPathToFavorites, TCHAR * pszPathToBookmarks, HWND hwnd)
|
|
{
|
|
// Prompt the user to insert floppy, format floppy or drive, remount mapped partition,
|
|
// or any create sub directories so pszPathToBookmarks becomes valid.
|
|
if (FAILED(SHPathPrepareForWriteWrap(hwnd, NULL, pszPathToBookmarks, FO_COPY, (SHPPFW_DEFAULT | SHPPFW_IGNOREFILENAME))))
|
|
return FALSE;
|
|
|
|
// Open output file REVIEW redo to use Win32 file apis
|
|
g_hOutputStream = CreateFile(
|
|
pszPathToBookmarks,
|
|
GENERIC_WRITE,
|
|
0, // no sharing,
|
|
NULL, // no security attribs
|
|
CREATE_ALWAYS, // overwrite if present
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL);
|
|
|
|
if (g_hOutputStream == INVALID_HANDLE_VALUE)
|
|
return FALSE;
|
|
|
|
//
|
|
// Output bookmark file header stuff
|
|
//
|
|
Output(VALIDATION_STR);
|
|
OutputLn("1>");
|
|
OutputLn(COMMENT_STR);
|
|
OutputLn(TITLE); // REVIEW put/persist users name in Title???
|
|
|
|
//
|
|
// Do the walk
|
|
//
|
|
OutputLn("<DL><p>");
|
|
WalkTree(pszPathToFavorites);
|
|
OutputLn(BEGIN_EXITDIR_TOKEN);
|
|
|
|
//
|
|
// Close output file handle
|
|
//
|
|
CloseHandle(g_hOutputStream); // REVIEW
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// Import/Export User interface dialog routines
|
|
//
|
|
|
|
//
|
|
// Standalone app for importing the Netscape Favorites into IE.
|
|
//
|
|
// julianj 3/9/98
|
|
//
|
|
|
|
#ifdef _WIN32_WINNT
|
|
#undef _WIN32_WINNT
|
|
#endif
|
|
#ifdef _WIN32_WINDOWS
|
|
#undef _WIN32_WINDOWS
|
|
#endif
|
|
#ifdef WINVER
|
|
#undef WINVER
|
|
#endif
|
|
#define _WIN32_WINDOWS 0x0400
|
|
#define _WIN32_WINNT 0x0400
|
|
#define WINVER 0x0400
|
|
|
|
|
|
|
|
TCHAR g_szPathToFavorites[MAX_PATH+1];
|
|
TCHAR g_szPathToBookmarks[MAX_PATH+1];
|
|
LPITEMIDLIST g_pidlFavorites = NULL;
|
|
|
|
enum DIALOG_TYPE {FILE_OPEN_DIALOG, FILE_SAVE_DIALOG};
|
|
|
|
BOOL BrowseForBookmarks(TCHAR *pszPathToBookmarks, int cchPathToBookmarks, HWND hwnd, DIALOG_TYPE dialogType)
|
|
{
|
|
TCHAR szFile[MAX_PATH];
|
|
TCHAR szDir[MAX_PATH];
|
|
TCHAR *pszFileName = PathFindFileName(pszPathToBookmarks);
|
|
TCHAR szDialogTitle[MAX_PATH];
|
|
|
|
//
|
|
// Now copy the filename into the buffer for use with OpenFile
|
|
// and then copy szDir from path to bookmarks and truncate it at filename
|
|
// so it contains the initial working directory for the dialog
|
|
//
|
|
StrCpyN(szFile, pszFileName, ARRAYSIZE(szFile));
|
|
StrCpyN(szDir, pszPathToBookmarks, ARRAYSIZE(szDir));
|
|
szDir[pszFileName-pszPathToBookmarks] = TEXT('\0');
|
|
|
|
//
|
|
// Use common dialog code to get path to folder
|
|
//
|
|
TCHAR filter[] = TEXT("HTML File\0*.HTM\0All Files\0*.*\0");
|
|
OPENFILENAME ofn = {0};
|
|
ofn.lStructSize = sizeof(ofn);
|
|
ofn.hwndOwner = hwnd;
|
|
ofn.hInstance = HINST_THISDLL;
|
|
ofn.lpstrFilter = filter;
|
|
ofn.lpstrFile = szFile;
|
|
ofn.nMaxFile = ARRAYSIZE(szFile);
|
|
ofn.lpstrInitialDir = szDir;
|
|
ofn.lpstrDefExt = TEXT("htm");
|
|
|
|
if (dialogType == FILE_SAVE_DIALOG)
|
|
{
|
|
MLLoadString(IDS_EXPORTDIALOGTITLE, szDialogTitle, ARRAYSIZE(szDialogTitle));
|
|
|
|
ofn.lpstrTitle = szDialogTitle;
|
|
ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
|
|
if (GetSaveFileName(&ofn))
|
|
{
|
|
StrCpyN(pszPathToBookmarks, szFile, cchPathToBookmarks);
|
|
return TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MLLoadString(IDS_IMPORTDIALOGTITLE, szDialogTitle, ARRAYSIZE(szDialogTitle));
|
|
|
|
ofn.lpstrTitle = szDialogTitle;
|
|
ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
|
|
if (GetOpenFileName(&ofn))
|
|
{
|
|
StrCpyN(pszPathToBookmarks, szFile, cchPathToBookmarks);
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
HRESULT CreateILFromPath(LPCTSTR pszPath, LPITEMIDLIST* ppidl)
|
|
{
|
|
// ASSERT(pszPath);
|
|
// ASSERT(ppidl);
|
|
|
|
HRESULT hr;
|
|
|
|
IShellFolder* pIShellFolder;
|
|
|
|
hr = SHGetDesktopFolder(&pIShellFolder);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// ASSERT(pIShellFolder);
|
|
|
|
WCHAR wszPath[MAX_PATH];
|
|
|
|
if (SHTCharToUnicode(pszPath, wszPath, ARRAYSIZE(wszPath)))
|
|
{
|
|
ULONG ucch;
|
|
|
|
hr = pIShellFolder->ParseDisplayName(NULL, NULL, wszPath, &ucch,
|
|
ppidl, NULL);
|
|
}
|
|
else
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
pIShellFolder->Release();
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
#define REG_STR_IMPEXP TEXT("Software\\Microsoft\\Internet Explorer\\Main")
|
|
#define REG_STR_PATHTOFAVORITES TEXT("FavoritesImportFolder")
|
|
#define REG_STR_PATHTOBOOKMARKS TEXT("FavoritesExportFile")
|
|
#define REG_STR_DESKTOP TEXT("Desktop")
|
|
#define REG_STR_SHELLFOLDERS TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders")
|
|
|
|
#ifndef UNIX
|
|
#define STR_BOOKMARK_FILE TEXT("\\bookmark.htm")
|
|
#else
|
|
#define STR_BOOKMARK_FILE TEXT("/bookmark.html")
|
|
#endif
|
|
|
|
//
|
|
// InitializePaths
|
|
//
|
|
void InitializePaths()
|
|
{
|
|
//
|
|
// Read the Netscape users bookmark file location and the
|
|
// current users favorite path from registry
|
|
//
|
|
if (!GetNavBkMkDir(g_szPathToBookmarks, MAX_PATH))
|
|
{
|
|
//
|
|
// If Nav isn't installed then use the desktop
|
|
//
|
|
GetPathFromRegistry(g_szPathToBookmarks, MAX_PATH, HKEY_CURRENT_USER,
|
|
REG_STR_SHELLFOLDERS, REG_STR_DESKTOP);
|
|
StrCatBuff(g_szPathToBookmarks, STR_BOOKMARK_FILE, ARRAYSIZE(g_szPathToBookmarks));
|
|
}
|
|
|
|
GetTargetFavoritesPath(g_szPathToFavorites, MAX_PATH);
|
|
|
|
if (FAILED(CreateILFromPath(g_szPathToFavorites, &g_pidlFavorites)))
|
|
g_pidlFavorites = NULL;
|
|
|
|
//
|
|
// Now override these values with values stored in the registry just for
|
|
// this tool, so if the user consistently wants to save their favorites
|
|
// out to a separate .HTM file its easy to do
|
|
//
|
|
HKEY hKey;
|
|
DWORD dwSize;
|
|
DWORD dwType;
|
|
|
|
if (RegOpenKeyEx(HKEY_CURRENT_USER, REG_STR_IMPEXP, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
|
|
{
|
|
// dsheldon: Setting dwType before RegQueryValueEx doesn't do anything. Should we check it afterwards?
|
|
dwSize = sizeof g_szPathToBookmarks;
|
|
dwType = REG_SZ;
|
|
RegQueryValueEx(hKey, REG_STR_PATHTOBOOKMARKS, 0, &dwType, (LPBYTE)g_szPathToBookmarks, &dwSize);
|
|
|
|
dwSize = sizeof g_szPathToFavorites;
|
|
dwType = REG_SZ;
|
|
RegQueryValueEx(hKey, REG_STR_PATHTOFAVORITES, 0, &dwType, (LPBYTE)g_szPathToFavorites, &dwSize);
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
}
|
|
|
|
void PersistPaths()
|
|
{
|
|
HKEY hKey;
|
|
DWORD dwDisp;
|
|
|
|
if (RegCreateKeyEx(HKEY_CURRENT_USER, REG_STR_IMPEXP, 0, NULL, 0, KEY_SET_VALUE, NULL, &hKey, &dwDisp) == ERROR_SUCCESS)
|
|
{
|
|
RegSetValueEx(hKey, REG_STR_PATHTOBOOKMARKS, 0, REG_SZ, (LPBYTE)g_szPathToBookmarks, (lstrlen(g_szPathToBookmarks)+1)*sizeof(TCHAR));
|
|
RegSetValueEx(hKey, REG_STR_PATHTOFAVORITES, 0, REG_SZ, (LPBYTE)g_szPathToFavorites, (lstrlen(g_szPathToFavorites)+1)*sizeof(TCHAR));
|
|
RegCloseKey(hKey);
|
|
}
|
|
}
|
|
|
|
#define REG_STR_IE_POLICIES TEXT("Software\\Policies\\Microsoft\\Internet Explorer")
|
|
#define REG_STR_IMPEXP_POLICIES TEXT("DisableImportExportFavorites")
|
|
|
|
BOOL IsImportExportDisabled(void)
|
|
{
|
|
HKEY hKey;
|
|
DWORD dwSize = sizeof(DWORD);
|
|
DWORD dwType;
|
|
DWORD value = 0;
|
|
BOOL bret = FALSE;
|
|
|
|
if (RegOpenKeyEx(HKEY_CURRENT_USER, REG_STR_IE_POLICIES, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
|
|
{
|
|
if (RegQueryValueEx(hKey, REG_STR_IMPEXP_POLICIES, 0, &dwType, (PBYTE)&value, &dwSize) == ERROR_SUCCESS &&
|
|
(dwType == REG_BINARY || dwType == REG_DWORD))
|
|
bret = (value) ? TRUE : FALSE;
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
return bret;
|
|
}
|
|
|
|
void DoImportOrExport(BOOL fImport, LPCWSTR pwszPath, LPCWSTR pwszImpExpPath, BOOL fConfirm)
|
|
{
|
|
BOOL fRemote = FALSE;
|
|
HWND hwnd = NULL;
|
|
TCHAR szImpExpPath[INTERNET_MAX_URL_LENGTH];
|
|
|
|
//
|
|
// REVIEW should this be passed in...
|
|
//
|
|
hwnd = GetActiveWindow();
|
|
|
|
// Decide if import/export is allowed here
|
|
if (IsImportExportDisabled())
|
|
{
|
|
MLShellMessageBox(
|
|
hwnd,
|
|
(fImport) ? MAKEINTRESOURCE(IDS_IMPORT_DISABLED) :
|
|
MAKEINTRESOURCE(IDS_EXPORT_DISABLED),
|
|
(fImport) ? MAKEINTRESOURCE(IDS_CONFIRM_IMPTTL_FAV) :
|
|
MAKEINTRESOURCE(IDS_CONFIRM_EXPTTL_FAV),
|
|
MB_OK);
|
|
return;
|
|
}
|
|
|
|
|
|
InitializePaths();
|
|
|
|
//
|
|
// Overwrite path to favorites with passed in one if present
|
|
//
|
|
if (pwszPath && *pwszPath != 0)
|
|
{
|
|
SHUnicodeToTChar(pwszPath, g_szPathToFavorites, ARRAYSIZE(g_szPathToFavorites));
|
|
}
|
|
|
|
//
|
|
// Decide if we export/import to/from an URL? or a file
|
|
// (we expect pwszImpExpPath an absolute path)
|
|
// if it's not a valid URL or filename, we give error message and bail out
|
|
//
|
|
if (pwszImpExpPath && *pwszImpExpPath != 0)
|
|
{
|
|
SHUnicodeToTChar(pwszImpExpPath, szImpExpPath, ARRAYSIZE(szImpExpPath));
|
|
|
|
if (PathIsURL(pwszImpExpPath))
|
|
{
|
|
|
|
TCHAR szDialogTitle[MAX_PATH];
|
|
TCHAR szfmt[MAX_PATH], szmsg[MAX_PATH+INTERNET_MAX_URL_LENGTH];
|
|
fRemote = TRUE;
|
|
|
|
if (fImport)
|
|
{
|
|
if (fConfirm)
|
|
{
|
|
//
|
|
// Show confirmation UI when importing over internet
|
|
//
|
|
MLLoadShellLangString(IDS_CONFIRM_IMPTTL_FAV, szDialogTitle, ARRAYSIZE(szDialogTitle));
|
|
MLLoadShellLangString(IDS_CONFIRM_IMPORT, szfmt, ARRAYSIZE(szfmt));
|
|
wnsprintf(szmsg, ARRAYSIZE(szmsg), szfmt, szImpExpPath);
|
|
if (MLShellMessageBox(hwnd, szmsg, szDialogTitle,
|
|
MB_YESNO | MB_ICONQUESTION) == IDNO)
|
|
return;
|
|
}
|
|
// download imported file to cache
|
|
|
|
if ( (IsGlobalOffline() && !InternetGoOnline(g_szPathToBookmarks,hwnd,0)) ||
|
|
FAILED(URLDownloadToCacheFile(NULL, szImpExpPath, g_szPathToBookmarks, MAX_PATH, 0, NULL)))
|
|
{
|
|
MLShellMessageBox(
|
|
hwnd,
|
|
MAKEINTRESOURCE(IDS_IMPORTFAILURE_FAV),
|
|
MAKEINTRESOURCE(IDS_CONFIRM_IMPTTL_FAV),
|
|
MB_OK);
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (fConfirm)
|
|
{
|
|
//
|
|
// Show confirmation UI when exporting over internet
|
|
//
|
|
MLLoadShellLangString(IDS_CONFIRM_EXPTTL_FAV, szDialogTitle, ARRAYSIZE(szDialogTitle));
|
|
MLLoadShellLangString(IDS_CONFIRM_EXPORT, szfmt, ARRAYSIZE(szfmt));
|
|
wnsprintf(szmsg, ARRAYSIZE(szmsg), szfmt, szImpExpPath);
|
|
if (MLShellMessageBox(hwnd, szmsg, szDialogTitle,
|
|
MB_YESNO | MB_ICONQUESTION) == IDNO)
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Create bookmark file name from bookmark directory with favorite name so we can export
|
|
// favorites to local file before posting to URL
|
|
//
|
|
TCHAR *pszFav = PathFindFileName(g_szPathToFavorites);
|
|
TCHAR *pszBMD = PathFindFileName(g_szPathToBookmarks);
|
|
if (pszFav && pszBMD)
|
|
{
|
|
StrCpyN(pszBMD, pszFav, ARRAYSIZE(g_szPathToBookmarks) - ((int)(pszBMD - g_szPathToBookmarks)));
|
|
StrCatBuff(pszBMD, TEXT(".htm"), ARRAYSIZE(g_szPathToBookmarks) - ((int)(pszBMD - g_szPathToBookmarks)));
|
|
}
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
if (fConfirm)
|
|
{
|
|
TCHAR szDialogTitle[MAX_PATH];
|
|
TCHAR szfmt[MAX_PATH], szmsg[MAX_PATH+INTERNET_MAX_URL_LENGTH];
|
|
|
|
if (fImport)
|
|
{
|
|
//
|
|
// Show confirmation UI when importing
|
|
//
|
|
MLLoadShellLangString(IDS_CONFIRM_IMPTTL_FAV, szDialogTitle, ARRAYSIZE(szDialogTitle));
|
|
MLLoadShellLangString(IDS_CONFIRM_IMPORT, szfmt, ARRAYSIZE(szfmt));
|
|
wnsprintf(szmsg, ARRAYSIZE(szmsg), szfmt, szImpExpPath);
|
|
if (MLShellMessageBox(hwnd, szmsg, szDialogTitle,
|
|
MB_YESNO | MB_ICONQUESTION) == IDNO)
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Show confirmation UI when exporting.
|
|
//
|
|
MLLoadShellLangString(IDS_CONFIRM_EXPTTL_FAV, szDialogTitle, ARRAYSIZE(szDialogTitle));
|
|
MLLoadShellLangString(IDS_CONFIRM_EXPORT, szfmt, ARRAYSIZE(szfmt));
|
|
wnsprintf(szmsg, ARRAYSIZE(szmsg), szfmt, szImpExpPath);
|
|
if (MLShellMessageBox(hwnd, szmsg, szDialogTitle,
|
|
MB_YESNO | MB_ICONQUESTION) == IDNO)
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (PathFindFileName(szImpExpPath) != szImpExpPath)
|
|
{
|
|
|
|
//override path to bookmarks with passed in one
|
|
StrCpyN(g_szPathToBookmarks, szImpExpPath, ARRAYSIZE(g_szPathToBookmarks));
|
|
|
|
}
|
|
else
|
|
{
|
|
MLShellMessageBox(
|
|
hwnd,
|
|
MAKEINTRESOURCE(IDS_IMPORTFAILURE_FAV),
|
|
MAKEINTRESOURCE(IDS_CONFIRM_IMPTTL_FAV),
|
|
MB_OK);
|
|
return;
|
|
}
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (fImport)
|
|
{
|
|
//
|
|
// Do Import Favorites UI
|
|
//
|
|
if (!BrowseForBookmarks(g_szPathToBookmarks, ARRAYSIZE(g_szPathToBookmarks), hwnd, FILE_OPEN_DIALOG))
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Do Export Favorites UI
|
|
//
|
|
if (!BrowseForBookmarks(g_szPathToBookmarks, ARRAYSIZE(g_szPathToBookmarks), hwnd, FILE_SAVE_DIALOG))
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (fImport)
|
|
{
|
|
if (ImportBookmarks(g_szPathToFavorites, g_szPathToBookmarks, hwnd))
|
|
{
|
|
MLShellMessageBox(
|
|
hwnd,
|
|
MAKEINTRESOURCE(IDS_IMPORTSUCCESS_FAV),
|
|
MAKEINTRESOURCE(IDS_CONFIRM_IMPTTL_FAV),
|
|
MB_OK);
|
|
#ifdef UNIX
|
|
SHChangeNotify(SHCNE_UPDATEDIR, SHCNF_PATH | SHCNF_FLUSH, g_szPathToFavorites, 0);
|
|
#endif
|
|
if (!fRemote)
|
|
PersistPaths();
|
|
}
|
|
else
|
|
{
|
|
; // ImportBookmarks will report errors
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ExportFavorites(g_szPathToFavorites, g_szPathToBookmarks, hwnd))
|
|
{
|
|
if (fRemote)
|
|
{
|
|
if ( (!IsGlobalOffline() || InternetGoOnline(g_szPathToBookmarks,hwnd,0)) &&
|
|
PostFavorites(g_szPathToBookmarks, szImpExpPath))
|
|
{
|
|
MLShellMessageBox(
|
|
hwnd,
|
|
MAKEINTRESOURCE(IDS_EXPORTSUCCESS_FAV),
|
|
MAKEINTRESOURCE(IDS_CONFIRM_EXPTTL_FAV),
|
|
MB_OK);
|
|
}
|
|
else
|
|
MLShellMessageBox(
|
|
hwnd,
|
|
MAKEINTRESOURCE(IDS_EXPORTFAILURE_FAV),
|
|
MAKEINTRESOURCE(IDS_CONFIRM_EXPTTL_FAV),
|
|
MB_OK);
|
|
|
|
//Remove temp file on local disk
|
|
DeleteFile(g_szPathToBookmarks);
|
|
}
|
|
else
|
|
{
|
|
MLShellMessageBox(
|
|
hwnd,
|
|
MAKEINTRESOURCE(IDS_EXPORTSUCCESS_FAV),
|
|
MAKEINTRESOURCE(IDS_CONFIRM_EXPTTL_FAV),
|
|
MB_OK);
|
|
PersistPaths();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MLShellMessageBox(
|
|
hwnd,
|
|
MAKEINTRESOURCE(IDS_EXPORTFAILURE_FAV),
|
|
MAKEINTRESOURCE(IDS_CONFIRM_EXPTTL_FAV),
|
|
MB_OK);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// *** POST FAVORITES HTML FILE ***
|
|
//
|
|
HINTERNET g_hInternet = 0;
|
|
HINTERNET g_hConnect = 0;
|
|
HINTERNET g_hHttpRequest = 0;
|
|
|
|
HANDLE g_hEvent = NULL;
|
|
|
|
typedef struct AsyncRes
|
|
{
|
|
DWORD_PTR Result;
|
|
DWORD_PTR Error;
|
|
} ASYNCRES;
|
|
|
|
#define STR_USERAGENT "PostFavorites"
|
|
|
|
void CloseRequest(void)
|
|
{
|
|
if (g_hHttpRequest)
|
|
InternetCloseHandle(g_hHttpRequest);
|
|
if (g_hConnect)
|
|
InternetCloseHandle(g_hConnect);
|
|
if (g_hInternet)
|
|
InternetCloseHandle(g_hInternet);
|
|
|
|
g_hInternet = g_hConnect = g_hHttpRequest = 0;
|
|
|
|
}
|
|
|
|
HRESULT InitRequest(LPSTR pszPostURL, BOOL bAsync, ASYNCRES *pasyncres)
|
|
{
|
|
char hostName[INTERNET_MAX_HOST_NAME_LENGTH+1];
|
|
char userName[INTERNET_MAX_USER_NAME_LENGTH+1];
|
|
char password[INTERNET_MAX_PASSWORD_LENGTH+1];
|
|
char urlPath[INTERNET_MAX_PATH_LENGTH+1];
|
|
URL_COMPONENTSA uc;
|
|
|
|
memset(&uc, 0, sizeof(URL_COMPONENTS));
|
|
uc.dwStructSize = sizeof(URL_COMPONENTS);
|
|
uc.lpszHostName = hostName;
|
|
uc.dwHostNameLength = sizeof(hostName);
|
|
uc.nPort = INTERNET_INVALID_PORT_NUMBER;
|
|
uc.lpszUserName = userName;
|
|
uc.dwUserNameLength = sizeof(userName);
|
|
uc.lpszPassword = password;
|
|
uc.dwPasswordLength = sizeof(password);
|
|
uc.lpszUrlPath = urlPath;
|
|
uc.dwUrlPathLength = sizeof(urlPath);
|
|
|
|
if (!InternetCrackUrlA(pszPostURL,lstrlenA(pszPostURL),ICU_DECODE, &uc))
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
if (bAsync)
|
|
{
|
|
// Create an auto-reset event
|
|
g_hEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
|
|
if (g_hEvent == NULL)
|
|
bAsync = FALSE;
|
|
}
|
|
|
|
g_hInternet = InternetOpenA(STR_USERAGENT, // used in User-Agent: header
|
|
INTERNET_OPEN_TYPE_PRECONFIG, //INTERNET_OPEN_TYPE_DIRECT,
|
|
NULL,
|
|
NULL,
|
|
(bAsync) ? INTERNET_FLAG_ASYNC : 0
|
|
);
|
|
|
|
if ( !g_hInternet )
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
if (bAsync)
|
|
{
|
|
if (INTERNET_INVALID_STATUS_CALLBACK == InternetSetStatusCallbackA(g_hInternet, StatusCallback))
|
|
return E_FAIL;
|
|
}
|
|
|
|
// Connect to host
|
|
g_hConnect = InternetConnectA(g_hInternet,
|
|
uc.lpszHostName,
|
|
uc.nPort, //INTERNET_INVALID_PORT_NUMBER,
|
|
uc.lpszUserName,
|
|
uc.lpszPassword,
|
|
INTERNET_SERVICE_HTTP,
|
|
0, //INTERNET_FLAG_KEEP_CONNECTION,
|
|
(bAsync)? (DWORD_PTR) pasyncres : 0);
|
|
|
|
if ( !g_hConnect )
|
|
{
|
|
if (bAsync && GetLastError() == ERROR_IO_PENDING)
|
|
{
|
|
WaitForSingleObject(g_hEvent, INFINITE);
|
|
if (pasyncres->Result == 0)
|
|
return E_FAIL;
|
|
|
|
g_hConnect = (HINTERNET)pasyncres->Result;
|
|
}
|
|
else
|
|
return E_FAIL;
|
|
}
|
|
|
|
// Create request.
|
|
g_hHttpRequest = HttpOpenRequestA
|
|
(
|
|
g_hConnect,
|
|
"POST",
|
|
uc.lpszUrlPath,
|
|
HTTP_VERSIONA,
|
|
NULL, //lpszReferer
|
|
NULL, //lpszAcceptTypes
|
|
INTERNET_FLAG_RELOAD
|
|
| INTERNET_FLAG_KEEP_CONNECTION
|
|
| SECURITY_INTERNET_MASK, // ignore SSL warnings
|
|
(bAsync)? (DWORD_PTR) pasyncres : 0);
|
|
|
|
|
|
if ( !g_hHttpRequest )
|
|
{
|
|
if (bAsync && GetLastError() == ERROR_IO_PENDING)
|
|
{
|
|
WaitForSingleObject(g_hEvent, INFINITE);
|
|
if (pasyncres->Result == 0)
|
|
return E_FAIL;
|
|
|
|
g_hHttpRequest = (HINTERNET)pasyncres->Result;
|
|
}
|
|
else
|
|
return E_FAIL;
|
|
}
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
const char c_szHeaders[] = "Content-Type: application/x-www-form-urlencoded\r\n";
|
|
#define c_ccHearders (ARRAYSIZE(c_szHeaders) - 1)
|
|
|
|
BOOL AddRequestHeaders
|
|
(
|
|
LPCSTR lpszHeaders,
|
|
DWORD dwHeadersLength,
|
|
DWORD dwAddFlag,
|
|
BOOL bAsync,
|
|
ASYNCRES *pasyncres
|
|
)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
|
|
bRet = HttpAddRequestHeadersA(g_hHttpRequest,
|
|
lpszHeaders,
|
|
dwHeadersLength,
|
|
HTTP_ADDREQ_FLAG_ADD | dwAddFlag);
|
|
|
|
if (bAsync && !bRet && GetLastError() == ERROR_IO_PENDING)
|
|
{
|
|
WaitForSingleObject(g_hEvent, INFINITE);
|
|
bRet = (BOOL)pasyncres->Result;
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
HRESULT SendRequest
|
|
(
|
|
LPCSTR lpszHeaders,
|
|
DWORD dwHeadersLength,
|
|
LPCSTR lpszOption,
|
|
DWORD dwOptionLength,
|
|
BOOL bAsync,
|
|
ASYNCRES *pasyncres
|
|
)
|
|
{
|
|
BOOL bRet=FALSE;
|
|
|
|
bRet = AddRequestHeaders((LPCSTR)c_szHeaders, (DWORD)-1L, 0, bAsync, pasyncres);
|
|
|
|
if (lpszHeaders && *lpszHeaders) // don't bother if it's empty
|
|
{
|
|
|
|
bRet = AddRequestHeaders(
|
|
(LPCSTR)lpszHeaders,
|
|
dwHeadersLength,
|
|
HTTP_ADDREQ_FLAG_REPLACE,
|
|
bAsync,
|
|
pasyncres);
|
|
if ( !bRet )
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
}
|
|
|
|
pasyncres->Result = 0;
|
|
|
|
bRet = HttpSendRequestA(g_hHttpRequest,
|
|
NULL, //HEADER_ENCTYPE,
|
|
0, //sizeof(HEADER_ENCTYPE),
|
|
(LPVOID)lpszOption,
|
|
dwOptionLength);
|
|
|
|
if ( !bRet )
|
|
{
|
|
DWORD_PTR dwLastError = GetLastError();
|
|
if (bAsync && dwLastError == ERROR_IO_PENDING)
|
|
{
|
|
WaitForSingleObject(g_hEvent, INFINITE);
|
|
dwLastError = pasyncres->Error;
|
|
bRet = (BOOL)pasyncres->Result;
|
|
if (!bRet)
|
|
{
|
|
TraceMsg(DM_ERROR, "Async HttpSendRequest returned FALSE");
|
|
if (dwLastError != ERROR_SUCCESS)
|
|
{
|
|
TraceMsg(DM_ERROR, "Async HttpSendRequest failed: Error = %lx", dwLastError);
|
|
return E_FAIL;
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
TraceMsg(DM_ERROR, "HttpSendRequest failed: Error = %lx", dwLastError);
|
|
return E_FAIL;
|
|
}
|
|
}
|
|
|
|
//
|
|
//verify request response here
|
|
//
|
|
DWORD dwBuffLen;
|
|
TCHAR buff[10];
|
|
|
|
dwBuffLen = sizeof(buff);
|
|
|
|
bRet = HttpQueryInfo(g_hHttpRequest,
|
|
HTTP_QUERY_STATUS_CODE, //HTTP_QUERY_RAW_HEADERS,
|
|
buff,
|
|
&dwBuffLen,
|
|
NULL);
|
|
|
|
int iretcode = StrToInt(buff);
|
|
TraceMsg(DM_TRACE, "HttpQueryInfo returned %d", iretcode);
|
|
return (iretcode == HTTP_STATUS_OK) ?
|
|
S_OK : E_FAIL;
|
|
|
|
}
|
|
|
|
DWORD ReadFavoritesFile(LPCTSTR lpFile, LPSTR* lplpbuf)
|
|
{
|
|
HANDLE hFile = NULL;
|
|
DWORD cbFile = 0;
|
|
DWORD cbRead;
|
|
|
|
hFile = CreateFile(lpFile,
|
|
GENERIC_READ,
|
|
0, //no sharing
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL);
|
|
|
|
if (hFile == INVALID_HANDLE_VALUE)
|
|
return 0;
|
|
|
|
cbFile = GetFileSize(hFile, NULL);
|
|
if (cbFile == 0xFFFFFFFF)
|
|
{
|
|
CloseHandle(hFile);
|
|
return 0;
|
|
}
|
|
|
|
*lplpbuf = (LPSTR)GlobalAlloc(LPTR, (cbFile + 2) * sizeof(CHAR));
|
|
cbRead = 0;
|
|
if (!*lplpbuf || !ReadFile(hFile, *lplpbuf, cbFile, &cbRead, NULL))
|
|
{
|
|
cbRead = 0;
|
|
}
|
|
|
|
ASSERT((cbRead == cbFile));
|
|
CloseHandle(hFile);
|
|
return cbRead;
|
|
}
|
|
|
|
|
|
BOOL PostFavorites(TCHAR *pszPathToBookmarks, TCHAR* pszPathToPost)
|
|
{
|
|
DWORD cbRead = 0;
|
|
LPSTR lpbuf = NULL;
|
|
BOOL bret = FALSE;
|
|
BOOL bAsync = TRUE;
|
|
CHAR szPathToPost[INTERNET_MAX_URL_LENGTH];
|
|
ASYNCRES asyncres = {0, 0};
|
|
|
|
cbRead = ReadFavoritesFile(pszPathToBookmarks, &lpbuf);
|
|
if (cbRead == 0)
|
|
{
|
|
if (lpbuf)
|
|
{
|
|
GlobalFree(lpbuf);
|
|
lpbuf = NULL;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
SHTCharToAnsi(pszPathToPost, szPathToPost, ARRAYSIZE(szPathToPost));
|
|
if (SUCCEEDED(InitRequest(szPathToPost, bAsync, &asyncres)))
|
|
{
|
|
bret = (SUCCEEDED(SendRequest(NULL, lstrlenA(""), lpbuf, cbRead, bAsync, &asyncres)));
|
|
}
|
|
|
|
CloseRequest();
|
|
|
|
if (lpbuf)
|
|
{
|
|
GlobalFree( lpbuf );
|
|
lpbuf = NULL;
|
|
}
|
|
|
|
return bret;
|
|
}
|
|
|
|
//
|
|
// Callback function for Asynchronous HTTP POST request
|
|
//
|
|
void CALLBACK StatusCallback(
|
|
HINTERNET hInternet,
|
|
DWORD_PTR dwContext,
|
|
DWORD dwStatus,
|
|
LPVOID lpvInfo,
|
|
DWORD dwInfoLength
|
|
)
|
|
{
|
|
switch (dwStatus)
|
|
{
|
|
|
|
case INTERNET_STATUS_REQUEST_COMPLETE:
|
|
{
|
|
ASYNCRES *pasyncres = (ASYNCRES *)dwContext;
|
|
|
|
pasyncres->Result = ((LPINTERNET_ASYNC_RESULT)lpvInfo)->dwResult;
|
|
pasyncres->Error = ((LPINTERNET_ASYNC_RESULT)lpvInfo)->dwError;
|
|
|
|
SetEvent(g_hEvent);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|