Logo Search packages:      
Sourcecode: jpilot-syncmal version File versions  Download package

syncmal.c

/* The contents of this file are subject to the Mozilla Public License
 * Version 1.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations
 * under the License.
 *
 * The Original Code is Mobile Application Link.
 *
 * The Initial Developer of the Original Code is AvantGo, Inc.
 * Portions created by AvantGo, Inc. are Copyright (C) 1997-1999
 * AvantGo, Inc. All Rights Reserved.
 *
 */

/* syncmal.c
 *
 * J-Pilot plugin callback functions by Jason Day, jasonday@worldnet.att.net
 * http://jasonday.home.att.net
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <utime.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <dirent.h>
#include <dlfcn.h>
#include <errno.h>

#include <pi-dlp.h>
#include <pi-file.h>
#include <pi-source.h>
#include <pi-socket.h>
#include <pi-version.h>

#include "libplugin.h"
#include "syncmal.h"
#include "libmal.h"



static char *RCSID = "$Id: syncmal.c,v 1.10 2003/02/23 18:19:43 jday Exp $";

/* Preferences */
static prefType syncmal_prefs[NUM_SMPREFS] = {
    {"sync_when",       INTTYPE,   INTTYPE,   EVERY_SYNC, NULL, 0},
    {"use_proxy",       INTTYPE,   INTTYPE,   0,          NULL, 0},
    {"proxy_address",   CHARTYPE,  CHARTYPE,  0,          NULL, 0},
    {"proxy_port",      CHARTYPE,  CHARTYPE,  0,          NULL, 0},
    {"proxy_username",  CHARTYPE,  CHARTYPE,  0,          NULL, 0},
    {"proxy_password",  CHARTYPE,  CHARTYPE,  0,          NULL, 0},
    {"use_socks",       INTTYPE,   INTTYPE,   0,          NULL, 0},
    {"socks_address",   CHARTYPE,  CHARTYPE,  0,          NULL, 0},
    {"socks_port",      CHARTYPE,  CHARTYPE,  0,          NULL, 0},
    {"last_sync",       CHARTYPE,  CHARTYPE,  0,          NULL, 0}
};


/*
 * These two arrays just hold pointers to some of the labels and text
 * entries. This makes it easier to enable/disable them and cuts down
 * on the number of global variables.
 */
#define PROXY_WIDGETS 8
static GtkWidget *proxy_widgets[PROXY_WIDGETS];
#define SOCKS_WIDGETS 4
static GtkWidget *socks_widgets[SOCKS_WIDGETS];


/* static function prototypes */
static int check_prefs_file();
static void cb_save (GtkWidget *widget, gpointer data);
static void cb_proxy_enabled (GtkWidget *widget, gpointer data);
static void cb_socks_enabled (GtkWidget *widget, gpointer data);
static void cb_proxy_address (GtkWidget *widget, GtkWidget *entry);
static void cb_proxy_port (GtkWidget *widget, GtkWidget *entry);
static void cb_proxy_username (GtkWidget *widget, GtkWidget *entry);
static void cb_proxy_password (GtkWidget *widget, GtkWidget *entry);
static void cb_socks_address (GtkWidget *widget, GtkWidget *entry);
static void cb_socks_port (GtkWidget *widget, GtkWidget *entry);
static void cb_toggle_button (GtkWidget *widget, gpointer data);
static gboolean skip_sync (void);


/*
 ****************************************************************************
 *                       J-Pilot Plugin API functions                       *
 ****************************************************************************
 */

/* This plugin was designed to work with version 0.99 or greater of jpilot */
void plugin_version (int *major_version, int *minor_version)
{
   *major_version = 0;
   *minor_version = 99;
}


int plugin_get_name (char *name, int len)
{
    strncpy (name, "SyncMAL " VERSION, len);
    return 0;
}

int plugin_get_menu_name (char *name, int len)
{
    strncpy(name, "SyncMAL", len);
    return 0;
}

int plugin_get_help_name (char *name, int len)
{
    strncpy(name, "About SyncMAL", len);
    return 0;
}

