Logo Search packages:      
Sourcecode: dcgui version File versions  Download package

main.c

/* dc_gui2 - a GTK+2 GUI for DCTC
 * Copyright (C) 2002 Eric Prevoteau
 *
 * main.c: Copyright (C) Eric Prevoteau <www@a2pb.gotdns.org>
 *
 * 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.
 */
/*
$Id: main.c,v 1.45 2004/01/21 15:41:26 ericprev Exp $
*/

/*
 * Initial main.c file generated by Glade. Edit as required.
 * Glade will not overwrite this file.
 */
#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <signal.h>
#include <db.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <getopt.h>
#include <gconf/gconf-client.h>
#include <gnome.h>

#include "interface.h"
#include "callbacks.h"
#include "support.h"
#include "main.h"
#include "init_fnc.h"
#include "bookmark.h"
#include "bdb.h"
#include "do_connect.h"

#include "gui_layout.h"
#include "misc_gtk.h"
#include "misc.h"
#include "unode.h"
#include "ls_cache_clist.h"
#include "running_hub_clist.h"
#include "public_hub_clist.h"
#include "recent_hub_clist.h"
#include "seen_hub_clist.h"
#include "user_clist.h"
#include "find_result_clist.h"
#include "locate_user_clist.h"
#include "uaddr_clist.h"
#include "unode_clist.h"
#include "flagged_user_clist.h"
#include "upload_clist.h"
#include "download_clist.h"
#include "user_file_list_clist.h"
#include "queue_clist.h"
#include "shared_dir_clist.h"
#include "gdl_ctree.h"
#include "custom_hublist_tree.h"
#include "dctc_process.h"
#include "notes_buffer.h"
#include "global_user.h"
#include "manage_chat.h"
#include "userinfo.h"
#include "gtk_helper.h"
#include "gui_define.h"
#include "proc_serv.h"

#ifndef min
#define min(a,b)        (((a)<(b))?(a):(b))
#endif

#include "dcgui.xpm"

int utf8_mode=FALSE;          /* if FALSE, dc_gui converts incoming data from locale to UTF8 and outgoing data from UTF8 to locale */
                                                /* if TRUE, dc_gui performs no conversion on incoming/outgoing data */

GtkWidget *main_window=NULL;

GtkWidget *dl_popup=NULL;
GtkWidget *ul_popup=NULL;
GtkWidget *q_popup=NULL;
GtkWidget *user_popup=NULL;
GtkWidget *start_dl_popup=NULL;
GtkWidget *gdl_popup=NULL;
GtkWidget *uaddr_popup=NULL;
GtkWidget *fav_popup=NULL;

/* this string is "$HOME/.dctc" */
GString *dctc_main_dir=NULL;

GString *dctc_dir;
GString *dctc_active_client_file;

GString *last_search[2]={NULL,NULL};            /* the last search is kept because if multi-hub search is enabled */
                                                                                    /* the command(s) must be resent */
int local_udp_socket=-1;                                    /* this socket is used to send data to DCTC UDP communication socket, it is not bind to anything */

GString *dc_gui2_cmdfile=NULL;                        /* name of the file containing commands to process by dc_gui2 = $HOME/.dc_gui2.cmd */
GString *bt2dc_gui2_directory=NULL;             /* name of the directory containing the directory used by dc_gui2 to store running bittorrent data = $HOME/.dc_gui2/bt2dc_gui2/ */

/***************************/
/* periodic internal tasks */
/***************************/
guint32 running_client_list_refresh_rate=0;     /* delay between 2 refresh of the running client list (in 1/1000ths of seconds) */
guint running_client_list_refresh_rate_gta=0;   /* handle returned by gtk_timeout_add for this refresh (only meaningful if the previous var !=0) */

guint32 favorite_client_autostart_check_rate=0; /* delay between 2 checks of the favorite client autostart (in 1/1000ths of seconds) */
guint favorite_client_autostart_check_rate_gta=0;     /* handle returned by gtk_timeout_add for this refresh (only meaningful if the previous var !=0) */

guint32 cmd_file_check_rate=0;      /* delay between 2 checks of the .dc_gui2.cmd file (in 1/1000ths of seconds) */
guint cmd_file_check_rate_gta=0;    /* handle returned by gtk_timeout_add for this refresh (only meaningful if the previous var !=0) */

guint32 global_user_purge_rate=0;         /* delay between 2 refresh of the bittorrent list (in 1/1000ths of seconds) */
guint global_user_purge_rate_gta=0;             /* handle returned by gtk_timeout_add for this refresh (only meaningful if the previous var !=0) */

int auto_start_disabled=FALSE;            /* if TRUE, don't start new client for hub having the autostart flag set and without client */
int start_and_quit_enabled=FALSE;   /* if TRUE, the GUI ends as soon as the -u or -g flag was processed */

char *use_this_hub_address=NULL;
char *use_this_dchuburl=NULL;
char *use_this_profile=NULL;

/* GConf variables */
GConfClient *engine;

