Yattm - unified GTK instant-messaging client logo
   [Generated for version 0.2-17 - Mon Jan 6 19:01:23 GMT+1 2003]

Home - Main Page - Data Structures - File List - Data Fields - Globals

util.c

Go to the documentation of this file.
00001 /*
00002  * Yattm 
00003  *
00004  * Copyright (C) 1999, Torrey Searle <tsearle@uci.edu>
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  */
00021 
00022 /*
00023  * util.c
00024  * just some handy functions to have around
00025  *
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #  include <config.h>
00030 #endif
00031 
00032 #include "intl.h"
00033 #include <string.h>
00034 #include <errno.h>
00035 #include <stdlib.h>
00036 #ifdef __MINGW32__
00037 #include <winsock2.h>
00038 #else
00039 #include <sys/wait.h>
00040 #include <sys/socket.h>
00041 #include <netinet/in.h>
00042 #include <arpa/inet.h>
00043 #include <netdb.h>
00044 #endif
00045 #include <ctype.h>
00046 #include <sys/stat.h>
00047 #include <assert.h>
00048 #include "util.h"
00049 #include "status.h"
00050 #include "globals.h"
00051 #include "chat_window.h"
00052 #include "value_pair.h"
00053 #include "plugin.h"
00054 
00055 #ifndef NAME_MAX
00056 #define NAME_MAX 4096
00057 #endif
00058 
00059 gint clean_pid(void * dummy)
00060 {
00061     int status;
00062     pid_t pid;
00063 
00064 #ifndef __MINGW32__
00065     pid = waitpid(-1, &status, WNOHANG);
00066 #endif
00067 
00068     if (pid == 0)
00069         return TRUE;
00070 
00071     return FALSE;
00072 }
00073 
00074 char * get_local_addresses()
00075 {
00076     static char addresses[1024];
00077     char buff[1024];
00078     char gateway[16];
00079     char  * c;
00080     struct hostent * hn;
00081     int i;
00082         FILE * f;
00083         //system("getip.pl > myip");
00084         f = popen("netstat -nr", "r");
00085         if((int)f < 1)
00086                 goto IP_TEST_2;
00087         while( fgets(buff, sizeof(buff), f)  != NULL )
00088         {
00089                 c = strtok( buff, " " );
00090                 if( (strstr(c, "default") || strstr(c,"0.0.0.0") ) &&
00091                                 !strstr(c, "127.0.0" ) )
00092                         break;
00093         }
00094         c = strtok( NULL, " " );
00095         pclose(f);
00096 
00097         strncpy(gateway,c, 16);
00098 
00099         
00100         
00101         for(i = strlen(gateway); gateway[i] != '.'; i-- )
00102         {
00103             gateway[i] = 0;
00104         }
00105 
00106         gateway[i] = 0;
00107 
00108         for(i = strlen(gateway); gateway[i] != '.'; i-- )
00109         {
00110             gateway[i] = 0;
00111         }
00112 
00113         //g_snprintf(buff, 1024, "/sbin/ifconfig -a|grep inet|grep %s", gateway );
00114         f = popen("/sbin/ifconfig -a", "r");
00115         if((int)f < 1)
00116                 goto IP_TEST_2;
00117         
00118         while( fgets(buff, sizeof(buff), f) != NULL )
00119         {
00120                 if( strstr(buff, "inet") && strstr(buff,gateway) )
00121                         break;
00122         }
00123         pclose(f);
00124         
00125         c = strtok( buff, " " );
00126         c = strtok( NULL, " " );
00127 
00128         strncpy ( addresses, c, sizeof(addresses) );
00129         c = strtok(addresses, ":" );
00130         strncpy ( buff, c, sizeof(buff) );
00131         if((c=strtok(NULL, ":")))
00132         {
00133             strncpy( buff, c, sizeof(buff) );
00134         }
00135 
00136         
00137         strncpy(addresses, buff, sizeof(addresses));
00138 
00139         return addresses;
00140         
00141         
00142 IP_TEST_2:
00143 
00144         gethostname(buff,sizeof(buff));
00145         
00146         hn = gethostbyname(buff);
00147         if(hn)
00148                 strncpy(addresses, inet_ntoa( *((struct in_addr*)hn->h_addr)), sizeof(addresses) );
00149         else
00150                 addresses[0] = 0;
00151         return addresses;
00152 }
00153 
00154 
00155 /* a valid domain name is one that contains only alphanumeric, - and . 
00156  * if it has anything else, then it can't be a domain name
00157  */
00158 
00159 gint is_valid_domain( gchar * name )
00160 {
00161     int i;
00162     int dot_count = 0;
00163     if( name[0] == '-' || name[0] == '.' )
00164     {
00165         return FALSE;
00166     }
00167     for( i = 0; name[i] && name[i] != '/' && name[i] != ':'; i++ )
00168     {
00169         if( !isalnum(name[i]) && name[i] != '.' && name[i] != '-' )
00170         {
00171             return FALSE;
00172         }
00173         if( name[i] == '.' )
00174         {
00175             if( name[i-1] == '.' ||
00176                 name[i-1] == '-' ||
00177                 name[i+1] == '.' ||
00178                 name[i+1] == '-' )
00179             {
00180                 return FALSE;
00181             }
00182             dot_count++;
00183         }
00184 
00185     }
00186     if( name[i] == ':' )
00187     {
00188         for( i = i+1; name[i] && name[i] != '/'; i++ )
00189         {
00190             if(!isdigit(name[i]))
00191             {
00192                 return FALSE;
00193             }
00194         }
00195     }
00196     return dot_count > 0;
00197 }
00198 
00199 char * escape_string(char * input)
00200 {
00201     GString * temp_result = g_string_sized_new(2048);
00202     gchar * result;
00203     int ipos = 0;
00204     for(ipos=0;input[ipos];ipos++)
00205     {
00206         if(input[ipos] == '\n')
00207         {
00208             g_string_append(temp_result, "\\n");
00209         }
00210         else if(input[ipos] == '\r')
00211         {
00212             g_string_append(temp_result, "\\r");
00213         }
00214         else if(input[ipos] == '\\')
00215         {
00216             g_string_append(temp_result, "\\\\");
00217         }
00218         else if(input[ipos] == '"')
00219         {
00220             g_string_append(temp_result, "\\\"");
00221         }
00222         else
00223         {
00224             g_string_append_c(temp_result, input[ipos]);
00225         }
00226     }
00227 
00228     result = temp_result->str;
00229     g_string_free(temp_result, FALSE);
00230     return result;
00231 }
00232 char * unescape_string(char * input)
00233 {
00234     gchar * result = g_malloc0(strlen(input)+1);
00235     int ipos=0, opos=0; 
00236     while(input[ipos])
00237     {
00238         char c = input[ipos++];
00239         if(c == '\\')
00240         {
00241             c = input[ipos++];
00242             switch(c)
00243             {
00244                 case 'n':
00245                     result[opos++] = '\n';
00246                     break;
00247                 case 'r':   
00248                     result[opos++] = '\r';
00249                     break;
00250                 case '\\':  
00251                     result[opos++] = '\\';
00252                     break;
00253                 case '\"':  
00254                     result[opos++] = '\"';
00255                     break;
00256             }
00257         }
00258         else
00259         {
00260             result[opos++] = c;
00261         }
00262     }
00263     result[opos] = '\0';
00264 
00265     return result;
00266 
00267 }
00268 /* this function will be used to determine if a given token is a link */
00269 
00270 gint is_link( gchar * token )
00271 {
00272     int i;
00273     int len = strlen(token);
00274     
00275     if( token[0] == '<' )
00276     {
00277         return TOKEN_NORMAL;
00278     }
00279     if(!strncasecmp( token, "http://", 7 ) )
00280     {
00281         if(is_valid_domain(token+7))
00282         {
00283             return TOKEN_HTTP;
00284         }
00285         else
00286         {
00287             return TOKEN_NORMAL;
00288         }
00289     }
00290     if(!strncasecmp( token, "ftp://", 6))
00291     {
00292         return TOKEN_FTP;
00293     }
00294     if(!strncasecmp( token, "mailto:", 7))
00295     {
00296         return TOKEN_EMAIL;
00297     }
00298     if(!strncasecmp( token, "www.", 4) && is_valid_domain(token))
00299     {
00300         return TOKEN_HTTP;
00301     }
00302     if(!strncasecmp( token, "ftp.", 4) && is_valid_domain(token))
00303     {
00304         return TOKEN_FTP;
00305     }
00306     if(strstr(token, "://") && !ispunct(token[0]) && !ispunct(token[strlen(token)]) )
00307     {
00308         return TOKEN_CUSTOM;
00309     }
00310 
00311     for(i = 0; i < len; i++ )
00312     {
00313         if(token[i] == '@' )
00314         {
00315             if( !ispunct(token[0]) && !ispunct(token[len-1]) )
00316             {
00317                 if(is_valid_domain(token+i+1))
00318                 {
00319                         return TOKEN_EMAIL;
00320                 }
00321                 break;
00322             }
00323         }
00324     }
00325     
00326     for(i=len; i >= 0; i-- )
00327     {
00328         if( token[i] == '.' )
00329         {
00330             if(!strcasecmp(token+i, ".edu") && is_valid_domain(token))
00331             {
00332                 return TOKEN_HTTP;
00333             }
00334             if(!strcasecmp(token+i, ".com") && is_valid_domain(token))
00335             {
00336                 return TOKEN_HTTP;
00337             }
00338             if(!strcasecmp(token+i, ".net") && is_valid_domain(token))
00339             {
00340                 return TOKEN_HTTP;
00341             }
00342             if(!strcasecmp(token+i, ".org") && is_valid_domain(token))
00343             {
00344                 return TOKEN_HTTP;
00345             }
00346             if(!strcasecmp(token+i, ".gov") && is_valid_domain(token))
00347             {
00348                 return TOKEN_HTTP;
00349             }
00350             break;
00351         }
00352     }
00353     return TOKEN_NORMAL;
00354 }
00355 
00356 GString * get_next_token(char * input)
00357 {
00358     int i = 0;
00359     int len = strlen(input);
00360     GString * string = g_string_sized_new(20);
00361 
00362     if(!strncasecmp(input, "<A", 2))
00363     {
00364         g_string_assign(string, "<A");
00365         for( i = 2; i < len; i++ )
00366         {
00367             g_string_append_c(string, input[i]);
00368             if( input[i] != '<' )
00369             {
00370                 continue;
00371             }
00372             g_string_append_c(string, input[++i]);
00373             if( input[i] != '/' )
00374             {
00375                 continue;
00376             }
00377             g_string_append_c(string, input[++i]);
00378             if( tolower(input[i]) != 'a' )
00379             {
00380                 continue;
00381             }
00382             g_string_append_c(string, input[++i]);
00383             break;
00384         }
00385         return string;
00386     }
00387     if(input[0] == '<')
00388     {
00389         for(i=0; i < len; i++)
00390         {
00391             g_string_append_c(string, input[i]);
00392             if(input[i] == '>')
00393             {
00394                 break;
00395             }
00396         }
00397         return string;
00398     }
00399 
00400     if( ispunct(input[0]) )
00401     {
00402         for( i=0; i < len; i++ )
00403         {
00404             if( ispunct(input[i]) && input[i] != '<' )
00405             {
00406                 g_string_append_c(string, input[i]);
00407             }
00408             else
00409             {
00410                 break;
00411             }
00412         }
00413         return string;
00414     }
00415 
00416     /*
00417      * now that we have covered prior html
00418      * we can do an (almost) simple word tokenization
00419      */
00420 
00421     for( i = 0; i < len; i++ )
00422     {
00423         if(!isspace(input[i]) && input[i] != '<' )
00424         {
00425             if(!ispunct(input[i]) || input[i] == '/' )
00426             {
00427                 g_string_append_c(string, input[i]);
00428             }
00429             else
00430             {
00431                 int j;
00432 #if 0
00433                 if( (i < len - 1 && !isspace(input[i+1])) || i==0 )
00434                 {
00435                     g_string_append_c(string, input[i]);
00436                 }
00437                 else
00438                 {
00439                     return string;
00440                 }
00441 #endif
00442                 for(j = i+1; j < len; j++ )
00443                 {
00444                     if( isspace(input[j] ) )
00445                     {
00446                         return string;
00447                     }
00448                     if( isalpha( input[j] ) || isdigit(input[j] ) ) 
00449                     {
00450                         break;
00451                     }
00452                 }
00453                 if( j == len )
00454                 {
00455                     return string;
00456                 }
00457                 else
00458                 {
00459                     g_string_append_c(string, input[i]);
00460                 }
00461                             
00462                             
00463             }
00464         }
00465         else
00466         {
00467             return string;
00468         }
00469     }
00470     return string;
00471 }
00472             
00473 void linkify_token( GString * token )
00474 {
00475     GString * g;
00476     GString * g2;
00477     int type = is_link(token->str);
00478 
00479     if(type == TOKEN_NORMAL)
00480         return;
00481 
00482     g = g_string_sized_new(token->len);
00483     g2 = g_string_sized_new(token->len);
00484 
00485     g_string_assign(g, token->str);
00486     g_string_assign(g2, token->str);
00487     
00488 
00489         
00490     if(type == TOKEN_HTTP && strncasecmp(token->str, "http://", 7))
00491     {
00492         g_string_prepend(g2, "http://");
00493     }
00494     else if( type == TOKEN_FTP && strncasecmp(token->str, "ftp://", 6))
00495     {
00496         g_string_prepend(g2, "ftp://");
00497     }
00498     else if( type == TOKEN_EMAIL && strncasecmp(token->str, "mailto:", 7))
00499     {
00500         g_string_prepend(g2, "mailto:");
00501     }
00502 
00503     eb_debug(DBG_HTML, "TOKEN: %s\n", token->str);
00504     g_string_sprintf(token, "<A HREF=\"%s\">%s</A>", g2->str, g->str);
00505 
00506     g_string_free(g,TRUE);
00507     g_string_free(g2,TRUE);
00508 }
00509 
00510 gchar * linkify( gchar * input )
00511 {
00512     int i = 0;
00513     int len = strlen(input);
00514     gchar * result;
00515     GString * temp_result;
00516     GString * temp = NULL;
00517 
00518     temp_result = g_string_sized_new(2048);
00519 
00520     while( i < len )
00521     {
00522         if( isspace(input[i]) )
00523         {
00524             g_string_append_c(temp_result, input[i]);
00525             i++;
00526         }
00527         else
00528         {
00529             temp = get_next_token(input+i);
00530             eb_debug(DBG_HTML, "%s\t%s\t%d\t%d\n", input, input+i, i, temp->len);
00531             i += temp->len;
00532             linkify_token(temp);
00533             g_string_append(temp_result, temp->str);
00534             g_string_free(temp, TRUE);
00535         }
00536     }
00537 
00538     result = temp_result->str;
00539     g_string_free(temp_result, FALSE);
00540     return result;
00541 }
00542 
00543 gchar * convert_eol (gchar * text) 
00544 {
00545     gchar * temp;
00546     gchar **data=NULL;
00547     int i;
00548     
00549     if (strstr (text, "\r\n") != NULL)
00550         return text;
00551     
00552     data = g_strsplit(text,"\n",64);
00553     temp = g_strdup(data[0]);
00554     for(i=1; data[i] != NULL; i++) {
00555         temp = g_strdup_printf("%s\r\n%s",temp,data[i]);
00556     }
00557     g_strfreev(data);
00558     return temp;
00559 }
00560 
00561 /* Parameters:
00562     remote - the account to find a local account for
00563     online - whether the local account needs to be online
00564 */
00565 eb_local_account * find_local_account_for_remote( eb_account *remote, gboolean online )
00566 {
00567     static GList * node = NULL;
00568     static eb_account *last_remote=NULL;
00569 
00570     /* If this is a normal call, start at the top and give the first, otherwise continue where we left off */
00571     if(remote) {
00572         node = accounts;
00573         last_remote=remote;
00574     }
00575     else {
00576         remote = last_remote;
00577         if(node)
00578             node=node->next;
00579     }
00580     for( ; node; node = node->next )
00581     {
00582         eb_local_account * ela = (eb_local_account *)(node->data);
00583         
00584         if (remote->service_id == ela->service_id)
00585         {
00586             if (eb_services[ela->service_id].sc->is_suitable != NULL)
00587             {
00588                 if (eb_services[ela->service_id].sc->is_suitable(ela, remote) == TRUE)
00589                 {
00590                     if (online && (! ela->connected)) {}
00591                     else
00592                     {
00593                         return (ela);
00594                     }
00595                 }
00596             }
00597             else
00598             {
00599                 if (online && (! ela->connected)) {}
00600                 else
00601                 {
00602                     return (ela);
00603                 }
00604             }
00605         }
00606     }
00607     
00608     /*We can't find anything, let's bail*/
00609     return NULL;
00610 }
00611 
00612 eb_local_account * find_suitable_local_account( eb_local_account * first,
00613                                                 gint second )
00614 {
00615     GList * node;
00616     GList * states;
00617     
00618     /*The last state in the list of states will be the OFFLINE state*
00619      *The first state in the list will be the ONLINE states         *
00620      *The rest of the states are the various AWAY states            */
00621     
00622     states = eb_services[second].sc->get_states();
00623     
00624     g_list_free(states);
00625     
00626     if( first && first->connected )
00627     {
00628         /* hurrah, we got our first choice */
00629         return first;
00630     }
00631             
00632     /*dang, we are out of luck with our first choice, do we have something
00633       else that uses the same service? */
00634 
00635     for( node = accounts; node; node = node->next )
00636     {
00637         eb_local_account * ela = (eb_local_account *)(node->data);
00638             eb_debug(DBG_CORE, "%s %s\n", eb_services[ela->service_id].name, ela->handle);
00639         
00640         if( ela->service_id == second && ela->connected )
00641         {
00642             return ela;
00643         }
00644         else if( !ela->connected )
00645         {
00646             eb_debug(DBG_CORE, "%s is offline!\n", ela->handle );
00647         }
00648             
00649     }
00650     
00651     /*We can't find anything, let's bail*/
00652     return NULL;
00653 }
00654 
00655 /* if contact can offline message, return the account,
00656    otherwise, return null 
00657 */
00658 
00659 eb_account * can_offline_message( struct contact * con )
00660 {
00661     GList * node;
00662     for(node = con->accounts; node; node=node->next)
00663     {
00664         eb_account * ea = (eb_account*)node->data;
00665         
00666         if( eb_services[ea->service_id].offline_messaging )
00667             return ea;
00668     }
00669     return 0;
00670 }   
00671     
00672 eb_account * find_suitable_remote_account( eb_account * first, 
00673                                            struct contact * rest )
00674 {
00675     GList * node;
00676     eb_account * possibility = NULL;
00677 
00678     if( first && eb_services[first->service_id].sc->query_connected(first) )
00679     {
00680         return first;
00681     }
00682     
00683     for(node = rest->accounts; node; node=node->next)
00684     {
00685         eb_account * ea = (eb_account*)node->data;
00686         
00687         if( eb_services[ea->service_id].sc->query_connected(ea) )
00688         {
00689             if(ea->service_id == rest->default_chatb )
00690             {
00691                 return ea;
00692             }
00693             else
00694             {
00695                 possibility = ea;
00696             }
00697         }
00698     }
00699     return possibility;
00700 }
00701     
00702 eb_account * find_suitable_file_transfer_account( eb_account * first, 
00703                            struct contact * rest )
00704 {
00705     GList * node;
00706     eb_account * possibility = NULL;
00707 
00708     if ( first == NULL )
00709         return NULL;
00710 
00711     if( first && eb_services[first->service_id].sc->query_connected(first)
00712             && eb_services[first->service_id].file_transfer )
00713     {
00714         return first;
00715     }
00716     
00717     for(node = rest->accounts; node; node=node->next)
00718     {
00719         eb_account * ea = (eb_account*)node->data;
00720         
00721         if( eb_services[ea->service_id].sc->query_connected(ea)
00722                 && eb_services[first->service_id].file_transfer )
00723         {
00724             if(ea->service_id == rest->default_chatb )
00725             {
00726                 return ea;
00727             }
00728             else
00729             {
00730                 possibility = ea;
00731             }
00732         }
00733     }
00734     return possibility;
00735 }
00736     
00737 eb_chat_room * find_chat_room_by_id( gchar * id )
00738 {
00739     GList * node = chat_rooms;
00740     for( node= chat_rooms; node; node=node->next)
00741     {
00742         eb_chat_room * ecr = node->data;
00743         eb_debug(DBG_CORE, "Comparing %s to %s\n", id, ecr->id );
00744         if(!strcmp(id, ecr->id))
00745             return ecr;
00746     }
00747     return NULL;
00748 
00749 }
00750 
00751 eb_chat_room * find_chat_room_by_name( gchar * name, gint service_id )
00752 {
00753     GList * node = chat_rooms;
00754     for( node= chat_rooms; node; node=node->next)
00755     {
00756         eb_chat_room * ecr = node->data;
00757         if(!strcmp(name, ecr->room_name)  && (ecr->chat_room_account->service_id == service_id) )
00758             return ecr;
00759     }
00760     return NULL;
00761 
00762 }
00763 
00764 grouplist * find_grouplist_by_name(gchar * name)
00765 {
00766     GList * l1;
00767 
00768     if (name == NULL) {
00769     return NULL;
00770     }
00771     for(l1 = groups; l1; l1=l1->next )
00772     {
00773         if(!g_strncasecmp(((grouplist *)l1->data)->name, name, strlen(name)+1))
00774         {
00775              return (grouplist*)l1->data;
00776         }
00777     }
00778     return NULL;
00779 }
00780 
00781 grouplist * find_grouplist_by_nick(gchar * nick)
00782 {
00783     GList * l1;
00784     GList * l2;
00785 
00786     if (nick == NULL) {
00787     return NULL;
00788     }
00789     for(l1 = groups; l1; l1=l1->next )
00790     {
00791         for(l2 = ((grouplist*)l1->data)->members; l2; l2=l2->next )
00792         {
00793             if(!strcmp(((struct contact*)l2->data)->nick, nick))
00794             {
00795                     return (grouplist*)l1->data;
00796             }
00797         }
00798     }
00799     return NULL;
00800 }
00801 
00802 struct contact * find_contact_by_handle( gchar * handle )
00803 {
00804     GList * l1;
00805     GList * l2;
00806     GList * l3;
00807 
00808     if (handle == NULL) {
00809     return NULL;
00810     }
00811     for(l1 = groups; l1; l1=l1->next )
00812     {
00813         for(l2 = ((grouplist*)l1->data)->members; l2; l2=l2->next )
00814         {
00815             for(l3 = ((struct contact*)l2->data)->accounts; l3; l3=l3->next)
00816             {
00817                 eb_account * account = (eb_account*)l3->data;
00818                 if(!strcmp(account->handle, handle))
00819                     return (struct contact*)l2->data;
00820             }
00821         }
00822     }
00823     return NULL;
00824 }
00825 
00826 struct contact * find_contact_by_nick( gchar * nick )
00827 {
00828     GList * l1;
00829     GList * l2;
00830 
00831     if (nick == NULL){
00832     return NULL;
00833     }
00834     for(l1 = groups; l1; l1=l1->next )
00835     {
00836         for(l2 = ((grouplist*)l1->data)->members; l2; l2=l2->next )
00837         {
00838             if(!g_strncasecmp(((struct contact*)l2->data)->nick, nick, strlen(nick)+1))
00839             {
00840                 return (struct contact*)l2->data;
00841             }
00842         }
00843     }
00844     return NULL;
00845 }
00846 
00847 struct contact * find_contact_in_group_by_nick( gchar * nick , grouplist *gl )
00848 {
00849     GList * l;
00850 
00851     if (nick == NULL || gl == NULL){
00852     return NULL;
00853     }
00854 
00855     for(l = gl->members; l; l=l->next )
00856     {
00857         if(!g_strncasecmp(((struct contact*)l->data)->nick, nick, strlen(nick)+1))
00858         {
00859             return (struct contact*)l->data;
00860         }
00861     }
00862 
00863     return NULL;
00864 }
00865 
00866 // FIXME: Do we really need to use aim_normalize?  I copied it from the libtoc/libtoc.c to facilitate making modules
00867 char *aim_normalize(char *s)
00868 {
00869     static char buf[255];
00870         char *t, *u;
00871         int x=0;
00872 
00873         u = t = g_malloc(strlen(s) + 1);
00874 
00875         strncpy(t, s, strlen(s)+1);
00876         g_strdown(t);
00877 
00878     while(*t) {
00879         if (*t != ' ') {
00880             buf[x] = *t;
00881             x++;
00882         }
00883         t++;
00884     }
00885         buf[x]='\0';
00886         g_free(u);
00887     return buf;
00888 }
00889 
00890 void refresh_service_contacts(gint type)
00891 {
00892     GList * l1;
00893     GList * l2;
00894     GList * l3;
00895     GList * config=NULL;
00896     struct contact *con=NULL;
00897 
00898     eb_debug(DBG_CORE, ">Refreshing contacts for %i\n", type);
00899     for(l1 = groups; l1; l1=l1->next )
00900     {
00901         for(l2 = ((grouplist*)l1->data)->members; l2; l2=l2->next )
00902         {
00903         con=(struct contact *)l2->data;
00904         if(con->chatwindow && con->chatwindow->perfered && (con->chatwindow->perfered->service_id==type))
00905         {
00906         eb_debug(DBG_MOD, "Setting the perfered service to NULL for %s\n", con->nick);
00907         con->chatwindow->perfered=NULL;
00908         }
00909             for(l3 = con->accounts; l3; l3=l3->next)
00910             {
00911                 eb_account * account = (eb_account*)l3->data;
00912                 if(account->service_id == type) {
00913                eb_debug(DBG_CORE, "Refreshing %s - %i\n", account->handle, type);
00914                config = value_pair_add(NULL, "NAME", account->handle);
00915                g_free(account->protocol_account_data);
00916                g_free(account);
00917                account = eb_services[type].sc->read_account_config(config, (struct contact*)l2->data);
00918                /* Is this a nomodule account?  Make it the right service number */
00919                if(account->service_id==-1)
00920                    account->service_id=type;
00921                value_pair_free(config);
00922                config=NULL;
00923                l3->data=account;
00924         }
00925             }
00926         }
00927     }
00928     eb_debug(DBG_CORE, "<Leaving\n");
00929     return;
00930 }
00931 
00932 eb_account * find_account_by_handle( gchar * handle, gint type )
00933 {
00934     GList * l1;
00935     GList * l2;
00936     GList * l3;
00937 
00938     if (handle == NULL) {
00939     return NULL;
00940     }
00941     for(l1 = groups; l1; l1=l1->next )
00942     {
00943         for(l2 = ((grouplist*)l1->data)->members; l2; l2=l2->next )
00944         {
00945             for(l3 = ((struct contact*)l2->data)->accounts; l3; l3=l3->next)
00946             {
00947                 eb_account * account = (eb_account*)l3->data;
00948         char string1[255];
00949         char string2[255];
00950         strcpy(string1, aim_normalize(account->handle));
00951         strcpy(string2, aim_normalize(handle));
00952                 if(!g_strncasecmp(string1, string2,strlen(string1)+1)
00953                         && account->service_id == type )
00954                     return account;
00955             }
00956         }
00957     }
00958     return NULL;
00959 }
00960 
00961 eb_account * find_account_by_handle_normalized( gchar * handle, gint type )
00962 {
00963     GList * l1;
00964     GList * l2;
00965     GList * l3;
00966  
00967     if (handle == NULL) {
00968         return NULL;
00969     }
00970     for(l1 = groups; l1; l1=l1->next )
00971     {
00972         for(l2 = ((grouplist*)l1->data)->members; l2; l2=l2->next )
00973         {
00974             for(l3 = ((struct contact*)l2->data)->accounts; l3; l3=l3->next)
00975             {
00976                 eb_account * account = (eb_account*)l3->data;
00977                 if(!g_strncasecmp(aim_normalize(account->handle), handle,strlen(handle)+1)
00978                                                 && account->service_id == type )
00979                     return account;
00980             }
00981         }
00982     }
00983     return NULL;
00984 }
00985 
00986 eb_local_account * find_local_account_by_handle( gchar * handle, gint type)
00987 {
00988     GList * l1;
00989 
00990     for(l1 = accounts; l1; l1=l1->next )
00991     {
00992          eb_local_account * account = (eb_local_account*)l1->data;
00993          if(account->service_id == type && !g_strncasecmp(account->handle, handle, strlen(handle)+1))
00994               return account;
00995     }
00996     return NULL;
00997 }
00998 
00999 void strip_html(gchar * text)
01000 {
01001     int i, j;
01002     int visible = 1;
01003     
01004     for( i=0, j=0; text[i]; i++ )
01005     {
01006         if(text[i]=='<')
01007         {
01008             switch(text[i+1])
01009             {
01010                 case 'a':
01011                 case 'A':
01012                     if(isspace(text[i+2]) || text[i+2] == '>')
01013                     {
01014                         visible = 0;
01015                     }
01016                     break;
01017 
01018                 case 'i':
01019                 case 'I':
01020                 case 'u':
01021                 case 'U':
01022                 case 'p':
01023                 case 'P':
01024                     if(text[i+2] == '>')
01025                     {
01026                         visible = 0;
01027                     }
01028                     break;
01029                 case 'b':
01030                 case 'B':
01031                     if(text[i+2] == '>')
01032                     {
01033                         visible = 0;
01034                     }
01035                     else if(text[i+2] == 'O' || text[i+2] == 'o')
01036                     {
01037                         if(text[i+3] == 'D' || text[i+3] == 'd' )
01038                         {
01039                             if(text[i+4] == 'Y' || text[i+4] == 'y' )
01040                             {
01041                                 if(isspace(text[i+5]) || text[i+5] == '>')
01042                                 {
01043                                     visible = 0;
01044                                 }
01045                             }
01046                         }
01047                     }
01048                     break;
01049                 case 'h':
01050                 case 'H':
01051                     if(text[i+2] == 'T' || text[i+2] == 't')
01052                     {
01053                         if(text[i+3] == 'M' || text[i+3] == 'm')
01054                         {
01055                             if(text[i+4] == 'L' || text[i+4] == 'l')
01056                             {
01057                                 if(isspace(text[i+5]) || text[i+5] == '>')
01058                                 {
01059                                     visible = 0;
01060                                 }
01061                             }
01062                         }
01063                     }
01064                     break;
01065                                 
01066                 case 'F':
01067                 case 'f':
01068                     if(text[i+2] == 'o' || text[i+2] == 'O')
01069                     {
01070                         if(text[i+3] == 'n' || text[i+3] == 'N')
01071                         {
01072                             if(text[i+4] == 't' || text[i+4] == 'T')
01073                             {
01074                                 if(isspace(text[i+5]) || text[i+5] == '>')
01075                                 {
01076                                     visible = 0;
01077                                 }
01078                             }
01079                         }
01080                     }
01081                     break;
01082                 case 's':
01083                     if (!strncmp(text+i+2,"miley", 5)) {
01084                         visible = 0;
01085                         text[j++]=' '; /*hack*/
01086                     }
01087                 case '/':
01088                     visible = 0;
01089                     break;
01090             }
01091         }
01092         else if(text[i] == '>')
01093         {
01094             if(!visible)
01095             {
01096                 visible = 1;
01097                 continue;
01098             }
01099         }
01100         if(visible)
01101         {
01102             text[j++] = text[i];
01103         }
01104     }
01105     text[j] = '\0';
01106 }
01107 
01108 
01109 void remove_account( eb_account * a )
01110 {
01111     struct contact * c = a->account_contact;
01112     buddy_logoff(a);
01113     remove_account_line(a);
01114     c->accounts = g_list_remove(c->accounts, a);
01115     RUN_SERVICE(a)->del_user(a);
01116     g_free(a);
01117 }
01118 void remove_contact( struct contact * c )
01119 {
01120     grouplist * g = c->group;
01121     if(c->chatwindow)
01122         gtk_widget_destroy(c->chatwindow->window);
01123     while(c->accounts)
01124     {
01125         remove_account(c->accounts->data);
01126     }
01127     remove_contact_line(c);
01128     g->members = g_list_remove(g->members, c);
01129     g_free(c);
01130 
01131 }
01132 void remove_group( grouplist * g )
01133 {
01134     while(g->members)
01135     {
01136         remove_contact(g->members->data);
01137     }
01138     remove_group_line(g);
01139     groups = g_list_remove(groups,g);
01140     g_free(g);
01141 }
01142 
01143 void add_group( gchar * name )
01144 {
01145     grouplist g, *eg;
01146     strncpy(g.name, name,255);
01147     g.members = NULL;
01148     g.list_item = NULL;
01149    
01150     groups = g_list_append( groups, eg = g_memdup(&g, sizeof(grouplist)));
01151     add_group_line(eg);
01152 }
01153 
01154 
01155 static gint contact_cmp(gconstpointer a, gconstpointer b)
01156 {
01157     const struct contact *ca=a, *cb=b;
01158 
01159     return strcasecmp(ca->nick, cb->nick);
01160 }
01161 
01162 struct contact * add_new_contact( gchar * group, gchar * con, gint type )
01163 {
01164     grouplist * g = find_grouplist_by_name( group);
01165     struct contact * c = g_new0( struct contact, 1);
01166     c->online = 0;
01167     if (con != NULL) {      // don't copy from null pointers !!
01168         strncpy(c->nick, con, 255);
01169     }
01170     c->default_chatb = c->default_filetransb = type;
01171    
01172     if(g)
01173     {
01174         g->members = g_list_insert_sorted(g->members, c, contact_cmp);
01175         c->group = g;
01176     }
01177     return c;
01178 }
01179 
01180 void add_account_verbose( gchar * contact, eb_account * account, gboolean verbosity )
01181 {
01182     struct contact * c = find_contact_by_nick( contact );
01183     eb_account * ea = find_account_by_handle(account->handle, account->service_id);
01184     if(ea)
01185     {
01186         if(!strcasecmp(ea->account_contact->nick, _("Unknown")))
01187         {
01188             struct contact * c2 = ea->account_contact;
01189             remove_account(ea);
01190             if(g_list_length(c2->accounts) == 0)
01191             {
01192                 remove_contact(c2);
01193             }
01194         }
01195         else
01196         {
01197             char buff[2048];
01198             g_snprintf(buff, 2048, _("The account already exists on your\ncontact list at the following location\nGroup: %s\nContact: %s\nPlease delete this account before\nadding it elsewhere."), ea->account_contact->group->name, ea->account_contact->nick );
01199 
01200             if( c && g_list_length(c->accounts) == 0)
01201             {
01202                 remove_contact(c);
01203             }
01204             if(verbosity)
01205                 do_error_dialog(buff, _("Error: account exists"));
01206             return;
01207         }
01208     }
01209     if( c )
01210     {
01211         c->accounts = g_list_append( c->accounts, account );
01212         account->account_contact = c;
01213         RUN_SERVICE(account)->add_user(account);
01214     
01215     if(!strcmp(c->group->name, _("Ignore")) && 
01216             RUN_SERVICE(account)->ignore_user)
01217         RUN_SERVICE(account)->ignore_user(account);
01218     }
01219     else add_unknown(account);
01220 }
01221 
01222 void add_account_silent ( gchar * contact, eb_account * account )
01223 {
01224     add_account_verbose(contact, account, FALSE);
01225 }
01226 void add_account( gchar * contact, eb_account * account )
01227 {
01228     add_account_verbose(contact, account, TRUE);
01229 }
01230 
01231 void add_contact( gchar * group, struct contact * user )
01232 {
01233     grouplist * grp = find_grouplist_by_name(group);
01234 
01235     if(!grp)
01236     {
01237         add_group(group);
01238     grp = find_grouplist_by_name(group);
01239     }
01240     if(!grp) {
01241         printf("Error adding group :(\n");
01242             return;
01243     }    
01244     grp->members = g_list_insert_sorted(grp->members, user, contact_cmp);
01245     user->group = grp;
01246 }
01247 
01248 void add_unknown( eb_account * ea )
01249 {
01250     struct contact * con = g_new0(struct contact, 1);
01251     strncpy(con->nick, ea->handle, 255);
01252     con->accounts = g_list_append( con->accounts, ea );
01253     con->default_chatb = ea->service_id;
01254     con->default_filetransb = ea->service_id;
01255     ea->account_contact = con;
01256     add_contact(_("Unknown"), con);
01257     ea->icon_handler = -1;
01258     ea->status_handler = -1;
01259     RUN_SERVICE(ea)->add_user(ea);
01260     write_contact_list();
01261 }
01262 
01263 void add_unknown_with_name( eb_account * ea, gchar * name )
01264 {
01265     struct contact * con = g_new0(struct contact, 1);
01266 
01267     /* Check that name is defined */
01268     if (name && strlen(name))
01269         strncpy(con->nick, name, 255);
01270     else
01271         strncpy(con->nick, ea->handle, 255);
01272 
01273     con->accounts = g_list_append( con->accounts, ea );
01274     con->default_chatb = ea->service_id;
01275     con->default_filetransb = ea->service_id;
01276     ea->account_contact = con;
01277     add_contact(_("Unknown"), con);
01278     ea->icon_handler = -1;
01279     ea->status_handler = -1;
01280     RUN_SERVICE(ea)->add_user(ea);
01281     write_contact_list();
01282 }
01283 
01284 static void handle_group_change(eb_account *ea, gchar *og, gchar *ng)
01285 {
01286     /* if the groups are same, do nothing */
01287     if(!strcasecmp(ng, og))
01288         return;
01289 
01290     /* adding to ignore */
01291     if(!strcmp(ng, _("Ignore")) && RUN_SERVICE(ea)->ignore_user)
01292         RUN_SERVICE(ea)->ignore_user(ea);
01293 
01294     /* remove from ignore */
01295     else if(!strcmp(og, _("Ignore")) && RUN_SERVICE(ea)->unignore_user)
01296         RUN_SERVICE(ea)->unignore_user(ea, ng);
01297         
01298     /* just your regular group change */
01299     else if(RUN_SERVICE(ea)->change_group)
01300         RUN_SERVICE(ea)->change_group(ea, ng);
01301 
01302 }
01303 
01304 void move_account (struct contact * con, eb_account *ea)
01305 {
01306     struct contact *c = ea->account_contact;
01307     gchar * new_group = con->group->name;
01308     gchar *old_group = c->group->name;
01309     
01310     handle_group_change(ea, old_group, new_group);
01311 
01312     c->accounts = g_list_remove(c->accounts, ea);
01313 
01314     remove_account_line(ea);
01315     if(g_list_length(c->accounts) == 0)
01316         remove_contact(c);
01317     else {
01318         GList *l;
01319         c->online = 0;
01320         for(l=c->accounts; l; l=l->next)
01321             if(((eb_account *)l->data)->online)
01322                 c->online++;
01323         if(!c->online)
01324             remove_contact_line(c);
01325         else
01326             add_contact_and_accounts(c);
01327     }
01328 
01329     con->accounts = g_list_append(con->accounts, ea);
01330 
01331     ea->account_contact = con;
01332     if(ea->online)
01333         con->online++;
01334 
01335     add_contact_and_accounts(con);
01336 }
01337 
01338 void move_contact (gchar * group, struct contact * c)
01339 {
01340     grouplist * g = c->group;
01341     struct contact *con;
01342     GList *l = c->accounts;
01343     
01344     g->members = g_list_remove(g->members, c);
01345     remove_contact_line(c);
01346     g = find_grouplist_by_name(group);
01347     
01348     if(!g)
01349     {
01350         add_group(group);
01351         g = find_grouplist_by_name(group);
01352     }
01353     add_group_line(g);
01354 
01355     for(; l; l=l->next)
01356     {
01357         eb_account *ea = l->data;
01358         handle_group_change(ea, c->group->name, group);
01359     }
01360 
01361     con = find_contact_by_nick(c->nick);
01362     if(con) 
01363     {
01364         l = c->accounts;
01365         while(l)
01366         {
01367             eb_account *ea = l->data;
01368 
01369                 ea->account_contact = con;
01370             con->accounts = g_list_append(con->accounts, ea);
01371             l = l->next;
01372         }
01373         g_list_free(c->accounts);
01374         add_contact_and_accounts(con);
01375     } else {
01376         g->members = g_list_insert_sorted(g->members, c, contact_cmp);
01377         c->group = g;
01378         add_contact_and_accounts(c);
01379     }
01380 }
01381 
01382 typedef struct _invite_request
01383 {
01384     eb_local_account * ela;
01385     void * id;
01386 } invite_request;
01387 
01388 static void process_invite( GtkWidget * widget, gpointer data )
01389 {
01390     invite_request * invite = data;
01391     int result = (int)gtk_object_get_user_data( GTK_OBJECT(widget));
01392 
01393     if( result )
01394     {
01395         RUN_SERVICE(invite->ela)->accept_invite( invite->ela, invite->id );
01396     }
01397     else
01398     {
01399         RUN_SERVICE(invite->ela)->decline_invite( invite->ela, invite->id);
01400     }
01401 
01402     g_free(invite);
01403 }
01404 
01405 
01406 void invite_dialog( eb_local_account * ela, char * user, char * chat_room,
01407                     void * id )
01408 {
01409     char * message = g_strdup_printf(
01410             _("User %s wants to invite you to\n%s\nWould you like to accept?"),
01411             user, chat_room);
01412     invite_request * invite = g_new0( invite_request, 1 );
01413 
01414     invite->ela = ela;
01415     invite->id = id;
01416     do_dialog( message, _("Chat Invite"), process_invite, invite );
01417     g_free(message);
01418 }
01419     
01420         
01421 
01422 
01423 void make_safe_filename(gchar *buff, gchar *name)  {
01424     
01425     /* i'm pretty sure the only illegal character is '/', but maybe 
01426      * there are others i'm forgetting */
01427     char *bad_chars="/";
01428     char *p;
01429     char holder[NAME_MAX];
01430 
01431     strncpy(holder, name, NAME_MAX);
01432 
01433     for (p=holder; *p; p++) {
01434         if ( strchr(bad_chars, *p) )
01435             *p='_';
01436     }
01437     g_snprintf(buff, NAME_MAX, "%slogs/%s", 
01438                 config_dir, holder);
01439 }
01440                     
01441 
01442 gint gtk_notebook_get_number_pages(GtkNotebook *notebook)
01443 {
01444   gint i = 0;  
01445 
01446   for (i = 0; gtk_notebook_get_nth_page(notebook, i) != NULL; i++) {
01447   }
01448 
01449   return i;
01450 }
01451 
01452 /* looks for lockfile, if found, returns the pid in the file */
01453 /* If not, creates the file, writes our pid, and returns -1 */
01454 pid_t create_lock_file(gchar* fname)
01455 {
01456   pid_t ourpid = -1;
01457   struct stat sbuff;
01458   FILE* f;
01459 
01460 #ifndef __MINGW32__
01461   if (stat(fname, &sbuff) != 0) { 
01462     /* file doesn't exist, so we're gonna open it to write out pid to it */
01463     ourpid = getpid();
01464     if ((f = fopen(fname, "a")) != NULL) {
01465       fprintf(f, "%d\n", ourpid);
01466       fclose(f);
01467       ourpid = -1;
01468     } else {
01469       ourpid = 0;       /* I guess could be considered an error condition */
01470                 /* in that we couldn't create the lock file */
01471     }           
01472   } else {
01473     /* this means that the file exists */
01474     if ((f = fopen(fname, "r")) != NULL) {
01475       char data[20];
01476       fscanf(f, "%d", &ourpid);
01477       fclose(f);
01478       sprintf(data, "/proc/%d", ourpid);
01479       if(stat(data, &sbuff) != 0) // we got a lock file but the process is gone
01480       {
01481           fprintf(stderr, _("deleting stale lock file\n"));
01482           unlink(fname); /*delete lock file and try again :) */
01483           return create_lock_file(fname);
01484       } else {
01485            FILE * fd = NULL;
01486            sprintf(data, "%s/cmdline", data);
01487        fd = fopen(data, "r");
01488        if(fd==NULL)
01489         perror("fopen");
01490        else {
01491             char cmd[1024];
01492         fgets(cmd, sizeof(cmd), fd);
01493         printf("registered PID is from %s\n",cmd);
01494         fclose(fd);
01495         if(cmd == NULL || strstr(cmd, "yattm") == NULL) {
01496           fprintf(stderr, _("deleting stale lock file\n"));
01497           unlink(fname); /*delete lock file and try again :) */
01498           return create_lock_file(fname);
01499         }
01500        }
01501       }
01502           
01503     } else {
01504       /* couldn't open it... bizarre... allow the program to run anyway... heh */
01505       ourpid = -1;
01506     }
01507   }
01508 #endif
01509 
01510   return ourpid;
01511 }
01512 
01513 void delete_lock_file(gchar* fname) 
01514 {
01515 #ifndef __MINGW32__
01516   gchar cmd[1024];
01517   /* non-portable?  Yeah... I'll fix it at a later date... */
01518   g_snprintf(cmd, sizeof(cmd), "rm %s", fname);
01519   system(cmd);
01520 #endif
01521 }
01522 
01523 void eb_generic_menu_function(GtkWidget *add_button, gpointer userdata)
01524 {
01525     menu_item_data *mid=(menu_item_data *)userdata;
01526     ebmCallbackData *ecd=NULL;
01527 
01528     assert(userdata);
01529     ecd=mid->data;
01530     /* Check for valid data type */
01531     if(!ecd || !IS_ebmCallbackData(ecd)) {
01532         g_warning(_("Unexpected datatype passed to eb_generic_menu_function, ignoring call!"));
01533         return;
01534     }
01535     if(!mid->callback) {
01536         g_warning(_("No callback defined in call to eb_generic_menu_function, ignoring call!"));
01537         return;
01538     }
01539     eb_debug(DBG_CORE, "Calling callback\n");
01540     mid->callback(ecd);
01541 }

Contact: Andy Maloney     [Documentation generated by doxygen]