int plugin_help (char **text, int *width, int *height)
{
    /* We could also pass back *text=NULL */
    *text = strdup(
                   /*-------------------------------------------*/
                   "SyncMAL plugin for J-Pilot\n"
                   "version " VERSION "\n"
                   "Jason Day (c) 2000-2002.\n"
                   "jasonday@worldnet.att.net\n"
                   "http://jasonday.home.att.net\n"
                  );
    *height = 0;
    *width = 0;
    return 0;
}


/*
 * This function is called when J-Pilot starts up. One-time plugin
 * initialization goes here.
 */
int plugin_startup (jp_startup_info *info)
{
    long ivalue;
    const char *svalue;

    /* You MUST call jp_init here! */
    jp_init();
    jp_logf (JP_LOG_DEBUG, "SyncMAL: plugin_startup\n");

    jp_pref_init (syncmal_prefs, NUM_SMPREFS);
    /* Open the prefs file.  Make sure it has the right permissions.  */
    if (check_prefs_file() < 0) {
        jp_logf (JP_LOG_FATAL,
                 "--------------------------------------------\n"
                 "ERROR: The preferences file " PREFS_FILE "\n"
                 "does not have the correct permissions and I\n"
                 "cannot change them. Please type\n"
                 "   chmod 0600 " PREFS_FILE "\n"
                 "in the ~/.jpilot directory to correct this.\n"
                 "--------------------------------------------\n");
    }
    if (jp_pref_read_rc_file (PREFS_FILE, syncmal_prefs, NUM_SMPREFS) < 0) {
        jp_logf (JP_LOG_WARN, "SyncMAL: Unable to load preferences file " PREFS_FILE "\n");
    }
    else {
        jp_logf (JP_LOG_DEBUG, "SyncMAL: loaded preferences from " PREFS_FILE "\n");
    }

    return 0;
}

/*
 * This function is called just before every sync.
 */
int plugin_pre_sync() {

    /*
     * Load the prefs file again. Note that we have to do this because the
     * sync process is forked from the main process, so all global data
     * (including the preferences) is just a copy.  Since we now have to
     * save the last sync time (starting in version 0.60) in the preferences,
     * we have to reload the prefs file every time we sync.
     */
    if (jp_pref_read_rc_file (PREFS_FILE, syncmal_prefs, NUM_SMPREFS) < 0) {
        jp_logf (JP_LOG_WARN, "SyncMAL: Unable to load preferences file " PREFS_FILE "\n");
    }
    else {
        jp_logf (JP_LOG_DEBUG, "SyncMAL: loaded preferences from " PREFS_FILE "\n");
    }

    return 0;
}