/********************************************/
/* set the periodic call rate of a function */
/*************************************************************/
/* if new_rate=0, a current running periodic call is removed */
/*************************************************************/
void set_periodic_function_call_rate(guint32 *rate, guint *handle, GtkFunction function_to_call, gpointer xtra_data_to_send_to_function, guint32 new_rate)
{
      if(new_rate==0)
      {
            /* disable periodic call */
            if(*handle!=0)
            {
                  gtk_timeout_remove(*handle);
                  *handle=0;
            }
            *rate=0;
      }
      else
      {     /* set a periodic call */
            if(*rate!=new_rate)
            {
                  /* at a different speed of the current one */
                  if(*handle!=0)
                        gtk_timeout_remove(*handle);
                  
                  *rate=new_rate;
                  *handle=gtk_timeout_add(new_rate, function_to_call, xtra_data_to_send_to_function);
            }
      }
}

/*******************************************************/
/* the following vars are used to manage I/O with dctc */
/*******************************************************/
DCTC_COM *current_dctc=NULL;        /* it is the descriptor of the DCTC connected to a hub */
DCTC_COM *gdl_dctc=NULL;                  /* it is the descriptor of the DCTC_master (the one handling all GDL transfers) */

GdkColor light_red, white, black, light_grey, green, light_orange;

GdkColor greyDD,greyEE;

static struct
{
   unsigned int r,v,b;
   GdkColor *ptr;
}alloc_color[]={
                                    {0xffff,0x0,0x0,&light_red},
                                    {0xffff,0xffff,0xffff,&white},
                                    {0,0,0,&black},
                                    {0xacac,0xacac,0xacac,&light_grey},
                                    {0x0,0xffff,0x0,&green},
                                    {0xffff,0xe7e7,0x8080,&light_orange},
                                    {0xdddd,0xdddd,0xdddd,&greyDD},
                                    {0xeeee,0xeeee,0xeeee,&greyEE},
                  {0,0,0,NULL}
               };

GtkStyle *sty_normal=NULL;
GtkStyle *sty_hilight=NULL;
static GPtrArray *label_blink_list=NULL;

gchar **last_started_search=NULL;         /* it is an array of gchar * produced by splitting the last entered search pattern */

LMP_ENTRY *unode_lmp=NULL;
G_LOCK_DEFINE(unode_lmp);

/*********************************/
/* add a label to the blink list */
/*********************************/
void blink_on(char *label_name)
{
      GtkWidget *w;
      int i;
      int fnd=0;

      /* restore original label style */
      w=get_widget_by_widget_name(main_window,label_name);
      if(w!=NULL)
      {
            gtk_widget_set_style(w,sty_hilight);
      }

      if(label_blink_list==NULL)
            label_blink_list=g_ptr_array_new();

      for(i=0;i<label_blink_list->len;i++)
      {
            char *t;

            t=g_ptr_array_index(label_blink_list,i);
            if((t!=NULL)&&(!strcmp(t,label_name)))
            {
                  fnd=1;
                  break;
            }
      }

      if(!fnd)
      {
            g_ptr_array_add(label_blink_list,strdup(label_name));
      }
}

/**************************************/
/* remove a label from the blink list */
/**************************************/
void blink_off(char *label_name)
{
      GtkWidget *w;
      int i;

      /* restore original label style */
      w=get_widget_by_widget_name(main_window,label_name);
      if(w!=NULL)
      {
            gtk_widget_set_style(w,sty_normal);
      }

      if(label_blink_list!=NULL)
      {
            for(i=0;i<label_blink_list->len;i++)
            {
                  char *t;

                  t=g_ptr_array_index(label_blink_list,i);
                  if((t!=NULL)&&(!strcmp(t,label_name)))
                  {
                        g_ptr_array_remove_index_fast(label_blink_list,i);
                        free(t);
                        break;
                  }
            }
      }
}

/*********************************************************/
/* we don't want to receive SIGPIPE, SIGHUP and SIG_CHLD */
/*********************************************************/
static void set_sig(void)
{
   struct sigaction act;
   sigset_t set;

   /* ignore SIGPIPE */
      /* ignore SIGCHLD */
      /* ignore SIGHUP */
   sigemptyset(&set);
   sigaddset(&set,SIGPIPE);
   sigaddset(&set,SIGCHLD);
   sigaddset(&set,SIGHUP);
   act.sa_handler=SIG_IGN;
   act.sa_mask=set;
   act.sa_flags=SA_RESTART;

   sigprocmask(SIG_UNBLOCK,&set,NULL);
      sigaction(SIGPIPE,&act,NULL);
      sigaction(SIGCHLD,&act,NULL);
      sigaction(SIGHUP,&act,NULL);
}

static void start_dctc_client_from_huburl(char *dchub_url,char *profile)
{
      GString *url;
      char *t;

      if(strncasecmp(dchub_url,"dchub://",strlen("dchub://")))
      {
            gtk_timeout_add(4000,(void*)gtk_main_quit,NULL);
            gnome_error_dialog(_("Invalid dchub URL. it must start with dchub://"));
            gtk_main();
            exit(1);
      }

      url=g_string_new(dchub_url+strlen("dchub://"));
      t=strchr(url->str,'/');
      if(t!=NULL)
      {
            url=g_string_truncate(url,t-url->str);
      }

      if(url->len<3)    /* 3 is perhaps not even enough to have a valid hostname, I don't know if a domain exists with only 1 letter */
      {
            gtk_timeout_add(4000,(void*)gtk_main_quit,NULL);
            gnome_error_dialog(_("Invalid dchub URL. The URL is too small to be valid"));
            gtk_main();
            exit(1);
      }

      start_a_new_dctc(url->str,0,profile);
      g_string_free(url,TRUE);
}

