netscape-revival
cmd/xfe/e_kit.c
/**********************************************************************
e_kit.c
By Daniel Malmer
10 Jan 1996
Implementation for client customization.
Copyright \051 1995 Netscape Communications Corporation, all rights reserved.
**********************************************************************/
#include <stdio.h>
#include <string.h>
#include "mozilla.h"
#include "xfe.h"
#include "xp_md5.h"
#include "e_kit.h"
#include "e_kit_patch.h"
#include "e_kit_resources.h"
#include "icondata.h"
#include "menu.h"
#include "net.h"
#include "xpgetstr.h"
#ifdef EDITOR
#include "xeditor.h"
#endif /*EDITOR*/
/* Messages declared in xfe_err.h */
extern int XFE_EKIT_LOCK_FILE_NOT_FOUND;
extern int XFE_EKIT_MODIFIED;
extern int XFE_EKIT_CANT_OPEN;
extern int XFE_EKIT_FILESIZE;
extern int XFE_EKIT_CANT_READ;
extern int XFE_ANIM_CANT_OPEN;
extern int XFE_ANIM_READING_SIZES;
extern int XFE_ANIM_READING_NUM_COLORS;
extern int XFE_ANIM_READING_COLORS;
extern int XFE_ANIM_READING_FRAMES;
extern int XFE_ANIM_NOT_AT_EOF;
extern int XFE_EKIT_ABOUT_MESSAGE;
#define HTTP_OFF 42
#define MAX_BUTTONS 32
#define MAX_RESOURCE_NAME_LEN 64
struct fe_icon_data* anim_custom_large = NULL;
struct fe_icon_data* anim_custom_small = NULL;
static int ekit_errno = 0;
static Widget top_level = NULL;
static Boolean load_resources(Widget top_level);
struct button {
char* name;
char* url;
char* (*url_routine)(void);
};
#define lock_pref(name, field) {\
if ( (tmp = resource_val(name)) != NULL ) {\
if ( fe_globalPrefs.field ) {\
free(fe_globalPrefs.field);\
}\
fe_globalPrefs.field = strdup(tmp);\
fe_defaultPrefs.field = tmp;\
}\
}
#define lock_pref_int(name, field) {\
if ( (tmp = resource_val(name)) != NULL ) {\
fe_globalPrefs.field = atoi(tmp);\
fe_defaultPrefs.field = atoi(tmp);\
}\
}
static char* resource_val(char* name);
static int read_colors(FILE* file, int num_colors);
static int count_buttons(char* bar, struct button buttons[], int max_buttons);
static Boolean resource_locked(char* resource);
static void fe_add_to_menu(Widget menubar, char* menu_name,
struct button buttons[], int num_buttons);
static void callback(Widget w, XtPointer closure, XtPointer client_data);
static Boolean load_resources(Widget top_level);
static Boolean load_animation(char* filename);
static char* get_database_filename(Widget top_level);
static void reset_default_resources(Widget top_level);
static void free_resource_list(XtResourceList list);
static XtResourceList create_resource_list(struct button* buttons,
int num_buttons, char* suffix);
static void un_funkify(char* funk);
static char* resource_name_to_value(char* resource_name);
static Boolean ekit_show_about_usenet(void);
extern char* xfe_go_get_url_whats_new(void);
extern char* xfe_go_get_url_whats_cool(void);
extern char* xfe_go_get_url_manual(void);
extern char* xfe_go_get_url_inet_search(void);
extern char* xfe_go_get_url_inet_directory(void);
extern char* xfe_go_get_url_software(void);
extern char* xfe_go_get_url_netscape(void);
extern char* xfe_go_get_url_galleria(void);
extern char* xfe_go_get_url_inet_white(void);
extern char* xfe_go_get_url_plugins(void);
extern char* xfe_go_get_url_reg(void);
extern char* xfe_go_get_url_relnotes(void);
extern char* xfe_go_get_url_faq(void);
extern char* xfe_go_get_url_usenet(void);
extern char* xfe_go_get_url_security(void);
extern char* xfe_go_get_url_feedback(void);
extern char* xfe_go_get_url_support(void);
extern char* xfe_go_get_url_howto(void);
extern char* xfe_go_get_url_inet_about(void);
extern char* xfe_go_get_url_destinations(void);
static struct button directory_buttons[] = {
{"whatsNew", NULL, xfe_go_get_url_whats_new},
{"whatsCool", NULL, xfe_go_get_url_whats_cool},
{"inetIndex", NULL, xfe_go_get_url_destinations},
{"inetSearch", NULL, xfe_go_get_url_inet_search},
{"inetWhite", NULL, xfe_go_get_url_inet_white},
{"upgrade", NULL, xfe_go_get_url_software},
};
static struct button directory_menu[] = {
{"netscape", NULL, xfe_go_get_url_netscape},
{"whatsNew", NULL, xfe_go_get_url_whats_new},
{"whatsCool", NULL, xfe_go_get_url_whats_cool},
{"directoryMenu4", NULL, NULL},
{"galleria", NULL, xfe_go_get_url_galleria},
{"inetIndex", NULL, xfe_go_get_url_destinations},
{"inetSearch", NULL, xfe_go_get_url_inet_search},
{"inetWhite", NULL, xfe_go_get_url_inet_white},
{"inetAbout", NULL, xfe_go_get_url_inet_about},
{"directoryMenu10", NULL, NULL},
{"directoryMenu11", NULL, NULL},
{"directoryMenu12", NULL, NULL},
{"directoryMenu13", NULL, NULL},
{"directoryMenu14", NULL, NULL},
{"directoryMenu15", NULL, NULL},
{"directoryMenu16", NULL, NULL},
{"directoryMenu17", NULL, NULL},
{"directoryMenu18", NULL, NULL},
{"directoryMenu19", NULL, NULL},
{"directoryMenu20", NULL, NULL},
{"directoryMenu21", NULL, NULL},
{"directoryMenu22", NULL, NULL},
{"directoryMenu23", NULL, NULL},
{"directoryMenu24", NULL, NULL},
{"directoryMenu25", NULL, NULL},
};
static struct button help_menu[] = {
{"aboutplugins", NULL, xfe_go_get_url_plugins},
{"registration", NULL, xfe_go_get_url_reg},
{"upgrade", NULL, xfe_go_get_url_software},
{"helpMenu4", NULL, NULL},
{"manual", NULL, xfe_go_get_url_manual},
{"relnotes", NULL, xfe_go_get_url_relnotes},
{"faq", NULL, xfe_go_get_url_faq},
{"aboutSecurity", NULL, xfe_go_get_url_security},
{"helpMenu9", NULL, NULL},
{"feedback", NULL, xfe_go_get_url_feedback},
{"support", NULL, xfe_go_get_url_support},
{"howTo", NULL, xfe_go_get_url_howto},
{"helpMenu13", NULL, NULL},
{"helpMenu14", NULL, NULL},
{"helpMenu15", NULL, NULL},
{"helpMenu16", NULL, NULL},
{"helpMenu17", NULL, NULL},
{"helpMenu18", NULL, NULL},
{"helpMenu19", NULL, NULL},
{"helpMenu20", NULL, NULL},
{"helpMenu21", NULL, NULL},
{"helpMenu22", NULL, NULL},
{"helpMenu23", NULL, NULL},
{"helpMenu24", NULL, NULL},
{"helpMenu25", NULL, NULL},
};
/*
* On X, the news help menu has "About Usenet".
* So, we have to repeat this stuff here, with the
* addition of the aboutUsenet menu item.
*/
static struct button news_help_menu[] = {
{"aboutplugins", NULL, xfe_go_get_url_plugins},
{"registration", NULL, xfe_go_get_url_reg},
{"upgrade", NULL, xfe_go_get_url_software},
{"helpMenu4", NULL, NULL},
{"manual", NULL, xfe_go_get_url_manual},
{"relnotes", NULL, xfe_go_get_url_relnotes},
{"faq", NULL, xfe_go_get_url_faq},
{"aboutUsenet", NULL, xfe_go_get_url_usenet},
{"aboutSecurity", NULL, xfe_go_get_url_security},
{"helpMenu9", NULL, NULL},
{"feedback", NULL, xfe_go_get_url_feedback},
{"support", NULL, xfe_go_get_url_support},
{"howTo", NULL, xfe_go_get_url_howto},
{"helpMenu13", NULL, NULL},
{"helpMenu14", NULL, NULL},
{"helpMenu15", NULL, NULL},
{"helpMenu16", NULL, NULL},
{"helpMenu17", NULL, NULL},
{"helpMenu18", NULL, NULL},
{"helpMenu19", NULL, NULL},
{"helpMenu20", NULL, NULL},
{"helpMenu21", NULL, NULL},
{"helpMenu22", NULL, NULL},
{"helpMenu23", NULL, NULL},
{"helpMenu24", NULL, NULL},
{"helpMenu25", NULL, NULL},
};
static int num_help_menu_items;
static int num_news_help_menu_items;
static int num_directory_menu_items;
static int num_directory_buttons;
/*
* ekit_error
* Pops up an error dialog if an ekit error has occured.
* Error strings are found in 'xfe_err.h'.
*/
static void
ekit_error(void)
{
if ( ekit_errno ) {
fe_dialog(top_level, "error", XP_GetString(ekit_errno),
FALSE, 0, TRUE, FALSE, 0);
}
}
/*
* un_funkify
* Un-obscures resource strings.
*/
static void
un_funkify(char* funk)
{
char* ptr;
for ( ptr = funk; *ptr != '\0'; ptr++ ) {
*ptr-= 69;
}
}
/*
* create_resource_list
* Creates a list suitable for passing to XtGetApplicationResources.
* This is done at run-time so we can change the names of the buttons
* without having to change several dozen resource names as well.
*/
static XtResourceList
create_resource_list(struct button* buttons, int num_buttons, char* suffix)
{
int i;
static char name[MAX_BUTTONS][MAX_RESOURCE_NAME_LEN];
XtResourceList list = (XtResourceList) malloc( (num_buttons+1) *
sizeof(*list));
#define diff(a, b) (Cardinal) ((char*) (a) - (char*) (b))
assert(num_buttons <= MAX_BUTTONS);
for ( i = 0; i < num_buttons; i++ ) {
assert((strlen(buttons[i].name) + strlen(suffix) + 3) <
MAX_RESOURCE_NAME_LEN);
sprintf(name[i], "%s%sUrl", buttons[i].name, suffix);
list[i].resource_name = name[i];
list[i].resource_class = XtCString;
list[i].resource_type = XtRString;
list[i].resource_size = sizeof(String);
list[i].resource_offset = diff(&(buttons[i].url), buttons);
list[i].default_type = XtRImmediate;
list[i].default_addr = NULL;
}
list[i].resource_name = NULL;
return list;
}
/*
* free_resource_list
* Frees a resource list that was allocated by create_resource_list.
*/
static void
free_resource_list(XtResourceList list)
{
free(list);
}
/*
* reset_default_resources
* For the purposes of the e-kit, some properties of the Navigator
* are specified with XResources. In order to prevent the user
* from changing these resources, we reset them here to their
* default value.
* 'fe_ekitDefaultDatabase' is a string that represents the default
* value of each of the e-kit resources. It is specified in e_kit.ad,
* which is turned into a header file by ad2c.
*/
static void
reset_default_resources(Widget top_level)
{
XrmDatabase source;
XrmDatabase target;
Boolean override = True;
char* string = strdup(fe_ekitDefaultDatabase);
un_funkify(string);
target = XrmGetDatabase(XtDisplay(top_level));
source = XrmGetStringDatabase(string);
XrmCombineDatabase(source, &target, override);
free(string);
}
/* The following have 42 added to each character to prevent user fiddling */
/* "Netscape." */
#define NSCP "\170\217\236\235\215\213\232\217\130"
/* "Netscape.animationFile" */
#define ANIM_FILE NSCP "\213\230\223\227\213\236\223\231\230\160\223\226\217"
/* "Netscape.logoButtonUrl" */
#define LOGO_URL NSCP "\226\231\221\231\154\237\236\236\231\230\177\234\226"
/* "Netscape.homePage" */
#define HOME_PAGE NSCP "\222\231\227\217\172\213\221\217"
/* "Netscape.userAgent" */
#define USER_AGENT NSCP "\237\235\217\234\153\221\217\230\236"
/* "Netscape.autoconfigUrl" */
#define AUTOCFG_URL NSCP "\213\237\236\231\215\231\230\220\223\221\177\234\226"
/* "Netscape.popServer" */
#define POP_SERVER NSCP "\232\231\232\175\217\234\240\217\234"
/* "Netscape.popName" */
#define POP_NAME NSCP "\232\231\232\170\213\227\217"
/* "Netscape.javaClasspath" */
#define JAVA_PATH NSCP "\224\213\240\213\155\226\213\235\235\232\213\236\222"
/* "Netscape.xFileSearchPath" */
#define X_PATH NSCP "\242\160\223\226\217\175\217\213\234\215\222\172\213\236\222"
/* "Netscape.pluginPath" */
#define PLUGIN_PATH NSCP "\232\226\237\221\223\230\172\213\236\222"
/*
* ekit_AnimationFile
* Returns the name of the e-kit animation file.
* If it return NULL, then there is no custom animation file.
*/
char*
ekit_AnimationFile(void)
{
return resource_name_to_value(ANIM_FILE);
}
/*
* ekit_LogoUrl
* Returns the URL that will be loaded if the logo button is pressed.
* It returns NULL if the user didn't specify one.
*/
char*
ekit_LogoUrl(void)
{
return resource_name_to_value(LOGO_URL);
}
/*
* ekit_HomePage
* Returns the Home Page to be loaded at start, or NULL if not specified.
*/
char*
ekit_HomePage(void)
{
return resource_name_to_value(HOME_PAGE);
}
/*
* ekit_UserAgent
* Returns the string to be appended to the User Agent, or NULL if not
* specified.
*/
char*
ekit_UserAgent(void)
{
return resource_name_to_value(USER_AGENT);
}
/*
* ekit_AutoconfigUrl
* Returns the Autoconfig Url, or NULL if not specified.
*/
char*
ekit_AutoconfigUrl(void)
{
return resource_name_to_value(AUTOCFG_URL);
}
/*
* ekit_PopServer
* Returns the Pop Server, or NULL if not specified.
*/
char*
ekit_PopServer(void)
{
return resource_name_to_value(POP_SERVER);
}
/*
* ekit_PopName
* Returns the Pop Name, or NULL if not specified.
*/
char*
ekit_PopName(void)
{
return resource_name_to_value(POP_NAME);
}
/*
* ekit_MsgSizeLimit
* Returns the Msg Size Limit
*/
Boolean
ekit_MsgSizeLimit(void)
{
return resource_locked("Netscape.maxSize");
}
/*
* env_var_append
* If the given environmental variable doesn't have a value,
* just sets the variable to the given value.
* Otherwise appends the value to the variable, separated
* by a colon.
*/
static void
env_var_append(char* var, char* value)
{
char* old_value;
char* new_value;
old_value = getenv(var);
new_value = (char*) malloc(strlen(var) + 1 +
(old_value ? (strlen(old_value) + 1) : 0) +
strlen(value) + 1);
strcpy(new_value, var);
strcat(new_value, "=");
strcat(new_value, old_value ? old_value : "");
strcat(new_value, old_value ? ":" : "");
strcat(new_value, value);
putenv(new_value);
free(new_value);
}
/*
* update_preferences
* Sets the current and default values of customizable paramaters to
* the value specified by the e-kit.
*/
static void
update_preferences(void)
{
char* tmp;
if ( resource_locked("maxSize") ) {
fe_defaultPrefs.pop3_msg_size_limit_p = True;
fe_globalPrefs.pop3_msg_size_limit_p = True;
}
if ( (tmp = resource_name_to_value(JAVA_PATH)) != NULL ) {
env_var_append("CLASSPATH", tmp);
}
if ( (tmp = resource_name_to_value(X_PATH)) != NULL ) {
env_var_append("XFILESEARCHPATH", tmp);
}
if ( (tmp = resource_name_to_value(PLUGIN_PATH)) != NULL ) {
env_var_append("NPX_PLUGIN_PATH", tmp);
}
lock_pref("ftpProxy", ftp_proxy);
lock_pref("gopherProxy", gopher_proxy);
lock_pref("httpProxy", http_proxy);
#ifdef HAVE_SECURITY
lock_pref("httpsProxy", https_proxy);
#endif
lock_pref("waisProxy", wais_proxy);
lock_pref("socksServer", socks_host);
lock_pref("noProxy", no_proxy);
lock_pref("autoconfigUrl", proxy_url);
lock_pref("homePage", home_document);
lock_pref("nntpServer", newshost);
lock_pref("smtpServer", mailhost);
lock_pref("popServer", pop3_host);
lock_pref("userOrganization", organization);
lock_pref("userAddr", email_address);
lock_pref("userName", real_name);
lock_pref("popName", pop3_user_id);
lock_pref_int("proxyMode", proxy_mode);
lock_pref_int("leaveOnServer", pop3_leave_mail_on_server);
lock_pref_int("maxSize", pop3_msg_size_limit);
lock_pref_int("askForPassword", ask_password);
lock_pref_int("passwordLifetime", password_timeout);
#if 0
/* use_password is no longer in prefs.h? */
lock_pref_int("usePassword", use_password);
#endif
#ifdef JAVA
lock_pref_int("disableJava", disable_java);
#endif
#ifdef MOCHA
lock_pref_int("disableJavascript", disable_javascript);
#endif
lock_pref_int("enableSSL2", ssl2_enable);
lock_pref_int("enableSSL3", ssl3_enable);
lock_pref_int("movemailWarn", movemail_warn);
/*
* For SGI's migration to Netscape mail.
* malmer 7/15/96
*/
lock_pref_int("useMovemailP", use_movemail_p);
lock_pref_int("builtinMovemailP", builtin_movemail_p);
lock_pref("movemailProgram", movemail_program);
lock_pref_int("biffInterval", biff_interval);
}
static int ekit_loaded = 0;
/*
* ekit_LockPrefs
* First, set resources back to their default values.
* If this is an Enterprise Kit binary, try to read in
* the lock file. If it doesn't exist, or has been changed,
* complain and die.
*/
void
ekit_LockPrefs(void)
{
if ( ekit_Enabled() == FALSE || ekit_loaded == FALSE ) return;
update_preferences();
if ( ekit_AnimationFile() ) {
if ( load_animation(ekit_AnimationFile()) == False ) {
ekit_error();
}
}
if ( ekit_AutoconfigUrl() ) {
NET_SetNoProxyFailover();
}
}
/*
* get_database_filename
* Looks for the Netscape.cfg file.
* "path" represents the search path for the config file.
* %E is replaced with the root directory that is specified
* at configure time by the e-kit locker, which is a binary
* patch program.
*/
static char*
get_database_filename(Widget top_level)
{
String filename;
SubstitutionRec sub = {'E', NULL};
Cardinal num_substitutions = 1;
String path = "%E/%L/%T/%N%C%S:"
"%E/%l/%T/%N%C%S:"
"%E/%T/%N%C%S:"
"%E/%L/%T/%N%S:"
"%E/%l/%T/%N%S:"
"%E/%T/%N%S";
sub.substitution = ekit_root();
filename = XtResolvePathname(XtDisplay(top_level),
"app-defaults",
"Netscape",
".cfg",
path,
&sub,
num_substitutions,
NULL);
if ( filename == NULL ) {
ekit_errno = XFE_EKIT_LOCK_FILE_NOT_FOUND;
}
return filename;
}
/*
* unobscure_string
* The e-kit compiler adds a number between 40 and 49 to each letter.
* This turns it back into readable text.
*/
static Boolean
unobscure_string(char* string)
{
int offset = 0;
for ( ; *string; string++, offset++ ) {
*string = *string - ( 40 + (offset%10));
}
return True;
}
/*
* verify_string
* The first line in the resource file is a comment that contains the
* md5 hash for the rest of the file.
*/
static Boolean
verify_string(char* string)
{
char* hash = string + 2;
char* rest_of_string = strchr(string, '\n');
if ( string[0] != '!' || string[1] != ' ' || rest_of_string == NULL ) {
ekit_errno = XFE_EKIT_MODIFIED;
return False;
}
*rest_of_string = '\0';
rest_of_string++;
if ( strcmp(XP_Md5PCPrintable(rest_of_string, strlen(rest_of_string)),
hash) ) {
ekit_errno = XFE_EKIT_MODIFIED;
return False;
}
*strchr(string, '\0') = '\n';
return True;
}
/*
* get_file_size
* Given a file pointer, returns the size of the file in bytes.
*/
static int
get_file_size(FILE* file)
{
struct stat buf;
if ( fstat(fileno(file), &buf) == -1 ) {
return -1;
}
return buf.st_size;
}
/*
* get_database_string
* Given the name of the Netscape.lock file, this routine returns
* a character string that represents the data in the file. The
* string will be in XResource file format.
* eg: "Netscape.homePage: http://home.netscape.com"
*/
static char*
get_database_string(char* filename)
{
FILE* file;
int file_size;
char* string;
if ( (file = fopen(filename, "r")) == NULL ) {
ekit_errno = XFE_EKIT_CANT_OPEN;
return NULL;
}
if ( (file_size = get_file_size(file)) < 0 ) {
ekit_errno = XFE_EKIT_FILESIZE;
return NULL;
}
if ( (string = (char*) malloc((file_size+1) * sizeof(char))) == NULL ) {
ekit_errno = XFE_EKIT_CANT_READ;
return NULL;
}
if ( fread(string, sizeof(char), file_size, file) != file_size ) {
free(string);
ekit_errno = XFE_EKIT_CANT_READ;
return NULL;
}
string[file_size] = '\0';
return string;
}
/*
* load_resources
* If there is a locked resource file 'Netscape.lock', merge its
* resources with the current database. This routine is called
* after XtAppInitialize handles app-defaults, .Xdefaults, command
* line switches, etc. So, the lock file has the last say.
*/
static Boolean
load_resources(Widget top_level)
{
String filename;
XrmDatabase source;
XrmDatabase target;
Boolean override = True;
char* db_string;
if ( (filename = get_database_filename(top_level)) == NULL ||
(db_string = get_database_string(filename)) == NULL ||
unobscure_string(db_string) == False ||
verify_string(db_string) == False ) {
return False;
}
source = XrmGetStringDatabase(db_string);
target = XrmGetDatabase(XtDisplay(top_level));
XrmCombineDatabase(source, &target, override);
return True;
}
/*
* callback
* Callback that is invoked when a menu item is selected or directory
* button is pushed, and a Url is to be loaded.
*/
static void
callback(Widget w, XtPointer closure, XtPointer client_data)
{
char* url;
char buf[1024], *in, *out;
MWContext* context = (MWContext*) closure;
fe_UserActivity (context);
XtVaGetValues(w, XmNuserData, &url, NULL);
if ( url ) {
for (in = url, out = buf; *in; in++, out++) *out = *in - HTTP_OFF;
*out = 0;
#ifdef EDITOR
if (EDT_IS_EDITOR(context))
fe_GetURLInBrowser(context, NET_CreateURLStruct(buf, FALSE));
else
#endif
fe_GetURL (context, NET_CreateURLStruct(buf, FALSE), FALSE);
}
}
/*
* count_buttons
* Returns the number of buttons in a list of buttons.
*/
static int
count_buttons(char* bar, struct button buttons[], int max_buttons)
{
char buf[256];
int count;
char* type;
XrmValue value;
char* value_str;
for ( count = 0; count < max_buttons; count++ ) {
sprintf(buf, "Netscape*%s*%s.labelString", bar, buttons[count].name);
XrmGetResource(XrmGetDatabase(XtDisplay(top_level)),
buf, XmCString, &type, &value);
value_str = (char*) value.addr;
if ( value_str == NULL || !strcmp(value_str, "") ) break;
if ( !strcmp(value_str, "-") ) buttons[count].name = "";
}
return count;
}
/*
* ekit_AddDirectoryMenu
* Adds menu items to the Directory menu.
*/
void
ekit_AddDirectoryMenu(Widget menubar)
{
fe_add_to_menu(menubar, "directory", directory_menu, num_directory_menu_items);
}
/*
* ekit_AddHelpMenu
* Adds menu items to the Help menu.
*/
void
ekit_AddHelpMenu(Widget menubar, MWContextType type)
{
if ( type == MWContextNews && ekit_show_about_usenet() ) {
fe_add_to_menu(menubar, "help", news_help_menu, num_news_help_menu_items);
} else {
fe_add_to_menu(menubar, "help", help_menu, num_help_menu_items);
}
}
/*
* fix_url
* Adds HTTP_OFF to the Url.
*/
static char*
fix_url(char* url)
{
char* ptr;
char* new_url = strdup(url);
for ( ptr = new_url; *ptr; ptr++ ) {
*ptr+= HTTP_OFF;
}
return new_url;
}
/*
* ekit_GetDirectoryButtons
*/
struct fe_button*
ekit_GetDirectoryButtons(void)
{
int i;
int num_buttons = ekit_NumDirectoryButtons();
struct fe_button* buttons = (struct fe_button*)
malloc(num_buttons * sizeof(struct fe_button));
for ( i = 0; i < num_buttons; i++ ) {
buttons[i].name = directory_buttons[i].name;
buttons[i].callback = callback;
buttons[i].type = SELECTABLE;
buttons[i].var = NULL;
buttons[i].offset = NULL;
if ( directory_buttons[i].url && *(directory_buttons[i].url) ) {
buttons[i].userdata = (XtPointer) fix_url(directory_buttons[i].url);
} else {
if ( directory_buttons[i].url_routine ) {
buttons[i].userdata = (XtPointer) directory_buttons[i].url_routine();
}
}
}
return buttons;
}
/*
* ekit_NumDirectoryButtons
*/
int
ekit_NumDirectoryButtons(void)
{
return num_directory_buttons;
}
/*
* fe_add_to_menu
* By Daniel Malmer
* 16 Jan 1996
*
* Alter the directory menu array, based on customizations.
*/
static void
fe_add_to_menu(Widget menubar, char* menu_name, struct button buttons[],
int num_buttons)
{
int i;
Widget cascade;
Widget menu;
struct fe_button* items;
fe_ContextData* data;
MWContext* context;
context = fe_WidgetToMWContext(menubar);
data = CONTEXT_DATA(context);
items = (struct fe_button*) malloc((num_buttons+1) * sizeof(*items));
cascade = XtNameToWidget(menubar, menu_name);
XtVaGetValues(cascade, XmNsubMenuId, &menu, NULL);
/* Terminate the list */
items[num_buttons].name = NULL;
for ( i = 0; i < num_buttons; i++ ) {
items[i].name = buttons[i].name;
items[i].callback = callback;
items[i].type = SELECTABLE;
items[i].var = NULL;
items[i].offset = NULL;
items[i].userdata = (XtPointer) buttons[i].url;
if ( buttons[i].url && *(buttons[i].url) ) {
items[i].userdata = (XtPointer) fix_url(buttons[i].url);
} else {
if ( buttons[i].url_routine ) {
items[i].userdata = (XtPointer) buttons[i].url_routine();
}
}
}
fe_CreateSubmenu(menu, items, context, context, CONTEXT_DATA(context));
free(items);
}
/*
* read_frames
* Reads animation frames from the animation input file.
*/
static int
read_frames(FILE* file, int num_frames, int width, int height,
struct fe_icon_data* anim)
{
int i;
int j;
int n = width*height;
int bytes_per_line = (width+7)/8;
int total_bytes = bytes_per_line*height;
for ( i = 0; i < num_frames; i++ ) {
anim[i].width = width;
anim[i].height = height;
anim[i].mono_bits = (uint8*) malloc(total_bytes);
anim[i].mask_bits = (uint8*) malloc(total_bytes);
anim[i].color_bits = (uint8*) malloc(n);
if ( fread(anim[i].mono_bits, sizeof(uint8), total_bytes, file) !=
total_bytes ) {
return -1;
}
if ( fread(anim[i].mask_bits, sizeof(uint8), total_bytes, file) !=
total_bytes ) {
return -1;
}
if ( fread(anim[i].color_bits, sizeof(uint8), n, file) != n ) {
return -1;
}
for ( j = 0; j < width*height; j++ ) {
anim[i].color_bits[j]+= fe_n_icon_colors;
}
}
return 0;
}
/*
* read_colors
* Reads color data from the animation data file.
*/
static int
read_colors(FILE* file, int num_colors)
{
int i;
uint16 r;
uint16 g;
uint16 b;
for ( i = 0; i < num_colors; i++ ) {
if ( fscanf(file, " %hx %hx %hx", &r, &g, &b) != 3 ) {
return -1;
}
fe_icon_colors[fe_n_icon_colors+i][0] = r;
fe_icon_colors[fe_n_icon_colors+i][1] = g;
fe_icon_colors[fe_n_icon_colors+i][2] = b;
}
if ( getc(file) != '\n' ) {
return -1;
}
return 0;
}
/*
* load_animation
* Given the name of an animation file, reads in data from
* that file.
*/
static Boolean
load_animation(char* filename)
{
int num_frames_small;
int width_small;
int height_small;
int num_frames_large;
int width_large;
int height_large;
int num_colors;
FILE* file;
if ( filename == NULL ) {
return False;
}
if ( (file = fopen(filename, "r")) == NULL ) {
ekit_errno = XFE_ANIM_CANT_OPEN;
return False;
}
if ( fscanf(file, " %d %d %d ",
&num_frames_large,
&width_large,
&height_large) != 3 ||
fscanf(file, " %d %d %d ",
&num_frames_small,
&width_small,
&height_small) != 3 ) {
ekit_errno = XFE_ANIM_READING_SIZES;
return False;
}
fe_anim_frames[7] = num_frames_large;
fe_anim_frames[8] = num_frames_small;
if ( fscanf(file, " %d ", &num_colors) != 1 ) {
ekit_errno = XFE_ANIM_READING_NUM_COLORS;
return False;
}
if ( read_colors(file, num_colors) == -1 ) {
ekit_errno = XFE_ANIM_READING_COLORS;
return False;
}
if ( num_frames_large ) {
anim_custom_large = (struct fe_icon_data*)
malloc(sizeof(struct fe_icon_data) * num_frames_large);
}
if ( num_frames_small ) {
anim_custom_small = (struct fe_icon_data*)
malloc(sizeof(struct fe_icon_data) * num_frames_small);
}
if ( read_frames(file, num_frames_large, width_large, height_large,
anim_custom_large) == -1 ||
read_frames(file, num_frames_small, width_small, height_small,
anim_custom_small) == -1 ) {
ekit_errno = XFE_ANIM_READING_FRAMES;
return False;
}
fe_n_icon_colors+= num_colors;
fscanf(file, " ");
if ( !feof(file) ) {
ekit_errno = XFE_ANIM_NOT_AT_EOF;
ekit_error();
}
return True;
}
/*
* resource_name_to_value
* If value is NULL, or *value is 0 (empty string)
* return NULL. Else return the value.
*/
static char*
resource_name_to_value(char* resource_name)
{
XrmValue xrm_value = {0};
char* value;
char* type = NULL;
char* in;
char* out;
char buf[256];
if ( !top_level ) return NULL;
for ( in = resource_name, out = buf; *in; in++, out++ ) *out = (*in)-42;
*out = '\0';
XrmGetResource(XrmGetDatabase(XtDisplay(top_level)),
buf, XmCString, &type, &xrm_value);
value = (char*) (xrm_value.addr);
return ( value && *value ) ? value : NULL;
}
/*
* ekit_AboutData
* Returns a pointer to the data that will be displayed when
* "about:custom" is loaded.
* The memory allocated here is freed in mkgeturl.c.
*/
char*
ekit_AboutData(void)
{
char buf[256];
if ( ekit_Enabled() ) {
sprintf(buf, XP_GetString(XFE_EKIT_ABOUT_MESSAGE), ekit_version());
if ( ekit_UserAgent() ) {
strcat(buf, "-");
strcat(buf, ekit_UserAgent());
}
return strdup(buf);
} else {
return strdup("");
}
}
/*
* ekit_Enabled
* The 'whacked' field is set to False in the source code,
* but may be set to True by the customer by using a program
* that finds that byte and changes it to True.
*/
Bool
ekit_Enabled(void)
{
return ekit_enabled();
}
/*
* resource_locked
*/
static Boolean
resource_locked(char* resource)
{
char* type;
XrmValue value;
XrmGetResource(XrmGetDatabase(XtDisplay(top_level)), resource,
XmCString, &type, &value);
return ( value.addr && *(value.addr) );
}
/*
* resource_val
* The value that we get from X cannot be freed.
* We have to return a copy of it.
*/
static char*
resource_val(char* name)
{
char* type;
char* value;
XrmValue xvalue;
char buf[256];
sprintf(buf, "%.64s.%.128s", fe_progclass, name);
XrmGetResource(XrmGetDatabase(XtDisplay(top_level)),
buf, XmCString, &type, &xvalue);
value = (char*) xvalue.addr;
return ( value && *value ) ? value : NULL;
}
/*
* ekit_Initialize
*/
void
ekit_Initialize(Widget toplevel)
{
XtResourceList list;
top_level = toplevel;
/* Set resource database back to default state */
reset_default_resources(top_level);
/* If this is an e-kit version, modify resource database */
if ( ekit_Enabled() ) {
if ( (ekit_loaded = load_resources(top_level)) == False ) {
if ( ekit_required() ) {
ekit_error();
exit(0);
}
}
}
/*
* These next steps must be done whether or not the
* e-kit is enabled, in order to set up the help
* menu, directory menu, etc.
*/
list = create_resource_list(help_menu, XtNumber(help_menu), "");
XtGetApplicationResources(top_level, help_menu,
list, XtNumber(help_menu), 0, 0);
free_resource_list(list);
list = create_resource_list(news_help_menu, XtNumber(news_help_menu), "");
XtGetApplicationResources(top_level, news_help_menu,
list, XtNumber(news_help_menu), 0, 0);
free_resource_list(list);
list = create_resource_list(directory_menu, XtNumber(directory_menu), "");
XtGetApplicationResources(top_level, directory_menu,
list, XtNumber(directory_menu), 0, 0);
free_resource_list(list);
list = create_resource_list(directory_buttons, XtNumber(directory_buttons),
"B");
XtGetApplicationResources(top_level, directory_buttons,
list, XtNumber(directory_buttons), 0, 0);
free_resource_list(list);
num_directory_buttons = count_buttons("urlBar", directory_buttons,
XtNumber(directory_buttons));
num_directory_menu_items = count_buttons("menuBar", directory_menu,
XtNumber(directory_menu));
num_help_menu_items = count_buttons("menuBar", help_menu,
XtNumber(help_menu));
num_news_help_menu_items = count_buttons("menuBar", news_help_menu,
XtNumber(news_help_menu));
}
#define suggest_pref(name, field) \
if ( (tmp = resource_val(name)) != NULL ) { \
default_prefs->field = strdup(tmp); \
}
#define suggest_pref_int(name, field) \
if ( (tmp = resource_val(name)) != NULL ) { \
default_prefs->field = atoi(tmp); \
}
/*
* ekit_DefaultPrefs
* Give E-kit a chance to override default prefs, thus providing
* suggestions as an alternative to locking.
*/
void
ekit_DefaultPrefs(XFE_GlobalPrefs* default_prefs)
{
char* tmp;
if ( ekit_Enabled() == FALSE || ekit_loaded == FALSE ) return;
suggest_pref("ftpProxyDef", ftp_proxy);
suggest_pref("gopherProxyDef", gopher_proxy);
suggest_pref("httpProxyDef", http_proxy);
#ifdef HAVE_SECURITY
suggest_pref("httpsProxyDef", https_proxy);
#endif
suggest_pref("waisProxyDef", wais_proxy);
suggest_pref("socksHostDef", socks_host);
suggest_pref("noProxyDef", no_proxy);
suggest_pref_int("proxyModeDef", proxy_mode);
suggest_pref("proxyUrlDef", proxy_url);
suggest_pref("homePageDef", home_document);
suggest_pref_int("leaveOnServerDef", pop3_leave_mail_on_server);
suggest_pref("nntpServerDef", newshost);
suggest_pref("smtpServerDef", mailhost);
suggest_pref("popServerDef", pop3_host);
suggest_pref("autoconfigUrlDef", proxy_url);
suggest_pref("userOrganizationDef", organization);
suggest_pref("userAddrDef", email_address);
suggest_pref("userNameDef", real_name);
suggest_pref("popNameDef", pop3_user_id);
suggest_pref_int("maxSizeDef", pop3_msg_size_limit);
suggest_pref_int("maxSizePDef", pop3_msg_size_limit_p);
suggest_pref_int("askForPasswordDef", ask_password);
suggest_pref_int("passwordLifetimeDef", password_timeout);
suggest_pref_int("enableSSL2Def", ssl2_enable);
suggest_pref_int("enableSSL3Def", ssl3_enable);
suggest_pref_int("movemailWarnDef", movemail_warn);
#ifdef JAVA
suggest_pref_int("disableJavaDef", disable_java);
#endif
#ifdef MOCHA
suggest_pref_int("disableJavascriptDef", disable_javascript);
#endif
suggest_pref("globalMailcapDef", global_mailcap_file);
suggest_pref("globalMimetypesDef", global_mime_types_file);
/*
* For SGI's migration to Netscape mail.
* malmer 7/15/96
*/
suggest_pref_int("useMovemailPDef", use_movemail_p);
suggest_pref_int("builtinMovemailPDef", builtin_movemail_p);
suggest_pref("movemailProgramDef", movemail_program);
suggest_pref_int("biffIntervalDef", biff_interval);
}
/*
* ekit_show_about_usenet
*/
static Boolean
ekit_show_about_usenet(void)
{
char* show = resource_val("showAboutUsenet");
return ( show && (*show == '1') );
}