int plugin_sync (int sd) {
    PalmSyncInfo * pInfo;
    long ivalue;
    const char *svalue;
    time_t ltime;

    /* See if we need to sync */
    if (skip_sync()) {
        jp_logf (JP_LOG_INFO | JP_LOG_GUI, "SyncMAL: skipping at user request\n");
        return 0;
    }

    /* check the prefs file again; refuse to work if the perms are wrong */
    if (check_prefs_file() < 0) {
        jp_logf (JP_LOG_FATAL,
                 "--------------------------------------------\n"
                 "ERROR: The preferences file " PREFS_FILE "\n"
                 "does not have the correct permissions and I\n"
                 "cannot change them. Please type\n"
                 "   chmod 0600 " PREFS_FILE "\n"
                 "in the ~/.jpilot directory to correct this.\n"
                 "--------------------------------------------\n");
        return -1;
    }

    /* are we using a proxy? */
    jp_get_pref (syncmal_prefs, SMPREF_USE_PROXY, &ivalue, NULL);
    if (ivalue) {
        jp_logf (JP_LOG_DEBUG, "plugin_sync - using http proxy\n");

        jp_get_pref (syncmal_prefs, SMPREF_PROXY_ADDRESS, &ivalue, &svalue);
        if (svalue) {
            jp_logf (JP_LOG_DEBUG, "plugin_sync - setting http proxy: %s\n", svalue);
            setHttpProxy ((char *)svalue);
        }
        else {
            jp_logf (JP_LOG_FATAL,
                     "--------------------------------------------\n"
                     "ERROR: Proxy enabled but no proxy specified.\n"
                     "Please specify a proxy address or unselect\n"
                     "the Use Proxy checkbox.\n"
                     "--------------------------------------------\n");
            return 1;
        }

        jp_get_pref (syncmal_prefs, SMPREF_PROXY_PORT, &ivalue, &svalue);
        if (svalue) {
            jp_logf (JP_LOG_DEBUG, "plugin_sync - setting http proxy port: %s\n", svalue);
            setHttpProxyPort (atoi (svalue));
        }
        else {
            jp_logf (JP_LOG_INFO | JP_LOG_GUI,
                     "SyncMAL: Using default proxy port 80\n");
            setHttpProxyPort (80);
        }

        jp_get_pref (syncmal_prefs, SMPREF_PROXY_USERNAME, &ivalue, &svalue);
        if (svalue) {
            if (strlen (svalue)) {
                jp_logf (JP_LOG_DEBUG, "plugin_sync - setting proxy username: %s\n", svalue);
                setProxyUsername ((char *)svalue);
            }
        }

        jp_get_pref (syncmal_prefs, SMPREF_PROXY_PASSWORD, &ivalue, &svalue);
        if (svalue) {
            if (strlen (svalue)) {
                jp_logf (JP_LOG_DEBUG, "plugin_sync - setting proxy password: xxxxxxxx\n");
                setProxyPassword ((char *)svalue);
            }
        }
    }

    /* are we using SOCKS? */
    jp_get_pref (syncmal_prefs, SMPREF_USE_SOCKS, &ivalue, NULL);
    if (ivalue) {
        jp_get_pref (syncmal_prefs, SMPREF_SOCKS_ADDRESS, &ivalue, &svalue);
        if (svalue) {
            jp_logf (JP_LOG_DEBUG, "plugin_sync - setting socks address: %s\n", svalue);
            setSocksProxy ((char *)svalue);
        }
        else {
            jp_logf (JP_LOG_FATAL,
                     "----------------------------------------------\n"
                     "ERROR: SOCKS enabled but no address specified.\n"
                     "Please specify an address or unselect the\n"
                     "Use SOCKS checkbox.\n"
                     "----------------------------------------------\n");
            return 1;
        }

        jp_get_pref (syncmal_prefs, SMPREF_SOCKS_PORT, &ivalue, &svalue);
        if (svalue) {
            jp_logf (JP_LOG_DEBUG, "plugin_sync - setting socks port: %s\n", svalue);
            setSocksProxyPort (atoi (svalue));
        }
        else {
            jp_logf (JP_LOG_INFO | JP_LOG_GUI,
                     "SyncMAL: Using default SOCKS port 1080\n");
            setSocksProxyPort (1080);
        }
    }

    /* call malsync */
    pInfo = syncInfoNew();
    if (NULL == pInfo) {
        return -1;
    }
    malsync (sd, pInfo);
    syncInfoFree(pInfo);

    /* update the last sync time */
    time (&ltime);
    svalue = g_strdup_printf ("%ld", ltime);
    jp_logf (JP_LOG_DEBUG, "setting last sync time: %s\n", svalue);
    jp_set_pref (syncmal_prefs, SMPREF_LAST_SYNC, 0, svalue);
    g_free ((char *)svalue);
    jp_pref_write_rc_file (PREFS_FILE, syncmal_prefs, NUM_SMPREFS);

    return 0;
}

/*
 * This function is called by J-Pilot when the user selects this plugin
 * from the plugin menu, or from the search window when a search result
 * record is chosen.  In the latter case, unique ID will be set.  This
 * application should go directly to that record in the case.
 */