static void ed2k_response_function (GtkDialog *dialog, gint arg1, gpointer user_data)
{
      if(GPOINTER_TO_INT(arg1)==GTK_RESPONSE_ACCEPT)
      {
            gconf_client_set_string(engine,"/desktop/gnome/url-handlers/ed2k/command",
                                                                         "cmd2dc_gui2 \"%s\"",NULL);
            gconf_client_set_bool(engine,"/desktop/gnome/url-handlers/ed2k/enabled",
                                                                         TRUE,NULL);
      }
      gtk_widget_destroy(GTK_WIDGET(user_data));
}

/**********************************************************************/
/* check if the gnome handler for the protocol ed2k:// is cmd2dc_gui2 */
/**********************************************************************/
void check_url_handler(void)
{
      gchar *str;
      int delta;
      const char *err_msg;

      str=gconf_client_get_string(engine,"/desktop/gnome/url-handlers/ed2k/command",NULL);
      if(str!=NULL)
      {
            delta=strcmp("cmd2dc_gui2 \"%s\"",str);
            g_free(str);
            if(delta)
            {
                  err_msg=_("ed2k:// URLs are handled by another program.\nUse this program instead ?");
                  goto reset_url_handler;
            }
      }
      else
      {
            /* no ed2k URL handler */
            err_msg=_("ed2k:// URLs are not handled by any program.\nUse this program for ed2k:// URLs ?");
            reset_url_handler:
            {
                  GtkWidget *dialog, *label;
                  dialog=gtk_dialog_new_with_buttons("ed2k URL handler",GTK_WINDOW(main_window),
                                                      GTK_DIALOG_DESTROY_WITH_PARENT,
                                                      GTK_STOCK_YES,GTK_RESPONSE_ACCEPT,
                                                      GTK_STOCK_NO,GTK_RESPONSE_REJECT,
                                                      NULL);

                  label=gtk_label_new(err_msg);
                  /* Add the label, and show everything we've added to the dialog. */
                  gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
                      label);

                  /* Ensure that the dialog box is destroyed when the user responds. */
                  g_signal_connect_swapped (GTK_OBJECT (dialog), "response",
                                          G_CALLBACK (ed2k_response_function), GTK_OBJECT (dialog));

                  gtk_widget_show_all(dialog);
            }
      }
}

static void discard_user(const char *nickname, gboolean *updated, GtkTreeModel *uclist)
{
      GLOB_USER *gu;

      gu=gu_get_user(nickname);
      if(gu)
      {
            notify_private_chat(gu);
            remove_user(gu,uclist);
            *updated=TRUE;
      }
}

static void instanciate_user(LMP_UINFO *user, gboolean *updated, GtkTreeModel *uclist)
{
      GLOB_USER *gu;

      if(user->entry_is_busy&UINFO_BIT_POPULATED)
      {
            /* FULL UINFO available */
            gu=add_or_update_user(user->cnx_type,user->nickname,user->share_size,
                                                            (strlen(user->uemail)?user->uemail:NULL),
                                                            (strlen(user->udesc)?user->udesc:NULL),
                                                            ((unsigned int)(user->uflag))&255,uclist,
                                          (user->entry_is_busy&UINFO_BIT_IS_ONLINE)?TRUE:FALSE,
                                          (user->entry_is_busy&UINFO_BIT_IS_OP)?TRUE:FALSE
                                          );
      }
      else
      {
            gu=add_or_update_user("",user->nickname,0,NULL,NULL,0,uclist,
                                          (user->entry_is_busy&UINFO_BIT_IS_ONLINE)?TRUE:FALSE,
                                          (user->entry_is_busy&UINFO_BIT_IS_OP)?TRUE:FALSE
                                          );
      }

      *updated=TRUE;
}

