00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
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
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
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
00156
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
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
00418
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
00562
00563
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
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
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
00619
00620
00621
00622 states = eb_services[second].sc->get_states();
00623
00624 g_list_free(states);
00625
00626 if( first && first->connected )
00627 {
00628
00629 return first;
00630 }
00631
00632
00633
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
00652 return NULL;
00653 }
00654
00655
00656
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
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
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++]=' ';
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) {
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
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
01287 if(!strcasecmp(ng, og))
01288 return;
01289
01290
01291 if(!strcmp(ng, _("Ignore")) && RUN_SERVICE(ea)->ignore_user)
01292 RUN_SERVICE(ea)->ignore_user(ea);
01293
01294
01295 else if(!strcmp(og, _("Ignore")) && RUN_SERVICE(ea)->unignore_user)
01296 RUN_SERVICE(ea)->unignore_user(ea, ng);
01297
01298
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
01426
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
01453
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
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;
01470
01471 }
01472 } else {
01473
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)
01480 {
01481 fprintf(stderr, _("deleting stale lock file\n"));
01482 unlink(fname);
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);
01498 return create_lock_file(fname);
01499 }
01500 }
01501 }
01502
01503 } else {
01504
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
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
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 }