int plugin_gui (GtkWidget *vbox, GtkWidget *hbox, unsigned int unique_id)
{
    GtkWidget *vbox1;
    GtkWidget *button;
    GtkWidget *temp_hbox;
    GtkWidget *label;
    GtkWidget *entry;
    GtkWidget *table;
    long ivalue;
    const char *svalue;

    jp_logf(JP_LOG_DEBUG, "SyncMAL: plugin gui started\n");

    vbox1 = gtk_vbox_new (FALSE, 0);
    gtk_box_pack_start (GTK_BOX(hbox), vbox1, TRUE, FALSE, 0);

    /* ----------------------------------- */
    /* Top portion of screen (preferences) */
    /* ----------------------------------- */

    /* Make a temporary hbox */
    temp_hbox = gtk_hbox_new (FALSE, 0);

    /* Sync when radio buttons */
    jp_get_pref (syncmal_prefs, SMPREF_SYNC_WHEN, &ivalue, NULL);

    label = gtk_label_new ("Run SyncMAL:");
    gtk_box_pack_start (GTK_BOX(temp_hbox), label, FALSE, FALSE, 5);

    button = gtk_radio_button_new_with_label (NULL, "Every Sync");
    gtk_signal_connect (GTK_OBJECT (button), "toggled",
                        GTK_SIGNAL_FUNC (cb_toggle_button),
                        GINT_TO_POINTER (EVERY_SYNC_BUTTON));
    gtk_box_pack_start (GTK_BOX (temp_hbox), button, TRUE, FALSE, 0);
    if (ivalue == EVERY_SYNC) {
        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
    }

    button = gtk_radio_button_new_with_label(gtk_radio_button_group (GTK_RADIO_BUTTON (button)),
                                             "Hourly");
    gtk_signal_connect (GTK_OBJECT (button), "toggled",
                        GTK_SIGNAL_FUNC (cb_toggle_button),
                        GINT_TO_POINTER (HOURLY_BUTTON));
    gtk_box_pack_start (GTK_BOX (temp_hbox), button, TRUE, FALSE, 0);
    if (ivalue == HOURLY) {
        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
    }

    button = gtk_radio_button_new_with_label(gtk_radio_button_group (GTK_RADIO_BUTTON (button)),
                                             "Morning & Afternoon");
    gtk_signal_connect (GTK_OBJECT (button), "toggled",
                        GTK_SIGNAL_FUNC (cb_toggle_button),
                        GINT_TO_POINTER (MORNING_AND_AFTERNOON_BUTTON));
    gtk_box_pack_start (GTK_BOX (temp_hbox), button, TRUE, FALSE, 0);
    if (ivalue == MORNING_AND_AFTERNOON) {
        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
    }

    button = gtk_radio_button_new_with_label(gtk_radio_button_group (GTK_RADIO_BUTTON (button)),
                                             "Daily");
    gtk_signal_connect (GTK_OBJECT (button), "toggled",
                        GTK_SIGNAL_FUNC (cb_toggle_button),
                        GINT_TO_POINTER (DAILY_BUTTON));
    gtk_box_pack_start (GTK_BOX (temp_hbox), button, TRUE, FALSE, 0);
    if (ivalue == DAILY) {
        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
    }

    button = gtk_radio_button_new_with_label(gtk_radio_button_group (GTK_RADIO_BUTTON (button)),
                                             "Disabled");
    gtk_signal_connect (GTK_OBJECT (button), "toggled",
                        GTK_SIGNAL_FUNC (cb_toggle_button),
                        GINT_TO_POINTER (DISABLED_BUTTON));
    gtk_box_pack_start (GTK_BOX (temp_hbox), button, TRUE, FALSE, 0);
    if (ivalue == DISABLED) {
        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
    }


    gtk_box_pack_start (GTK_BOX(vbox1), temp_hbox, FALSE, FALSE, 5);
    gtk_box_pack_start (GTK_BOX(vbox1), gtk_hseparator_new(), FALSE, FALSE, 0);

    /* --------------*/
    /* Proxy Options */
    /* --------------*/
    button = gtk_check_button_new_with_label ("Use Proxy");
    jp_get_pref (syncmal_prefs, SMPREF_USE_PROXY, &ivalue, &svalue);
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(button), ivalue);
    gtk_signal_connect (GTK_OBJECT (button), "toggled",
                        GTK_SIGNAL_FUNC (cb_proxy_enabled), NULL);
    gtk_box_pack_start (GTK_BOX(vbox1), button, FALSE, FALSE, 5);


    table = gtk_table_new (4, 2, FALSE);

    label = gtk_label_new ("Proxy Address:");
    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
    proxy_widgets[0] = label;
    gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 0, 1);
    entry = gtk_entry_new();
    proxy_widgets[1] = entry;
    jp_get_pref (syncmal_prefs, SMPREF_PROXY_ADDRESS, &ivalue, &svalue);
    if (svalue) {
        gtk_entry_set_text (GTK_ENTRY(entry), svalue);
    }
    gtk_signal_connect(GTK_OBJECT(entry), "changed",
                       GTK_SIGNAL_FUNC(cb_proxy_address),
                       entry);
    gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 0, 1,
                      (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
                      (GtkAttachOptions) (0), 10, 0);


    label = gtk_label_new ("Proxy Port:");
    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
    proxy_widgets[2] = label;
    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
    gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 1, 2);
    entry = gtk_entry_new();
    proxy_widgets[3] = entry;
    jp_get_pref (syncmal_prefs, SMPREF_PROXY_PORT, &ivalue, &svalue);
    if (svalue) {
        gtk_entry_set_text (GTK_ENTRY(entry), svalue);
    }
    gtk_signal_connect(GTK_OBJECT(entry), "changed",
                       GTK_SIGNAL_FUNC(cb_proxy_port),
                       entry);
    gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 1, 2,
                      (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
                      (GtkAttachOptions) (0), 10, 0);


    label = gtk_label_new ("Proxy Username:");
    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
    proxy_widgets[4] = label;
    gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 2, 3);
    entry = gtk_entry_new();
    proxy_widgets[5] = entry;
    jp_get_pref (syncmal_prefs, SMPREF_PROXY_USERNAME, &ivalue, &svalue);
    if (svalue) {
        gtk_entry_set_text (GTK_ENTRY(entry), svalue);
    }
    gtk_signal_connect(GTK_OBJECT(entry), "changed",
                       GTK_SIGNAL_FUNC(cb_proxy_username),
                       entry);
    gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 2, 3,
                      (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
                      (GtkAttachOptions) (0), 10, 0);


    label = gtk_label_new ("Proxy Password:");
    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
    proxy_widgets[6] = label;
    gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 3, 4);
    entry = gtk_entry_new();
    proxy_widgets[7] = entry;
    jp_get_pref (syncmal_prefs, SMPREF_PROXY_PASSWORD, &ivalue, &svalue);
    if (svalue) {
        gtk_entry_set_text (GTK_ENTRY(entry), svalue);
    }
    gtk_signal_connect(GTK_OBJECT(entry), "changed",
                       GTK_SIGNAL_FUNC(cb_proxy_password),
                       entry);
    gtk_entry_set_visibility (GTK_ENTRY(entry), FALSE);
    gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 3, 4,
                      (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
                      (GtkAttachOptions) (0), 10, 0);


    gtk_box_pack_start (GTK_BOX(vbox1), table, FALSE, FALSE, 0);
    cb_proxy_enabled (button, NULL);

    gtk_box_pack_start (GTK_BOX(vbox1), gtk_hseparator_new(), FALSE, FALSE, 5);

    /* --------------*/
    /* Socks Options */
    /* --------------*/
    button = gtk_check_button_new_with_label ("Use SOCKS");
    jp_get_pref (syncmal_prefs, SMPREF_USE_SOCKS, &ivalue, NULL);
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(button), ivalue);
    gtk_signal_connect (GTK_OBJECT (button), "toggled",
                        GTK_SIGNAL_FUNC (cb_socks_enabled), NULL);
    gtk_box_pack_start (GTK_BOX(vbox1), button, FALSE, FALSE, 5);

    table = gtk_table_new (2, 2, FALSE);

    label = gtk_label_new ("SOCKS Proxy:");
    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
    socks_widgets[0] = label;
    gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 0, 1);
    entry = gtk_entry_new();
    socks_widgets[1] = entry;
    jp_get_pref (syncmal_prefs, SMPREF_SOCKS_ADDRESS, &ivalue, &svalue);
    if (svalue) {
        gtk_entry_set_text (GTK_ENTRY(entry), svalue);
    }
    gtk_signal_connect(GTK_OBJECT(entry), "changed",
                       GTK_SIGNAL_FUNC(cb_socks_address),
                       entry);
    gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 0, 1,
                      (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
                      (GtkAttachOptions) (0), 10, 0);

    label = gtk_label_new ("SOCKS Port:");
    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
    socks_widgets[2] = label;
    gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 1, 2);
    entry = gtk_entry_new();
    socks_widgets[3] = entry;
    jp_get_pref (syncmal_prefs, SMPREF_SOCKS_PORT, &ivalue, &svalue);
    if (svalue) {
        gtk_entry_set_text (GTK_ENTRY(entry), svalue);
    }
    gtk_signal_connect(GTK_OBJECT(entry), "changed",
                       GTK_SIGNAL_FUNC(cb_socks_port),
                       entry);
    gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 1, 2,
                      (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
                      (GtkAttachOptions) (0), 10, 0);

    gtk_box_pack_start (GTK_BOX(vbox1), table, FALSE, FALSE, 5);
    cb_socks_enabled (button, NULL);

    /* ------------ */
    /* Apply button */
    /* ------------ */
    gtk_box_pack_start (GTK_BOX(vbox1), gtk_hseparator_new(), FALSE, FALSE, 5);

    button = gtk_button_new_with_label ("Save Changes");
    gtk_signal_connect (GTK_OBJECT(button), "clicked",
                        GTK_SIGNAL_FUNC(cb_save), NULL);
    gtk_box_pack_start (GTK_BOX(vbox1), button, FALSE, FALSE, 5);


    gtk_widget_show_all (hbox);
    return 0;
}