void sync_user_list_with_dctc(void)
{
      if(current_dctc!=NULL)
      {
            LMP_UINFO *addr;
            int nb_records;
            gboolean has_update=FALSE;

            SORT_VARS( )

            GtkTreeModel *gtm;
            GtkListStore *gls;
            {
                  GtkWidget *w;
                  w=get_widget_by_widget_name(main_window,"user_clist");

                  gls=GTK_LIST_STORE(gtm=gtk_tree_view_get_model(GTK_TREE_VIEW(w)));
            }

            SORT_SAVE_GLS_TO_UNSORTED(,gtm,gls)

            if(!get_user_info_lmp_copy(current_dctc->user_info_lmp,&addr,&nb_records))
            {
                  int low;
                  int i;
                  /* now, compare the copy and the current state */

                  low=min(nb_records,current_dctc->user_info_nb_records_sync_last_state);

                  for(i=1;i<low;i++)            /* the first record (idx=0) is reserved for header */
                  {
                        gboolean nu=(addr[i].entry_is_busy&UINFO_BIT_BUSY)?TRUE:FALSE;
                        gboolean old=(current_dctc->user_info_lmp_sync_last_state[i].entry_is_busy&UINFO_BIT_BUSY)?TRUE:FALSE;

                        if(nu==FALSE)
                        {
                              if(old==FALSE)
                                    continue;               /* both entries where empty */
                              else if(old==TRUE)
                              {
                                    /* someone has left the hub */
                                    discard_user(current_dctc->user_info_lmp_sync_last_state[i].nickname,&has_update,gtm);
                              }
                        }
                        else
                        {
                              if(old==FALSE)
                              {
                                    /* someone has entered the hub */
                                    instanciate_user(&(addr[i]),&has_update,gtm);
                              }
                              else
                              {
                                    /* the entry has changed */
                                    if(!strcmp(addr[i].nickname,current_dctc->user_info_lmp_sync_last_state[i].nickname))
                                    {
                                          /* but the nickname is unchanged */
                                          if((addr[i].share_size!=current_dctc->user_info_lmp_sync_last_state[i].share_size)||
                                                (addr[i].uflag!=current_dctc->user_info_lmp_sync_last_state[i].uflag)||
                                                (strcmp(addr[i].cnx_type,current_dctc->user_info_lmp_sync_last_state[i].cnx_type))||
                                                (strcmp(addr[i].uemail,current_dctc->user_info_lmp_sync_last_state[i].uemail))||
                                                (strcmp(addr[i].udesc,current_dctc->user_info_lmp_sync_last_state[i].udesc))
                                            )
                                          {
                                                instanciate_user(&addr[i],&has_update,gtm);           /* just update the entry */
                                          }
                                    }
                                    else
                                    {
                                          /* and the nickname has changed */
                                          discard_user(current_dctc->user_info_lmp_sync_last_state[i].nickname,&has_update,gtm);
                                          instanciate_user(&addr[i],&has_update,gtm);           /* just update the entry */
                                    }
                              }
                        }
                  }
                  
                  /* we have now the rest of the list */
                  if(nb_records>low)      /* more record now than before ? */
                  {
                        /* the new list is bigger, add new user */
                        for(i=low;i<nb_records;i++)
                        {
                              if(addr[i].entry_is_busy&UINFO_BIT_BUSY)
                                    instanciate_user(&addr[i],&has_update,gtm);           /* add the entry */
                        }
                  }
                  else
                  {
                        for(i=low;i<current_dctc->user_info_nb_records_sync_last_state;i++)
                        {
                              if(current_dctc->user_info_lmp_sync_last_state[i].entry_is_busy&UINFO_BIT_BUSY)
                                    discard_user(current_dctc->user_info_lmp_sync_last_state[i].nickname,&has_update,gtm);
                        }
                  }

                  /* and replace the current copy by the new one */
                  if(current_dctc->user_info_lmp_sync_last_state)
                        free(current_dctc->user_info_lmp_sync_last_state);
                  current_dctc->user_info_lmp_sync_last_state=addr;
                  current_dctc->user_info_nb_records_sync_last_state=nb_records;
            }
            if(has_update)
                  update_users_info();

            SORT_RESTORE(,gtm)
      }
}

gint do_gu_purge(gpointer data)
{
      static gboolean sync_in_progress=FALSE;

      /* because we make calls to GTK here, GTK itself can call the periodic 'do_purge' function creating a loop */
      /* very visible on big user lists */
      if(!sync_in_progress)
      {
            sync_in_progress=TRUE;
            gu_purge();
            sync_user_list_with_dctc();
            sync_in_progress=FALSE;
      }
      return TRUE;      /* don't stop periodic call */
}

/* gconf_path always ends with a '/' */
static void convert_value_from_gnome_config_to_gconf(const char *gconf_path, const char *key, const char *value)
{
      /* all keys are integers except *_ent_cnt (string), *_scale_val (float) and *_spin_val (float) */
      int ln;
      char fpath[2048];

      sprintf(fpath,"%s%s",gconf_path,key);

      ln=strlen(key);

      if( (ln>strlen("_ent_cnt"))&&(!strcmp(key+ln-strlen("_ent_cnt"),"_ent_cnt")))
      {
            gconf_client_set_string(engine,fpath,value,NULL);
      }
      else if( (ln>strlen("_scale_val"))&&(!strcmp(key+ln-strlen("_scale_val"),"_scale_val")))
      {
            gconf_client_set_float(engine,fpath,atof(value),NULL);
      }
      else if( (ln>strlen("_spin_val"))&&(!strcmp(key+ln-strlen("_spin_val"),"_spin_val")))
      {
            gconf_client_set_float(engine,fpath,atof(value),NULL);
      }
      else
      {
            gconf_client_set_int(engine,fpath,atoi(value),NULL);
      }
}

