gecko-dev/cmd/winfe/ownedlst.cpp
1998-03-28 02:44:41 +00:00

703 lines
21 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "stdafx.h"
#include "helper.h"
#include "ownedlst.h"
#include "ngdwtrst.h"
#include "mozilla.h"
#include "shcut.h"
// Registry key constants
static const CString strMARKUP_KEY = "NetscapeMarkup";
static const CString strOPEN_CMD_FMT = "%s\\shell\\open\\command";
static const CString strDDE_EXEC_FMT = "%s\\shell\\open\\ddeexec";
static const CString strDDE_APP_FMT = "%s\\shell\\open\\ddeexec\\Application";
static const CString strDDE_APP_NAME = "NSShell";
static const CString strDDE_OLDAPP_NAME = "Netscape";
static const CString strDEF_ICON_FMT = "%s\\DefaultIcon";
static const CString strDDE_EXEC_VALUE = "%1";
static const CString strDDE_TOPIC_FMT = "%s\\shell\\open\\ddeexec\\Topic";
static const CString strEDIT_CMD_FMT = "%s\\shell\\edit\\command";
COwnedLostItem::COwnedLostItem(CString mimeType)
:m_csMimeType(mimeType), m_bIgnored(FALSE), m_bBroken(FALSE)
{
SetHandledViaNetscape();
}
COwnedLostItem::COwnedLostItem(CString mimeType, CString ignored)
:m_csMimeType(mimeType), m_bBroken(FALSE)
{
m_bIgnored = (ignored == "Ignored");
SetHandledViaNetscape();
}
void COwnedLostItem::GiveControlToNetscape()
{
char buffer[_MAX_PATH];
::GetModuleFileName(theApp.m_hInstance, buffer, _MAX_PATH);
// Get the app's directory into a short file name
char shortBuffer[_MAX_PATH];
GetShortPathName(buffer, shortBuffer, _MAX_PATH);
CString directoryName(shortBuffer);
directoryName.MakeUpper(); // This is what we'll write to the registry
CString strValueName, strCmdPath;
// Special Internet Shortcut check
if (IsInternetShortcut())
{
CInternetShortcut internetShortcut;
if (internetShortcut.ShellSupport())
{
// Need to take over lots of stuff
CString strType = GetInternetShortcutFileClass();
// Set the open command path
strValueName.Format(strOPEN_CMD_FMT, (const char *)strType);
strCmdPath = directoryName + " -h \"%1\"";
FEU_RegistryWizard(HKEY_CLASSES_ROOT, strValueName, strCmdPath);
// Set the DDE exec value
strValueName.Format(strDDE_EXEC_FMT, (const char *)strType);
FEU_RegistryWizard(HKEY_CLASSES_ROOT, strValueName, strDDE_EXEC_VALUE);
// Set the DDE app name
strValueName.Format(strDDE_APP_FMT, (const char *)strType);
FEU_RegistryWizard(HKEY_CLASSES_ROOT, strValueName, strDDE_APP_NAME);
// Set the DDE topic
strValueName.Format(strDDE_TOPIC_FMT, (const char *)strType);
CString strDDETopic;
strDDETopic.LoadString(IDS_DDE_OPENURL);
FEU_RegistryWizard(HKEY_CLASSES_ROOT, strValueName, strDDETopic);
// Set the Default Icon
CString strIconPath;
if ((strType == "news") || (strType == "snews"))
{
// Use the news icon from URL.DLL
::GetSystemDirectory(buffer, _MAX_PATH);
strIconPath = CString(buffer) + "\\URL.DLL,1";
}
else
{
// Use the document icon
strIconPath = CString(buffer) + ",1";
}
strValueName.Format(strDEF_ICON_FMT, (const char *)strType);
FEU_RegistryWizard(HKEY_CLASSES_ROOT, strValueName, strIconPath);
// Take over printing (applies to ALL Internet Shortcuts. If we own one, we'll take
// over printing for ALL of them).
CString csMunge = directoryName + " /print(\"%1\")";
FEU_RegistryWizard(HKEY_CLASSES_ROOT, "InternetShortcut\\shell\\print\\command", csMunge);
FEU_RegistryWizard(HKEY_CLASSES_ROOT, "InternetShortcut\\shell\\print\\ddeexec", "[print(\"%1\")]");
FEU_RegistryWizard(HKEY_CLASSES_ROOT, "InternetShortcut\\shell\\print\\ddeexec\\Application", strDDE_APP_NAME);
// The PrintTo Command.
csMunge = directoryName + " /printto(\"%1\",\"%2\",\"%3\",\"%4\")";
FEU_RegistryWizard(HKEY_CLASSES_ROOT, "InternetShortcut\\shell\\PrintTo\\command", csMunge);
FEU_RegistryWizard(HKEY_CLASSES_ROOT, "InternetShortcut\\shell\\PrintTo\\ddeexec", "[printto(\"%1\",\"%2\",\"%3\",\"%4\")]");
FEU_RegistryWizard(HKEY_CLASSES_ROOT, "InternetShortcut\\shell\\PrintTo\\ddeexec\\Application", strDDE_APP_NAME);
}
return;
}
CPtrList* allHelpers = &(CHelperApp::m_cplHelpers);
for (POSITION pos = allHelpers->GetHeadPosition(); pos != NULL;)
{
CHelperApp* app = (CHelperApp*)allHelpers->GetNext(pos);
CString helperMime(app->cd_item->ci.type);
if (helperMime == m_csMimeType)
{
// Found the helper app. Get the file class.
CString fileClass(app->strFileClass);
if (fileClass != "")
{
// We have some registry work to do.
// In the case where this is text/html, we point .htm and .html to
// NetscapeMarkup.
HKEY hKey;
DWORD dwDisp;
if (m_csMimeType == "text/html")
{
::RegCreateKeyEx(HKEY_CLASSES_ROOT,
".htm", 0L, NULL,
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
&hKey, &dwDisp);
::RegSetValueEx(hKey, NULL, 0L, REG_SZ,
(const BYTE *)((const char *)strMARKUP_KEY),
strMARKUP_KEY.GetLength() + 1);
::RegCloseKey(hKey);
::RegCreateKeyEx(HKEY_CLASSES_ROOT,
".html", 0L, NULL,
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
&hKey, &dwDisp);
::RegSetValueEx(hKey, NULL, 0L, REG_SZ,
(const BYTE *)((const char *)strMARKUP_KEY),
strMARKUP_KEY.GetLength() + 1);
::RegCloseKey(hKey);
}
// In the case where this is application/x-unknown-content-type-NetscapeMarkup,
// we point .shtml to NetscapeMarkup.
else if (m_csMimeType == "application/x-unknown-content-type-NetscapeMarkup")
{
::RegCreateKeyEx(HKEY_CLASSES_ROOT,
".shtml", 0L, NULL,
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
&hKey, &dwDisp);
::RegSetValueEx(hKey, NULL, 0L, REG_SZ,
(const BYTE *)((const char *)strMARKUP_KEY),
strMARKUP_KEY.GetLength() + 1);
::RegCloseKey(hKey);
}
// In all other cases, we should use the existing file class
else
{
// Need to take over lots of stuff
CString strType = fileClass;
if (strType == "NetscapeMarkup")
return; // Don't let ANYTHING mess with NetscapeMarkup.
// Someone might point something to it later, and
// we don't want this code changing the stuff that's already there.
// Set the open command path
strValueName.Format(strOPEN_CMD_FMT, (const char *)strType);
strCmdPath = directoryName + " \"%1\"";
FEU_RegistryWizard(HKEY_CLASSES_ROOT, strValueName, strCmdPath);
// Set the DDE exec value
strValueName.Format(strDDE_EXEC_FMT, (const char *)strType);
FEU_RegistryWizard(HKEY_CLASSES_ROOT, strValueName, strDDE_EXEC_VALUE);
// Set the DDE app name
strValueName.Format(strDDE_APP_FMT, (const char *)strType);
FEU_RegistryWizard(HKEY_CLASSES_ROOT, strValueName, strDDE_APP_NAME);
// Set the DDE topic
strValueName.Format(strDDE_TOPIC_FMT, (const char *)strType);
CString strDDETopic;
strDDETopic.LoadString(IDS_DDE_OPENURL);
FEU_RegistryWizard(HKEY_CLASSES_ROOT, strValueName, strDDETopic);
// Set the Default Icon
CString strIconPath;
CString iconString = ",1";
if (m_csMimeType == "text/x-javascript" || m_csMimeType == "application/x-javascript")
iconString = ",7";
else if (m_csMimeType.Left(5) == "image")
iconString = ",6";
strIconPath = CString(buffer) + iconString;
strValueName.Format(strDEF_ICON_FMT, (const char *)strType);
FEU_RegistryWizard(HKEY_CLASSES_ROOT, strValueName, strIconPath);
}
}
return;
}
}
}
void COwnedLostItem::SetHandledViaNetscape()
{
m_nHandleMethod = OL_OTHER_APP;
// Get the app's name.
CString netscapeName;
char buffer[_MAX_PATH+1];
::GetModuleFileName(theApp.m_hInstance, buffer, _MAX_PATH);
char *pSlash = ::strrchr(buffer, '\\');
netscapeName = (char*)(pSlash+1);
netscapeName.MakeUpper();
// Get the app's directory. Adequate heuristic for version-checking Netscape
CString directoryName(buffer);
directoryName.MakeUpper();
// Special Internet Shortcut check
if (IsInternetShortcut())
{
CInternetShortcut internetShortcut;
if (!internetShortcut.ShellSupport())
{
m_nHandleMethod = OL_CURRENT_NETSCAPE;
return;
}
CString fileClass = GetInternetShortcutFileClass();
SetHandleMethodViaFileClass(fileClass, netscapeName, directoryName);
return;
}
CPtrList* allHelpers = &(CHelperApp::m_cplHelpers);
for (POSITION pos = allHelpers->GetHeadPosition(); pos != NULL;)
{
CHelperApp* app = (CHelperApp*)allHelpers->GetNext(pos);
CString helperMime(app->cd_item->ci.type);
if (helperMime == m_csMimeType)
{
// Found the helper app. See if Netscape is truly handling this mime type.
CString fileClass(app->strFileClass);
if (fileClass != "")
{
SetHandleMethodViaFileClass(fileClass, netscapeName, directoryName);
return;
}
else m_bBroken = TRUE; // Treat as if ignored. Don't want to pop up a dialog over this.
if (app->how_handle == HANDLE_VIA_NETSCAPE)
m_nHandleMethod = OL_CURRENT_NETSCAPE;
else m_nHandleMethod = OL_OTHER_APP;
return;
}
}
m_bBroken = TRUE; // Didn't even find this mime type. Don't want to fool with it.
}
void COwnedLostItem::SetHandleMethodViaFileClass(const CString& fileClass,
const CString& netscapeName,
const CString& directoryName)
{
// We have a place to look in the registry
char lpszOpenCommand[_MAX_PATH+1];
CString theString = fileClass + "\\shell\\open\\command";
LONG size = _MAX_PATH;
if (::RegQueryValue(HKEY_CLASSES_ROOT, theString, lpszOpenCommand, &size) !=
ERROR_SUCCESS)
{
m_nHandleMethod = OL_OTHER_APP;
return;
}
CString openCommand(lpszOpenCommand);
openCommand.MakeUpper();
if (openCommand.Find(netscapeName) != -1)
{
// Handled by a version of Netscape.
char shortBuffer[_MAX_PATH];
GetShortPathName(directoryName, shortBuffer, _MAX_PATH);
CString shortName(shortBuffer);
shortName.MakeUpper();
if (openCommand.Find(directoryName) != -1 ||
openCommand.Find(shortName) != -1)
{
// Handled by current version.
m_nHandleMethod = OL_CURRENT_NETSCAPE;
}
else m_nHandleMethod = OL_OLD_NETSCAPE;
}
else m_nHandleMethod = OL_OTHER_APP;
}
CString COwnedLostItem::GetInternetShortcutFileClass()
{
int startIndex = m_csMimeType.Find('-');
int endIndex = m_csMimeType.ReverseFind('-');
return m_csMimeType.Mid(startIndex+1, endIndex-startIndex-1);
}
void COwnedLostItem::FetchPrettyName()
{
if (IsInternetShortcut())
m_csPrettyName = MakeInternetShortcutName();
CPtrList* allHelpers = &(CHelperApp::m_cplHelpers);
for (POSITION pos = allHelpers->GetHeadPosition(); pos != NULL;)
{
CHelperApp* app = (CHelperApp*)allHelpers->GetNext(pos);
CString helperMime(app->cd_item->ci.type);
if (helperMime == m_csMimeType)
{
CString returnString = app->cd_item->ci.desc;
if (returnString == "")
returnString = "File Type";
if (app->cd_item->num_exts > 0)
{
returnString += " (";
for (int i = 0; i < app->cd_item->num_exts; i++)
{
returnString += "*.";
returnString += app->cd_item->exts[i];
if (i < app->cd_item->num_exts-1)
returnString += "; ";
}
returnString += ")";
}
m_csPrettyName = returnString;
}
}
}
BOOL COwnedLostItem::IsInternetShortcut()
{
return (m_csMimeType == "application/x-http-protocol" ||
m_csMimeType == "application/x-https-protocol" ||
m_csMimeType == "application/x-ftp-protocol" ||
m_csMimeType == "application/x-news-protocol" ||
m_csMimeType == "application/x-snews-protocol" ||
m_csMimeType == "application/x-gopher-protocol");
}
CString COwnedLostItem::MakeInternetShortcutName()
{
CString protocolName = GetInternetShortcutFileClass();
protocolName.MakeUpper();
return protocolName + CString(" Internet Shortcuts");
}
// =====================================================================================
// COWNEDANDLOSTLIST
// =====================================================================================
COwnedAndLostList::~COwnedAndLostList()
{
int count = m_OwnedList.GetSize();
for (int i = 0; i < count; i++)
{
COwnedLostItem* theItem = (COwnedLostItem*)(m_OwnedList[0]);
m_OwnedList.RemoveAt(0);
delete theItem;
}
count = m_LostList.GetSize();
for (i = 0; i < count; i++)
{
COwnedLostItem* theItem = (COwnedLostItem*)(m_LostList[0]);
m_LostList.RemoveAt(0);
delete theItem;
}
}
void COwnedAndLostList::ConstructLists()
{
CString pathString;
pathString.LoadString(IDS_NETHELP_REGISTRY); // Software\Netscape\Netscape Navigator
// Read in the owned list
// Look for owned subkey
// If subkey exists, iterate over its subkeys and build the owned list
// If subkey does not exist, the owned list should contain a certain
// list of built-in types. These are the types that Netscape defends initially.
HKEY ownedKey, lostKey;
CString ownerPath = pathString + "Owned";
LONG result = ::RegOpenKey(HKEY_CURRENT_USER, ownerPath, &ownedKey);
// Prepopulate our list with some types we want to defend.
int dwIndex;
char nameBuffer[_MAX_PATH];
unsigned long nameBufferSize, valueBufferSize;
unsigned char valueBuffer[_MAX_PATH];
unsigned long typeCodeBuffer = 0;
if (result != ERROR_SUCCESS)
{
m_OwnedList.Add(new COwnedLostItem("text/html"));
m_OwnedList.Add(new COwnedLostItem("image/jpeg"));
m_OwnedList.Add(new COwnedLostItem("image/pjpeg"));
m_OwnedList.Add(new COwnedLostItem("image/gif"));
m_OwnedList.Add(new COwnedLostItem("application/x-javascript"));
m_OwnedList.Add(new COwnedLostItem("image/x-xbitmap"));
// Be prepared to defend Internet Shortcuts if they are ever installed
// later!
m_OwnedList.Add(new COwnedLostItem("application/x-http-protocol"));
m_OwnedList.Add(new COwnedLostItem("application/x-https-protocol"));
m_OwnedList.Add(new COwnedLostItem("application/x-news-protocol"));
m_OwnedList.Add(new COwnedLostItem("application/x-snews-protocol"));
m_OwnedList.Add(new COwnedLostItem("application/x-ftp-protocol"));
m_OwnedList.Add(new COwnedLostItem("application/x-gopher-protocol"));
}
else
{
// Read in the owned list
dwIndex = 0;
valueBufferSize = sizeof(valueBuffer);
nameBufferSize = sizeof(nameBuffer);
while (RegEnumValue(ownedKey, dwIndex, nameBuffer,
&nameBufferSize, NULL, &typeCodeBuffer, valueBuffer,
&valueBufferSize) != ERROR_NO_MORE_ITEMS)
{
m_OwnedList.Add(new COwnedLostItem(nameBuffer, valueBuffer));
dwIndex++;
valueBufferSize = sizeof(valueBuffer);
nameBufferSize = sizeof(nameBuffer);
}
}
// Read in the lost list
// Look for lost subkey
// If subkey exists, iterate over its subkeys and build the lost list
// If subkey does not exist, the lost list is initially empty. Do nothing.
CString lostPath = pathString + "Lost";
result = ::RegOpenKey(HKEY_CURRENT_USER, lostPath, &lostKey);
if (result == ERROR_SUCCESS)
{
// Read in the lost list
dwIndex = 0;
valueBufferSize = sizeof(valueBuffer);
nameBufferSize = sizeof(nameBuffer);
while (RegEnumValue(lostKey, dwIndex, nameBuffer,
&nameBufferSize, NULL, &typeCodeBuffer, valueBuffer,
&valueBufferSize) != ERROR_NO_MORE_ITEMS)
{
m_LostList.Add(new COwnedLostItem(nameBuffer, valueBuffer));
dwIndex++;
valueBufferSize = sizeof(valueBuffer);
nameBufferSize = sizeof(nameBuffer);
}
}
// Iterate over the owned list. Look up each entry in the helper app list. If
// it is not handled by the current Netscape, then move it to the lost list.
int count = m_OwnedList.GetSize();
for (int i = 0; i < count; i++)
{
COwnedLostItem* theItem = (COwnedLostItem*)(m_OwnedList[i]);
if (theItem->m_nHandleMethod != OL_CURRENT_NETSCAPE)
{
// Move to the lost list
void* thePtr = m_OwnedList[i];
m_OwnedList.RemoveAt(i);
m_LostList.Add(thePtr);
i--;
count--;
}
}
// Iterate over the lost list. If any entry is now handled by the current Netscape, move it to
// the owner list
count = m_LostList.GetSize();
for (i = 0; i < count; i++)
{
COwnedLostItem* theItem = (COwnedLostItem*)(m_LostList[i]);
if (theItem->m_nHandleMethod == OL_CURRENT_NETSCAPE)
{
// Move to the owned list
m_LostList.RemoveAt(i);
m_OwnedList.Add(theItem);
i--;
count--;
}
}
// Iterate over all the helper apps and find any additional entries that aren't in the
// owned list or lost list (and that should be).
CPtrList* allHelpers = &(CHelperApp::m_cplHelpers);
for (POSITION pos = allHelpers->GetHeadPosition(); pos != NULL;)
{
CHelperApp* app = (CHelperApp*)allHelpers->GetNext(pos);
CString helperMime(app->cd_item->ci.type);
COwnedLostItem theItem(helperMime);
if (theItem.m_nHandleMethod == OL_CURRENT_NETSCAPE &&
!IsInOwnedList(helperMime))
{
// This should be in the owned list, since we apparently control it.
COwnedLostItem* realItem = new COwnedLostItem(helperMime);
m_OwnedList.Add(realItem);
}
else if (theItem.m_nHandleMethod == OL_OLD_NETSCAPE &&
!IsInLostList(helperMime))
{
// This item is currently used by the old Netscape. Let's
// offer to update to the current version of NS.
COwnedLostItem* realItem = new COwnedLostItem(helperMime);
m_LostList.Add(realItem);
}
}
// Netscape will automatically wrest control of HTML files from a previous version
// so we don't REALLY want HTML in our lost list if it is controlled by an older version
// of netscape. It should be moved to our OWNED list instead, and the handle method
// should be updated.
if (IsInLostList("text/html"))
{
COwnedLostItem* theItem = RemoveFromLostList("text/html");
if (theItem)
{
if (theItem->m_nHandleMethod == OL_OLD_NETSCAPE)
{
theItem->m_nHandleMethod = OL_CURRENT_NETSCAPE;
m_OwnedList.Add(theItem); // Move it to the owned list
}
else m_LostList.Add(theItem); // Put it back
}
}
if (IsInLostList("application/x-unknown-content-type-NetscapeMarkup"))
{
COwnedLostItem* theItem = RemoveFromLostList("application/x-unknown-content-type-NetscapeMarkup");
if (theItem)
{
if (theItem->m_nHandleMethod == OL_OLD_NETSCAPE)
{
theItem->m_nHandleMethod = OL_CURRENT_NETSCAPE;
m_OwnedList.Add(theItem); // Move it to the owned list
}
else m_LostList.Add(theItem); // Put it back
}
}
}
void COwnedAndLostList::WriteLists()
{
// Need to write each of these lists.
CString pathString;
pathString.LoadString(IDS_NETHELP_REGISTRY); // Software\Netscape\Netscape Navigator
// Write the ignored list and lost lists
CString path = pathString + "Lost";
::RegDeleteKey(HKEY_CURRENT_USER, path);
HKEY key;
if (::RegCreateKey(HKEY_CURRENT_USER, path, &key) == ERROR_SUCCESS)
{
// Write out all the lost elements
int count = m_LostList.GetSize();
for (int i = 0; i < count; i++)
{
COwnedLostItem* theItem = (COwnedLostItem*)(m_LostList[i]);
CString regValue = theItem->GetRegistryValue();
RegSetValueEx(key, theItem->m_csMimeType, NULL, REG_SZ,
(const unsigned char*)(const char*)regValue, regValue.GetLength() + 1);
}
}
::RegCloseKey(key);
path = pathString + "Owned";
::RegDeleteKey(HKEY_CURRENT_USER, path);
if (::RegCreateKey(HKEY_CURRENT_USER, path, &key) == ERROR_SUCCESS)
{
// Write out all the lost elements
int count = m_OwnedList.GetSize();
for (int i = 0; i < count; i++)
{
COwnedLostItem* theItem = (COwnedLostItem*)(m_OwnedList[i]);
CString regValue = theItem->GetRegistryValue();
RegSetValueEx(key, theItem->m_csMimeType, NULL, REG_SZ,
(const unsigned char*)(const char*)regValue, regValue.GetLength() + 1);
}
}
::RegCloseKey(key);
}
BOOL COwnedAndLostList::IsInOwnedList(const CString& mimeType)
{
int count = m_OwnedList.GetSize();
for (int i = 0; i < count; i++)
{
COwnedLostItem* theItem = (COwnedLostItem*)m_OwnedList[i];
if (theItem->m_csMimeType == mimeType)
return TRUE;
}
return FALSE;
}
BOOL COwnedAndLostList::IsInLostList(const CString& mimeType)
{
int count = m_LostList.GetSize();
for (int i = 0; i < count; i++)
{
COwnedLostItem* theItem = (COwnedLostItem*)m_LostList[i];
if (theItem->m_csMimeType == mimeType)
return TRUE;
}
return FALSE;
}
COwnedLostItem* COwnedAndLostList::RemoveFromLostList(const CString& mimeType)
{
int count = m_LostList.GetSize();
for (int i = 0; i < count; i++)
{
COwnedLostItem* theItem = (COwnedLostItem*)(m_LostList[i]);
if (mimeType == theItem->m_csMimeType)
{
m_LostList.RemoveAt(i);
return theItem;
}
}
return NULL;
}
BOOL COwnedAndLostList::NonemptyLostIgnoredIntersection()
{
int count = m_LostList.GetSize();
for (int i = 0; i < count; i++)
{
COwnedLostItem* theItem = (COwnedLostItem*)(m_LostList[i]);
if (!theItem->m_bIgnored && !theItem->m_bBroken)
return TRUE;
}
return FALSE;
}