/* ----------------------------------------------------------------- */

/*
 * The prefs file must have the same uid as the real uid of this process,
 * it must have permissions no greater than 0700, and it must not be a
 * symbolic link.
 */
static int check_prefs_file() {
    char filename[256];
    struct stat statb;

    errno = 0;

    jp_get_home_file_name (PREFS_FILE, filename, 255);
    jp_logf (JP_LOG_DEBUG, "SyncMAL: prefs filename is %s\n", filename);

    if (lstat (filename, &statb) == -1) {
        if (errno == ENOENT) {
            /* doesn't exist */
            return 0;
        }
        else {
            jp_logf (JP_LOG_FATAL,
                         "SyncMAL: Error checking prefs file %s: %s\n",
                         filename,
                         strerror (errno));
            return -1;
        }
    }

    /*
     * The following code is adapted from code contained in the file
     * `rcfile_y.y' from the fetchmail-5.3.8 distribution.
     */
    if ((statb.st_mode & S_IFLNK) == S_IFLNK) {
        jp_logf (JP_LOG_FATAL,
                     "SyncMAL: Prefs file %s must not be a symbolic link.\n",
                     filename);
        return -1;
    }

    if (statb.st_uid != getuid()) {
        jp_logf (JP_LOG_FATAL,
                     "SyncMAL: Prefs file %s must be owned by you.\n",
                     filename);
        return -1;
    }

    if (statb.st_mode & ~(S_IFREG | S_IREAD | S_IWRITE | S_IEXEC)) {
        jp_logf (JP_LOG_INFO | JP_LOG_GUI,
                     "SyncMAL: Prefs file %s must have no more than\n"
                     "-rwx------ (0700) permissions.\n"
                     "Attempting to set permissions to 0600.\n",
                     filename);
        if (chmod (filename, S_IREAD | S_IWRITE) == -1) {
            return -1;
        }
        jp_logf (JP_LOG_INFO | JP_LOG_GUI,
                     "SyncMAL: Permissions on prefs file %s set to 0600\n",
                     filename);
    }

    return 0;
}