/* update prefs from gnome_config format to gconf format */
static void update_config_from_gnome_config_to_gconf(void)
{
      gint v=0;
      void *iter;

      v=gconf_client_get_int(engine,"/apps/" PROGNAME "/pref_version",NULL);
      if(v==0)
      {
            /* preferences are in gnome_config format */
            printf("converting keys\n");

            /* 1) convert geometry information */
            /* scan all /Dc_gui2/Geometry keys and convert all keys except ones beginning with Profile. and GUIPrefs. */
            /* into /apps/Dc_gui2/Geometry gconf */
            iter=gnome_config_init_iterator("/" PROGNAME "/Geometry");
            while(iter!=NULL)
            {
                  char *key=NULL;
                  char *buf=NULL;

                  iter=gnome_config_iterator_next(iter,&key,&buf);
                  if(iter!=NULL)
                  {
                        if( (strncmp(key,"Profile.",8)) && (strncmp(key,"GUIPrefs.",9)))
                        {
                              convert_value_from_gnome_config_to_gconf("/apps/" PROGNAME "/Geometry/",key,buf);
                        }
                  }
            }

            /* 2) convert profiles information */
            /* scan all /Dc_gui2/Geometry keys and convert keys beginning with Profile. */
            /* into /apps/Dc_gui2/Profile/prof_name/gconf */
            iter=gnome_config_init_iterator("/" PROGNAME "/Geometry");
            while(iter!=NULL)
            {
                  char *key=NULL;
                  char *buf=NULL;

                  iter=gnome_config_iterator_next(iter,&key,&buf);
                  if(iter!=NULL)
                  {
                        if(!strncmp(key,"Profile.",8))
                        {
                              char new_gc_path[2048];
                              char new_key[2048];
                              char *t;
                              int i;
                              strcpy(new_gc_path,"/apps/" PROGNAME "/");
                              t=new_gc_path+strlen(new_gc_path);
                              strcpy(t,key);

                              for(i=0;t[i]!='.';i++);
                              t[i++]='/';       /* convert "Profile.profname.*" into "Profile/profname.*" */

                              for(;t[i]!='.';i++);
                              t[i++]='/';       /* convert "Profile/profname.*" into "Profile/profname/*" */
                              strcpy(new_key,t+i);
                              t[i]='\0';              /* => "Profile/profname/" */
                              
                              convert_value_from_gnome_config_to_gconf(new_gc_path,new_key,buf);
                        }
                  }
            }

            /* 3) convert profiles information */
            /* scan all /Dc_gui2/Geometry keys and convert keys beginning with GUIPrefs. */
            /* into /apps/Dc_gui2/Profile/GUIPrefs */
            iter=gnome_config_init_iterator("/" PROGNAME "/Geometry");
            while(iter!=NULL)
            {
                  char *key=NULL;
                  char *buf=NULL;

                  iter=gnome_config_iterator_next(iter,&key,&buf);
                  if(iter!=NULL)
                  {
                        if(!strncmp(key,"GUIPrefs.",9))
                        {
                              char new_gc_path[2048];
                              char new_key[2048];
                              char *t;
                              int i;
                              strcpy(new_gc_path,"/apps/" PROGNAME "/");
                              t=new_gc_path+strlen(new_gc_path);
                              strcpy(t,key);

                              for(i=0;t[i]!='.';i++);
                              t[i++]='/';       /* convert "GUIPrefs.*" into "GUIPrefs/*" */
                              strcpy(new_key,t+i);
                              t[i]='\0';              /* => "GUIPrefs/" */
                              
                              convert_value_from_gnome_config_to_gconf(new_gc_path,new_key,buf);
                        }
                  }
            }

            /* 4) set the pref version */
            gconf_client_set_int(engine,"/apps/" PROGNAME "/pref_version",1,NULL);

            gconf_client_suggest_sync(engine,NULL);
      }
}

/****************************/
/* start an embedded client */
/**********************************************************************************/
/* input: exec_name= name of the program to start                                 */
/*        with_io_channel= TRUE if a com channel must be created for this program */
/*        widget_container= widget to embed the display (can be NULL)             */
/**********************************************************************************/
static void start_embedded(const char *exec_name, gboolean with_io_channel, GtkContainer *widget_container)
{
      int sockpair[2];
      GdkNativeWindow sock_id=0;

      if(widget_container!=NULL)
      {
            GtkWidget *socket;

            socket=gtk_socket_new();
            gtk_widget_show(socket);
            gtk_container_add(widget_container,socket);
            gtk_widget_realize(socket);
            sock_id=gtk_socket_get_id(GTK_SOCKET(socket));
      }

      if(with_io_channel)
      {
            if(socketpair(AF_UNIX,SOCK_STREAM,0,sockpair)==-1)
            {
                  perror("socketpair");
                  with_io_channel=FALSE;
            }
      }

      switch(fork())
      {
            case -1:          perror("fork");
                                    break;

            case 0:           {
                                          char buf[32];

                                          if(widget_container!=NULL)
                                          {
                                                sprintf(buf,"%lu",(unsigned long)sock_id);
                                                setenv("EMB_WID",buf,TRUE);
                                          }

                                          if(with_io_channel)
                                          {
                                                sprintf(buf,"%d",sockpair[1]);
                                                setenv("EMB_IOC",buf,TRUE);
                                                close(sockpair[0]);
                                          }
                                          execlp(exec_name,exec_name,NULL);
                                          fprintf(stderr,"Fail to star '%s': %s\n",exec_name,strerror(errno));
                                          _exit(0);
                                    }

            default:          if(with_io_channel)
                                    {
                                          close(sockpair[1]);
                                          if(register_entry(sockpair[0],exec_name)==NULL)
                                          {
                                                fprintf(stderr,"Register entry error.\n");
                                          }
                                    }
                                    break;
      }
      return;
}

