gaim/gaim

Parents 898768c560a0
Children b5b9e682678c
Use GLib 2.6's gstdio functions. This should fix gaim not liking non-ascii filenames in win32.
--- a/plugins/mailchk.c Wed Feb 09 09:58:22 2005 -0500
+++ b/plugins/mailchk.c Wed Feb 09 19:07:39 2005 -0500
@@ -33,7 +33,7 @@
if (!filename)
filename = g_strconcat("/var/spool/mail/", g_get_user_name(), NULL);
- if (stat(filename, &s) < 0) {
+ if (g_stat(filename, &s) < 0) {
g_free(filename);
return -1;
}
--- a/plugins/spellchk.c Wed Feb 09 09:58:22 2005 -0500
+++ b/plugins/spellchk.c Wed Feb 09 19:07:39 2005 -0500
@@ -340,11 +340,11 @@
if(fclose(f)) {
gaim_debug(GAIM_DEBUG_ERROR, "spellchk",
"Error writing to %s: %m\n", tempfilename);
- unlink(tempfilename);
+ g_unlink(tempfilename);
g_free(name);
return;
}
- rename(tempfilename, name);
+ g_rename(tempfilename, name);
g_free(name);
}
--- a/plugins/tcl/tcl.c Wed Feb 09 09:58:22 2005 -0500
+++ b/plugins/tcl/tcl.c Wed Feb 09 19:07:39 2005 -0500
@@ -161,8 +161,7 @@
const char *next;
int len, found = 0, err = 0, nelems;
gboolean status = FALSE;
-
- if ((fp = fopen(plugin->path, "r")) == NULL)
+ if ((fp = g_fopen(plugin->path, "r")) == NULL)
return FALSE;
if (fstat(fileno(fp), &st)) {
fclose(fp);
--- a/src/Makefile.mingw Wed Feb 09 09:58:22 2005 -0500
+++ b/src/Makefile.mingw Wed Feb 09 19:07:39 2005 -0500
@@ -173,7 +173,7 @@
-lws2_32 \
-liberty \
-lwinmm \
- -lzdll \
+ -lz \
-lidletrack \
-lnss3 \
-lnspr4 \
@@ -202,7 +202,7 @@
all: $(TARGET).exe $(TARGET).dll
-install:
+install: all
cp $(GAIM_SRC)/gaim.exe $(GAIM_SRC)/gaim.dll $(GAIM_INSTALL_DIR)
$(IDLETRACK_TOP)/idletrack.dll:
--- a/src/account.c Wed Feb 09 09:58:22 2005 -0500
+++ b/src/account.c Wed Feb 09 19:07:39 2005 -0500
@@ -1379,16 +1379,16 @@
gaim_debug(GAIM_DEBUG_INFO, "accounts", "Writing accounts to disk.\n");
- fp = fopen(user_dir, "r");
+ fp = g_fopen(user_dir, "r");
if (fp == NULL)
- mkdir(user_dir, S_IRUSR | S_IWUSR | S_IXUSR);
+ g_mkdir(user_dir, S_IRUSR | S_IWUSR | S_IXUSR);
else
fclose(fp);
filename = g_build_filename(user_dir, "accounts.xml.save", NULL);
- if ((fp = fopen(filename, "w")) != NULL) {
+ if ((fp = g_fopen(filename, "w")) != NULL) {
GList *l;
fprintf(fp, "<?xml version='1.0' encoding='UTF-8' ?>\n\n");
@@ -1409,16 +1409,16 @@
return;
}
- if (stat(filename, &st) || (st.st_size == 0)) {
+ if (g_stat(filename, &st) || (st.st_size == 0)) {
gaim_debug_error("accounts", "Failed to save accounts\n");
- unlink(filename);
+ g_unlink(filename);
g_free(filename);
return;
}
filename_real = g_build_filename(user_dir, "accounts.xml", NULL);
- if (rename(filename, filename_real) < 0) {
+ if (g_rename(filename, filename_real) < 0) {
gaim_debug(GAIM_DEBUG_ERROR, "accounts", "Error renaming %s to %s\n",
filename, filename_real);
}
--- a/src/blist.c Wed Feb 09 09:58:22 2005 -0500
+++ b/src/blist.c Wed Feb 09 19:07:39 2005 -0500
@@ -1969,7 +1969,7 @@
filename);
name = g_build_filename(gaim_user_dir(), "blist.xml~", NULL);
- if ((backup = fopen(name, "w"))) {
+ if ((backup = g_fopen(name, "w"))) {
fwrite(contents, length, 1, backup);
fclose(backup);
chmod(name, S_IRUSR | S_IWUSR);
@@ -2399,15 +2399,15 @@
return;
}
- file = fopen(user_dir, "r");
+ file = g_fopen(user_dir, "r");
if (!file)
- mkdir(user_dir, S_IRUSR | S_IWUSR | S_IXUSR);
+ g_mkdir(user_dir, S_IRUSR | S_IWUSR | S_IXUSR);
else
fclose(file);
filename = g_build_filename(user_dir, "blist.xml.save", NULL);
- if ((file = fopen(filename, "w"))) {
+ if ((file = g_fopen(filename, "w"))) {
gaim_blist_write(file, NULL);
fclose(file);
chmod(filename, S_IRUSR | S_IWUSR);
@@ -2418,16 +2418,16 @@
return;
}
- if (stat(filename, &st) || (st.st_size == 0)) {
+ if (g_stat(filename, &st) || (st.st_size == 0)) {
gaim_debug_error("blist", "Failed to save blist\n");
- unlink(filename);
+ g_unlink(filename);
g_free(filename);
return;
}
filename_real = g_build_filename(user_dir, "blist.xml", NULL);
- if (rename(filename, filename_real) < 0)
+ if (g_rename(filename, filename_real) < 0)
gaim_debug(GAIM_DEBUG_ERROR, "blist save",
"Error renaming %s to %s\n", filename, filename_real);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/buddyicon.c Wed Feb 09 19:07:39 2005 -0500
@@ -0,0 +1,453 @@
+/**
+ * @file icon.c Buddy Icon API
+ * @ingroup core
+ *
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include "internal.h"
+#include "buddyicon.h"
+#include "conversation.h"
+#include "debug.h"
+#include "util.h"
+
+static GHashTable *account_cache = NULL;
+static char *cache_dir = NULL;
+static gboolean icon_caching = TRUE;
+
+static GaimBuddyIcon *
+gaim_buddy_icon_create(GaimAccount *account, const char *username)
+{
+ GaimBuddyIcon *icon;
+ GHashTable *icon_cache;
+
+ icon = g_new0(GaimBuddyIcon, 1);
+
+ gaim_buddy_icon_set_account(icon, account);
+ gaim_buddy_icon_set_username(icon, username);
+
+ icon_cache = g_hash_table_lookup(account_cache, account);
+
+ if (icon_cache == NULL)
+ {
+ icon_cache = g_hash_table_new(g_str_hash, g_str_equal);
+
+ g_hash_table_insert(account_cache, account, icon_cache);
+ }
+
+ g_hash_table_insert(icon_cache,
+ (char *)gaim_buddy_icon_get_username(icon), icon);
+ return icon;
+}
+
+GaimBuddyIcon *
+gaim_buddy_icon_new(GaimAccount *account, const char *username,
+ void *icon_data, size_t icon_len)
+{
+ GaimBuddyIcon *icon;
+
+ g_return_val_if_fail(account != NULL, NULL);
+ g_return_val_if_fail(username != NULL, NULL);
+ g_return_val_if_fail(icon_data != NULL, NULL);
+ g_return_val_if_fail(icon_len > 0, NULL);
+
+ icon = gaim_buddy_icons_find(account, username);
+
+ if (icon == NULL)
+ icon = gaim_buddy_icon_create(account, username);
+
+ gaim_buddy_icon_ref(icon);
+ gaim_buddy_icon_set_data(icon, icon_data, icon_len);
+ gaim_buddy_icon_unref(icon);
+
+ /* We don't take a reference here. gaim_buddy_icon_set_data() makes blist.c or
+ conversation.c, or both, do that for us.
+ */
+ return icon;
+}
+
+void
+gaim_buddy_icon_destroy(GaimBuddyIcon *icon)
+{
+ GaimConversation *conv;
+ GaimAccount *account;
+ GHashTable *icon_cache;
+ const char *username;
+ GSList *sl, *list;
+
+ g_return_if_fail(icon != NULL);
+
+ if (icon->ref_count > 0)
+ {
+ /* If the ref count is greater than 0, then we weren't called from
+ * gaim_buddy_icon_unref(). So we go through and ask everyone to
+ * unref us. Then we return, since we know somewhere along the
+ * line we got called recursively by one of the unrefs, and the
+ * icon is already destroyed.
+ */
+ account = gaim_buddy_icon_get_account(icon);
+ username = gaim_buddy_icon_get_username(icon);
+
+ conv = gaim_find_conversation_with_account(username, account);
+ if (conv != NULL && gaim_conversation_get_type(conv) == GAIM_CONV_IM)
+ gaim_conv_im_set_icon(GAIM_CONV_IM(conv), NULL);
+
+ for (list = sl = gaim_find_buddies(account, username); sl != NULL;
+ sl = sl->next)
+ {
+ GaimBuddy *buddy = (GaimBuddy *)sl->data;
+
+ gaim_buddy_set_icon(buddy, NULL);
+ }
+
+ g_slist_free(list);
+
+ return;
+ }
+
+ icon_cache = g_hash_table_lookup(account_cache,
+ gaim_buddy_icon_get_account(icon));
+
+ if (icon_cache != NULL)
+ g_hash_table_remove(icon_cache, gaim_buddy_icon_get_username(icon));
+
+ if (icon->username != NULL)
+ g_free(icon->username);
+
+ if (icon->data != NULL)
+ g_free(icon->data);
+
+ g_free(icon);
+}
+
+GaimBuddyIcon *
+gaim_buddy_icon_ref(GaimBuddyIcon *icon)
+{
+ g_return_val_if_fail(icon != NULL, NULL);
+
+ icon->ref_count++;
+
+ return icon;
+}
+
+GaimBuddyIcon *
+gaim_buddy_icon_unref(GaimBuddyIcon *icon)
+{
+ g_return_val_if_fail(icon != NULL, NULL);
+
+ if (icon->ref_count <= 0)
+ return NULL;
+
+ icon->ref_count--;
+
+ if (icon->ref_count == 0)
+ {
+ gaim_buddy_icon_destroy(icon);
+
+ return NULL;
+ }
+
+ return icon;
+}
+
+void
+gaim_buddy_icon_update(GaimBuddyIcon *icon)
+{
+ GaimConversation *conv;
+ GaimAccount *account;
+ const char *username;
+ GSList *sl, *list;
+
+ g_return_if_fail(icon != NULL);
+
+ account = gaim_buddy_icon_get_account(icon);
+ username = gaim_buddy_icon_get_username(icon);
+
+ for (list = sl = gaim_find_buddies(account, username); sl != NULL;
+ sl = sl->next)
+ {
+ GaimBuddy *buddy = (GaimBuddy *)sl->data;
+
+ gaim_buddy_set_icon(buddy, icon);
+ }
+
+ g_slist_free(list);
+
+ conv = gaim_find_conversation_with_account(username, account);
+
+ if (conv != NULL && gaim_conversation_get_type(conv) == GAIM_CONV_IM)
+ gaim_conv_im_set_icon(GAIM_CONV_IM(conv), icon);
+}
+
+void
+gaim_buddy_icon_cache(GaimBuddyIcon *icon, GaimBuddy *buddy)
+{
+ const void *data;
+ const char *dirname;
+ char *random;
+ char *filename;
+ const char *old_icon;
+ size_t len;
+ struct stat st;
+ FILE *file = NULL;
+
+ g_return_if_fail(icon != NULL);
+ g_return_if_fail(buddy != NULL);
+
+ if (!gaim_buddy_icons_is_caching())
+ return;
+
+ data = gaim_buddy_icon_get_data(icon, &len);
+
+ random = g_strdup_printf("%x", g_random_int());
+ dirname = gaim_buddy_icons_get_cache_dir();
+ filename = g_build_filename(dirname, random, NULL);
+ old_icon = gaim_blist_node_get_string((GaimBlistNode*)buddy, "buddy_icon");
+
+ if (!g_file_test(dirname, G_FILE_TEST_IS_DIR))
+ {
+ gaim_debug_info("buddy icons", "Creating icon cache directory.\n");
+
+ if (g_mkdir(dirname, S_IRUSR | S_IWUSR | S_IXUSR) < 0)
+ {
+ gaim_debug_error("buddy icons",
+ "Unable to create directory %s: %s\n",
+ dirname, strerror(errno));
+ }
+ }
+
+ if ((file = g_fopen(filename, "wb")) != NULL)
+ {
+ fwrite(data, 1, len, file);
+ fclose(file);
+ }
+
+ g_free(filename);
+
+ if (old_icon != NULL)
+ {
+ if(!g_stat(old_icon, &st))
+ g_unlink(old_icon);
+ else {
+ filename = g_build_filename(dirname, old_icon, NULL);
+ if(!g_stat(filename, &st))
+ g_unlink(filename);
+ g_free(filename);
+ }
+ }
+
+ gaim_blist_node_set_string((GaimBlistNode *)buddy, "buddy_icon", random);
+
+ g_free(random);
+}
+
+void
+gaim_buddy_icon_set_account(GaimBuddyIcon *icon, GaimAccount *account)
+{
+ g_return_if_fail(icon != NULL);
+ g_return_if_fail(account != NULL);
+
+ icon->account = account;
+}
+
+void
+gaim_buddy_icon_set_username(GaimBuddyIcon *icon, const char *username)
+{
+ g_return_if_fail(icon != NULL);
+ g_return_if_fail(username != NULL);
+
+ if (icon->username != NULL)
+ g_free(icon->username);
+
+ icon->username = g_strdup(username);
+}
+
+void
+gaim_buddy_icon_set_data(GaimBuddyIcon *icon, void *data, size_t len)
+{
+ g_return_if_fail(icon != NULL);
+
+ if (icon->data != NULL)
+ g_free(icon->data);
+
+ if (data != NULL && len > 0)
+ {
+ icon->data = g_memdup(data, len);
+ icon->len = len;
+ }
+ else
+ {
+ icon->data = NULL;
+ icon->len = 0;
+ }
+
+ gaim_buddy_icon_update(icon);
+}
+
+GaimAccount *
+gaim_buddy_icon_get_account(const GaimBuddyIcon *icon)
+{
+ g_return_val_if_fail(icon != NULL, NULL);
+
+ return icon->account;
+}
+
+const char *
+gaim_buddy_icon_get_username(const GaimBuddyIcon *icon)
+{
+ g_return_val_if_fail(icon != NULL, NULL);
+
+ return icon->username;
+}
+
+const void *
+gaim_buddy_icon_get_data(const GaimBuddyIcon *icon, size_t *len)
+{
+ g_return_val_if_fail(icon != NULL, NULL);
+
+ if (len != NULL)
+ *len = icon->len;
+
+ return icon->data;
+}
+
+void
+gaim_buddy_icons_set_for_user(GaimAccount *account, const char *username,
+ void *icon_data, size_t icon_len)
+{
+ g_return_if_fail(account != NULL);
+ g_return_if_fail(username != NULL);
+
+ if (icon_data == NULL || icon_len == 0)
+ {
+ GaimBuddyIcon *buddy_icon;
+
+ buddy_icon = gaim_buddy_icons_find(account, username);
+
+ if (buddy_icon != NULL)
+ gaim_buddy_icon_destroy(buddy_icon);
+ }
+ else
+ {
+ gaim_buddy_icon_new(account, username, icon_data, icon_len);
+ }
+}
+
+GaimBuddyIcon *
+gaim_buddy_icons_find(GaimAccount *account, const char *username)
+{
+ GHashTable *icon_cache;
+ GaimBuddyIcon *ret = NULL;
+ char *filename = NULL;
+
+ g_return_val_if_fail(account != NULL, NULL);
+ g_return_val_if_fail(username != NULL, NULL);
+
+ icon_cache = g_hash_table_lookup(account_cache, account);
+
+ if ((icon_cache == NULL) || ((ret = g_hash_table_lookup(icon_cache, username)) == NULL)) {
+ const char *file;
+ struct stat st;
+ GaimBuddy *b = gaim_find_buddy(account, username);
+
+ if (!b)
+ return NULL;
+
+ if ((file = gaim_blist_node_get_string((GaimBlistNode*)b, "buddy_icon")) == NULL)
+ return NULL;
+
+ if (!g_stat(file, &st))
+ filename = g_strdup(file);
+ else
+ filename = g_build_filename(gaim_buddy_icons_get_cache_dir(), file, NULL);
+
+ if (!g_stat(filename, &st)) {
+ FILE *f = g_fopen(filename, "rb");
+ if (f) {
+ char *data = g_malloc(st.st_size);
+ fread(data, 1, st.st_size, f);
+ fclose(f);
+ ret = gaim_buddy_icon_create(account, username);
+ gaim_buddy_icon_ref(ret);
+ gaim_buddy_icon_set_data(ret, data, st.st_size);
+ gaim_buddy_icon_unref(ret);
+ g_free(data);
+ g_free(filename);
+ return ret;
+ }
+ }
+ g_free(filename);
+ }
+
+ return ret;
+}
+
+void
+gaim_buddy_icons_set_caching(gboolean caching)
+{
+ icon_caching = caching;
+}
+
+gboolean
+gaim_buddy_icons_is_caching(void)
+{
+ return icon_caching;
+}
+
+void
+gaim_buddy_icons_set_cache_dir(const char *dir)
+{
+ g_return_if_fail(cache_dir != NULL);
+
+ if (cache_dir != NULL)
+ g_free(cache_dir);
+
+ cache_dir = g_strdup(dir);
+}
+
+const char *
+gaim_buddy_icons_get_cache_dir(void)
+{
+ return cache_dir;
+}
+
+void *
+gaim_buddy_icons_get_handle()
+{
+ static int handle;
+
+ return &handle;
+}
+
+void
+gaim_buddy_icons_init()
+{
+ account_cache = g_hash_table_new_full(
+ g_direct_hash, g_direct_equal,
+ NULL, (GFreeFunc)g_hash_table_destroy);
+
+ cache_dir = g_build_filename(gaim_user_dir(), "icons", NULL);
+}
+
+void
+gaim_buddy_icons_uninit()
+{
+ g_hash_table_destroy(account_cache);
+}
--- a/src/ft.c Wed Feb 09 09:58:22 2005 -0500
+++ b/src/ft.c Wed Feb 09 19:07:39 2005 -0500
@@ -170,7 +170,7 @@
xfer = (GaimXfer *)user_data;
- if (stat(filename, &st) != 0) {
+ if (g_stat(filename, &st) != 0) {
/* File not found. */
if (gaim_xfer_get_type(xfer) == GAIM_XFER_RECEIVE) {
gaim_xfer_request_accepted(xfer, filename);
@@ -367,7 +367,7 @@
return;
}
- if (stat(filename, &st) == -1) {
+ if (g_stat(filename, &st) == -1) {
gaim_xfer_show_file_error(xfer, filename);
gaim_xfer_unref(xfer);
return;
@@ -789,7 +789,7 @@
{
GaimXferType type = gaim_xfer_get_type(xfer);
- xfer->dest_fp = fopen(gaim_xfer_get_local_filename(xfer),
+ xfer->dest_fp = g_fopen(gaim_xfer_get_local_filename(xfer),
type == GAIM_XFER_RECEIVE ? "wb" : "rb");
if (xfer->dest_fp == NULL) {
--- a/src/gtkaccount.c Wed Feb 09 09:58:22 2005 -0500
+++ b/src/gtkaccount.c Wed Feb 09 19:07:39 2005 -0500
@@ -306,7 +306,7 @@
GTK_FILE_SELECTION(dialog->icon_filesel)));
#endif /* FILECHOOSER */
- if (!filename || stat(filename, &st))
+ if (!filename || g_stat(filename, &st))
{
g_free(filename);
return;
@@ -522,7 +522,7 @@
format = gdk_pixbuf_get_file_info (path, &width, &height);
#else
loader = gdk_pixbuf_loader_new();
- if (!stat(path, &st) && (file = fopen(path, "rb")) != NULL) {
+ if (!g_stat(path, &st) && (file = g_fopen(path, "rb")) != NULL) {
data = g_malloc(st.st_size);
fread(data, 1, st.st_size, file);
fclose(file);
@@ -588,7 +588,7 @@
if (!g_file_test(dirname, G_FILE_TEST_IS_DIR)) {
gaim_debug_info("buddyicon", "Creating icon cache directory.\n");
- if (mkdir(dirname, S_IRUSR | S_IWUSR | S_IXUSR) < 0) {
+ if (g_mkdir(dirname, S_IRUSR | S_IWUSR | S_IXUSR) < 0) {
gaim_debug_error("buddyicon",
"Unable to create directory %s: %s\n",
dirname, strerror(errno));
--- a/src/gtkconv.c Wed Feb 09 09:58:22 2005 -0500
+++ b/src/gtkconv.c Wed Feb 09 19:07:39 2005 -0500
@@ -901,7 +901,7 @@
FILE *fp;
const char *name;
- if ((fp = fopen(filename, "w+")) == NULL) {
+ if ((fp = g_fopen(filename, "w+")) == NULL) {
gaim_notify_error(conv, NULL, _("Unable to open file."), NULL);
return;
}
@@ -2616,7 +2616,7 @@
const void *data;
size_t len;
- if ((fp = fopen(filename, "wb")) == NULL) {
+ if ((fp = g_fopen(filename, "wb")) == NULL) {
gaim_notify_error(conv, NULL, _("Unable to open file."), NULL);
return;
}
@@ -5817,7 +5817,7 @@
"%s" G_DIR_SEPARATOR_S "gaimicon-%s.%d",
g_get_tmp_dir(), gaim_conversation_get_name(conv), getpid());
- if (!(file = fopen(filename, "wb")))
+ if (!(file = g_fopen(filename, "wb")))
return;
fwrite(data, 1, len, file);
@@ -5825,7 +5825,7 @@
gtkconv->u.im->anim = gdk_pixbuf_animation_new_from_file(filename, &err);
/* make sure we remove the file as soon as possible */
- unlink(filename);
+ g_unlink(filename);
if (err) {
gaim_debug(GAIM_DEBUG_ERROR, "gtkconv",
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gtkdebug.c Wed Feb 09 19:07:39 2005 -0500
@@ -0,0 +1,537 @@
+/**
+ * @file gtkdebug.c GTK+ Debug API
+ * @ingroup gtkui
+ *
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include "internal.h"
+#include "gtkgaim.h"
+
+#include "notify.h"
+#include "prefs.h"
+#include "request.h"
+#include "util.h"
+
+#include "gtkdebug.h"
+#include "gtkdialogs.h"
+#include "gtkimhtml.h"
+#include "gtkutils.h"
+#include "stock.h"
+
+extern int opt_debug;
+
+typedef struct
+{
+ GtkWidget *window;
+ GtkWidget *text;
+ GtkWidget *find;
+
+ gboolean timestamps;
+ gboolean paused;
+
+ guint timestamps_handle;
+
+} DebugWindow;
+
+static char debug_fg_colors[][8] = {
+ "#000000", /**< All debug levels. */
+ "#666666", /**< Misc. */
+ "#000000", /**< Information. */
+ "#660000", /**< Warnings. */
+ "#FF0000", /**< Errors. */
+ "#FF0000", /**< Fatal errors. */
+};
+
+static DebugWindow *debug_win = NULL;
+
+struct _find {
+ DebugWindow *window;
+ GtkWidget *entry;
+};
+
+static gint
+debug_window_destroy(GtkWidget *w, GdkEvent *event, void *unused)
+{
+ if (debug_win->timestamps_handle != 0)
+ gaim_prefs_disconnect_callback(debug_win->timestamps_handle);
+
+ /* If the "Save Log" dialog is open then close it */
+ gaim_request_close_with_handle(debug_win);
+
+ g_free(debug_win);
+ debug_win = NULL;
+
+ gaim_prefs_set_bool("/gaim/gtk/debug/enabled", FALSE);
+
+ return FALSE;
+}
+
+static gboolean
+configure_cb(GtkWidget *w, GdkEventConfigure *event, DebugWindow *win)
+{
+ if (GTK_WIDGET_VISIBLE(w)) {
+ gaim_prefs_set_int("/gaim/gtk/debug/width", event->width);
+ gaim_prefs_set_int("/gaim/gtk/debug/height", event->height);
+ }
+
+ return FALSE;
+}
+
+static void
+do_find_cb(GtkWidget *widget, gint response, struct _find *f)
+{
+ switch (response) {
+ case GTK_RESPONSE_OK:
+ gtk_imhtml_search_find(GTK_IMHTML(f->window->text),
+ gtk_entry_get_text(GTK_ENTRY(f->entry)));
+ break;
+
+ case GTK_RESPONSE_DELETE_EVENT:
+ case GTK_RESPONSE_CLOSE:
+ gtk_imhtml_search_clear(GTK_IMHTML(f->window->text));
+ gtk_widget_destroy(f->window->find);
+ f->window->find = NULL;
+ g_free(f);
+ break;
+ }
+}
+
+static void
+find_cb(GtkWidget *w, DebugWindow *win)
+{
+ GtkWidget *hbox, *img, *label;
+ struct _find *f;
+
+ if(win->find)
+ {
+ gtk_window_present(GTK_WINDOW(win->find));
+ return;
+ }
+
+ f = g_malloc(sizeof(struct _find));
+ f->window = win;
+ win->find = gtk_dialog_new_with_buttons(_("Find"),
+ GTK_WINDOW(win->window), GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
+ GTK_STOCK_FIND, GTK_RESPONSE_OK, NULL);
+ gtk_dialog_set_default_response(GTK_DIALOG(win->find),
+ GTK_RESPONSE_OK);
+ g_signal_connect(G_OBJECT(win->find), "response",
+ G_CALLBACK(do_find_cb), f);
+
+ gtk_container_set_border_width(GTK_CONTAINER(win->find), 6);
+ gtk_window_set_resizable(GTK_WINDOW(win->find), FALSE);
+ gtk_dialog_set_has_separator(GTK_DIALOG(win->find), FALSE);
+ gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(win->find)->vbox), 12);
+ gtk_container_set_border_width(
+ GTK_CONTAINER(GTK_DIALOG(win->find)->vbox), 6);
+
+ hbox = gtk_hbox_new(FALSE, 12);
+ gtk_container_add(GTK_CONTAINER(GTK_DIALOG(win->find)->vbox),
+ hbox);
+ img = gtk_image_new_from_stock(GAIM_STOCK_DIALOG_QUESTION,
+ GTK_ICON_SIZE_DIALOG);
+ gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0);
+
+ gtk_misc_set_alignment(GTK_MISC(img), 0, 0);
+ gtk_dialog_set_response_sensitive(GTK_DIALOG(win->find),
+ GTK_RESPONSE_OK, FALSE);
+
+ label = gtk_label_new(NULL);
+ gtk_label_set_markup_with_mnemonic(GTK_LABEL(label), _("_Search for:"));
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+
+ f->entry = gtk_entry_new();
+ gtk_entry_set_activates_default(GTK_ENTRY(f->entry), TRUE);
+ gtk_label_set_mnemonic_widget(GTK_LABEL(label), GTK_WIDGET(f->entry));
+ g_signal_connect(G_OBJECT(f->entry), "changed",
+ G_CALLBACK(gaim_gtk_set_sensitive_if_input),
+ win->find);
+ gtk_box_pack_start(GTK_BOX(hbox), f->entry, FALSE, FALSE, 0);
+
+ gtk_widget_show_all(win->find);
+ gtk_widget_grab_focus(f->entry);
+}
+
+static void
+save_writefile_cb(void *user_data, const char *filename)
+{
+ DebugWindow *win = (DebugWindow *)user_data;
+ FILE *fp;
+ char *tmp;
+
+ if ((fp = g_fopen(filename, "w+")) == NULL) {
+ gaim_notify_error(win, NULL, _("Unable to open file."), NULL);
+ return;
+ }
+
+ tmp = gtk_imhtml_get_text(GTK_IMHTML(win->text), NULL, NULL);
+ fprintf(fp, "Gaim Debug log : %s\n", gaim_date_full());
+ fprintf(fp, "%s", tmp);
+ g_free(tmp);
+
+ fclose(fp);
+}
+
+static void
+save_cb(GtkWidget *w, DebugWindow *win)
+{
+ gaim_request_file(win, _("Save Debug Log"), "gaim-debug.log", TRUE,
+ G_CALLBACK(save_writefile_cb), NULL, win);
+}
+
+static void
+clear_cb(GtkWidget *w, DebugWindow *win)
+{
+ gtk_imhtml_clear(GTK_IMHTML(win->text));
+}
+
+static void
+pause_cb(GtkWidget *w, DebugWindow *win)
+{
+ win->paused = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w));
+}
+
+static void
+timestamps_cb(GtkWidget *w, DebugWindow *win)
+{
+ win->timestamps = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w));
+
+ gaim_prefs_set_bool("/gaim/gtk/debug/timestamps", win->timestamps);
+}
+
+static void
+timestamps_pref_cb(const char *name, GaimPrefType type, gpointer value,
+ gpointer data)
+{
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data), GPOINTER_TO_INT(value));
+}
+
+static DebugWindow *
+debug_window_new(void)
+{
+ DebugWindow *win;
+ GtkWidget *vbox;
+ GtkWidget *toolbar;
+ GtkWidget *sw;
+ GtkWidget *button;
+ GtkWidget *image;
+ int width, height;
+
+ win = g_new0(DebugWindow, 1);
+
+ width = gaim_prefs_get_int("/gaim/gtk/debug/width");
+ height = gaim_prefs_get_int("/gaim/gtk/debug/height");
+
+ GAIM_DIALOG(win->window);
+ gaim_debug(GAIM_DEBUG_INFO, "gtkdebug", "Setting dimensions to %d, %d\n",
+ width, height);
+
+ gtk_window_set_default_size(GTK_WINDOW(win->window), width, height);
+ gtk_window_set_role(GTK_WINDOW(win->window), "debug");
+ gtk_window_set_title(GTK_WINDOW(win->window), _("Debug Window"));
+
+ g_signal_connect(G_OBJECT(win->window), "delete_event",
+ G_CALLBACK(debug_window_destroy), NULL);
+ g_signal_connect(G_OBJECT(win->window), "configure_event",
+ G_CALLBACK(configure_cb), win);
+
+ /* Setup the vbox */
+ vbox = gtk_vbox_new(FALSE, 0);
+ gtk_container_add(GTK_CONTAINER(win->window), vbox);
+
+ if (gaim_prefs_get_bool("/gaim/gtk/debug/toolbar")) {
+ /* Setup our top button bar thingie. */
+ toolbar = gtk_toolbar_new();
+ gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_BOTH_HORIZ);
+ gtk_toolbar_set_icon_size(GTK_TOOLBAR(toolbar),
+ GTK_ICON_SIZE_SMALL_TOOLBAR);
+
+ gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 0);
+
+ /* Find button */
+ gtk_toolbar_insert_stock(GTK_TOOLBAR(toolbar), GTK_STOCK_FIND,
+ NULL, NULL, G_CALLBACK(find_cb), win, -1);
+
+ /* Save */
+ gtk_toolbar_insert_stock(GTK_TOOLBAR(toolbar), GTK_STOCK_SAVE,
+ NULL, NULL, G_CALLBACK(save_cb), win, -1);
+
+ /* Clear button */
+ gtk_toolbar_insert_stock(GTK_TOOLBAR(toolbar), GTK_STOCK_CLEAR,
+ NULL, NULL, G_CALLBACK(clear_cb), win, -1);
+
+ gtk_toolbar_insert_space(GTK_TOOLBAR(toolbar), -1);
+
+ /* Pause */
+ image = gtk_image_new_from_stock(GAIM_STOCK_PAUSE, GTK_ICON_SIZE_MENU);
+ button = gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
+ GTK_TOOLBAR_CHILD_TOGGLEBUTTON,
+ NULL, _("Pause"), NULL, NULL,
+ image, G_CALLBACK(pause_cb), win);
+
+ /* Timestamps */
+ button = gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
+ GTK_TOOLBAR_CHILD_TOGGLEBUTTON,
+ NULL, _("Timestamps"), NULL, NULL,
+ NULL, G_CALLBACK(timestamps_cb),
+ win);
+
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),
+ gaim_prefs_get_bool("/gaim/gtk/debug/timestamps"));
+
+ win->timestamps_handle =
+ gaim_prefs_connect_callback("/gaim/gtk/debug/timestamps",
+ timestamps_pref_cb, button);
+ }
+
+ /* Now our scrolled window... */
+ sw = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
+ gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
+ GTK_SHADOW_IN);
+
+ /* ... which has a gtkimhtml in it. */
+ win->text = gtk_imhtml_new(NULL, NULL);
+
+ gtk_container_add(GTK_CONTAINER(sw), win->text);
+
+ /* Pack it in... Not like that, sicko. */
+ gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0);
+
+ gtk_widget_show_all(win->window);
+
+ return win;
+}
+
+static void
+debug_enabled_cb(const char *name, GaimPrefType type, gpointer value,
+ gpointer data)
+{
+ if (value)
+ gaim_gtk_debug_window_show();
+ else
+ gaim_gtk_debug_window_hide();
+}
+
+static void
+gaim_glib_log_handler(const gchar *domain, GLogLevelFlags flags,
+ const gchar *msg, gpointer user_data)
+{
+ GaimDebugLevel level;
+ char *new_msg = NULL;
+ char *new_domain = NULL;
+
+ if ((flags & G_LOG_LEVEL_ERROR) == G_LOG_LEVEL_ERROR)
+ level = GAIM_DEBUG_ERROR;
+ else if ((flags & G_LOG_LEVEL_CRITICAL) == G_LOG_LEVEL_CRITICAL)
+ level = GAIM_DEBUG_FATAL;
+ else if ((flags & G_LOG_LEVEL_WARNING) == G_LOG_LEVEL_WARNING)
+ level = GAIM_DEBUG_WARNING;
+ else if ((flags & G_LOG_LEVEL_MESSAGE) == G_LOG_LEVEL_MESSAGE)
+ level = GAIM_DEBUG_INFO;
+ else if ((flags & G_LOG_LEVEL_INFO) == G_LOG_LEVEL_INFO)
+ level = GAIM_DEBUG_INFO;
+ else if ((flags & G_LOG_LEVEL_DEBUG) == G_LOG_LEVEL_DEBUG)
+ level = GAIM_DEBUG_MISC;
+ else
+ {
+ gaim_debug_warning("gtkdebug",
+ "Unknown glib logging level in %d\n", flags);
+
+ level = GAIM_DEBUG_MISC; /* This will never happen. */
+ }
+
+ if (msg != NULL)
+ new_msg = gaim_utf8_try_convert(msg);
+
+ if (domain != NULL)
+ new_domain = gaim_utf8_try_convert(domain);
+
+ if (new_msg != NULL)
+ {
+ gaim_debug(level, (new_domain != NULL ? new_domain : "g_log"),
+ "%s\n", new_msg);
+
+ g_free(new_msg);
+ }
+
+ if (new_domain != NULL)
+ g_free(new_domain);
+}
+
+#ifdef _WIN32
+static void
+gaim_glib_dummy_print_handler(const gchar *string)
+{
+}
+#endif
+
+void
+gaim_gtk_debug_init(void)
+{
+ /* Debug window preferences. */
+ /*
+ * NOTE: This must be set before prefs are loaded, and the callbacks
+ * set after they are loaded, since prefs sets the enabled
+ * preference here and that loads the window, which calls the
+ * configure event, which overrides the width and height! :P
+ */
+
+ gaim_prefs_add_none("/gaim/gtk/debug");
+ gaim_prefs_add_bool("/gaim/gtk/debug/enabled", FALSE);
+ gaim_prefs_add_bool("/gaim/gtk/debug/timestamps", FALSE);
+ gaim_prefs_add_bool("/gaim/gtk/debug/toolbar", TRUE);
+ gaim_prefs_add_int("/gaim/gtk/debug/width", 450);
+ gaim_prefs_add_int("/gaim/gtk/debug/height", 250);
+
+ gaim_prefs_connect_callback("/gaim/gtk/debug/enabled",
+ debug_enabled_cb, NULL);
+
+#define REGISTER_G_LOG_HANDLER(name) \
+ g_log_set_handler((name), G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL \
+ | G_LOG_FLAG_RECURSION, \
+ gaim_glib_log_handler, NULL)
+
+ /* Register the glib/gtk log handlers. */
+ REGISTER_G_LOG_HANDLER(NULL);
+ REGISTER_G_LOG_HANDLER("Gdk");
+ REGISTER_G_LOG_HANDLER("Gtk");
+ REGISTER_G_LOG_HANDLER("GdkPixbuf");
+ REGISTER_G_LOG_HANDLER("GLib");
+ REGISTER_G_LOG_HANDLER("GModule");
+ REGISTER_G_LOG_HANDLER("GLib-GObject");
+ REGISTER_G_LOG_HANDLER("GThread");
+
+#ifdef _WIN32
+ if (!opt_debug)
+ g_set_print_handler(gaim_glib_dummy_print_handler);
+#endif
+}
+
+void
+gaim_gtk_debug_window_show(void)
+{
+ if (debug_win == NULL)
+ debug_win = debug_window_new();
+
+ gtk_widget_show(debug_win->window);
+
+ gaim_prefs_set_bool("/gaim/gtk/debug/enabled", TRUE);
+}
+
+void
+gaim_gtk_debug_window_hide(void)
+{
+ if (debug_win != NULL) {
+ gtk_widget_destroy(debug_win->window);
+ debug_window_destroy(NULL, NULL, NULL);
+ }
+}
+
+static void
+gaim_gtk_debug_print(GaimDebugLevel level, const char *category,
+ const char *format, va_list args)
+{
+ gchar *arg_s, *ts_s;
+ gboolean timestamps;
+
+ timestamps = gaim_prefs_get_bool("/gaim/gtk/debug/timestamps");
+
+ arg_s = g_strdup_vprintf(format, args);
+
+ if (category == NULL) {
+ ts_s = g_strdup("");
+ }
+ else {
+ /*
+ * If the category is not NULL, then do timestamps.
+ * This IS right. :)
+ */
+ if (timestamps) {
+ gchar mdate[64];
+ time_t mtime = time(NULL);
+
+ strftime(mdate, sizeof(mdate), "%H:%M:%S", localtime(&mtime));
+
+ ts_s = g_strdup_printf("(%s) ", mdate);
+ }
+ else
+ ts_s = g_strdup("");
+ }
+
+ if (gaim_prefs_get_bool("/gaim/gtk/debug/enabled") &&
+ debug_win != NULL && !debug_win->paused) {
+
+ gchar *esc_s, *cat_s, *utf8_s, *s;
+
+ if (category == NULL)
+ cat_s = g_strdup("");
+ else
+ cat_s = g_strdup_printf("<b>%s:</b> ", category);
+
+ esc_s = g_markup_escape_text(arg_s, -1);
+
+ s = g_strdup_printf("<font color=\"%s\">%s%s%s</font>",
+ debug_fg_colors[level], ts_s, cat_s, esc_s);
+
+ g_free(esc_s);
+
+ utf8_s = gaim_utf8_try_convert(s);
+ g_free(s);
+ s = utf8_s;
+
+ if (level == GAIM_DEBUG_FATAL) {
+ gchar *temp = s;
+
+ s = g_strdup_printf("<b>%s</b>", temp);
+ g_free(temp);
+ }
+
+ g_free(cat_s);
+
+ gtk_imhtml_append_text(GTK_IMHTML(debug_win->text), s, 0);
+
+ g_free(s);
+ }
+
+ if (opt_debug) {
+ if (category == NULL)
+ g_print("%s%s", ts_s, arg_s);
+ else
+ g_print("%s%s: %s", ts_s, category, arg_s);
+ }
+
+ g_free(ts_s);
+ g_free(arg_s);
+}
+
+static GaimDebugUiOps ops =
+{
+ gaim_gtk_debug_print
+};
+
+GaimDebugUiOps *
+gaim_gtk_debug_get_ui_ops(void)
+{
+ return &ops;
+}
--- a/src/gtkimhtml.c Wed Feb 09 09:58:22 2005 -0500
+++ b/src/gtkimhtml.c Wed Feb 09 19:07:39 2005 -0500
@@ -147,7 +147,7 @@
gaim_debug_info("imhtml clipboard", "from clipboard: %s\n", clipboard);
- fd = fopen("e:\\gaimcb.txt", "wb");
+ fd = g_fopen("e:\\gaimcb.txt", "wb");
fprintf(fd, "%s", clipboard);
fclose(fd);
#endif
--- a/src/gtkprefs.c Wed Feb 09 09:58:22 2005 -0500
+++ b/src/gtkprefs.c Wed Feb 09 19:07:39 2005 -0500
@@ -585,7 +585,7 @@
theme_install_theme(path, data);
- unlink(path);
+ g_unlink(path);
g_free(path);
}
--- a/src/internal.h Wed Feb 09 09:58:22 2005 -0500
+++ b/src/internal.h Wed Feb 09 19:07:39 2005 -0500
@@ -113,11 +113,27 @@
#define PATHSIZE 1024
#include <glib.h>
+#if GLIB_CHECK_VERSION(2,6,0)
+# include <glib/gstdio.h>
+#endif
#ifdef _WIN32
#include "win32dep.h"
#endif
+#if !GLIB_CHECK_VERSION(2,6,0)
+# define g_freopen freopen
+# define g_fopen fopen
+# define g_rmdir rmdir
+# define g_remove remove
+# define g_unlink unlink
+# define g_lstat lstat
+# define g_stat stat
+# define g_mkdir mkdir
+# define g_rename rename
+# define g_open open
+#endif
+
/* stupid, stupid, stupid */
/* This is a workaround for the fact that G_GINT64_MODIFIER and
* G_GUINT64_FORMAT are wrong, even in Glib >= 2.4 */
--- a/src/log.c Wed Feb 09 09:58:22 2005 -0500
+++ b/src/log.c Wed Feb 09 19:07:39 2005 -0500
@@ -392,7 +392,7 @@
log->logger_data = data = g_new0(struct generic_logger_data, 1);
- data->file = fopen(path, "a");
+ data->file = g_fopen(path, "a");
if (!data->file) {
gaim_debug(GAIM_DEBUG_ERROR, "log",
"Could not create log file %s\n", path);
@@ -447,7 +447,7 @@
struct stat st;
struct generic_logger_data *data = log->logger_data;
- if (!data->path || stat(data->path, &st))
+ if (!data->path || g_stat(data->path, &st))
st.st_size = 0;
return st.st_size;
@@ -490,7 +490,7 @@
char *filename = g_build_filename(dir, date, NULL);
g_free(dir);
- log->logger_data = fopen(filename, "a");
+ log->logger_data = g_fopen(filename, "a");
if (!log->logger_data) {
gaim_debug(GAIM_DEBUG_ERROR, "log", "Could not create log file %s\n", filename);
g_free(filename);
@@ -851,7 +851,7 @@
g_free(logfile);
g_free(pathstr);
- if (!(file = fopen(gaim_stringref_value(pathref), "rb"))) {
+ if (!(file = g_fopen(gaim_stringref_value(pathref), "rb"))) {
gaim_stringref_unref(pathref);
return NULL;
}
@@ -962,7 +962,7 @@
int size;
struct stat st;
- if (stat(pathstr, &st))
+ if (g_stat(pathstr, &st))
size = 0;
else
size = st.st_size;
@@ -976,7 +976,7 @@
static char * old_logger_read (GaimLog *log, GaimLogReadFlags *flags)
{
struct old_logger_data *data = log->logger_data;
- FILE *file = fopen(gaim_stringref_value(data->pathref), "rb");
+ FILE *file = g_fopen(gaim_stringref_value(data->pathref), "rb");
char *read = g_malloc(data->length + 1);
fseek(file, data->offset, SEEK_SET);
fread(read, data->length, 1, file);
--- a/src/pounce.c Wed Feb 09 09:58:22 2005 -0500
+++ b/src/pounce.c Wed Feb 09 19:07:39 2005 -0500
@@ -866,16 +866,16 @@
gaim_debug(GAIM_DEBUG_INFO, "pounces", "Writing pounces to disk.\n");
- fp = fopen(user_dir, "r");
+ fp = g_fopen(user_dir, "r");
if (fp == NULL)
- mkdir(user_dir, S_IRUSR | S_IWUSR | S_IXUSR);
+ g_mkdir(user_dir, S_IRUSR | S_IWUSR | S_IXUSR);
else
fclose(fp);
filename = g_build_filename(user_dir, "pounces.xml.save", NULL);
- if ((fp = fopen(filename, "w")) != NULL) {
+ if ((fp = g_fopen(filename, "w")) != NULL) {
GList *l;
fprintf(fp, "<?xml version='1.0' encoding='UTF-8' ?>\n\n");
@@ -896,16 +896,16 @@
return;
}
- if (stat(filename, &st) || (st.st_size == 0)) {
+ if (g_stat(filename, &st) || (st.st_size == 0)) {
gaim_debug_error("pounces", "Failed to save pounces\n");
- unlink(filename);
+ g_unlink(filename);
g_free(filename);
return;
}
filename_real = g_build_filename(user_dir, "pounces.xml", NULL);
- if (rename(filename, filename_real) < 0) {
+ if (g_rename(filename, filename_real) < 0) {
gaim_debug(GAIM_DEBUG_ERROR, "pounces", "Error renaming %s to %s\n",
filename, filename_real);
}
--- a/src/prefs.c Wed Feb 09 09:58:22 2005 -0500
+++ b/src/prefs.c Wed Feb 09 19:07:39 2005 -0500
@@ -784,15 +784,15 @@
gaim_debug(GAIM_DEBUG_INFO, "prefs", "writing prefs out to disk.\n");
- file = fopen(user_dir, "r");
+ file = g_fopen(user_dir, "r");
if(!file)
- mkdir(user_dir, S_IRUSR | S_IWUSR | S_IXUSR);
+ g_mkdir(user_dir, S_IRUSR | S_IWUSR | S_IXUSR);
else
fclose(file);
filename = g_build_filename(user_dir, "prefs.xml.save", NULL);
- if((file = fopen(filename, "w"))) {
+ if((file = g_fopen(filename, "w"))) {
gaim_prefs_write(file, NULL, 0);
fclose(file);
chmod(filename, S_IRUSR | S_IWUSR);
@@ -803,15 +803,15 @@
return;
}
- if (stat(filename, &st) || (st.st_size == 0)) {
+ if (g_stat(filename, &st) || (st.st_size == 0)) {
gaim_debug_error("prefs", "Failed to save prefs\n");
- unlink(filename);
+ g_unlink(filename);
g_free(filename);
return;
}
filename_real = g_build_filename(user_dir, "prefs.xml", NULL);
- if(rename(filename, filename_real) < 0)
+ if(g_rename(filename, filename_real) < 0)
gaim_debug(GAIM_DEBUG_ERROR, "prefs", "Error renaming %s to %s\n",
filename, filename_real);
--- a/src/protocols/msn/directconn.c Wed Feb 09 09:58:22 2005 -0500
+++ b/src/protocols/msn/directconn.c Wed Feb 09 19:07:39 2005 -0500
@@ -189,7 +189,7 @@
char *str;
str = g_strdup_printf("%s/msntest/w%.4d.bin", g_get_home_dir(), directconn->c);
- FILE *tf = fopen(str, "w");
+ FILE *tf = g_fopen(str, "w");
fwrite(buffer, 1, buf_size, tf);
fclose(tf);
@@ -208,7 +208,7 @@
char *str;
str = g_strdup_printf("/home/revo/msntest/w%.4d.bin", directconn->c);
- FILE *tf = fopen(str, "w");
+ FILE *tf = g_fopen(str, "w");
fwrite(&len, 1, sizeof(len), tf);
fwrite(data, 1, len, tf);
fclose(tf);
@@ -331,7 +331,7 @@
#ifdef DEBUG_DC
str = g_strdup_printf("/home/revo/msntest/r%.4d.bin", directconn->c);
- FILE *tf = fopen(str, "w");
+ FILE *tf = g_fopen(str, "w");
fwrite(body, 1, len, tf);
fclose(tf);
--- a/src/protocols/msn/msn.c Wed Feb 09 09:58:22 2005 -0500
+++ b/src/protocols/msn/msn.c Wed Feb 09 19:07:39 2005 -0500
@@ -354,7 +354,7 @@
slplink = xfer->data;
- if ((fp = fopen(filename, "rb")) == NULL)
+ if ((fp = g_fopen(filename, "rb")) == NULL)
{
GaimAccount *account;
GaimConnection *gc;
--- a/src/protocols/msn/notification.c Wed Feb 09 09:58:22 2005 -0500
+++ b/src/protocols/msn/notification.c Wed Feb 09 19:07:39 2005 -0500
@@ -914,7 +914,7 @@
if (session->passport_info.file != NULL)
{
- unlink(session->passport_info.file);
+ g_unlink(session->passport_info.file);
g_free(session->passport_info.file);
}
@@ -967,7 +967,7 @@
"Error closing temp passport file: %s\n",
strerror(errno));
- unlink(session->passport_info.file);
+ g_unlink(session->passport_info.file);
g_free(session->passport_info.file);
session->passport_info.file = NULL;
}
--- a/src/protocols/msn/session.c Wed Feb 09 09:58:22 2005 -0500
+++ b/src/protocols/msn/session.c Wed Feb 09 19:07:39 2005 -0500
@@ -87,7 +87,7 @@
if (session->passport_info.file != NULL)
{
- unlink(session->passport_info.file);
+ g_unlink(session->passport_info.file);
g_free(session->passport_info.file);
}
--- a/src/protocols/msn/slplink.c Wed Feb 09 09:58:22 2005 -0500
+++ b/src/protocols/msn/slplink.c Wed Feb 09 19:07:39 2005 -0500
@@ -46,7 +46,7 @@
dir = send ? "send" : "recv";
c = send ? m_sc++ : m_rc++;
tmp = g_strdup_printf("%s/msntest/%s/%03d", g_get_home_dir(), dir, c);
- tf = fopen(tmp, "wb");
+ tf = g_fopen(tmp, "wb");
pload = msn_message_gen_payload(msg, &pload_size);
fwrite(pload, 1, pload_size, tf);
fclose(tf);
@@ -502,7 +502,7 @@
if (xfer != NULL)
{
slpmsg->fp =
- fopen(gaim_xfer_get_local_filename(slpmsg->slpcall->xfer),
+ g_fopen(gaim_xfer_get_local_filename(slpmsg->slpcall->xfer),
"wb");
}
}
@@ -636,7 +636,7 @@
glong uni_len = 0;
gsize len;
- if (stat(file_path, &st) == 0)
+ if (g_stat(file_path, &st) == 0)
size = st.st_size;
if(!file_name) {
--- a/src/protocols/msn/slpmsg.c Wed Feb 09 09:58:22 2005 -0500
+++ b/src/protocols/msn/slpmsg.c Wed Feb 09 19:07:39 2005 -0500
@@ -114,9 +114,9 @@
{
struct stat st;
- slpmsg->fp = fopen(file_name, "rb");
+ slpmsg->fp = g_fopen(file_name, "rb");
- if (stat(file_name, &st) == 0)
+ if (g_stat(file_name, &st) == 0)
slpmsg->size = st.st_size;
}
--- a/src/protocols/msn/user.c Wed Feb 09 09:58:22 2005 -0500
+++ b/src/protocols/msn/user.c Wed Feb 09 19:07:39 2005 -0500
@@ -173,11 +173,11 @@
g_return_if_fail(user != NULL);
- if (filename == NULL || stat(filename, &st) == -1)
+ if (filename == NULL || g_stat(filename, &st) == -1)
{
msn_user_set_object(user, NULL);
}
- else if ((fp = fopen(filename, "rb")) != NULL)
+ else if ((fp = g_fopen(filename, "rb")) != NULL)
{
unsigned char *buf;
SHA_CTX ctx;
--- a/src/protocols/oscar/oscar.c Wed Feb 09 09:58:22 2005 -0500
+++ b/src/protocols/oscar/oscar.c Wed Feb 09 19:07:39 2005 -0500
@@ -3297,9 +3297,9 @@
FILE *file;
struct stat st;
- if (!stat(iconfile, &st)) {
+ if (!g_stat(iconfile, &st)) {
char *buf = g_malloc(st.st_size);
- file = fopen(iconfile, "rb");
+ file = g_fopen(iconfile, "rb");
if (file) {
/* XXX - Use g_file_get_contents() */
int len = fread(buf, 1, st.st_size, file);
@@ -4627,9 +4627,9 @@
const char *iconfile = gaim_account_get_buddy_icon(gaim_connection_get_account(gc));
if (iconfile == NULL) {
aim_ssi_delicon(od->sess);
- } else if (!stat(iconfile, &st)) {
+ } else if (!g_stat(iconfile, &st)) {
char *buf = g_malloc(st.st_size);
- FILE *file = fopen(iconfile, "rb");
+ FILE *file = g_fopen(iconfile, "rb");
if (file) {
/* XXX - Use g_file_get_contents()? */
fread(buf, 1, st.st_size, file);
@@ -5441,8 +5441,8 @@
bi->ico_need = FALSE;
}
- if (iconfile && !stat(iconfile, &st)) {
- FILE *file = fopen(iconfile, "rb");
+ if (iconfile && !g_stat(iconfile, &st)) {
+ FILE *file = g_fopen(iconfile, "rb");
if (file) {
char *buf = g_malloc(st.st_size);
/* XXX - Use g_file_get_contents()? */
@@ -6723,9 +6723,9 @@
const char *iconfile = gaim_account_get_buddy_icon(gaim_connection_get_account(gc));
if (iconfile == NULL) {
aim_ssi_delicon(od->sess);
- } else if (!stat(iconfile, &st)) {
+ } else if (!g_stat(iconfile, &st)) {
char *buf = g_malloc(st.st_size);
- FILE *file = fopen(iconfile, "rb");
+ FILE *file = g_fopen(iconfile, "rb");
if (file) {
/* XXX - Use g_file_get_contents()? */
fread(buf, 1, st.st_size, file);
@@ -7225,9 +7225,9 @@
if (iconfile == NULL) {
aim_ssi_delicon(od->sess);
- } else if (!stat(iconfile, &st)) {
+ } else if (!g_stat(iconfile, &st)) {
char *buf = g_malloc(st.st_size);
- file = fopen(iconfile, "rb");
+ file = g_fopen(iconfile, "rb");
if (file) {
md5_state_t *state;
char md5[16];
--- a/src/protocols/rendezvous/rendezvous.c Wed Feb 09 09:58:22 2005 -0500
+++ b/src/protocols/rendezvous/rendezvous.c Wed Feb 09 19:07:39 2005 -0500
@@ -464,10 +464,10 @@
g_return_val_if_fail(filename != NULL, NULL);
- if (stat(filename, &st))
+ if (g_stat(filename, &st))
return NULL;
- if (!(file = fopen(filename, "rb")))
+ if (!(file = g_fopen(filename, "rb")))
return NULL;
*length = st.st_size;
--- a/src/protocols/silc/buddy.c Wed Feb 09 09:58:22 2005 -0500
+++ b/src/protocols/silc/buddy.c Wed Feb 09 19:07:39 2005 -0500
@@ -917,10 +917,10 @@
return;
/* Create dir if it doesn't exist */
- if ((stat(filename, &st)) == -1) {
+ if ((g_stat(filename, &st)) == -1) {
if (errno == ENOENT) {
if (pw->pw_uid == geteuid())
- mkdir(filename, 0755);
+ g_mkdir(filename, 0755);
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/protocols/silc/ft.c Wed Feb 09 19:07:39 2005 -0500
@@ -0,0 +1,408 @@
+/*
+
+ silcgaim_ft.c
+
+ Author: Pekka Riikonen <priikone@silcnet.org>
+
+ Copyright (C) 2004 Pekka Riikonen
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+*/
+
+#include "silcincludes.h"
+#include "silcclient.h"
+#include "silcgaim.h"
+
+/****************************** File Transfer ********************************/
+
+/* This implements the secure file transfer protocol (SFTP) using the SILC
+ SFTP library implementation. The API we use from the SILC Toolkit is the
+ SILC Client file transfer API, as it provides a simple file transfer we
+ need in this case. We could use the SILC SFTP API directly, but it would
+ be an overkill since we'd effectively re-implement the file transfer what
+ the SILC Client's file transfer API already provides.
+
+ From Gaim we do NOT use the FT API to do the transfer as it is very limiting.
+ In fact it does not suite to file transfers like SFTP at all. For example,
+ it assumes that read operations are synchronous what they are not in SFTP.
+ It also assumes that the file transfer socket is to be handled by the Gaim
+ eventloop, and this naturally is something we don't want to do in case of
+ SILC Toolkit. The FT API suites well to purely stream based file transfers
+ like HTTP GET and similar.
+
+ For this reason, we directly access the Gaim GKT FT API and hack the FT
+ API to merely provide the user interface experience and all the magic
+ is done in the SILC Toolkit. Ie. we update the statistics information in
+ the FT API for user interface, and that's it. A bit dirty but until the
+ FT API gets better this is the way to go. Good thing that FT API allowed
+ us to do this. */
+
+typedef struct {
+ SilcGaim sg;
+ SilcClientEntry client_entry;
+ SilcUInt32 session_id;
+ char *hostname;
+ SilcUInt16 port;
+ GaimXfer *xfer;
+
+ SilcClientFileName completion;
+ void *completion_context;
+} *SilcGaimXfer;
+
+static void
+silcgaim_ftp_monitor(SilcClient client,
+ SilcClientConnection conn,
+ SilcClientMonitorStatus status,
+ SilcClientFileError error,
+ SilcUInt64 offset,
+ SilcUInt64 filesize,
+ SilcClientEntry client_entry,
+ SilcUInt32 session_id,
+ const char *filepath,
+ void *context)
+{
+ SilcGaimXfer xfer = context;
+ GaimConnection *gc = xfer->sg->gc;
+ char tmp[256];
+
+ if (status == SILC_CLIENT_FILE_MONITOR_CLOSED) {
+ gaim_xfer_unref(xfer->xfer);
+ silc_free(xfer);
+ return;
+ }
+
+ if (status == SILC_CLIENT_FILE_MONITOR_KEY_AGREEMENT)
+ return;
+
+ if (status == SILC_CLIENT_FILE_MONITOR_ERROR) {
+ if (error == SILC_CLIENT_FILE_NO_SUCH_FILE) {
+ g_snprintf(tmp, sizeof(tmp), "No such file %s",
+ filepath ? filepath : "[N/A]");
+ gaim_notify_error(gc, _("Secure File Transfer"),
+ _("Error during file transfer"), tmp);
+ } else if (error == SILC_CLIENT_FILE_PERMISSION_DENIED) {
+ gaim_notify_error(gc, _("Secure File Transfer"),
+ _("Error during file transfer"),
+ _("Permission denied"));
+ } else if (error == SILC_CLIENT_FILE_KEY_AGREEMENT_FAILED) {
+ gaim_notify_error(gc, _("Secure File Transfer"),
+ _("Error during file transfer"),
+ _("Key agreement failed"));
+ } else if (error == SILC_CLIENT_FILE_UNKNOWN_SESSION) {
+ gaim_notify_error(gc, _("Secure File Transfer"),
+ _("Error during file transfer"),
+ _("File transfer sessions does not exist"));
+ } else {
+ gaim_notify_error(gc, _("Secure File Transfer"),
+ _("Error during file transfer"), NULL);
+ }
+ silc_client_file_close(client, conn, session_id);
+ gaim_xfer_unref(xfer->xfer);
+ silc_free(xfer);
+ return;
+ }
+
+ /* Update file transfer UI */
+ if (!offset && filesize)
+ gaim_xfer_set_size(xfer->xfer, filesize);
+ if (offset && filesize) {
+ xfer->xfer->bytes_sent = offset;
+ xfer->xfer->bytes_remaining = filesize - offset;
+ }
+ gaim_xfer_update_progress(xfer->xfer);
+
+ if (status == SILC_CLIENT_FILE_MONITOR_SEND ||
+ status == SILC_CLIENT_FILE_MONITOR_RECEIVE) {
+ if (offset == filesize) {
+ /* Download finished */
+ gaim_xfer_set_completed(xfer->xfer, TRUE);
+ silc_client_file_close(client, conn, session_id);
+ }
+ }
+}
+
+static void
+silcgaim_ftp_cancel(GaimXfer *x)
+{
+ SilcGaimXfer xfer = x->data;
+ xfer->xfer->status = GAIM_XFER_STATUS_CANCEL_LOCAL;
+ gaim_xfer_update_progress(xfer->xfer);
+ silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id);
+}
+
+static void
+silcgaim_ftp_ask_name_cancel(GaimXfer *x)
+{
+ SilcGaimXfer xfer = x->data;
+
+ /* Cancel the transmission */
+ xfer->completion(NULL, xfer->completion_context);
+ silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id);
+}
+
+static void
+silcgaim_ftp_ask_name_ok(GaimXfer *x)
+{
+ SilcGaimXfer xfer = x->data;
+ const char *name;
+
+ name = gaim_xfer_get_local_filename(x);
+ g_unlink(name);
+ xfer->completion(name, xfer->completion_context);
+}
+
+static void
+silcgaim_ftp_ask_name(SilcClient client,
+ SilcClientConnection conn,
+ SilcUInt32 session_id,
+ const char *remote_filename,
+ SilcClientFileName completion,
+ void *completion_context,
+ void *context)
+{
+ SilcGaimXfer xfer = context;
+
+ xfer->completion = completion;
+ xfer->completion_context = completion_context;
+
+ gaim_xfer_set_init_fnc(xfer->xfer, silcgaim_ftp_ask_name_ok);
+ gaim_xfer_set_request_denied_fnc(xfer->xfer, silcgaim_ftp_ask_name_cancel);
+
+ /* Request to save the file */
+ gaim_xfer_set_filename(xfer->xfer, remote_filename);
+ gaim_xfer_request(xfer->xfer);
+}
+
+static void
+silcgaim_ftp_request_result(GaimXfer *x)
+{
+ SilcGaimXfer xfer = x->data;
+ SilcClientFileError status;
+ GaimConnection *gc = xfer->sg->gc;
+
+ if (gaim_xfer_get_status(x) != GAIM_XFER_STATUS_ACCEPTED)
+ return;
+
+ /* Start the file transfer */
+ status = silc_client_file_receive(xfer->sg->client, xfer->sg->conn,
+ silcgaim_ftp_monitor, xfer,
+ NULL, xfer->session_id,
+ silcgaim_ftp_ask_name, xfer);
+ switch (status) {
+ case SILC_CLIENT_FILE_OK:
+ return;
+ break;
+
+ case SILC_CLIENT_FILE_UNKNOWN_SESSION:
+ gaim_notify_error(gc, _("Secure File Transfer"),
+ _("No file transfer session active"), NULL);
+ break;
+
+ case SILC_CLIENT_FILE_ALREADY_STARTED:
+ gaim_notify_error(gc, _("Secure File Transfer"),
+ _("File transfer already started"), NULL);
+ break;
+
+ case SILC_CLIENT_FILE_KEY_AGREEMENT_FAILED:
+ gaim_notify_error(gc, _("Secure File Transfer"),
+ _("Could not perform key agreement for file transfer"),
+ NULL);
+ break;
+
+ default:
+ gaim_notify_error(gc, _("Secure File Transfer"),
+ _("Could not start the file transfer"), NULL);
+ break;
+ }
+
+ /* Error */
+ gaim_xfer_unref(xfer->xfer);
+ g_free(xfer->hostname);
+ silc_free(xfer);
+}
+
+static void
+silcgaim_ftp_request_denied(GaimXfer *x)
+{
+
+}
+
+void silcgaim_ftp_request(SilcClient client, SilcClientConnection conn,
+ SilcClientEntry client_entry, SilcUInt32 session_id,
+ const char *hostname, SilcUInt16 port)
+{
+ GaimConnection *gc = client->application;
+ SilcGaim sg = gc->proto_data;
+ SilcGaimXfer xfer;
+
+ xfer = silc_calloc(1, sizeof(*xfer));
+ if (!xfer) {
+ silc_client_file_close(sg->client, sg->conn, xfer->session_id);
+ return;
+ }
+
+ xfer->sg = sg;
+ xfer->client_entry = client_entry;
+ xfer->session_id = session_id;
+ xfer->hostname = g_strdup(hostname);
+ xfer->port = port;
+ xfer->xfer = gaim_xfer_new(xfer->sg->account, GAIM_XFER_RECEIVE,
+ xfer->client_entry->nickname);
+ if (!xfer->xfer) {
+ silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id);
+ g_free(xfer->hostname);
+ silc_free(xfer);
+ return;
+ }
+ gaim_xfer_set_init_fnc(xfer->xfer, silcgaim_ftp_request_result);
+ gaim_xfer_set_request_denied_fnc(xfer->xfer, silcgaim_ftp_request_denied);
+ gaim_xfer_set_cancel_recv_fnc(xfer->xfer, silcgaim_ftp_cancel);
+ xfer->xfer->remote_ip = g_strdup(hostname);
+ xfer->xfer->remote_port = port;
+ xfer->xfer->data = xfer;
+
+ /* File transfer request */
+ gaim_xfer_request(xfer->xfer);
+}
+
+static void
+silcgaim_ftp_send_cancel(GaimXfer *x)
+{
+ SilcGaimXfer xfer = x->data;
+ silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id);
+ gaim_xfer_unref(xfer->xfer);
+ g_free(xfer->hostname);
+ silc_free(xfer);
+}
+
+static void
+silcgaim_ftp_send(GaimXfer *x)
+{
+ SilcGaimXfer xfer = x->data;
+ const char *name;
+ char *local_ip = NULL, *remote_ip = NULL;
+ gboolean local = TRUE;
+
+ name = gaim_xfer_get_local_filename(x);
+
+ /* Do the same magic what we do with key agreement (see silcgaim_buddy.c)
+ to see if we are behind NAT. */
+ if (silc_net_check_local_by_sock(xfer->sg->conn->sock->sock,
+ NULL, &local_ip)) {
+ /* Check if the IP is private */
+ if (silcgaim_ip_is_private(local_ip)) {
+ local = FALSE;
+ /* Local IP is private, resolve the remote server IP to see whether
+ we are talking to Internet or just on LAN. */
+ if (silc_net_check_host_by_sock(xfer->sg->conn->sock->sock, NULL,
+ &remote_ip))
+ if (silcgaim_ip_is_private(remote_ip))
+ /* We assume we are in LAN. Let's provide the connection point. */
+ local = TRUE;
+ }
+ }
+
+ if (local && !local_ip)
+ local_ip = silc_net_localip();
+
+ /* Send the file */
+ silc_client_file_send(xfer->sg->client, xfer->sg->conn,
+ silcgaim_ftp_monitor, xfer,
+ local_ip, 0, !local, xfer->client_entry,
+ name, &xfer->session_id);
+
+ silc_free(local_ip);
+ silc_free(remote_ip);
+}
+
+static void
+silcgaim_ftp_send_file_resolved(SilcClient client,
+ SilcClientConnection conn,
+ SilcClientEntry *clients,
+ SilcUInt32 clients_count,
+ void *context)
+{
+ GaimConnection *gc = client->application;
+ char tmp[256];
+
+ if (!clients) {
+ g_snprintf(tmp, sizeof(tmp),
+ _("User %s is not present in the network"),
+ (const char *)context);
+ gaim_notify_error(gc, _("Secure File Transfer"),
+ _("Cannot send file"), tmp);
+ silc_free(context);
+ return;
+ }
+
+ silcgaim_ftp_send_file(client->application, (const char *)context, NULL);
+ silc_free(context);
+}
+
+void silcgaim_ftp_send_file(GaimConnection *gc, const char *name, const char *file)
+{
+ SilcGaim sg = gc->proto_data;
+ SilcClient client = sg->client;
+ SilcClientConnection conn = sg->conn;
+ SilcClientEntry *clients;
+ SilcUInt32 clients_count;
+ SilcGaimXfer xfer;
+ char *nickname;
+
+ if (!name)
+ return;
+
+ if (!silc_parse_userfqdn(name, &nickname, NULL))
+ return;
+
+#ifndef _WIN32
+ silc_debug = TRUE;
+ silc_log_set_debug_string("*client*,*ftp*");
+#endif
+
+ /* Find client entry */
+ clients = silc_client_get_clients_local(client, conn, nickname, name,
+ &clients_count);
+ if (!clients) {
+ silc_client_get_clients(client, conn, nickname, NULL,
+ silcgaim_ftp_send_file_resolved,
+ strdup(name));
+ silc_free(nickname);
+ return;
+ }
+
+ xfer = silc_calloc(1, sizeof(*xfer));
+ if (!xfer)
+ return;
+ xfer->sg = sg;
+ xfer->client_entry = clients[0];
+ xfer->xfer = gaim_xfer_new(xfer->sg->account, GAIM_XFER_SEND,
+ xfer->client_entry->nickname);
+ if (!xfer->xfer) {
+ silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id);
+ g_free(xfer->hostname);
+ silc_free(xfer);
+ return;
+ }
+ gaim_xfer_set_init_fnc(xfer->xfer, silcgaim_ftp_send);
+ gaim_xfer_set_request_denied_fnc(xfer->xfer, silcgaim_ftp_request_denied);
+ gaim_xfer_set_cancel_send_fnc(xfer->xfer, silcgaim_ftp_send_cancel);
+ xfer->xfer->data = xfer;
+
+ /* Choose file to send */
+ if (file)
+ gaim_xfer_request_accepted(xfer->xfer, file);
+ else
+ gaim_xfer_request(xfer->xfer);
+
+ silc_free(clients);
+ silc_free(nickname);
+}
--- a/src/protocols/silc/ops.c Wed Feb 09 09:58:22 2005 -0500
+++ b/src/protocols/silc/ops.c Wed Feb 09 19:07:39 2005 -0500
@@ -1469,7 +1469,7 @@
case SILC_CLIENT_CONN_SUCCESS_RESUME:
gaim_connection_set_state(gc, GAIM_CONNECTED);
serv_finish_login(gc);
- unlink(silcgaim_session_file(gaim_account_get_username(sg->account)));
+ g_unlink(silcgaim_session_file(gaim_account_get_username(sg->account)));
/* Send any UMODEs configured for account */
reject_watch = gaim_account_get_bool(sg->account, "reject-watch", FALSE);
@@ -1489,7 +1489,7 @@
break;
case SILC_CLIENT_CONN_ERROR:
gaim_connection_error(gc, _("Error during connecting to SILC Server"));
- unlink(silcgaim_session_file(gaim_account_get_username(sg->account)));
+ g_unlink(silcgaim_session_file(gaim_account_get_username(sg->account)));
break;
case SILC_CLIENT_CONN_ERROR_KE:
@@ -1504,7 +1504,7 @@
gaim_connection_error(gc,
_("Resuming detached session failed. "
"Press Reconnect to create new connection."));
- unlink(silcgaim_session_file(gaim_account_get_username(sg->account)));
+ g_unlink(silcgaim_session_file(gaim_account_get_username(sg->account)));
break;
case SILC_CLIENT_CONN_ERROR_TIMEOUT:
@@ -1531,7 +1531,7 @@
SilcGaim sg = gc->proto_data;
if (sg->resuming && !sg->detaching)
- unlink(silcgaim_session_file(gaim_account_get_username(sg->account)));
+ g_unlink(silcgaim_session_file(gaim_account_get_username(sg->account)));
sg->conn = NULL;
@@ -1822,7 +1822,7 @@
/* Save the detachment data to file. */
file = silcgaim_session_file(gaim_account_get_username(sg->account));
- unlink(file);
+ g_unlink(file);
silc_file_writefile(file, detach_data, detach_data_len);
}
--- a/src/protocols/silc/pk.c Wed Feb 09 09:58:22 2005 -0500
+++ b/src/protocols/silc/pk.c Wed Feb 09 19:07:39 2005 -0500
@@ -216,7 +216,7 @@
babbleprint = verify->babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
/* Check whether this key already exists */
- if (stat(ipf, &st) < 0 && (!hostf || stat(hostf, &st) < 0)) {
+ if (g_stat(ipf, &st) < 0 && (!hostf || g_stat(hostf, &st) < 0)) {
/* Key does not exist, ask user to verify the key and save it */
silcgaim_verify_ask(name ? name : entity,
fingerprint, babbleprint, verify);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/protocols/silc/util.c Wed Feb 09 19:07:39 2005 -0500
@@ -0,0 +1,568 @@
+/*
+
+ silcgaim_util.c
+
+ Author: Pekka Riikonen <priikone@silcnet.org>
+
+ Copyright (C) 2004 Pekka Riikonen
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+*/
+
+#include "silcincludes.h"
+#include "silcclient.h"
+#include "silcgaim.h"
+
+/**************************** Utility Routines *******************************/
+
+static char str[256], str2[256];
+
+const char *silcgaim_silcdir(void)
+{
+ const char *hd = gaim_home_dir();
+ memset(str, 0, sizeof(str));
+ g_snprintf(str, sizeof(str) - 1, "%s" G_DIR_SEPARATOR_S ".silc", hd ? hd : "/tmp");
+ return (const char *)str;
+}
+
+const char *silcgaim_session_file(const char *account)
+{
+ memset(str2, 0, sizeof(str2));
+ g_snprintf(str2, sizeof(str2) - 1, "%s" G_DIR_SEPARATOR_S "%s_session",
+ silcgaim_silcdir(), account);
+ return (const char *)str2;
+}
+
+gboolean silcgaim_ip_is_private(const char *ip)
+{
+ if (silc_net_is_ip4(ip)) {
+ if (!strncmp(ip, "10.", 3)) {
+ return TRUE;
+ } else if (!strncmp(ip, "172.", 4) && strlen(ip) > 6) {
+ char tmp[3];
+ int s;
+ memset(tmp, 0, sizeof(tmp));
+ strncpy(tmp, ip + 4, 2);
+ s = atoi(tmp);
+ if (s >= 16 && s <= 31)
+ return TRUE;
+ } else if (!strncmp(ip, "192.168.", 8)) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/* This checks stats for various SILC files and directories. First it
+ checks if ~/.silc directory exist and is owned by the correct user. If
+ it doesn't exist, it will create the directory. After that it checks if
+ user's Public and Private key files exists and creates them if needed. */
+
+gboolean silcgaim_check_silc_dir(GaimConnection *gc)
+{
+ char filename[256], file_public_key[256], file_private_key[256];
+ char servfilename[256], clientfilename[256], friendsfilename[256];
+ struct stat st;
+ struct passwd *pw;
+
+ pw = getpwuid(getuid());
+ if (!pw) {
+ gaim_debug_error("silc", "silc: %s\n", strerror(errno));
+ return FALSE;
+ }
+
+ g_snprintf(filename, sizeof(filename) - 1, "%s", silcgaim_silcdir());
+ g_snprintf(servfilename, sizeof(servfilename) - 1, "%s" G_DIR_SEPARATOR_S "serverkeys",
+ silcgaim_silcdir());
+ g_snprintf(clientfilename, sizeof(clientfilename) - 1, "%s" G_DIR_SEPARATOR_S "clientkeys",
+ silcgaim_silcdir());
+ g_snprintf(friendsfilename, sizeof(friendsfilename) - 1, "%s" G_DIR_SEPARATOR_S "friends",
+ silcgaim_silcdir());
+
+ /*
+ * Check ~/.silc directory
+ */
+ if ((g_stat(filename, &st)) == -1) {
+ /* If dir doesn't exist */
+ if (errno == ENOENT) {
+ if (pw->pw_uid == geteuid()) {
+ if ((g_mkdir(filename, 0755)) == -1) {
+ gaim_debug_error("silc", "Couldn't create '%s' directory\n", filename);
+ return FALSE;
+ }
+ } else {
+ gaim_debug_error("silc", "Couldn't create '%s' directory due to a wrong uid!\n",
+ filename);
+ return FALSE;
+ }
+ } else {
+ gaim_debug_error("silc", "Couldn't stat '%s' directory, error: %s\n", filename, strerror(errno));
+ return FALSE;
+ }
+ } else {
+#ifndef _WIN32
+ /* Check the owner of the dir */
+ if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
+ gaim_debug_error("silc", "You don't seem to own '%s' directory\n",
+ filename);
+ return FALSE;
+ }
+#endif
+ }
+
+ /*
+ * Check ~./silc/serverkeys directory
+ */
+ if ((g_stat(servfilename, &st)) == -1) {
+ /* If dir doesn't exist */
+ if (errno == ENOENT) {
+ if (pw->pw_uid == geteuid()) {
+ if ((g_mkdir(servfilename, 0755)) == -1) {
+ gaim_debug_error("silc", "Couldn't create '%s' directory\n", servfilename);
+ return FALSE;
+ }
+ } else {
+ gaim_debug_error("silc", "Couldn't create '%s' directory due to a wrong uid!\n",
+ servfilename);
+ return FALSE;
+ }
+ } else {
+ gaim_debug_error("silc", "Couldn't stat '%s' directory, error: %s\n",
+ servfilename, strerror(errno));
+ return FALSE;
+ }
+ }
+
+ /*
+ * Check ~./silc/clientkeys directory
+ */
+ if ((g_stat(clientfilename, &st)) == -1) {
+ /* If dir doesn't exist */
+ if (errno == ENOENT) {
+ if (pw->pw_uid == geteuid()) {
+ if ((g_mkdir(clientfilename, 0755)) == -1) {
+ gaim_debug_error("silc", "Couldn't create '%s' directory\n", clientfilename);
+ return FALSE;
+ }
+ } else {
+ gaim_debug_error("silc", "Couldn't create '%s' directory due to a wrong uid!\n",
+ clientfilename);
+ return FALSE;
+ }
+ } else {
+ gaim_debug_error("silc", "Couldn't stat '%s' directory, error: %s\n",
+ clientfilename, strerror(errno));
+ return FALSE;
+ }
+ }
+
+ /*
+ * Check ~./silc/friends directory
+ */
+ if ((g_stat(friendsfilename, &st)) == -1) {
+ /* If dir doesn't exist */
+ if (errno == ENOENT) {
+ if (pw->pw_uid == geteuid()) {
+ if ((g_mkdir(friendsfilename, 0755)) == -1) {
+ gaim_debug_error("silc", "Couldn't create '%s' directory\n", friendsfilename);
+ return FALSE;
+ }
+ } else {
+ gaim_debug_error("silc", "Couldn't create '%s' directory due to a wrong uid!\n",
+ friendsfilename);
+ return FALSE;
+ }
+ } else {
+ gaim_debug_error("silc", "Couldn't stat '%s' directory, error: %s\n",
+ friendsfilename, strerror(errno));
+ return FALSE;
+ }
+ }
+
+ /*
+ * Check Public and Private keys
+ */
+ g_snprintf(file_public_key, sizeof(file_public_key) - 1, "%s",
+ gaim_prefs_get_string("/plugins/prpl/silc/pubkey"));
+ g_snprintf(file_private_key, sizeof(file_public_key) - 1, "%s",
+ gaim_prefs_get_string("/plugins/prpl/silc/privkey"));
+
+ if ((g_stat(file_public_key, &st)) == -1) {
+ /* If file doesn't exist */
+ if (errno == ENOENT) {
+ gaim_connection_update_progress(gc, _("Creating SILC key pair..."), 1, 5);
+ silc_create_key_pair(SILCGAIM_DEF_PKCS,
+ SILCGAIM_DEF_PKCS_LEN,
+ file_public_key, file_private_key, NULL,
+ (gc->account->password == NULL) ? "" : gc->account->password,
+ NULL, NULL, NULL, FALSE);
+ g_stat(file_public_key, &st);
+ } else {
+ gaim_debug_error("silc", "Couldn't stat '%s' public key, error: %s\n",
+ file_public_key, strerror(errno));
+ return FALSE;
+ }
+ }
+
+#ifndef _WIN32
+ /* Check the owner of the public key */
+ if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
+ gaim_debug_error("silc", "You don't seem to own your public key!?\n");
+ return FALSE;
+ }
+#endif
+
+ if ((g_stat(file_private_key, &st)) == -1) {
+ /* If file doesn't exist */
+ if (errno == ENOENT) {
+ gaim_connection_update_progress(gc, _("Creating SILC key pair..."), 1, 5);
+ silc_create_key_pair(SILCGAIM_DEF_PKCS,
+ SILCGAIM_DEF_PKCS_LEN,
+ file_public_key, file_private_key, NULL,
+ (gc->account->password == NULL) ? "" : gc->account->password,
+ NULL, NULL, NULL, FALSE);
+ g_stat(file_private_key, &st);
+ } else {
+ gaim_debug_error("silc", "Couldn't stat '%s' private key, error: %s\n",
+ file_private_key, strerror(errno));
+ return FALSE;
+ }
+ }
+
+#ifndef _WIN32
+ /* Check the owner of the private key */
+ if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
+ gaim_debug_error("silc", "You don't seem to own your private key!?\n");
+ return FALSE;
+ }
+
+ /* Check the permissions for the private key */
+ if ((st.st_mode & 0777) != 0600) {
+ gaim_debug_warning("silc", "Wrong permissions in your private key file `%s'!\n"
+ "Trying to change them ... ", file_private_key);
+ if ((chmod(file_private_key, 0600)) == -1) {
+ gaim_debug_error("silc",
+ "Failed to change permissions for private key file!\n"
+ "Permissions for your private key file must be 0600.\n");
+ return FALSE;
+ }
+ gaim_debug_warning("silc", "Done.\n\n");
+ }
+#endif
+
+ return TRUE;
+}
+
+#ifdef _WIN32
+struct passwd *getpwuid(uid_t uid) {
+ struct passwd *pwd = calloc(1, sizeof(struct passwd));
+ return pwd;
+}
+
+uid_t getuid() {
+ return 0;
+}
+
+uid_t geteuid() {
+ return 0;
+}
+#endif
+
+void silcgaim_show_public_key(SilcGaim sg,
+ const char *name, SilcPublicKey public_key,
+ GCallback callback, void *context)
+{
+ SilcPublicKeyIdentifier ident;
+ SilcPKCS pkcs;
+ char *fingerprint, *babbleprint;
+ unsigned char *pk;
+ SilcUInt32 pk_len, key_len = 0;
+ GString *s;
+ char *buf;
+
+ ident = silc_pkcs_decode_identifier(public_key->identifier);
+ if (!ident)
+ return;
+
+ pk = silc_pkcs_public_key_encode(public_key, &pk_len);
+ fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
+ babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
+
+ if (silc_pkcs_alloc(public_key->name, &pkcs)) {
+ key_len = silc_pkcs_public_key_set(pkcs, public_key);
+ silc_pkcs_free(pkcs);
+ }
+
+ s = g_string_new("");
+ if (ident->realname)
+ /* Hint for translators: Please check the tabulator width here and in
+ the next strings (short strings: 2 tabs, longer strings 1 tab,
+ sum: 3 tabs or 24 characters) */
+ g_string_append_printf(s, _("Real Name: \t%s\n"), ident->realname);
+ if (ident->username)
+ g_string_append_printf(s, _("User Name: \t%s\n"), ident->username);
+ if (ident->email)
+ g_string_append_printf(s, _("EMail: \t\t%s\n"), ident->email);
+ if (ident->host)
+ g_string_append_printf(s, _("Host Name: \t%s\n"), ident->host);
+ if (ident->org)
+ g_string_append_printf(s, _("Organization: \t%s\n"), ident->org);
+ if (ident->country)
+ g_string_append_printf(s, _("Country: \t%s\n"), ident->country);
+ g_string_append_printf(s, _("Algorithm: \t%s\n"), public_key->name);
+ g_string_append_printf(s, _("Key Length: \t%d bits\n"), (int)key_len);
+ g_string_append_printf(s, "\n");
+ g_string_append_printf(s, _("Public Key Fingerprint:\n%s\n\n"), fingerprint);
+ g_string_append_printf(s, _("Public Key Babbleprint:\n%s"), babbleprint);
+
+ buf = g_string_free(s, FALSE);
+
+ gaim_request_action(NULL, _("Public Key Information"),
+ _("Public Key Information"),
+ buf, 0, context, 1,
+ _("Close"), callback);
+
+ g_free(buf);
+ silc_free(fingerprint);
+ silc_free(babbleprint);
+ silc_free(pk);
+ silc_pkcs_free_identifier(ident);
+}
+
+SilcAttributePayload
+silcgaim_get_attr(SilcDList attrs, SilcAttribute attribute)
+{
+ SilcAttributePayload attr = NULL;
+
+ if (!attrs)
+ return NULL;
+
+ silc_dlist_start(attrs);
+ while ((attr = silc_dlist_get(attrs)) != SILC_LIST_END)
+ if (attribute == silc_attribute_get_attribute(attr))
+ break;
+
+ return attr;
+}
+
+void silcgaim_get_umode_string(SilcUInt32 mode, char *buf,
+ SilcUInt32 buf_size)
+{
+ memset(buf, 0, buf_size);
+ if ((mode & SILC_UMODE_SERVER_OPERATOR) ||
+ (mode & SILC_UMODE_ROUTER_OPERATOR)) {
+ strcat(buf, (mode & SILC_UMODE_SERVER_OPERATOR) ?
+ "[server operator] " :
+ (mode & SILC_UMODE_ROUTER_OPERATOR) ?
+ "[SILC operator] " : "[unknown mode] ");
+ }
+ if (mode & SILC_UMODE_GONE)
+ strcat(buf, "[away] ");
+ if (mode & SILC_UMODE_INDISPOSED)
+ strcat(buf, "[indisposed] ");
+ if (mode & SILC_UMODE_BUSY)
+ strcat(buf, "[busy] ");
+ if (mode & SILC_UMODE_PAGE)
+ strcat(buf, "[wake me up] ");
+ if (mode & SILC_UMODE_HYPER)
+ strcat(buf, "[hyperactive] ");
+ if (mode & SILC_UMODE_ROBOT)
+ strcat(buf, "[robot] ");
+ if (mode & SILC_UMODE_ANONYMOUS)
+ strcat(buf, "[anonymous] ");
+ if (mode & SILC_UMODE_BLOCK_PRIVMSG)
+ strcat(buf, "[blocks private messages] ");
+ if (mode & SILC_UMODE_DETACHED)
+ strcat(buf, "[detached] ");
+ if (mode & SILC_UMODE_REJECT_WATCHING)
+ strcat(buf, "[rejects watching] ");
+ if (mode & SILC_UMODE_BLOCK_INVITE)
+ strcat(buf, "[blocks invites] ");
+}
+
+void silcgaim_get_chmode_string(SilcUInt32 mode, char *buf,
+ SilcUInt32 buf_size)
+{
+ memset(buf, 0, buf_size);
+ if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)
+ strcat(buf, "[permanent] ");
+ if (mode & SILC_CHANNEL_MODE_PRIVATE)
+ strcat(buf, "[private] ");
+ if (mode & SILC_CHANNEL_MODE_SECRET)
+ strcat(buf, "[secret] ");
+ if (mode & SILC_CHANNEL_MODE_SECRET)
+ strcat(buf, "[secret] ");
+ if (mode & SILC_CHANNEL_MODE_PRIVKEY)
+ strcat(buf, "[private key] ");
+ if (mode & SILC_CHANNEL_MODE_INVITE)
+ strcat(buf, "[invite only] ");
+ if (mode & SILC_CHANNEL_MODE_TOPIC)
+ strcat(buf, "[topic restricted] ");
+ if (mode & SILC_CHANNEL_MODE_ULIMIT)
+ strcat(buf, "[user count limit] ");
+ if (mode & SILC_CHANNEL_MODE_PASSPHRASE)
+ strcat(buf, "[passphrase auth] ");
+ if (mode & SILC_CHANNEL_MODE_CHANNEL_AUTH)
+ strcat(buf, "[public key auth] ");
+ if (mode & SILC_CHANNEL_MODE_SILENCE_USERS)
+ strcat(buf, "[users silenced] ");
+ if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS)
+ strcat(buf, "[operators silenced] ");
+}
+
+void silcgaim_get_chumode_string(SilcUInt32 mode, char *buf,
+ SilcUInt32 buf_size)
+{
+ memset(buf, 0, buf_size);
+ if (mode & SILC_CHANNEL_UMODE_CHANFO)
+ strcat(buf, "[founder] ");
+ if (mode & SILC_CHANNEL_UMODE_CHANOP)
+ strcat(buf, "[operator] ");
+ if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)
+ strcat(buf, "[blocks messages] ");
+ if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)
+ strcat(buf, "[blocks user messages] ");
+ if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)
+ strcat(buf, "[blocks robot messages] ");
+ if (mode & SILC_CHANNEL_UMODE_QUIET)
+ strcat(buf, "[quieted] ");
+}
+
+void
+silcgaim_parse_attrs(SilcDList attrs, char **moodstr, char **statusstr,
+ char **contactstr, char **langstr, char **devicestr,
+ char **tzstr, char **geostr)
+{
+ SilcAttributePayload attr;
+ SilcAttributeMood mood = 0;
+ SilcAttributeContact contact;
+ SilcAttributeObjDevice device;
+ SilcAttributeObjGeo geo;
+
+ char tmp[1024];
+ GString *s;
+
+ *moodstr = NULL;
+ *statusstr = NULL;
+ *contactstr = NULL;
+ *langstr = NULL;
+ *devicestr = NULL;
+ *tzstr = NULL;
+ *geostr = NULL;
+
+ if (!attrs)
+ return;
+
+ s = g_string_new("");
+ attr = silcgaim_get_attr(attrs, SILC_ATTRIBUTE_STATUS_MOOD);
+ if (attr && silc_attribute_get_object(attr, &mood, sizeof(mood))) {
+ if (mood & SILC_ATTRIBUTE_MOOD_HAPPY)
+ g_string_append_printf(s, "[%s] ", _("Happy"));
+ if (mood & SILC_ATTRIBUTE_MOOD_SAD)
+ g_string_append_printf(s, "[%s] ", _("Sad"));
+ if (mood & SILC_ATTRIBUTE_MOOD_ANGRY)
+ g_string_append_printf(s, "[%s] ", _("Angry"));
+ if (mood & SILC_ATTRIBUTE_MOOD_JEALOUS)
+ g_string_append_printf(s, "[%s] ", _("Jealous"));
+ if (mood & SILC_ATTRIBUTE_MOOD_ASHAMED)
+ g_string_append_printf(s, "[%s] ", _("Ashamed"));
+ if (mood & SILC_ATTRIBUTE_MOOD_INVINCIBLE)
+ g_string_append_printf(s, "[%s] ", _("Invincible"));
+ if (mood & SILC_ATTRIBUTE_MOOD_INLOVE)
+ g_string_append_printf(s, "[%s] ", _("In Love"));
+ if (mood & SILC_ATTRIBUTE_MOOD_SLEEPY)
+ g_string_append_printf(s, "[%s] ", _("Sleepy"));
+ if (mood & SILC_ATTRIBUTE_MOOD_BORED)
+ g_string_append_printf(s, "[%s] ", _("Bored"));
+ if (mood & SILC_ATTRIBUTE_MOOD_EXCITED)
+ g_string_append_printf(s, "[%s] ", _("Excited"));
+ if (mood & SILC_ATTRIBUTE_MOOD_ANXIOUS)
+ g_string_append_printf(s, "[%s] ", _("Anxious"));
+ }
+ if (strlen(s->str)) {
+ *moodstr = s->str;
+ g_string_free(s, FALSE);
+ } else
+ g_string_free(s, TRUE);
+
+ attr = silcgaim_get_attr(attrs, SILC_ATTRIBUTE_STATUS_FREETEXT);
+ memset(tmp, 0, sizeof(tmp));
+ if (attr && silc_attribute_get_object(attr, tmp, sizeof(tmp)))
+ *statusstr = g_strdup(tmp);
+
+ s = g_string_new("");
+ attr = silcgaim_get_attr(attrs, SILC_ATTRIBUTE_PREFERRED_CONTACT);
+ if (attr && silc_attribute_get_object(attr, &contact, sizeof(contact))) {
+ if (contact & SILC_ATTRIBUTE_CONTACT_CHAT)
+ g_string_append_printf(s, "[%s] ", _("Chat"));
+ if (contact & SILC_ATTRIBUTE_CONTACT_EMAIL)
+ g_string_append_printf(s, "[%s] ", _("Email"));
+ if (contact & SILC_ATTRIBUTE_CONTACT_CALL)
+ g_string_append_printf(s, "[%s] ", _("Phone"));
+ if (contact & SILC_ATTRIBUTE_CONTACT_PAGE)
+ g_string_append_printf(s, "[%s] ", _("Paging"));
+ if (contact & SILC_ATTRIBUTE_CONTACT_SMS)
+ g_string_append_printf(s, "[%s] ", _("SMS"));
+ if (contact & SILC_ATTRIBUTE_CONTACT_MMS)
+ g_string_append_printf(s, "[%s] ", _("MMS"));
+ if (contact & SILC_ATTRIBUTE_CONTACT_VIDEO)
+ g_string_append_printf(s, "[%s] ", _("Video Conferencing"));
+ }
+ if (strlen(s->str)) {
+ *contactstr = s->str;
+ g_string_free(s, FALSE);
+ } else
+ g_string_free(s, TRUE);
+
+ attr = silcgaim_get_attr(attrs, SILC_ATTRIBUTE_PREFERRED_LANGUAGE);
+ memset(tmp, 0, sizeof(tmp));
+ if (attr && silc_attribute_get_object(attr, tmp, sizeof(tmp)))
+ *langstr = g_strdup(tmp);
+
+ s = g_string_new("");
+ attr = silcgaim_get_attr(attrs, SILC_ATTRIBUTE_DEVICE_INFO);
+ memset(&device, 0, sizeof(device));
+ if (attr && silc_attribute_get_object(attr, &device, sizeof(device))) {
+ if (device.type == SILC_ATTRIBUTE_DEVICE_COMPUTER)
+ g_string_append_printf(s, "%s: ", _("Computer"));
+ if (device.type == SILC_ATTRIBUTE_DEVICE_MOBILE_PHONE)
+ g_string_append_printf(s, "%s: ", _("Mobile Phone"));
+ if (device.type == SILC_ATTRIBUTE_DEVICE_PDA)
+ g_string_append_printf(s, "%s: ", _("PDA"));
+ if (device.type == SILC_ATTRIBUTE_DEVICE_TERMINAL)
+ g_string_append_printf(s, "%s: ", _("Terminal"));
+ g_string_append_printf(s, "%s %s %s %s",
+ device.manufacturer ? device.manufacturer : "",
+ device.version ? device.version : "",
+ device.model ? device.model : "",
+ device.language ? device.language : "");
+ }
+ if (strlen(s->str)) {
+ *devicestr = s->str;
+ g_string_free(s, FALSE);
+ } else
+ g_string_free(s, TRUE);
+
+ attr = silcgaim_get_attr(attrs, SILC_ATTRIBUTE_TIMEZONE);
+ memset(tmp, 0, sizeof(tmp));
+ if (attr && silc_attribute_get_object(attr, tmp, sizeof(tmp)))
+ *tzstr = g_strdup(tmp);
+
+ attr = silcgaim_get_attr(attrs, SILC_ATTRIBUTE_GEOLOCATION);
+ memset(&geo, 0, sizeof(geo));
+ if (attr && silc_attribute_get_object(attr, &geo, sizeof(geo)))
+ *geostr = g_strdup_printf("%s %s %s (%s)",
+ geo.longitude ? geo.longitude : "",
+ geo.latitude ? geo.latitude : "",
+ geo.altitude ? geo.altitude : "",
+ geo.accuracy ? geo.accuracy : "");
+}
--- a/src/protocols/toc/toc.c Wed Feb 09 09:58:22 2005 -0500
+++ b/src/protocols/toc/toc.c Wed Feb 09 19:07:39 2005 -0500
@@ -1676,7 +1676,7 @@
write(source, ft, 256);
if (ft->files == 1) {
- ft->file = fopen(ft->filename, "w");
+ ft->file = g_fopen(ft->filename, "w");
if (!ft->file) {
buf = g_strdup_printf(_("Could not open %s for writing!"), ft->filename);
gaim_notify_error(ft->gc, NULL, buf, strerror(errno));
@@ -1691,7 +1691,7 @@
}
} else {
buf = g_strdup_printf("%s/%s", ft->filename, ft->hdr.name);
- ft->file = fopen(buf, "w");
+ ft->file = g_fopen(buf, "w");
g_free(buf);
if (!ft->file) {
buf = g_strdup_printf("Could not open %s/%s for writing!", ft->filename,
@@ -1839,7 +1839,7 @@
read(source, &ft->hdr.bcookie, MIN(256 - 8, ntohs(ft->hdr.hdrlen) - 8));
debug_header(ft);
- stat(ft->filename, &st);
+ g_stat(ft->filename, &st);
fortime = localtime(&st.st_mtime);
basename = g_path_get_basename(ft->filename);
g_snprintf(buf, sizeof(buf), "%2d/%2d/%4d %2d:%2d %8ld %s\r\n",
@@ -1981,7 +1981,7 @@
return;
ft = g_new0(struct file_transfer, 1);
ft->filename = g_strdup(dirname);
- ft->file = fopen(ft->filename, "r");
+ ft->file = g_fopen(ft->filename, "r");
if (!ft->file) {
buf = g_strdup_printf("Unable to open %s for transfer.", ft->filename);
gaim_notify_error(ft->gc, NULL, buf, NULL);
@@ -1990,7 +1990,7 @@
g_free(ft);
return;
}
- if (stat(dirname, &ft->st)) {
+ if (g_stat(dirname, &ft->st)) {
buf = g_strdup_printf("Unable to examine %s.", dirname);
gaim_notify_error(ft->gc, NULL, buf, NULL);
g_free(buf);
--- a/src/protocols/trepia/trepia.c Wed Feb 09 09:58:22 2005 -0500
+++ b/src/protocols/trepia/trepia.c Wed Feb 09 19:07:39 2005 -0500
@@ -1152,10 +1152,10 @@
TrepiaSession *session = gc->proto_data;
struct stat sb;
- if (!stat(filename, &sb)) {
+ if (!g_stat(filename, &sb)) {
FILE *fp;
- if ((fp = fopen(filename, "rb")) != NULL) {
+ if ((fp = g_fopen(filename, "rb")) != NULL) {
char *buf = g_malloc(sb.st_size + 1);
char *temp;
char *out_buf;
--- a/src/protocols/yahoo/yahoo_picture.c Wed Feb 09 09:58:22 2005 -0500
+++ b/src/protocols/yahoo/yahoo_picture.c Wed Feb 09 19:07:39 2005 -0500
@@ -484,8 +484,8 @@
if (yd->logged_in)
yahoo_send_picture_update(gc, 0);
/* TODO: check if we're connected and tell everyone we ain't not one no more */
- } else if (!stat(iconfile, &st)) {
- file = fopen(iconfile, "rb");
+ } else if (!g_stat(iconfile, &st)) {
+ file = g_fopen(iconfile, "rb");
if (file) {
GString *s = g_string_sized_new(st.st_size);
size_t len;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/protocols/zephyr/ZGetWGPort.c Wed Feb 09 19:07:39 2005 -0500
@@ -0,0 +1,42 @@
+/* This file is part of the Project Athena Zephyr Notification System.
+ * It contains source for the ZGetWGPort function.
+ *
+ * Created by: Robert French
+ *
+ * $Source$
+ * $Author$
+ *
+ * Copyright (c) 1987 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, see the file
+ * "mit-copyright.h".
+ */
+/* $Header$ */
+
+#ifndef lint
+static char rcsid_ZGetWGPort_c[] = "$Header$";
+#endif
+
+#include "internal.h"
+
+int ZGetWGPort()
+{
+ char *envptr, name[128];
+ FILE *fp;
+ int wgport;
+
+ envptr = getenv("WGFILE");
+ if (!envptr) {
+ (void) sprintf(name, "/tmp/wg.%d", getuid());
+ envptr = name;
+ }
+ if (!(fp = g_fopen(envptr, "r")))
+ return (-1);
+
+ /* if fscanf fails, return -1 via wgport */
+ if (fscanf(fp, "%d", &wgport) != 1)
+ wgport = -1;
+
+ (void) fclose(fp);
+
+ return (wgport);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/protocols/zephyr/ZVariables.c Wed Feb 09 19:07:39 2005 -0500
@@ -0,0 +1,192 @@
+/* This file is part of the Project Athena Zephyr Notification System.
+ * It contains source for the ZGetVariable, ZSetVariable, and ZUnsetVariable
+ * functions.
+ *
+ * Created by: Robert French
+ *
+ * $Source$
+ * $Author$
+ *
+ * Copyright (c) 1987 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, see the file
+ * "mit-copyright.h".
+ */
+/* $Header$ */
+
+#ifndef lint
+static char rcsid_ZVariables_c[] = "$Header$";
+#endif
+
+#include "internal.h"
+#include "util.h"
+
+#include <ctype.h>
+#include <pwd.h>
+
+static int get_localvarfile __P((char *bfr));
+static char *get_varval __P((char *fn, char *val));
+static int varline __P((char *bfr, char *var));
+
+char *ZGetVariable(var)
+ char *var;
+{
+ char varfile[128], *ret;
+ char *get_varval();
+
+ if (get_localvarfile(varfile))
+ return ((char *)0);
+
+ if ((ret = get_varval(varfile, var)) != ZERR_NONE)
+ return (ret);
+
+ sprintf(varfile, "%s/zephyr.vars", CONFDIR);
+ return (get_varval(varfile, var));
+}
+
+Code_t ZSetVariable(var, value)
+ char *var;
+ char *value;
+{
+ int written;
+ FILE *fpin, *fpout;
+ char varfile[128], varfilebackup[128], varbfr[512];
+
+ written = 0;
+
+ if (get_localvarfile(varfile))
+ return (ZERR_INTERNAL);
+
+ (void) strcpy(varfilebackup, varfile);
+ (void) strcat(varfilebackup, ".backup");
+
+ if (!(fpout = g_fopen(varfilebackup, "w")))
+ return (errno);
+ if ((fpin = g_fopen(varfile, "r")) != NULL) {
+ while (fgets(varbfr, sizeof varbfr, fpin) != (char *) 0) {
+ if (varbfr[strlen(varbfr)-1] < ' ')
+ varbfr[strlen(varbfr)-1] = '\0';
+ if (varline(varbfr, var)) {
+ fprintf(fpout, "%s = %s\n", var, value);
+ written = 1;
+ }
+ else
+ fprintf(fpout, "%s\n", varbfr);
+ }
+ (void) fclose(fpin); /* don't care about errs on input */
+ }
+ if (!written)
+ fprintf(fpout, "%s = %s\n", var, value);
+ if (fclose(fpout) == EOF)
+ return(EIO); /* can't rely on errno */
+ if (g_rename(varfilebackup, varfile))
+ return (errno);
+ return (ZERR_NONE);
+}
+
+Code_t ZUnsetVariable(var)
+ char *var;
+{
+ FILE *fpin, *fpout;
+ char varfile[128], varfilebackup[128], varbfr[512];
+
+ if (get_localvarfile(varfile))
+ return (ZERR_INTERNAL);
+
+ (void) strcpy(varfilebackup, varfile);
+ (void) strcat(varfilebackup, ".backup");
+
+ if (!(fpout = g_fopen(varfilebackup, "w")))
+ return (errno);
+ if ((fpin = g_fopen(varfile, "r")) != NULL) {
+ while (fgets(varbfr, sizeof varbfr, fpin) != (char *) 0) {
+ if (varbfr[strlen(varbfr)-1] < ' ')
+ varbfr[strlen(varbfr)-1] = '\0';
+ if (!varline(varbfr, var))
+ fprintf(fpout, "%s\n", varbfr);
+ }
+ (void) fclose(fpin); /* don't care about read close errs */
+ }
+ if (fclose(fpout) == EOF)
+ return(EIO); /* errno isn't reliable */
+ if (g_rename(varfilebackup, varfile))
+ return (errno);
+ return (ZERR_NONE);
+}
+
+static int get_localvarfile(bfr)
+ char *bfr;
+{
+ const char *envptr;
+ struct passwd *pwd;
+
+ envptr = gaim_home_dir();
+ if (envptr)
+ (void) strcpy(bfr, envptr);
+ else {
+ if (!(pwd = getpwuid((int) getuid()))) {
+ fprintf(stderr, "Zephyr internal failure: Can't find your entry in /etc/passwd\n");
+ return (1);
+ }
+ (void) strcpy(bfr, pwd->pw_dir);
+ }
+
+ (void) strcat(bfr, "/");
+ (void) strcat(bfr, ".zephyr.vars");
+ return (0);
+}
+
+static char *get_varval(fn, var)
+ char *fn;
+ char *var;
+{
+ FILE *fp;
+ static char varbfr[512];
+ int i;
+
+ fp = g_fopen(fn, "r");
+ if (!fp)
+ return ((char *)0);
+
+ while (fgets(varbfr, sizeof varbfr, fp) != (char *) 0) {
+ if (varbfr[strlen(varbfr)-1] < ' ')
+ varbfr[strlen(varbfr)-1] = '\0';
+ if (!(i = varline(varbfr, var)))
+ continue;
+ (void) fclose(fp); /* open read-only, don't care */
+ return (varbfr+i);
+ }
+ (void) fclose(fp); /* open read-only, don't care */
+ return ((char *)0);
+}
+
+/* If the variable in the line bfr[] is the same as var, return index to
+ the variable value, else return 0. */
+static int varline(bfr, var)
+ char *bfr;
+ char *var;
+{
+ register char *cp;
+
+
+ if (!bfr[0] || bfr[0] == '#') /* comment or null line */
+ return (0);
+
+ cp = bfr;
+ while (*cp && !isspace(*cp) && (*cp != '='))
+ cp++;
+
+#define max(a,b) ((a > b) ? (a) : (b))
+
+ if (strncasecmp(bfr, var, max(strlen(var),cp - bfr)))
+ return(0); /* var is not the var in
+ bfr ==> no match */
+
+ cp = strchr(bfr, '=');
+ if (!cp)
+ return(0);
+ cp++;
+ while (*cp && isspace(*cp)) /* space up to variable value */
+ cp++;
+
+ return (cp - bfr); /* return index */
+}
--- a/src/protocols/zephyr/zephyr.c Wed Feb 09 09:58:22 2005 -0500
+++ b/src/protocols/zephyr/zephyr.c Wed Feb 09 19:07:39 2005 -0500
@@ -1315,7 +1315,7 @@
gchar buff[BUFSIZ];
fname = g_strdup_printf("%s/.zephyr.subs", gaim_home_dir());
- f = fopen(fname, "r");
+ f = g_fopen(fname, "r");
if (f) {
char **triple;
char *recip;
@@ -1411,7 +1411,7 @@
}
filename = g_strconcat(gaim_home_dir(), "/.anyone", NULL);
- if ((fd = fopen(filename, "r")) != NULL) {
+ if ((fd = g_fopen(filename, "r")) != NULL) {
while (fgets(buff, BUFSIZ, fd)) {
strip_comments(buff);
if (buff[0]) {
@@ -1716,7 +1716,7 @@
char **triple;
fname = g_strdup_printf("%s/.zephyr.subs", gaim_home_dir());
- fd = fopen(fname, "w");
+ fd = g_fopen(fname, "w");
if (!fd) {
g_free(fname);
@@ -1778,7 +1778,7 @@
FILE *fd;
zephyr_account* zephyr = gc->proto_data;
fname = g_strdup_printf("%s/.anyone", gaim_home_dir());
- fd = fopen(fname, "w");
+ fd = g_fopen(fname, "w");
if (!fd) {
g_free(fname);
return;
--- a/src/status.c Wed Feb 09 09:58:22 2005 -0500
+++ b/src/status.c Wed Feb 09 19:07:39 2005 -0500
@@ -206,16 +206,16 @@
gaim_debug(GAIM_DEBUG_INFO, "status", "Saving statuses to disk\n");
- fp = fopen(user_dir, "r");
+ fp = g_fopen(user_dir, "r");
if (fp == NULL)
- mkdir(user_dir, S_IRUSR | S_IWUSR | S_IXUSR);
+ g_mkdir(user_dir, S_IRUSR | S_IWUSR | S_IXUSR);
else
fclose(fp);
filename = g_build_filename(user_dir, "status.xml.save", NULL);
- if ((fp = fopen(filename, "w")) != NULL) {
+ if ((fp = g_fopen(filename, "w")) != NULL) {
GSList *l;
fprintf(fp, "<?xml version='1.0' encoding='UTF-8' ?>\n\n");
@@ -238,7 +238,7 @@
filename_real = g_build_filename(user_dir, "status.xml", NULL);
- if (rename(filename, filename_real) < 0) {
+ if (g_rename(filename, filename_real) < 0) {
gaim_debug(GAIM_DEBUG_ERROR, "status", "Error renaming %s to %s\n",
filename, filename_real);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/themes.c Wed Feb 09 19:07:39 2005 -0500
@@ -0,0 +1,263 @@
+/*
+ * Themes for Gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#include "internal.h"
+#include "gtkgaim.h"
+
+#include "conversation.h"
+#include "debug.h"
+#include "prpl.h"
+#include "util.h"
+
+#include "gtkconv.h"
+#include "gtkdialogs.h"
+#include "gtkimhtml.h"
+
+struct smiley_list {
+ char *sml;
+ GSList *smileys;
+ struct smiley_list *next;
+};
+
+GSList *smiley_themes = NULL;
+struct smiley_theme *current_smiley_theme;
+
+void smiley_themeize(GtkWidget *imhtml)
+{
+ struct smiley_list *list;
+ if (!current_smiley_theme)
+ return;
+
+ gtk_imhtml_remove_smileys(GTK_IMHTML(imhtml));
+ list = current_smiley_theme->list;
+ while (list) {
+ char *sml = !strcmp(list->sml, "default") ? NULL : list->sml;
+ GSList *icons = list->smileys;
+ while (icons) {
+ gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml), sml, icons->data);
+ icons = icons->next;
+ }
+ list = list->next;
+ }
+}
+
+void load_smiley_theme(const char *file, gboolean load)
+{
+ FILE *f = g_fopen(file, "r");
+ char buf[256];
+ char *i;
+ struct smiley_theme *theme=NULL;
+ struct smiley_list *list = NULL;
+ GSList *lst = smiley_themes;
+ char *dirname;
+
+ if (!f)
+ return;
+
+ while (lst) {
+ struct smiley_theme *thm = lst->data;
+ if (!strcmp(thm->path, file)) {
+ theme = thm;
+ break;
+ }
+ lst = lst->next;
+ }
+
+ if (!theme) {
+ theme = g_new0(struct smiley_theme, 1);
+ theme->path = g_strdup(file);
+ smiley_themes = g_slist_append(smiley_themes, theme);
+ }
+
+ dirname = g_path_get_dirname(file);
+ if (load) {
+ if (current_smiley_theme) {
+ GSList *already_freed = NULL;
+ struct smiley_list *wer = current_smiley_theme->list, *wer2;
+ while (wer) {
+ while (wer->smileys) {
+ GtkIMHtmlSmiley *uio = wer->smileys->data;
+ if (uio->icon)
+ g_object_unref(uio->icon);
+ if (!g_slist_find(already_freed, uio->file)) {
+ g_free(uio->file);
+ already_freed = g_slist_append(already_freed, uio->file);
+ }
+ g_free(uio->smile);
+ g_free(uio);
+ wer->smileys=g_slist_remove(wer->smileys, uio);
+ }
+ wer2 = wer->next;
+ g_free(wer->sml);
+ g_free(wer);
+ wer = wer2;
+ }
+ current_smiley_theme->list = NULL;
+ g_slist_free(already_freed);
+ }
+ current_smiley_theme = theme;
+ }
+
+
+ while (!feof(f)) {
+ if (!fgets(buf, sizeof(buf), f)) {
+ break;
+ }
+
+ if (buf[0] == '#' || buf[0] == '\0')
+ continue;
+
+ i = buf;
+ while (isspace(*i))
+ i++;
+
+ if (*i == '[' && strchr(i, ']') && load) {
+ struct smiley_list *child = g_new0(struct smiley_list, 1);
+ child->sml = g_strndup(i+1, strchr(i, ']') - i - 1);
+ if (theme->list)
+ list->next = child;
+ else
+ theme->list = child;
+ list = child;
+ } else if (!g_ascii_strncasecmp(i, "Name=", strlen("Name="))) {
+ if(theme->name)
+ g_free(theme->name);
+ theme->name = g_strdup(i+ strlen("Name="));
+ theme->name[strlen(theme->name)-1] = 0;
+ } else if (!g_ascii_strncasecmp(i, "Description=", strlen("Description="))) {
+ if(theme->desc)
+ g_free(theme->desc);
+ theme->desc = g_strdup(i + strlen("Description="));
+ theme->desc[strlen(theme->desc)-1] = 0;
+ } else if (!g_ascii_strncasecmp(i, "Icon=", strlen("Icon="))) {
+ if(theme->icon)
+ g_free(theme->icon);
+ theme->icon = g_build_filename(dirname, i + strlen("Icon="), NULL);
+ theme->icon[strlen(theme->icon)-1] = 0;
+ } else if (!g_ascii_strncasecmp(i, "Author=", strlen("Author="))) {
+ if(theme->author)
+ g_free(theme->author);
+ theme->author = g_strdup(i + strlen("Author="));
+ theme->author[strlen(theme->author)-1] = 0;
+ } else if (load && list) {
+ gboolean hidden = FALSE;
+ char *sfile = NULL;
+
+ if (*i == '!' && *(i + 1) == ' ') {
+ hidden = TRUE;
+ i = i + 2;
+ }
+ while (*i) {
+ char l[64];
+ int li = 0;
+ while (!isspace(*i))
+ l[li++] = *(i++);
+ if (!sfile) {
+ l[li] = 0;
+ sfile = g_build_filename(dirname, l, NULL);
+ } else {
+ GtkIMHtmlSmiley *smiley = g_new0(GtkIMHtmlSmiley, 1);
+ l[li] = 0;
+ smiley->file = sfile;
+ smiley->smile = g_strdup(l);
+ smiley->hidden = hidden;
+ list->smileys = g_slist_append(list->smileys, smiley);
+ }
+ while (isspace(*i))
+ i++;
+
+ }
+ }
+ }
+
+ if (load) {
+ GList *cnv;
+
+ for (cnv = gaim_get_conversations(); cnv != NULL; cnv = cnv->next) {
+ GaimConversation *conv = cnv->data;
+
+ if (GAIM_IS_GTK_CONVERSATION(conv)) {
+ smiley_themeize(GAIM_GTK_CONVERSATION(conv)->imhtml);
+ smiley_themeize(GAIM_GTK_CONVERSATION(conv)->entry);
+ }
+ }
+ }
+
+ g_free(dirname);
+ fclose(f);
+}
+
+void smiley_theme_probe()
+{
+ GDir *dir;
+ const gchar *file;
+ gchar *path;
+ int l;
+
+ char* probedirs[3];
+ probedirs[0] = g_build_filename(DATADIR, "pixmaps", "gaim", "smileys", NULL);
+ probedirs[1] = g_build_filename(gaim_user_dir(), "smileys", NULL);
+ probedirs[2] = 0;
+ for (l=0; probedirs[l]; l++) {
+ dir = g_dir_open(probedirs[l], 0, NULL);
+ if (dir) {
+ while ((file = g_dir_read_name(dir))) {
+ path = g_build_filename(probedirs[l], file, "theme", NULL);
+
+ /* Here we check to see that the theme has proper syntax.
+ * We set the second argument to FALSE so that it doesn't load
+ * the theme yet.
+ */
+ load_smiley_theme(path, FALSE);
+ g_free(path);
+ }
+ g_dir_close(dir);
+ } else if (l == 1) {
+ g_mkdir(probedirs[l], S_IRUSR | S_IWUSR | S_IXUSR);
+ }
+ g_free(probedirs[l]);
+ }
+}
+
+GSList *get_proto_smileys(const char *id) {
+ GaimPlugin *proto = gaim_find_prpl(id);
+ struct smiley_list *list, *def;
+
+ if(!current_smiley_theme)
+ return NULL;
+
+ if(!current_smiley_theme->list)
+ return NULL;
+
+ def = list = current_smiley_theme->list;
+
+ while(list) {
+ if(!strcmp(list->sml, "default"))
+ def = list;
+ else if(proto && !strcmp(proto->info->name, list->sml))
+ break;
+
+ list = list->next;
+ }
+
+ return list ? list->smileys : def->smileys;
+}
--- a/src/util.c Wed Feb 09 09:58:22 2005 -0500
+++ b/src/util.c Wed Feb 09 19:07:39 2005 -0500
@@ -1927,7 +1927,7 @@
return -1;
}
- if (mkdir(dir, mode) < 0) {
+ if (g_mkdir(dir, mode) < 0) {
gaim_debug_warning("build_dir", "mkdir: %s\n", strerror(errno));
g_strfreev(components);
g_free(dir);
@@ -1972,7 +1972,7 @@
"Problem creating the template\n");
else
{
- if( (fp = fopen( result, "w+" )) == NULL ) {
+ if( (fp = g_fopen( result, "w+" )) == NULL ) {
gaim_debug(GAIM_DEBUG_ERROR, "gaim_mkstemp",
"Couldn't fopen() %s\n", result);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/win32/libc_interface.c Wed Feb 09 19:07:39 2005 -0500
@@ -0,0 +1,376 @@
+/*
+ * gaim
+ *
+ * File: libc_interface.c
+ * Date: October 14, 2002
+ * Description: libc interface for Windows api
+ *
+ * Copyright (C) 2002-2003, Herman Bloggs <hermanator12002@yahoo.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <io.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/timeb.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <glib.h>
+#include "debug.h"
+#include "libc_internal.h"
+
+#if !GLIB_CHECK_VERSION(2,6,0)
+# define g_remove remove
+#endif
+/*
+ * PROTOS
+ */
+
+/*
+ * LOCALS
+ */
+
+static char errbuf[1024];
+
+/*
+ * CODE
+ */
+
+/* helpers */
+static int wgaim_is_socket( int fd ) {
+ int optval;
+ unsigned int optlen = sizeof(int);
+
+ if( (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void*)&optval, &optlen)) == SOCKET_ERROR ) {
+ int error = WSAGetLastError();
+ if( error == WSAENOTSOCK )
+ return FALSE;
+ else {
+ gaim_debug(GAIM_DEBUG_WARNING, "wgaim", "wgaim_is_socket: getsockopt returned error: %d\n", error);
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+/* socket.h */
+int wgaim_socket (int namespace, int style, int protocol) {
+ int ret;
+
+ ret = socket( namespace, style, protocol );
+
+ if( ret == INVALID_SOCKET ) {
+ errno = WSAGetLastError();
+ return -1;
+ }
+ return ret;
+}
+
+int wgaim_connect(int socket, struct sockaddr *addr, u_long length) {
+ int ret;
+
+ ret = connect( socket, addr, length );
+
+ if( ret == SOCKET_ERROR ) {
+ errno = WSAGetLastError();
+ if( errno == WSAEWOULDBLOCK )
+ errno = WSAEINPROGRESS;
+ return -1;
+ }
+ return 0;
+}
+
+int wgaim_getsockopt(int socket, int level, int optname, void *optval, socklen_t *optlenptr) {
+ if(getsockopt(socket, level, optname, optval, optlenptr) == SOCKET_ERROR ) {
+ errno = WSAGetLastError();
+ return -1;
+ }
+ return 0;
+}
+
+int wgaim_setsockopt(int socket, int level, int optname, const void *optval, socklen_t optlen) {
+ if(setsockopt(socket, level, optname, optval, optlen) == SOCKET_ERROR ) {
+ errno = WSAGetLastError();
+ return -1;
+ }
+ return 0;
+}
+
+int wgaim_getsockname(int socket, struct sockaddr *addr, socklen_t *lenptr) {
+ if(getsockname(socket, addr, lenptr) == SOCKET_ERROR) {
+ errno = WSAGetLastError();
+ return -1;
+ }
+ return 0;
+}
+
+int wgaim_bind(int socket, struct sockaddr *addr, socklen_t length) {
+ if(bind(socket, addr, length) == SOCKET_ERROR) {
+ errno = WSAGetLastError();
+ return -1;
+ }
+ return 0;
+}
+
+int wgaim_listen(int socket, unsigned int n) {
+ if(listen(socket, n) == SOCKET_ERROR) {
+ errno = WSAGetLastError();
+ return -1;
+ }
+ return 0;
+}
+
+/* fcntl.h */
+/* This is not a full implementation of fcntl. Update as needed.. */
+int wgaim_fcntl(int socket, int command, int val) {
+ switch( command ) {
+ case F_SETFL:
+ {
+ int ret=0;
+
+ switch( val ) {
+ case O_NONBLOCK:
+ {
+ u_long imode=1;
+ ret = ioctlsocket(socket, FIONBIO, &imode);
+ break;
+ }
+ case 0:
+ {
+ u_long imode=0;
+ ret = ioctlsocket(socket, FIONBIO, &imode);
+ break;
+ }
+ default:
+ errno = EINVAL;
+ return -1;
+ }/*end switch*/
+ if( ret == SOCKET_ERROR ) {
+ errno = WSAGetLastError();
+ return -1;
+ }
+ return 0;
+ }
+ default:
+ gaim_debug(GAIM_DEBUG_WARNING, "wgaim", "wgaim_fcntl: Unsupported command\n");
+ return -1;
+ }/*end switch*/
+}
+
+/* sys/ioctl.h */
+int wgaim_ioctl(int fd, int command, void* val) {
+ switch( command ) {
+ case FIONBIO:
+ {
+ if (ioctlsocket(fd, FIONBIO, (unsigned long *)val) == SOCKET_ERROR) {
+ errno = WSAGetLastError();
+ return -1;
+ }
+ return 0;
+ }
+ default:
+ errno = EINVAL;
+ return -1;
+ }/*end switch*/
+}
+
+/* arpa/inet.h */
+int wgaim_inet_aton(const char *name, struct in_addr *addr) {
+ if((addr->s_addr = inet_addr(name)) == INADDR_NONE)
+ return 0;
+ else
+ return 1;
+}
+
+/* netdb.h */
+struct hostent* wgaim_gethostbyname(const char *name) {
+ struct hostent *hp;
+
+ if((hp = gethostbyname(name)) == NULL) {
+ errno = WSAGetLastError();
+ return NULL;
+ }
+ return hp;
+}
+
+/* string.h */
+char* wgaim_strerror( int errornum ) {
+ if( errornum > WSABASEERR ) {
+ sprintf( errbuf, "Windows socket error #%d", errornum );
+ return errbuf;
+ }
+ else
+ return strerror( errornum );
+}
+
+/* unistd.h */
+
+/*
+ * We need to figure out whether fd is a file or socket handle.
+ */
+int wgaim_read(int fd, void *buf, unsigned int size) {
+ int ret;
+
+ if( wgaim_is_socket(fd) ) {
+ if( (ret = recv(fd, buf, size, 0)) == SOCKET_ERROR ) {
+ errno = WSAGetLastError();
+ return -1;
+ }
+ else if( ret == 0 ) {
+ /* connection has been gracefully closed */
+ errno = WSAENOTCONN;
+ return -1;
+ }
+ else {
+ /* success reading socket */
+ return ret;
+ }
+ }
+ else {
+ /* fd is not a socket handle.. pass it off to read */
+ return read(fd, buf, size);
+ }
+}
+
+int wgaim_write(int fd, const void *buf, unsigned int size) {
+ int ret;
+
+ if( wgaim_is_socket(fd) ) {
+ if( (ret = send(fd, buf, size, 0)) == SOCKET_ERROR ) {
+ errno = WSAGetLastError();
+ return -1;
+ }
+ else {
+ /* success */
+ return ret;
+ }
+
+ }
+ else
+ return write(fd, buf, size);
+}
+
+int wgaim_close(int fd) {
+ int ret;
+
+ if( wgaim_is_socket(fd) ) {
+ if( (ret = closesocket(fd)) == SOCKET_ERROR ) {
+ errno = WSAGetLastError();
+ return -1;
+ }
+ else
+ return 0;
+ }
+ else
+ return close(fd);
+}
+
+int wgaim_gethostname(char *name, size_t size) {
+ if(gethostname(name, size) == SOCKET_ERROR) {
+ errno = WSAGetLastError();
+ return -1;
+ }
+ return 0;
+}
+
+/* sys/time.h */
+
+int wgaim_gettimeofday(struct timeval *p, struct timezone *z) {
+ int res = 0;
+ struct _timeb timebuffer;
+
+ if (z != 0) {
+ _tzset();
+ z->tz_minuteswest = _timezone/60;
+ z->tz_dsttime = _daylight;
+ }
+
+ if (p != 0) {
+ _ftime(&timebuffer);
+ p->tv_sec = timebuffer.time; /* seconds since 1-1-1970 */
+ p->tv_usec = timebuffer.millitm*1000; /* microseconds */
+ }
+
+ return res;
+}
+
+/* stdio.h */
+
+#if !GLIB_CHECK_VERSION(2,6,0)
+int wgaim_rename (const char *oldname, const char *newname) {
+ struct _stat oldstat, newstat;
+
+ if(_stat(oldname, &oldstat) == 0) {
+ /* newname exists */
+ if(_stat(newname, &newstat) == 0) {
+ /* oldname is a dir */
+ if(_S_ISDIR(oldstat.st_mode)) {
+ if(!_S_ISDIR(newstat.st_mode)) {
+ return rename(oldname, newname);
+ }
+ /* newname is a dir */
+ else {
+ /* This is not quite right.. If newname is empty and
+ is not a sub dir of oldname, newname should be
+ deleted and oldname should be renamed.
+ */
+ gaim_debug(GAIM_DEBUG_WARNING, "wgaim", "wgaim_rename does not behave here as it should\n");
+ return rename(oldname, newname);
+ }
+ }
+ /* oldname is not a dir */
+ else {
+ /* newname is a dir */
+ if(_S_ISDIR(newstat.st_mode)) {
+ errno = EISDIR;
+ return -1;
+ }
+ /* newname is not a dir */
+ else {
+ g_remove(newname);
+ return rename(oldname, newname);
+ }
+ }
+ }
+ /* newname doesn't exist */
+ else
+ return rename(oldname, newname);
+ }
+ else {
+ /* oldname doesn't exist */
+ errno = ENOENT;
+ return -1;
+ }
+
+}
+#endif
+
+/* time.h */
+
+struct tm * wgaim_localtime_r (const time_t *time, struct tm *resultp) {
+ struct tm* tmptm;
+
+ if(!time)
+ return NULL;
+ tmptm = localtime(time);
+ if(resultp && tmptm)
+ return memcpy(resultp, tmptm, sizeof(struct tm));
+ else
+ return NULL;
+}
--- a/src/win32/libc_interface.h Wed Feb 09 09:58:22 2005 -0500
+++ b/src/win32/libc_interface.h Wed Feb 09 19:07:39 2005 -0500
@@ -27,6 +27,7 @@
#include <io.h>
#include <errno.h>
#include "libc_internal.h"
+#include <glib.h>
/* sys/socket.h */
extern int wgaim_socket(int namespace, int style, int protocol);
@@ -67,7 +68,9 @@
#define fcntl( fd, command, val ) \
wgaim_fcntl( fd, command, val )
-#define open( args... ) _open( args )
+#if !GLIB_CHECK_VERSION(2,6,0)
+# define open( args... ) _open( args )
+#endif
/* arpa/inet.h */
extern int wgaim_inet_aton(const char *name, struct in_addr *addr);
@@ -90,10 +93,6 @@
#define strerror( errornum ) \
wgaim_strerror( errornum )
-extern char* wgaim_strsep(char **stringp, const char *delim);
-#define strsep( stringp, delim ) \
-wgaim_strsep( stringp, delim )
-
#define bzero( dest, size ) memset( dest, 0, size )
/* unistd.h */
@@ -126,12 +125,18 @@
#define snprintf _snprintf
#define vsnprintf _vsnprintf
+#if !GLIB_CHECK_VERSION(2,6,0)
+/* I think that this can probably go away, in favor of g_rename() */
extern int wgaim_rename(const char *oldname, const char *newname);
#define rename( oldname, newname ) \
wgaim_rename( oldname, newname )
+#endif
/* sys/stat.h */
+
+#if !GLIB_CHECK_VERSION(2,6,0)
#define mkdir(a,b) _mkdir((a))
+#endif
#define fchmod(a,b)
/* time.h */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/win32/untar.c Wed Feb 09 19:07:39 2005 -0500
@@ -0,0 +1,633 @@
+/* untar.c */
+
+/*#define VERSION "1.4"*/
+
+/* DESCRIPTION:
+ * Untar extracts files from an uncompressed tar archive, or one which
+ * has been compressed with gzip. Usually such archives will have file
+ * names that end with ".tar" or ".tgz" respectively, although untar
+ * doesn't depend on any naming conventions. For a summary of the
+ * command-line options, run untar with no arguments.
+ *
+ * HOW TO COMPILE:
+ * Untar doesn't require any special libraries or compile-time flags.
+ * A simple "cc untar.c -o untar" (or the local equivalent) is
+ * sufficient. Even "make untar" works, without needing a Makefile.
+ * For Microsoft Visual C++, the command is "cl /D_WEAK_POSIX untar.c"
+ * (for 32 bit compilers) or "cl /F 1400 untar.c" (for 16-bit).
+ *
+ * IF YOU SEE COMPILER WARNINGS, THAT'S NORMAL; you can ignore them.
+ * Most of the warnings could be eliminated by adding #include <string.h>
+ * but that isn't portable -- some systems require <strings.h> and
+ * <malloc.h>, for example. Because <string.h> isn't quite portable,
+ * and isn't really necessary in the context of this program, it isn't
+ * included.
+ *
+ * PORTABILITY:
+ * Untar only requires the <stdio.h> header. It uses old-style function
+ * definitions. It opens all files in binary mode. Taken together,
+ * this means that untar should compile & run on just about anything.
+ *
+ * If your system supports the POSIX chmod(2), utime(2), link(2), and
+ * symlink(2) calls, then you may wish to compile with -D_POSIX_SOURCE,
+ * which will enable untar to use those system calls to restore the
+ * timestamp and permissions of the extracted files, and restore links.
+ * (For Linux, _POSIX_SOURCE is always defined.)
+ *
+ * For systems which support some POSIX features but not enough to support
+ * -D_POSIX_SOURCE, you might be able to use -D_WEAK_POSIX. This allows
+ * untar to restore time stamps and file permissions, but not links.
+ * This should work for Microsoft systems, and hopefully others as well.
+ *
+ * AUTHOR & COPYRIGHT INFO:
+ * Written by Steve Kirkendall, kirkenda@cs.pdx.edu
+ * Placed in public domain, 6 October 1995
+ *
+ * Portions derived from inflate.c -- Not copyrighted 1992 by Mark Adler
+ * version c10p1, 10 January 1993
+ *
+ * Altered by Herman Bloggs <hermanator12002@yahoo.com>
+ * April 4, 2003
+ * Changes: Stripped out gz compression code, added better interface for
+ * untar.
+ */
+#include <windows.h>
+#include <stdio.h>
+#include <io.h>
+#include <string.h>
+#include <stdlib.h>
+#ifndef SEEK_SET
+# define SEEK_SET 0
+#endif
+
+#ifdef _WEAK_POSIX
+# ifndef _POSIX_SOURCE
+# define _POSIX_SOURCE
+# endif
+#endif
+
+#ifdef _POSIX_SOURCE
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <sys/utime.h>
+# ifdef _WEAK_POSIX
+# define mode_t int
+# else
+# include <unistd.h>
+# endif
+#endif
+#include "debug.h"
+#include "untar.h"
+#include <glib.h>
+
+#if GLIB_CHECK_VERSION(2,6,0)
+# include <glib/gstdio.h>
+#else
+#define mkdir(a,b) _mkdir((a))
+#define g_mkdir mkdir
+#define g_fopen fopen
+#define g_unlink unlink
+#endif
+
+#define untar_error( error, args... ) gaim_debug(GAIM_DEBUG_ERROR, "untar", error, ## args )
+#define untar_warning( warning, args... ) gaim_debug(GAIM_DEBUG_WARNING, "untar", warning, ## args )
+#define untar_verbose( args... ) gaim_debug(GAIM_DEBUG_INFO, "untar", ## args )
+
+#define WSIZE 32768 /* size of decompression buffer */
+#define TSIZE 512 /* size of a "tape" block */
+#define CR 13 /* carriage-return character */
+#define LF 10 /* line-feed character */
+
+typedef unsigned char Uchar_t;
+typedef unsigned short Ushort_t;
+typedef unsigned long Ulong_t;
+
+typedef struct
+{
+ char filename[100]; /* 0 name of next file */
+ char mode[8]; /* 100 Permissions and type (octal digits) */
+ char owner[8]; /* 108 Owner ID (ignored) */
+ char group[8]; /* 116 Group ID (ignored) */
+ char size[12]; /* 124 Bytes in file (octal digits) */
+ char mtime[12]; /* 136 Modification time stamp (octal digits)*/
+ char checksum[8]; /* 148 Header checksum (ignored) */
+ char type; /* 156 File type (see below) */
+ char linkto[100]; /* 157 Linked-to name */
+ char brand[8]; /* 257 Identifies tar version (ignored) */
+ char ownername[32]; /* 265 Name of owner (ignored) */
+ char groupname[32]; /* 297 Name of group (ignored) */
+ char devmajor[8]; /* 329 Device major number (ignored) */
+ char defminor[8]; /* 337 Device minor number (ignored) */
+ char prefix[155]; /* 345 Prefix of name (optional) */
+ char RESERVED[12]; /* 500 Pad header size to 512 bytes */
+} tar_t;
+#define ISREGULAR(hdr) ((hdr).type < '1' || (hdr).type > '6')
+
+Uchar_t slide[WSIZE];
+
+static const char *inname = NULL; /* name of input archive */
+static FILE *infp = NULL; /* input byte stream */
+static FILE *outfp = NULL; /* output stream, for file currently being extracted */
+static Ulong_t outsize = 0; /* number of bytes remainin in file currently being extracted */
+static char **only = NULL; /* array of filenames to extract/list */
+static int nonlys = 0; /* number of filenames in "only" array; 0=extract all */
+static int didabs = 0; /* were any filenames affected by the absence of -p? */
+
+static untar_opt untarops = 0; /* Untar options */
+
+/* Options checked during untar process */
+#define LISTING (untarops & UNTAR_LISTING) /* 1 if listing, 0 if extracting */
+#define QUIET (untarops & UNTAR_QUIET) /* 1 to write nothing to stdout, 0 for normal chatter */
+#define VERBOSE (untarops & UNTAR_VERBOSE) /* 1 to write extra information to stdout */
+#define FORCE (untarops & UNTAR_FORCE) /* 1 to overwrite existing files, 0 to skip them */
+#define ABSPATH (untarops & UNTAR_ABSPATH) /* 1 to allow leading '/', 0 to strip leading '/' */
+#define CONVERT (untarops & UNTAR_CONVERT) /* 1 to convert newlines, 0 to leave unchanged */
+
+/*----------------------------------------------------------------------------*/
+
+/* create a file for writing. If necessary, create the directories leading up
+ * to that file as well.
+ */
+static FILE *createpath(name)
+ char *name; /* pathname of file to create */
+{
+ FILE *fp;
+ int i;
+
+ /* if we aren't allowed to overwrite and this file exists, return NULL */
+ if (!FORCE && access(name, 0) == 0)
+ {
+ untar_warning("%s: exists, will not overwrite without \"FORCE option\"\n", name);
+ return NULL;
+ }
+
+ /* first try creating it the easy way */
+ fp = g_fopen(name, CONVERT ? "w" : "wb");
+ if (fp)
+ return fp;
+
+ /* Else try making all of its directories, and then try creating
+ * the file again.
+ */
+ for (i = 0; name[i]; i++)
+ {
+ /* If this is a slash, then temporarily replace the '/'
+ * with a '\0' and do a mkdir() on the resulting string.
+ * Ignore errors for now.
+ */
+ if (name[i] == '/')
+ {
+ name[i] = '\0';
+ (void)g_mkdir(name, 0777);
+ name[i] = '/';
+ }
+ }
+ fp = g_fopen(name, CONVERT ? "w" : "wb");
+ if (!fp)
+ untar_error("Error opening: %s\n", name);
+ return fp;
+}
+
+/* Create a link, or copy a file. If the file is copied (not linked) then
+ * give a warning.
+ */
+static void linkorcopy(src, dst, sym)
+ char *src; /* name of existing source file */
+ char *dst; /* name of new destination file */
+ int sym; /* use symlink instead of link */
+{
+ FILE *fpsrc;
+ FILE *fpdst;
+ int c;
+
+ /* Open the source file. We do this first to make sure it exists */
+ fpsrc = g_fopen(src, "rb");
+ if (!fpsrc)
+ {
+ untar_error("Error opening: %s\n", src);
+ return;
+ }
+
+ /* Create the destination file. On POSIX systems, this is just to
+ * make sure the directory path exists.
+ */
+ fpdst = createpath(dst);
+ if (!fpdst)
+ /* error message already given */
+ return;
+
+#ifdef _POSIX_SOURCE
+# ifndef _WEAK_POSIX
+ /* first try to link it over, instead of copying */
+ fclose(fpdst);
+ g_unlink(dst);
+ if (sym)
+ {
+ if (symlink(src, dst))
+ {
+ perror(dst);
+ }
+ fclose(fpsrc);
+ return;
+ }
+ if (!link(src, dst))
+ {
+ /* This story had a happy ending */
+ fclose(fpsrc);
+ return;
+ }
+
+ /* Dang. Reopen the destination again */
+ fpdst = g_fopen(dst, "wb");
+ /* This *can't* fail */
+
+# endif /* _WEAK_POSIX */
+#endif /* _POSIX_SOURCE */
+
+ /* Copy characters */
+ while ((c = getc(fpsrc)) != EOF)
+ putc(c, fpdst);
+
+ /* Close the files */
+ fclose(fpsrc);
+ fclose(fpdst);
+
+ /* Give a warning */
+ untar_warning("%s: copy instead of link\n", dst);
+}
+
+/* This calls fwrite(), possibly after converting CR-LF to LF */
+static void cvtwrite(blk, size, fp)
+ Uchar_t *blk; /* the block to be written */
+ Ulong_t size; /* number of characters to be written */
+ FILE *fp; /* file to write to */
+{
+ int i, j;
+ static Uchar_t mod[TSIZE];
+
+ if (CONVERT)
+ {
+ for (i = j = 0; i < size; i++)
+ {
+ /* convert LF to local newline convention */
+ if (blk[i] == LF)
+ mod[j++] = '\n';
+ /* If CR-LF pair, then delete the CR */
+ else if (blk[i] == CR && (i+1 >= size || blk[i+1] == LF))
+ ;
+ /* other characters copied literally */
+ else
+ mod[j++] = blk[i];
+ }
+ size = j;
+ blk = mod;
+ }
+
+ fwrite(blk, (size_t)size, sizeof(Uchar_t), fp);
+}
+
+
+/* Compute the checksum of a tar header block, and return it as a long int.
+ * The checksum can be computed using either POSIX rules (unsigned bytes)
+ * or Sun rules (signed bytes).
+ */
+static long checksum(tblk, sunny)
+ tar_t *tblk; /* buffer containing the tar header block */
+ int sunny; /* Boolean: Sun-style checksums? (else POSIX) */
+{
+ long sum;
+ char *scan;
+
+ /* compute the sum of the first 148 bytes -- everything up to but not
+ * including the checksum field itself.
+ */
+ sum = 0L;
+ for (scan = (char *)tblk; scan < tblk->checksum; scan++)
+ {
+ sum += (*scan) & 0xff;
+ if (sunny && (*scan & 0x80) != 0)
+ sum -= 256;
+ }
+
+ /* for the 8 bytes of the checksum field, add blanks to the sum */
+ sum += ' ' * sizeof tblk->checksum;
+ scan += sizeof tblk->checksum;
+
+ /* finish counting the sum of the rest of the block */
+ for (; scan < (char *)tblk + sizeof *tblk; scan++)
+ {
+ sum += (*scan) & 0xff;
+ if (sunny && (*scan & 0x80) != 0)
+ sum -= 256;
+ }
+
+ return sum;
+}
+
+
+
+/* list files in an archive, and optionally extract them as well */
+static int untar_block(Uchar_t *blk) {
+ static char nbuf[256];/* storage space for prefix+name, combined */
+ static char *name,*n2;/* prefix and name, combined */
+ static int first = 1;/* Boolean: first block of archive? */
+ long sum; /* checksum for this block */
+ int i;
+ tar_t tblk[1];
+
+#ifdef _POSIX_SOURCE
+ static mode_t mode; /* file permissions */
+ static struct utimbuf timestamp; /* file timestamp */
+#endif
+
+ /* make a local copy of the block, and treat it as a tar header */
+ tblk[0] = *(tar_t *)blk;
+
+ /* process each type of tape block differently */
+ if (outsize > TSIZE)
+ {
+ /* data block, but not the last one */
+ if (outfp)
+ cvtwrite(blk, (Ulong_t)TSIZE, outfp);
+ outsize -= TSIZE;
+ }
+ else if (outsize > 0)
+ {
+ /* last data block of current file */
+ if (outfp)
+ {
+ cvtwrite(blk, outsize, outfp);
+ fclose(outfp);
+ outfp = NULL;
+#ifdef _POSIX_SOURCE
+ utime(nbuf, &timestamp);
+ chmod(nbuf, mode);
+#endif
+ }
+ outsize = 0;
+ }
+ else if ((tblk)->filename[0] == '\0')
+ {
+ /* end-of-archive marker */
+ if (didabs)
+ untar_warning("Removed leading slashes because \"ABSPATH option\" wasn't given.\n");
+ return 1;
+ }
+ else
+ {
+ /* file header */
+
+ /* half-assed verification -- does it look like header? */
+ if ((tblk)->filename[99] != '\0'
+ || ((tblk)->size[0] < '0'
+ && (tblk)->size[0] != ' ')
+ || (tblk)->size[0] > '9')
+ {
+ if (first)
+ {
+ untar_error("%s: not a valid tar file\n", inname);
+ return 0;
+ }
+ else
+ {
+ untar_error("Garbage detected; preceding file may be damaged\n");
+ return 0;
+ }
+ }
+
+ /* combine prefix and filename */
+ memset(nbuf, 0, sizeof nbuf);
+ name = nbuf;
+ if ((tblk)->prefix[0])
+ {
+ strncpy(name, (tblk)->prefix, sizeof (tblk)->prefix);
+ strcat(name, "/");
+ strncat(name + strlen(name), (tblk)->filename,
+ sizeof (tblk)->filename);
+ }
+ else
+ {
+ strncpy(name, (tblk)->filename,
+ sizeof (tblk)->filename);
+ }
+
+ /* Convert any backslashes to forward slashes, and guard
+ * against doubled-up slashes. (Some DOS versions of "tar"
+ * get this wrong.) Also strip off leading slashes.
+ */
+ if (!ABSPATH && (*name == '/' || *name == '\\'))
+ didabs = 1;
+ for (n2 = nbuf; *name; name++)
+ {
+ if (*name == '\\')
+ *name = '/';
+ if (*name != '/'
+ || (ABSPATH && n2 == nbuf)
+ || (n2 != nbuf && n2[-1] != '/'))
+ *n2++ = *name;
+ }
+ if (n2 == nbuf)
+ *n2++ = '/';
+ *n2 = '\0';
+
+ /* verify the checksum */
+ for (sum = 0L, i = 0; i < sizeof((tblk)->checksum); i++)
+ {
+ if ((tblk)->checksum[i] >= '0'
+ && (tblk)->checksum[i] <= '7')
+ sum = sum * 8 + (tblk)->checksum[i] - '0';
+ }
+ if (sum != checksum(tblk, 0) && sum != checksum(tblk, 1))
+ {
+ if (!first)
+ untar_error("Garbage detected; preceding file may be damaged\n");
+ untar_error("%s: header has bad checksum for %s\n", inname, nbuf);
+ return 0;
+ }
+
+ /* From this point on, we don't care whether this is the first
+ * block or not. Might as well reset the "first" flag now.
+ */
+ first = 0;
+
+ /* if last character of name is '/' then assume directory */
+ if (*nbuf && nbuf[strlen(nbuf) - 1] == '/')
+ (tblk)->type = '5';
+
+ /* convert file size */
+ for (outsize = 0L, i = 0; i < sizeof((tblk)->size); i++)
+ {
+ if ((tblk)->size[i] >= '0' && (tblk)->size[i] <= '7')
+ outsize = outsize * 8 + (tblk)->size[i] - '0';
+ }
+
+#ifdef _POSIX_SOURCE
+ /* convert file timestamp */
+ for (timestamp.modtime=0L, i=0; i < sizeof((tblk)->mtime); i++)
+ {
+ if ((tblk)->mtime[i] >= '0' && (tblk)->mtime[i] <= '7')
+ timestamp.modtime = timestamp.modtime * 8
+ + (tblk)->mtime[i] - '0';
+ }
+ timestamp.actime = timestamp.modtime;
+
+ /* convert file permissions */
+ for (mode = i = 0; i < sizeof((tblk)->mode); i++)
+ {
+ if ((tblk)->mode[i] >= '0' && (tblk)->mode[i] <= '7')
+ mode = mode * 8 + (tblk)->mode[i] - '0';
+ }
+#endif
+
+ /* If we have an "only" list, and this file isn't in it,
+ * then skip it.
+ */
+ if (nonlys > 0)
+ {
+ for (i = 0;
+ i < nonlys
+ && strcmp(only[i], nbuf)
+ && (strncmp(only[i], nbuf, strlen(only[i]))
+ || nbuf[strlen(only[i])] != '/');
+ i++)
+ {
+ }
+ if (i >= nonlys)
+ {
+ outfp = NULL;
+ return 1;
+ }
+ }
+
+ /* list the file */
+ if (VERBOSE)
+ untar_verbose("%c %s",
+ ISREGULAR(*tblk) ? '-' : ("hlcbdp"[(tblk)->type - '1']),
+ nbuf);
+ else if (!QUIET)
+ untar_verbose("%s\n", nbuf);
+
+ /* if link, then do the link-or-copy thing */
+ if (tblk->type == '1' || tblk->type == '2')
+ {
+ if (VERBOSE)
+ untar_verbose(" -> %s\n", tblk->linkto);
+ if (!LISTING)
+ linkorcopy(tblk->linkto, nbuf, tblk->type == '2');
+ outsize = 0L;
+ return 1;
+ }
+
+ /* If directory, then make a weak attempt to create it.
+ * Ideally we would do the "create path" thing, but that
+ * seems like more trouble than it's worth since traditional
+ * tar archives don't contain directories anyway.
+ */
+ if (tblk->type == '5')
+ {
+ if (LISTING)
+ n2 = " directory";
+#ifdef _POSIX_SOURCE
+ else if (mkdir(nbuf, mode) == 0)
+#else
+ else if (g_mkdir(nbuf, 0755) == 0)
+#endif
+ n2 = " created";
+ else
+ n2 = " ignored";
+ if (VERBOSE)
+ untar_verbose("%s\n", n2);
+ return 1;
+ }
+
+ /* if not a regular file, then skip it */
+ if (!ISREGULAR(*tblk))
+ {
+ if (VERBOSE)
+ untar_verbose(" ignored\n");
+ outsize = 0L;
+ return 1;
+ }
+
+ /* print file statistics */
+ if (VERBOSE)
+ {
+ untar_verbose(" (%ld byte%s, %ld tape block%s)\n",
+ outsize,
+ outsize == 1 ? "" : "s",
+ (outsize + TSIZE - 1) / TSIZE,
+ (outsize > 0 && outsize <= TSIZE) ? "" : "s");
+ }
+
+ /* if extracting, then try to create the file */
+ if (!LISTING)
+ outfp = createpath(nbuf);
+ else
+ outfp = NULL;
+
+ /* if file is 0 bytes long, then we're done already! */
+ if (outsize == 0 && outfp)
+ {
+ fclose(outfp);
+#ifdef _POSIX_SOURCE
+ utime(nbuf, &timestamp);
+ chmod(nbuf, mode);
+#endif
+ }
+ }
+ return 1;
+}
+
+/* Process an archive file. This involves reading the blocks one at a time
+ * and passing them to a untar() function.
+ */
+int untar(const char *filename, const char* destdir, untar_opt options) {
+ int ret=1;
+ char curdir[_MAX_PATH];
+ untarops = options;
+ /* open the archive */
+ inname = filename;
+ infp = g_fopen(filename, "rb");
+ if (!infp)
+ {
+ untar_error("Error opening: %s\n", filename);
+ return 0;
+ }
+
+ /* Set current directory */
+ if(!GetCurrentDirectory(_MAX_PATH, curdir)) {
+ untar_error("Could not get current directory (error %d).\n", GetLastError());
+ fclose(infp);
+ return 0;
+ }
+ if(!SetCurrentDirectory(destdir)) {
+ untar_error("Could not set current directory to (error %d): %s\n", GetLastError(), destdir);
+ fclose(infp);
+ return 0;
+ } else {
+ /* UNCOMPRESSED */
+ /* send each block to the untar_block() function */
+ while (fread(slide, 1, TSIZE, infp) == TSIZE) {
+ if(!untar_block(slide)) {
+ untar_error("untar failure: %s\n", filename);
+ fclose(infp);
+ ret=0;
+ }
+ }
+ if (outsize > 0 && ret) {
+ untar_warning("Last file might be truncated!\n");
+ fclose(outfp);
+ outfp = NULL;
+ }
+ if(!SetCurrentDirectory(curdir)) {
+ untar_error("Could not set current dir back to original (error %d).\n", GetLastError());
+ ret=0;
+ }
+ }
+
+ /* close the archive file. */
+ fclose(infp);
+
+ return ret;
+}
+
--- a/src/win32/win32dep.c Wed Feb 09 09:58:22 2005 -0500
+++ b/src/win32/win32dep.c Wed Feb 09 19:07:39 2005 -0500
@@ -27,9 +27,16 @@
#include <stdlib.h>
#include <stdio.h>
#include <winuser.h>
+#include <shlobj.h>
#include <gtk/gtk.h>
#include <glib.h>
+#if GLIB_CHECK_VERSION(2,6,0)
+# include <glib/gstdio.h>
+#else
+# define g_fopen fopen
+# define g_unlink unlink
+#endif
#include <gdk/gdkwin32.h>
#include "gaim.h"
@@ -56,16 +63,14 @@
*/
/* For shfolder.dll */
-typedef HRESULT (CALLBACK* LPFNSHGETFOLDERPATH)(HWND, int, HANDLE, DWORD, LPTSTR);
+typedef HRESULT (CALLBACK* LPFNSHGETFOLDERPATHA)(HWND, int, HANDLE, DWORD, LPSTR);
+typedef HRESULT (CALLBACK* LPFNSHGETFOLDERPATHW)(HWND, int, HANDLE, DWORD, LPWSTR);
typedef enum {
SHGFP_TYPE_CURRENT = 0, // current value for user, verify it exists
SHGFP_TYPE_DEFAULT = 1, // default value, may not exist
} SHGFP_TYPE;
-#define CSIDL_APPDATA 0x001a
-#define CSIDL_FLAG_CREATE 0x8000
-
/* flash info */
typedef BOOL (CALLBACK* LPFNFLASHWINDOWEX)(PFLASHWINFO);
@@ -78,7 +83,7 @@
/*
* LOCALS
*/
-static char app_data_dir[MAX_PATH] = "C:";
+static char app_data_dir[MAX_PATH + 1] = "C:";
static char install_dir[MAXPATHLEN];
static char lib_dir[MAXPATHLEN];
static char locale_dir[MAXPATHLEN];
@@ -94,7 +99,8 @@
* PROTOS
*/
LPFNFLASHWINDOWEX MyFlashWindowEx = NULL;
-LPFNSHGETFOLDERPATH MySHGetFolderPath = NULL;
+LPFNSHGETFOLDERPATHA MySHGetFolderPathA = NULL;
+LPFNSHGETFOLDERPATHW MySHGetFolderPathW = NULL;
FARPROC wgaim_find_and_loadproc(char*, char*);
extern void wgaim_gtkspell_init();
@@ -142,136 +148,15 @@
MyFlashWindowEx = (LPFNFLASHWINDOWEX)wgaim_find_and_loadproc("user32.dll", "FlashWindowEx" );
}
-#if 0
-static char* base_name(char* path) {
- char *tmp = path;
- char *prev = NULL;
-
- while((tmp=strchr(tmp, '\\'))) {
- prev = tmp;
- tmp += 1;
- }
- if(prev)
- return ++prev;
- else
- return NULL;
-}
-#endif
-
-BOOL folder_exists(char *folder) {
- BOOL ret = FALSE;
- WIN32_FIND_DATA fileinfo;
- HANDLE fh;
-
- memset(&fileinfo, 0, sizeof(WIN32_FIND_DATA));
- if((fh=FindFirstFile(folder, &fileinfo))) {
- if(fileinfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
- ret = TRUE;
- SetLastError(ERROR_SUCCESS);
- }
- else
- SetLastError(ERROR_FILE_EXISTS);
- FindClose(fh);
- }
- return ret;
-}
-
-/* Recursively create directories in the dest path */
-static BOOL CreateDirectoryR(char *dest) {
- static BOOL start = TRUE;
- BOOL ret = FALSE;
-
- if(!dest)
- return ret;
-
- if(start) {
- char *str = g_strdup(dest);
- start = FALSE;
- ret = CreateDirectoryR(str);
- g_free(str);
- start = TRUE;
- }
- else {
- char *tmp1 = dest;
- char *tmp=NULL;
-
- while((tmp1=strchr(tmp1, '\\'))) {
- tmp = tmp1;
- tmp1+=1;
- }
-
- if(tmp) {
- tmp[0] = '\0';
- CreateDirectoryR(dest);
- tmp[0] = '\\';
- if(CreateDirectory(dest, NULL) == 0 && GetLastError() != ERROR_ALREADY_EXISTS) {
- gaim_debug(GAIM_DEBUG_ERROR, "wgaim",
- "Error creating directory: %s. Errno: %u\n",
- dest, (UINT)GetLastError());
- }
- else
- ret = TRUE;
- }
- }
- return ret;
-}
-
-#if 0
-static BOOL move_folder(char *src, char* dest, char* copytitle, BOOL overwrite) {
- char *tsrc, *tdest;
- SHFILEOPSTRUCT dirmove;
- BOOL ret = FALSE;
-
- g_return_val_if_fail(src!=NULL, ret);
- g_return_val_if_fail(dest!=NULL, ret);
-
- if(!folder_exists(src)) {
- gaim_debug(GAIM_DEBUG_WARNING, "wgaim",
- "move_folder: Source folder %s, does not exist\n", src);
- return ret;
- }
- if(!overwrite) {
- char *dstpath = g_strdup_printf("%s\\%s", dest, base_name(src));
-
- if(folder_exists(dstpath)) {
- gaim_debug(GAIM_DEBUG_WARNING, "wgaim",
- "move_folder: Destination Folder %s, already exists\n", dstpath);
- g_free(dstpath);
- return ret;
- }
- g_free(dstpath);
- }
-
- /* Create dest folder if it doesn't exist */
- if(!CreateDirectoryR(dest)) {
- gaim_debug(GAIM_DEBUG_ERROR, "wgaim", "Error creating directory: %s\n", dest);
- return ret;
- }
-
- tsrc = g_strdup_printf("%s%c", src, '\0');
- tdest = g_strdup_printf("%s%c", dest, '\0');
-
- memset(&dirmove, 0, sizeof(SHFILEOPSTRUCT));
- dirmove.wFunc = FO_MOVE;
- dirmove.pFrom = tsrc;
- dirmove.pTo = tdest;
- dirmove.fFlags = FOF_NOCONFIRMATION | FOF_SIMPLEPROGRESS;
- dirmove.hNameMappings = 0;
- dirmove.lpszProgressTitle = copytitle;
-
- if(SHFileOperation(&dirmove)==0)
- ret = TRUE;
-
- g_free(tsrc);
- g_free(tdest);
- return ret;
-}
-#endif
-
static void wgaim_debug_print(GaimDebugLevel level, const char *category, const char *format, va_list args) {
- char *str = g_strdup_vprintf(format, args);
- printf("%s%s%s", category?category:"", category?": ":"",str);
- g_free(str);
+ char *str = NULL;
+ if (args != NULL) {
+ str = g_strdup_vprintf(format, args);
+ } else {
+ str = g_strdup(format);
+ }
+ printf("%s%s%s", category?category:"", category?": ":"",str);
+ g_free(str);
}
static GaimDebugUiOps ops = {
@@ -448,7 +333,7 @@
int ret;
if((fin = gzopen(in, "rb"))) {
- if(!(fout = fopen(out, "wb"))) {
+ if(!(fout = g_fopen(out, "wb"))) {
gaim_debug(GAIM_DEBUG_ERROR, "wgaim_gz_decompress", "Error opening file: %s\n", out);
gzclose(fin);
return 0;
@@ -491,7 +376,7 @@
gaim_debug(GAIM_DEBUG_ERROR, "wgaim_gz_untar", "Failure untaring %s\n", tmpfile);
ret=0;
}
- unlink(tmpfile);
+ g_unlink(tmpfile);
return ret;
}
else {
@@ -569,13 +454,33 @@
/* Set app data dir, used by gaim_home_dir */
newenv = (char*)g_getenv("GAIMHOME");
if(!newenv) {
- if((MySHGetFolderPath = (LPFNSHGETFOLDERPATH)wgaim_find_and_loadproc("shfolder.dll", "SHGetFolderPathA"))) {
- MySHGetFolderPath(NULL,
- CSIDL_APPDATA,
- NULL, SHGFP_TYPE_CURRENT, app_data_dir);
- }
- else
- strcpy(app_data_dir, "C:");
+#if GLIB_CHECK_VERSION(2,6,0)
+ if ((MySHGetFolderPathW = (LPFNSHGETFOLDERPATHW) wgaim_find_and_loadproc("shfolder.dll", "SHGetFolderPathW"))) {
+ wchar_t utf_16_dir[MAX_PATH +1];
+ char *temp;
+ MySHGetFolderPathW(NULL, CSIDL_APPDATA, NULL,
+ SHGFP_TYPE_CURRENT, utf_16_dir);
+ temp = g_utf16_to_utf8(utf_16_dir, -1, NULL, NULL, NULL);
+ g_strlcpy(app_data_dir, temp, sizeof(app_data_dir));
+ g_free(temp);
+ } else if ((MySHGetFolderPathA = (LPFNSHGETFOLDERPATHA) wgaim_find_and_loadproc("shfolder.dll", "SHGetFolderPathA"))) {
+ char locale_dir[MAX_PATH + 1];
+ char *temp;
+ MySHGetFolderPathA(NULL, CSIDL_APPDATA, NULL,
+ SHGFP_TYPE_CURRENT, locale_dir);
+ temp = g_locale_to_utf8(locale_dir, -1, NULL, NULL, NULL);
+ g_strlcpy(app_data_dir, temp, sizeof(app_data_dir));
+ g_free(temp);
+ }
+#else
+ if ((MySHGetFolderPathA = (LPFNSHGETFOLDERPATHA) wgaim_find_and_loadproc("shfolder.dll", "SHGetFolderPathA"))) {
+ MySHGetFolderPathA(NULL, CSIDL_APPDATA, NULL,
+ SHGFP_TYPE_CURRENT, app_data_dir);
+ }
+#endif
+ else {
+ strcpy(app_data_dir, "C:");
+ }
}
else {
g_strlcpy(app_data_dir, newenv, sizeof(app_data_dir));