/*
 * This is called by plugin_sync to see if we need to skip the sync based
 * on the user's preferences. We just check the last sync time, compare it
 * with the current time, then see if the required amount of time has
 * passed.
 *
 * Returns TRUE if the sync should be skipped,
 *    ie TRUE == do not sync, FALSE == perform sync
 */
static gboolean skip_sync() {
    time_t last_sync;
    time_t ltime;
    struct tm *timep;
    long ivalue;
    const char *svalue;
    int last_year, now_year;
    int last_yday, now_yday;
    int last_hour, now_hour;
    gboolean rval = FALSE;   /* DON'T skip by default */

    /* Get the last sync time from the prefs */
    jp_get_pref (syncmal_prefs, SMPREF_LAST_SYNC, &ivalue, &svalue);
    last_sync = (time_t)atol (svalue);
    time (&ltime);
    jp_logf (JP_LOG_DEBUG, "SyncMAL::skip_sync() - last_sync = %ld, now = %ld\n", last_sync, ltime);

    /*
     * Extract the relevant parts of the last sync time and the local time.
     * Note that, despite what the man pages would seem to indicate, the
     * localtime function returns a pointer to a single globally allocated
     * structure which is overwritten with each call.
     */
    timep = localtime (&last_sync);
    last_year = timep->tm_year;
    last_yday = timep->tm_yday;
    last_hour = timep->tm_hour;
    jp_logf (JP_LOG_DEBUG,
             "SyncMAL::skip_sync() - last sync = %d/%d/%d %d:%d:%d\n",
             timep->tm_mon + 1, timep->tm_mday, timep->tm_year + 1900,
             timep->tm_hour, timep->tm_min, timep->tm_sec);

    timep = localtime (&ltime);
    now_year = timep->tm_year;
    now_yday = timep->tm_yday;
    now_hour = timep->tm_hour;
    jp_logf (JP_LOG_DEBUG,
             "SyncMAL::skip_sync() - now = %d/%d/%d %d:%d:%d\n",
             timep->tm_mon + 1, timep->tm_mday, timep->tm_year + 1900,
             timep->tm_hour, timep->tm_min, timep->tm_sec);

    /* Get the sync-when pref, and decide if we need to sync. */
    jp_get_pref (syncmal_prefs, SMPREF_SYNC_WHEN, &ivalue, NULL);
    switch (ivalue) {
        case EVERY_SYNC:
            rval = FALSE;
            break;

        case HOURLY:
            timep = localtime (&last_sync);
            timep->tm_hour++;
            if (mktime (timep) > ltime) {
                rval = TRUE;
            }
            break;

        case MORNING_AND_AFTERNOON:
            /* First, see if the last sync was on the same day */
            if (last_year != now_year) {
                rval = FALSE;
                break;
            }
            if (last_yday != now_yday) {
                rval = FALSE;
                break;
            }

            if (last_hour < 12) {
                /* morning */
                if (now_hour < 12) {
                    rval = TRUE;
                }
                else {
                    rval = FALSE;
                }
            }
            else {
                /* afternoon */
                if (now_hour >= 12) {
                    rval = TRUE;
                }
                else {
                    rval = FALSE;
                }
            }

            break;

        case DAILY:
            timep = localtime (&last_sync);
            timep->tm_mday++;
            if (mktime (timep) > ltime) {
                rval = TRUE;
            }
            break;

        case DISABLED:
            rval = TRUE;
            break;

        default:
            jp_logf (JP_LOG_WARN,
                    "Unrecognized pref value for sync_when: %d\n",
                    ivalue);
    }

    return rval;
}