int
main (int argc, char *argv[])
{
      char *path;
      GdkColormap *colormap;
      int i;

#ifdef ENABLE_NLS
  bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
  textdomain (GETTEXT_PACKAGE);
#endif

      path=getenv("HOME");
      
      /* cmd file= $HOME/.dc_gui2.cmd */
      dc_gui2_cmdfile=g_string_new(NULL);
      g_string_sprintf(dc_gui2_cmdfile,"%s/.dc_gui2.cmd",(path!=NULL)?path:".");
      if(access(dc_gui2_cmdfile->str,R_OK|W_OK))
      {
            if(errno!=ENOENT)
            {
                  fprintf(stderr,"You have no access rights on %s, abort.\n",dc_gui2_cmdfile->str);
                  exit(1);
            }
      }

      /* bittorrent directory = $HOME/.dc_gui2/bt2dc_gui2/ */
      bt2dc_gui2_directory=g_string_new(NULL);
      g_string_sprintf(bt2dc_gui2_directory,"%s/.dc_gui2/bt2dc_gui2/",(path!=NULL)?path:".");

      /* "notes" file */
      dc_gui2_note_file=g_string_new(NULL);
      g_string_sprintf(dc_gui2_note_file,"%s/.dc_gui2/notes",(path!=NULL)?path:".");

      /* main dir= $HOME/.dctc */
      dctc_main_dir=g_string_new(NULL);
      g_string_sprintf(dctc_main_dir,"%s/.dctc",(path!=NULL)?path:".");
      if(access(dctc_main_dir->str,R_OK|W_OK|X_OK))
      {
            if(errno==ENOENT)
            {
                  if(mkdir(dctc_main_dir->str,0777))
                  {
                        perror("mkdir");
                        fprintf(stderr,"Unable to create %s, abort.\n",dctc_main_dir->str);
                        exit(1);
                  }
            }
            else
            {
                  fprintf(stderr,"You have no access rights on %s, abort.\n",dctc_main_dir->str);
                  exit(1);
            }
      }

      dctc_dir=g_string_new(NULL);
      g_string_sprintf(dctc_dir,"%s/running",dctc_main_dir->str);
      if(access(dctc_dir->str,R_OK|W_OK|X_OK))
      {
            if(errno==ENOENT)
            {
                  if(mkdir(dctc_dir->str,0777))
                  {
                        perror("mkdir");
                        fprintf(stderr,"Unable to create %s, abort.\n",dctc_dir->str);
                        exit(1);
                  }
            }
            else
            {
                  fprintf(stderr,"You have no access rights on %s, abort.\n",dctc_dir->str);
                  exit(1);
            }
      }
      dctc_active_client_file=g_string_new(NULL);
      g_string_sprintf(dctc_active_client_file,"%s/gstatus",dctc_main_dir->str);

      /* this socket is used to send data to DCTC UDP communication socket, it is not bind to anything */
      local_udp_socket=socket(AF_UNIX,SOCK_DGRAM,0);

      {
            GString *tmp;

            /* create uaddr_ready file */
            tmp=g_string_new(dctc_main_dir->str);
            g_string_sprintfa(tmp,"/unode.%d",sizeof(UNODE_DATA));

            unode_lmp=lmp_new(tmp->str,sizeof(UNODE_DATA));
            if(unode_lmp==NULL)
            {
                  fprintf(stderr,"unable to create %s\n",tmp->str);
                  g_string_free(tmp,TRUE);
                  exit(1);
            }
            g_string_free(tmp,TRUE);
      }

#if 0
      gnome_program_init (PACKAGE, VERSION, LIBGNOMEUI_MODULE,
                      argc, argv,
                      GNOME_PARAM_APP_DATADIR, PACKAGE_DATA_DIR,
                      NULL);
#warning CODE REPLACED (no backward compatibile function)
#else

      {
            struct poptOption start_options[]={
                                                      /* -s (auto_start_disabled) */
                                                      {"autostart",'s',POPT_ARG_NONE,&auto_start_disabled,0,_("Disable auto-start of DCTC clients"),NULL},
                                                      /* -h hub_address (address of a hub to connect to) */
                                                      {"hubaddress",'h',POPT_ARG_STRING,&use_this_hub_address,0,_("Start a new DCTC client for the given hub address"),NULL},
                                                      /* -u dchub_url (dchub://address of a hub to connect to) */
                                                      {"dchuburl",'u',POPT_ARG_STRING,&use_this_dchuburl,0,_("Start a new DCTC client for the given dchub URL"),NULL},
                                                      /* -p profilename (profile to use for the -g flag) */
                                                      {"profile",'p',POPT_ARG_STRING,&use_this_profile,0,_("Profile to use for the hub specified with the -g flag (mandatory if -g or -u is used"),NULL},
                                                      /* -e (start_and_quit_enabled) */
                                                      {"exit",'e',POPT_ARG_NONE,&start_and_quit_enabled,0,_("Quit the GUI immediatly. This option is useful only if -h or -u is used"),NULL},
                                                      {NULL, '\0', 0, NULL, 0, NULL, NULL }
                                                      };

            gnome_program_init (PACKAGE, VERSION, LIBGNOMEUI_MODULE,
                        argc, argv,
                                                //GNOME_PROGRAM_STANDARD_PROPERTIES,
                        GNOME_PARAM_APP_DATADIR, PACKAGE_DATA_DIR,
                                                GNOME_PARAM_POPT_TABLE, start_options,
                        NULL);
      }
#endif

      if( ((use_this_hub_address!=NULL) || (use_this_dchuburl!=NULL)) && (use_this_profile==NULL) )
      {
            GtkWidget *w;

            w=gnome_error_dialog(_("You must specify a profile to use using -p flag if you use either -h or -u flag"));
      g_signal_connect((gpointer)w,"hide",G_CALLBACK(gtk_main_quit),NULL);
            gtk_main();
            exit(1);
      }

      if(use_this_dchuburl!=NULL)
      {
            start_dctc_client_from_huburl(use_this_dchuburl,use_this_profile);
      }
      else if(use_this_hub_address!=NULL)
      {
            /* too easy to program it :) */
            start_a_new_dctc(use_this_hub_address,0,use_this_profile);
      }

      if(start_and_quit_enabled==TRUE)
      {     /* the option -a (--saq) allows a GUI to start a DCTC client (using -h or -u) and immediatly leaves */
            /* to avoid to have as many GUI as DCTC client. */
            exit(0);
      }

      set_sig();

      engine=gconf_client_get_default();
      /* update prefs from gnome_config format to gconf format */
      update_config_from_gnome_config_to_gconf();

  /*
   * The following code was added by Glade to create one of each component
   * (except popup menus), just so that you see something after building
   * the project. Delete any components that you don't want shown initially.
   */
      main_window = create_app1 ();

      dl_popup=create_dl_popup_menu ();
      ul_popup=create_ul_popup_menu ();
      q_popup=create_q_popup_menu ();
      user_popup=create_user_popup_menu ();
      start_dl_popup=create_start_dl_popup_menu ();
      gdl_popup=create_gdl_popup_menu ();
      uaddr_popup=create_uaddr_popup_menu ();

      /* create models for list and tree */
      bmav4_cached_user_list_clist();
      bmav4_running_hub_clist();
      bmav4_user_clist();
      bmav4_hub_favorite_clist();
      bmav4_public_hub_clist();
      bmav4_recent_hub_clist();
      bmav4_seen_hub_clist();
      bmav4_find_result_clist();
      bmav4_locate_user_clist();
      bmav4_uaddr_clist();
      bmav4_unode_clist();
      bmav4_flagged_user_clist();
      bmav4_upload_clist();
      bmav4_download_clist();
      bmav4_user_file_list_clist();
      bmav4_queue_clist();
      bmav4_shared_dir_clist();
      bmav4_gdl_ctree();
      bmav4_custom_hublist_tree();

      gui_full_restore(main_window,NULL);
      gtk_widget_realize(main_window);
      on_get_uinfo_checkbutton_toggled(NULL,NULL);
#if 0
      gnome_window_icon_set_from_file(GTK_WINDOW(main_window),"icon.xpm");
#else
      {
            static GdkPixmap *win_pix=NULL;
            static GdkBitmap *win_bit=NULL;

            win_pix=gdk_pixmap_create_from_xpm_d(main_window->window,&win_bit,NULL,dcgui_xpm);

            gdk_window_set_icon_name (main_window->window, "DCgui " VERSION);
            gdk_window_set_icon(main_window->window,NULL,win_pix,win_bit);
      }
#endif
      gtk_widget_show (main_window);


      /* preallocate some useful colors */
      colormap=gdk_window_get_colormap(main_window->window);
      i=0;
      while(alloc_color[i].ptr!=NULL)
      {
            alloc_color[i].ptr->red=(guint16)alloc_color[i].r;
            alloc_color[i].ptr->green=(guint16)alloc_color[i].v;
            alloc_color[i].ptr->blue=(guint16)alloc_color[i].b;
      
            /* Allocate color */
            gdk_color_alloc (colormap, alloc_color[i].ptr);
            i++;
      }

      /* fill running hub clist */
      fill_recent_hub_clist();
      fill_running_hub_clist();
      fix_pref_window();
      convert_old_bookmark_to_new_bookmark_format();
      reload_bookmark();

      init_clist();
      do_berkeley_init();
      begin_xfer_list_fnc(NULL);

      gtk_widget_show(get_widget_by_widget_name(main_window,"bookmark_button"));
      gtk_widget_hide(get_widget_by_widget_name(main_window,"delete_selected_bookmark_button"));
      gtk_widget_hide(get_widget_by_widget_name(main_window,"start_dctc_selected_hub_button"));
      gtk_widget_hide(get_widget_by_widget_name(main_window,"hide_search_user_button"));
      gtk_widget_hide(get_widget_by_widget_name(main_window,"user_search_vbox"));

      /* misc style used by labels */
      sty_normal=gtk_style_copy(gtk_widget_get_style(get_widget_by_widget_name(main_window,"chat_page")));
      sty_hilight=gtk_style_copy(sty_normal);
      sty_hilight->fg[GTK_STATE_NORMAL]=
      sty_hilight->text[GTK_STATE_NORMAL]=
      sty_hilight->fg[GTK_STATE_ACTIVE]=
      sty_hilight->text[GTK_STATE_ACTIVE]=
      sty_hilight->fg[GTK_STATE_PRELIGHT]=
      sty_hilight->text[GTK_STATE_PRELIGHT]=
      sty_hilight->fg[GTK_STATE_SELECTED]=
      sty_hilight->text[GTK_STATE_SELECTED]=
      sty_hilight->fg[GTK_STATE_INSENSITIVE]=
      sty_hilight->text[GTK_STATE_INSENSITIVE]=green;

      /* start periodic task */
      set_periodic_function_call_rate(&running_client_list_refresh_rate,&running_client_list_refresh_rate_gta,
                                                                        running_client_list_periodic_refresh,NULL,
                                                                        1000*gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(get_widget_by_widget_name(main_window,"running_client_list_refresh_rate_spinbutton"))) );
      set_periodic_function_call_rate(&favorite_client_autostart_check_rate,&favorite_client_autostart_check_rate_gta,
                                                                        favorite_client_periodic_autostart,NULL,
                                                                        1000*gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(get_widget_by_widget_name(main_window,"favorite_client_autostart_check_rate_spinbutton"))) );

      set_periodic_function_call_rate(&cmd_file_check_rate,&cmd_file_check_rate_gta,
                                                                        cmd_file_check,NULL, 1000);   /* 1 time per second */

      set_periodic_function_call_rate(&global_user_purge_rate,&global_user_purge_rate,
                                                                        do_gu_purge,NULL, 5000);      /* 1 time per 5 second */

      /* check the url handler only if not already done */
      {
            gboolean flag;
            GError *err=NULL;

            flag=gconf_client_get_bool(engine,"/apps/" PROGNAME "/Flags/NoCheckUrlHandler",&err);
            if(err!=NULL)
            {
                  flag=FALSE;
                  g_error_free(err);
            }

            if(flag==FALSE)
            {
                  check_url_handler();
                  gconf_client_set_bool(engine,"/apps/" PROGNAME "/Flags/NoCheckUrlHandler",TRUE,NULL);
            }
      }

      {
            gboolean flag;
            GError *err=NULL;

            flag=gconf_client_get_bool(engine,"/apps/" PROGNAME "/Flags/NoProfileWarning",&err);
            if(err!=NULL)
            {
                  flag=FALSE;
                  g_error_free(err);
            }

            if(flag==FALSE)
            {
                  gnome_warning_dialog(_("If you have used dc_gui2 previous version(s), there is some minor changes to take into account.\n"
                                                            "  1) the profile named 'default' is MANDATORY\n"
                                                            "  2) if you have multiple profiles with multiple download directories, dc_gui2 will only display information of the 'default' profile download directory."));
                  gconf_client_set_bool(engine,"/apps/" PROGNAME "/Flags/NoProfileWarning",TRUE,NULL);
            }
      }


      {
            gboolean hublist_available=FALSE;
            gboolean dctc_available=FALSE;
            gboolean dctc_master_available=FALSE;
            int combo;
            gboolean usable_dir=FALSE;
            GString *err_msg;

            char *err_msg_array[]={
                                                /* 0 */     _("hublist, dctc and dctc_master are not found in the path, fix it and restart the program"),
                                                /* 1 */     _("dctc and dctc_master are not found in the path, fix it and restart the program"),
                                                /* 2 */     _("hublist and dctc_master are not found in the path, fix it and restart the program"),
                                                /* 3 */     _("dctc_master is not found in the path, fix it and restart the program"),
                                                /* 4 */     _("hublist and dctc are not found in the path, fix it and restart the program"),
                                                /* 5 */     _("dctc is not found in the path, fix it and restart the program"),
                                                /* 6 */     _("hublist is not found in the path, fix it and restart the program"),
                                                /* 7 */     NULL
                                                };

            hublist_available=check_prog_in_path("hublist");
            dctc_available=check_prog_in_path("dctc");
            dctc_master_available=check_prog_in_path("dctc_master");

            combo=0;
            if(hublist_available)
                  combo|=1;
            if(dctc_available)
                  combo|=2;
            if(dctc_master_available)
                  combo|=4;

            err_msg=g_string_new("");
            if(err_msg_array[combo]!=NULL)
            {
                  g_string_append(err_msg,err_msg_array[combo]);
            }

            {     /* check if a socket can be created in $HOME/.dctc/ */
                  gchar *dc_path;

                  dc_path=g_strconcat( ((path!=NULL)?path:"."),"/.dctc",NULL);
                  usable_dir=check_socket_creation_in_directory(dc_path,"dctc-unode.udp","__junk_dcgui2");
                  g_free(dc_path);
            }

            if(usable_dir==FALSE)
            {
                  if(err_msg->len!=0)
                        g_string_append_c(err_msg,'\n');
                  g_string_append(err_msg,_("$HOME/.dctc directory is not usable (cannot create unix socket inside)"));
            }

            if(err_msg->len)
            {
                  GtkWidget *dialog;

                  dialog=gtk_message_dialog_new(GTK_WINDOW(main_window),GTK_DIALOG_DESTROY_WITH_PARENT,
                                                                  GTK_MESSAGE_ERROR,
                                                                  GTK_BUTTONS_CLOSE,
                                                                  err_msg->str);
                  gtk_dialog_run (GTK_DIALOG (dialog));
                  gtk_widget_destroy (dialog);
            }

            g_string_free(err_msg,TRUE);
      }
      load_notes_text_buffer();

      /* embed done process */
      start_embedded("dc_gui2_stat",FALSE,GTK_CONTAINER(gtk_notebook_get_nth_page(GTK_NOTEBOOK(get_widget_by_widget_name(main_window,"xfer_notebook")),XFER_DONE_TAB)));
      start_embedded("dc_gui2_unattached_gdl",TRUE,GTK_CONTAINER(gtk_notebook_get_nth_page(GTK_NOTEBOOK(get_widget_by_widget_name(main_window,"xfer_notebook")),XFER_UATGDL_TAB)));
      start_embedded("dc_gui2_bt",TRUE,GTK_CONTAINER(gtk_notebook_get_nth_page(GTK_NOTEBOOK(get_widget_by_widget_name(main_window,"xfer_notebook")),XFER_BITTORRENT_TAB)));

      gtk_main ();
      do_berkeley_exit();
      g_object_unref(G_OBJECT(engine));
      return 0;
}


Generated by  Doxygen 1.6.0   Back to index