/* ----------------------------------------------------------------- */
/* Callbacks */

static void cb_save (GtkWidget *widget, gpointer data) {
    jp_pref_write_rc_file (PREFS_FILE, syncmal_prefs, NUM_SMPREFS);
    if (check_prefs_file() < 0) {
        jp_logf (JP_LOG_FATAL,
                     "--------------------------------------------\n"
                     "ERROR: The preferences file " PREFS_FILE "\n"
                     "does not have the correct permissions and I\n"
                     "cannot change them. Please type\n"
                     "   chmod 0600 " PREFS_FILE "\n"
                     "in the ~/.jpilot directory to correct this.\n"
                     "--------------------------------------------\n");
    }
}

static void cb_proxy_enabled (GtkWidget *widget, gpointer data)
{
    int i;
    gboolean enabled = GTK_TOGGLE_BUTTON(widget)->active;

    jp_set_pref (syncmal_prefs, SMPREF_USE_PROXY, enabled, NULL);
    for (i = 0; i < PROXY_WIDGETS; i++) {
        gtk_widget_set_sensitive (proxy_widgets[i], enabled);
    }
}

static void cb_socks_enabled (GtkWidget *widget, gpointer data)
{
    int i;
    gboolean enabled = GTK_TOGGLE_BUTTON(widget)->active;

    jp_set_pref (syncmal_prefs, SMPREF_USE_SOCKS, enabled, NULL);
    for (i = 0; i < SOCKS_WIDGETS; i++) {
        gtk_widget_set_sensitive (socks_widgets[i], enabled);
    }
}

static void cb_proxy_address (GtkWidget *widget, GtkWidget *entry)
{
    const gchar *httpProxy = gtk_entry_get_text(GTK_ENTRY(entry));
    jp_set_pref (syncmal_prefs, SMPREF_PROXY_ADDRESS, 0, httpProxy);
}

static void cb_proxy_port (GtkWidget *widget, GtkWidget *entry)
{
    int httpProxyPort = atoi (gtk_entry_get_text(GTK_ENTRY(entry)));
    jp_set_pref (syncmal_prefs,
                 SMPREF_PROXY_PORT,
                 httpProxyPort,
                 gtk_entry_get_text(GTK_ENTRY(entry)));
}

static void cb_proxy_username (GtkWidget *widget, GtkWidget *entry)
{
    const gchar *proxyUsername = gtk_entry_get_text(GTK_ENTRY(entry));
    jp_set_pref (syncmal_prefs, SMPREF_PROXY_USERNAME, 0, proxyUsername);
}

static void cb_proxy_password (GtkWidget *widget, GtkWidget *entry)
{
    const gchar *proxyPassword = gtk_entry_get_text(GTK_ENTRY(entry));
    jp_set_pref (syncmal_prefs, SMPREF_PROXY_PASSWORD, 0, proxyPassword);
}

static void cb_socks_address (GtkWidget *widget, GtkWidget *entry)
{
    const gchar *socksProxy = gtk_entry_get_text(GTK_ENTRY(entry));
    jp_set_pref (syncmal_prefs, SMPREF_SOCKS_ADDRESS, 0, socksProxy);
}

static void cb_socks_port (GtkWidget *widget, GtkWidget *entry)
{
    int socksProxyPort = atoi (gtk_entry_get_text(GTK_ENTRY(entry)));
    jp_set_pref (syncmal_prefs,
                 SMPREF_SOCKS_PORT,
                 socksProxyPort,
                 gtk_entry_get_text (GTK_ENTRY(entry)));
}

static void cb_toggle_button (GtkWidget *widget, gpointer data) {

    switch (GPOINTER_TO_INT (data)) {
        case EVERY_SYNC_BUTTON:
            jp_logf (JP_LOG_DEBUG, "every sync button\n");
            jp_set_pref (syncmal_prefs,
                         SMPREF_SYNC_WHEN,
                         EVERY_SYNC,
                         NULL);
            break;

        case HOURLY_BUTTON:
            jp_logf (JP_LOG_DEBUG, "hourly button\n");
            jp_set_pref (syncmal_prefs,
                         SMPREF_SYNC_WHEN,
                         HOURLY,
                         NULL);
            break;

        case MORNING_AND_AFTERNOON_BUTTON:
            jp_logf (JP_LOG_DEBUG, "morning & afternoon button\n");
            jp_set_pref (syncmal_prefs,
                         SMPREF_SYNC_WHEN,
                         MORNING_AND_AFTERNOON,
                         NULL);
            break;

        case DAILY_BUTTON:
            jp_logf (JP_LOG_DEBUG, "daily button\n");
            jp_set_pref (syncmal_prefs,
                         SMPREF_SYNC_WHEN,
                         DAILY,
                         NULL);
            break;

        case DISABLED_BUTTON:
            jp_logf (JP_LOG_DEBUG, "disabled button\n");
            jp_set_pref (syncmal_prefs,
                         SMPREF_SYNC_WHEN,
                         DISABLED,
                         NULL);
            break;

        default:
            jp_logf (JP_LOG_WARN, "Invalid button data: %d\n",
                    GPOINTER_TO_INT (data));
    }
}

Generated by  Doxygen 1.6.0   Back to index