/***************************************************************************** * util.c * * 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. * * Copyright (C) 2000-2002 Chris Pinkham * Released under the terms of the GPL. * *NO WARRANTY* * * cpinkham@corp.infi.net, cpinkham@bc2va.org * http://www4.infi.net/~cpinkham/gyach/ *****************************************************************************/ #include "config.h" #include #include #include #include #include #include #include #include #include #ifdef USE_PTHREAD_CREATE #include #endif #ifdef USE_GDK_PIXBUF #include #endif #include "gyach.h" #include "commands.h" #include "gyach_int.h" #include "interface.h" #include "main.h" #include "support.h" #include "users.h" #include "util.h" SMILEY *smileys; char mail_user[65] = ""; char *recv_sound = NULL; char *send_sound = NULL; int profile_viewer = 0; void strip_html_tags( char *str ) { char *to, *from; DBG( 21, "strip_html_tags()\n" ); to = str; from = str; while( *from ) { if ( *from == '<' ) { from++; while(( *from ) && ( *from != '>' ) && ( *from != '<' )) { from++; } if ( *from ) from++; } else { *to = *from; to++; from++; } } *to = *from; to = str; from = str; while( *from ) { if ( *from == '\r' ) { from++; } else if ( *from == '&' ) { if ( *(from+1) == '#' ) { while( *from != ';' ) { from++; } } else if (( *(from+1) == 'n' ) && ( *(from+2) == 'b' ) && ( *(from+3) == 's' ) && ( *(from+4) == 'p' ) && ( *(from+5) == ';' )) { from += 5; *to = ' '; to++; } from++; } else { *to = *from; to++; from++; } } *to = *from; to = str; from = str; while( *from ) { if (( *from == '\n' ) && ( *(from+1) == '\n' )) { } else { *to = *from; to++; } from++; } *to = *from; /* now strip "\033[30m" style entries */ to = str; from = str; while( *from ) { if ( *from == '\033' ) { while(( *from ) && ( *from != 'm' )) { from++; } } else { *to = *from; to++; } if ( *from ) from++; } *to = *from; } int my_system( char *command ) { int pid; int status; if ( ! command ) { return( 1 ); } pid = fork(); if ( pid == -1 ) { return( -1 ); } else if ( pid == 0 ) { char *argv[4]; argv[0] = "sh"; argv[1] = "-c"; argv[2] = command; argv[3] = 0; execv( "/bin/sh", argv ); exit( 127 ); } else { while( 1 ) { if ( waitpid( pid, &status, 0 ) == -1 ) { return( -1 ); } else { return( status ); } } } } /* NOTE: this function frees *arg when done, so use strdup() before calling */ void *display_url( void *arg ) { char *url = (char *)arg; char cmd[1025]; char new_url[1025]; DBG( 11, "display_url( '%s' )\n", (char *)arg ); if ( ! url ) return( NULL ); if ( strlen( url ) == 0 ) { free( url ); return( NULL ); } /* quick sanity check */ if (( strchr( url, ';' )) || ( strchr( url, '`' ))) { free( url ); return( NULL ); } if ((( ! strcmp( url, "http://mail.yahoo.com" )) || ( ! strcmp( url, "mail.yahoo.com" )) || ( ! strcmp( url, "https://mail.yahoo.com" ))) && ( strcmp( mail_user, ymsg_sess->user ))) { my_strncpy( mail_user, ymsg_sess->user, 64 ); snprintf( new_url, 1024, "https://login.yahoo.com/config/login?.src=ym&.v=0" "&.u=30d2s70uso5fa&.last=&promo=&.intl=us&.bypass=&.partner=" "&.done=&login=%s&passwd=%s", ymsg_sess->user, ymsg_sess->password ); snprintf( cmd, 1024, browser_command, new_url ); } else { snprintf( cmd, 1024, browser_command, url ); } my_system( cmd ); free( url ); return( NULL ); } void lower_str( char *str ) { char tmp[2048]; char *dst = str; char *src = tmp; DBG( 21, "lower_str( '%s' )\n", str ); my_strncpy( tmp, str, sizeof(tmp)); while( *src ) { *(dst++) = tolower( *(src++) ); } DBG( 22, "RETURN lower_str() == '%s'\n", str ); } /* this list is prioritized a little, since a few smileys are the same */ /* as others except for one extra char at the end */ SMILEY default_smileys[] = { { ":))", "18.png" }, { ":-))", "18.png" }, { ":)", "01.png" }, { "(:", "01.png" }, { "(-:", "01.png" }, { ":-)", "01.png" }, { ":((", "17.png" }, { ":-((", "17.png" }, { ":(", "02.png" }, { ":-(", "02.png" }, { ";;)", "05.png" }, { ";;-)", "05.png" }, { ";)", "03.png" }, { ";-)", "03.png" }, { ":D", "04.png" }, { ":-D", "04.png" }, { ":-/", "06.png" }, { ":-\\", "06.png" }, { ":x", "07.png" }, { ":-x", "07.png" }, { ":X", "07.png" }, { ":-X", "07.png" }, { ":\">", "08.png" }, { ":p", "09.png" }, { ":-p", "09.png" }, { ":P", "09.png" }, { ":-P", "09.png" }, { "=*", "10.png" }, { ":*", "10.png" }, { ":-*", "10.png" }, { ":O", "11.png" }, { ":-O", "11.png" }, { ":0", "11.png" }, { ":-0", "11.png" }, { "X(", "12.png" }, { "X-(", "12.png" }, { ":>", "13.png" }, { ":->", "13.png" }, { "B-)", "14.png" }, { ":-s", "15.png" }, { ">:)", "16.png" }, { ":|", "19.png" }, { ":-|", "19.png" }, { "/:-)", "20.png" }, { "/:)", "20.png" }, { "0:-)", "21.png" }, { "o:-)", "21.png" }, { "o:)", "21.png" }, { ":-B", "22.png" }, { "=;", "23.png" }, { "I-)", "24.png" }, { "|-)", "24.png" }, { "8-|", "25.png" }, { ":-&", "26.png" }, { ":-$", "27.png" }, { "[-(", "28.png" }, { ":o)", "29.png" }, { ":O)", "29.png" }, { ":0)", "29.png" }, { "8-}", "30.png" }, { "(:|", "31.png" }, { "=p~", "32.png" }, { ":-?", "33.png" }, { "#-o", "34.png" }, { "=D>", "35.png" }, { ":@)", "36.png" }, { "3:-0", "37.png" }, { "3:-O", "37.png" }, { "3:-o", "37.png" }, { ":(|)", "38.png" }, { "~:>", "39.png" }, { "@};-", "40.png" }, { "%%-", "41.png" }, { "**==", "42.png" }, { "(~~)", "43.png" }, { "~o)", "44.png" }, { "*-:)", "45.png" }, { "8-x", "46.png" }, { "8-X", "46.png" }, { "=:)", "47.png" }, { "=:-)", "47.png" }, { ">-)", "48.png" }, { ":-L", "49.png" }, { "<):)", "50.png" }, { "[-o<", "51.png" }, { "@-)", "52.png" }, { "$-)", "53.png" }, { ":-\"", "54.png" }, { ":^0", "55.png" }, { ":^o", "55.png" }, { "b-(", "56.png" }, { ":)>-", "57.png" }, { "[-X", "58.png" }, { "[-x", "58.png" }, { "\\:D/", "59.png" }, { ">:D<", "60.png" }, { "o->", "61.png" }, { "o=>", "62.png" }, { "o-+", "63.png" }, { "(%)", "64.png" }, { 0, 0 } }; SMILEY read_smileys[1024]; void smileys_load() { SMILEY *sm_ptr; char filename[256]; FILE *fp; struct stat sbuf; char buf[201]; char *sm_text; char *sm_file; char *end; snprintf( filename, sizeof(filename), "%s/.yahoorc/gyach/emoticons", getenv( "HOME" )); if ( stat( filename, &sbuf )) { /* doesn't exist so write and use default */ fp = fopen( filename, "w" ); if ( fp ) { fprintf( fp, "# format of file is emoticon_textemoticon_file\n" ); sm_ptr = default_smileys; while( sm_ptr->sm_file ) { fprintf( fp, "%s %s\n", sm_ptr->sm_text, sm_ptr->sm_file ); sm_ptr++; } fclose( fp ); } smileys = default_smileys; } else { /* exists, so open and read */ smileys = read_smileys; sm_ptr = smileys; fp = fopen( filename, "r" ); if ( fp ) { while( fgets( buf, 200, fp )) { /* chop the newline */ buf[strlen(buf)-1] = '\0'; sm_text = skip_whitespace( buf ); if ( *sm_text == '#' ) { continue; } end = find_whitespace( sm_text ); if ( ! *end ) { /* invalid line, no filename given */ continue; } *end = '\0'; sm_file = skip_whitespace( end + 1 ); end = find_whitespace( sm_file ); *end = '\0'; sm_ptr->sm_text = strdup( sm_text ); sm_ptr->sm_file = strdup( sm_file ); sm_ptr++; } fclose( fp ); sm_ptr->sm_text = NULL; sm_ptr->sm_file = NULL; } } } int check_smiley( char *str ) { SMILEY *sm_ptr; sm_ptr = &smileys[0]; while( sm_ptr->sm_text ) { if (( !strncmp( str, sm_ptr->sm_text, strlen(sm_ptr->sm_text))) && (( strchr( " \n", str[strlen(sm_ptr->sm_text)] )) || ( ! str[strlen(sm_ptr->sm_text)] ))) { return( 1 ); } sm_ptr++; } return( 0 ); } void convert_smileys( char *str ) { char tmp[4097]; char sm_code[10]; char *from; char *to; int found; SMILEY *sm_ptr; /* return if too long */ if ( strlen( str ) > 4096 ) return; my_strncpy( tmp, str, sizeof(tmp)); from = tmp; to = str; *to = '\0'; while( *from ) { found = 0; sm_ptr = &smileys[0]; while(( sm_ptr->sm_text ) && ( ! found )) { /* fixme, should maybe change this to match no matter what is */ /* next in the string, so you can have multiple smileys in a */ /* row like :):):), but maybe not. we'll see I guess... :) */ /* if ( !strncmp( from, sm_ptr->sm_text, strlen(sm_ptr->sm_text))) { */ if (( !strncmp( from, sm_ptr->sm_text, strlen(sm_ptr->sm_text))) && (( from[strlen(sm_ptr->sm_text)] == ' ' ) || ( from[strlen(sm_ptr->sm_text)] == ',' ) || ( from[strlen(sm_ptr->sm_text)] == '\033' ) || ( from[strlen(sm_ptr->sm_text)] == '\n' ) || ( ! from[strlen(sm_ptr->sm_text)] ))) { /* found a smiley */ found = 1; snprintf( sm_code, sizeof(sm_code), "\033|%s ", sm_ptr->sm_file ); my_strncat( to, sm_code, strlen(tmp)); to += strlen( sm_code ); from += strlen( sm_ptr->sm_text ); } sm_ptr++; } if ( ! found ) { *to = *from; to++; from++; *to = '\0'; } } } char *get_last_color( char *str ) { char *ptr; ptr = str + strlen( str ); while(( ptr > str ) && ( *ptr != '|' )) { ptr--; } if ( ptr == str ) { return( ptr ); } if ( *ptr == '|' ) { *ptr = '\0'; ptr++; return( ptr ); } /* should never get here */ return( YAHOO_COLOR_BLACK ); } /* * attempt to highlight urls if they aren't already highlighted along with * turning html style tags into esc sequences. */ void convert_tags( char *str ) { char tmp[4097]; char *from; char *to; char *ptr; char *ptr2; char *ptr3; int len = 0; char tmp2[512]; char colors[2048] = YAHOO_COLOR_BLACK; char prev_color[25] = YAHOO_COLOR_BLACK; char *cptr; int slen = 1020; DBG( 21, "convert_tags( '%s' )\n", str ); /* return if too long */ if ( strlen( str ) > 4096 ) return; /* convert html tags to ESC sequences */ if ( strchr( str, '<' )) { memset( tmp, 0, sizeof( tmp )); from = str; to = tmp; ptr = strchr( from, '<' ); while( ptr ) { len = ptr - from; strncpy( to, from, len ); to += len; *to = '\0'; from += len; if ( !strncasecmp( from, "", 7 )) { if ( show_html ) { my_strncat( to, YAHOO_COLOR_BLACK, slen ); to += strlen( YAHOO_COLOR_BLACK ); my_strncat( colors, "|", sizeof(colors)); my_strncat( colors, prev_color, sizeof(colors)); strcpy( prev_color, YAHOO_COLOR_BLACK ); } from += 7; } else if ( !strncasecmp( from, "", 6 )) { if ( show_html ) { my_strncat( to, YAHOO_COLOR_BLUE, slen ); to += strlen( YAHOO_COLOR_BLUE ); my_strncat( colors, "|", sizeof(colors)); my_strncat( colors, prev_color, sizeof(colors)); strcpy( prev_color, YAHOO_COLOR_BLUE ); } from += 6; } else if ( !strncasecmp( from, "", 6 )) { if ( show_html ) { my_strncat( to, YAHOO_COLOR_CYAN, slen ); to += strlen( YAHOO_COLOR_CYAN ); my_strncat( colors, "|", sizeof(colors)); my_strncat( colors, prev_color, sizeof(colors)); strcpy( prev_color, YAHOO_COLOR_CYAN ); } from += 6; } else if ( !strncasecmp( from, "", 6 )) { if ( show_html ) { my_strncat( to, YAHOO_COLOR_GRAY, slen ); to += strlen( YAHOO_COLOR_GRAY ); my_strncat( colors, "|", sizeof(colors)); my_strncat( colors, prev_color, sizeof(colors)); strcpy( prev_color, YAHOO_COLOR_GRAY ); } from += 6; } else if ( !strncasecmp( from, "", 7 )) { if ( show_html ) { my_strncat( to, YAHOO_COLOR_GREEN, slen ); to += strlen( YAHOO_COLOR_GREEN ); my_strncat( colors, "|", sizeof(colors)); my_strncat( colors, prev_color, sizeof(colors)); strcpy( prev_color, YAHOO_COLOR_GREEN ); } from += 7; } else if ( !strncasecmp( from, "", 6 )) { if ( show_html ) { my_strncat( to, YAHOO_COLOR_PINK, slen ); to += strlen( YAHOO_COLOR_PINK ); my_strncat( colors, "|", sizeof(colors)); my_strncat( colors, prev_color, sizeof(colors)); strcpy( prev_color, YAHOO_COLOR_PINK ); } from += 6; } else if ( !strncasecmp( from, "", 8 )) { if ( show_html ) { my_strncat( to, YAHOO_COLOR_PURPLE, slen ); to += strlen( YAHOO_COLOR_PURPLE ); my_strncat( colors, "|", sizeof(colors)); my_strncat( colors, prev_color, sizeof(colors)); strcpy( prev_color, YAHOO_COLOR_PURPLE ); } from += 8; } else if ( !strncasecmp( from, "", 8 )) { if ( show_html ) { my_strncat( to, YAHOO_COLOR_ORANGE, slen ); to += strlen( YAHOO_COLOR_ORANGE ); my_strncat( colors, "|", sizeof(colors)); my_strncat( colors, prev_color, sizeof(colors)); strcpy( prev_color, YAHOO_COLOR_ORANGE ); } from += 8; } else if ( !strncasecmp( from, "", 5 )) { if ( show_html ) { my_strncat( to, YAHOO_COLOR_RED, slen ); to += strlen( YAHOO_COLOR_RED ); my_strncat( colors, "|", sizeof(colors)); my_strncat( colors, prev_color, sizeof(colors)); strcpy( prev_color, YAHOO_COLOR_RED ); } from += 5; } else if ( !strncasecmp( from, "", 8 )) { if ( show_html ) { my_strncat( to, "\033[#ffff00m", slen ); to += strlen( "\033[#ffff00m" ); my_strncat( colors, "|", sizeof(colors)); my_strncat( colors, prev_color, sizeof(colors)); strcpy( prev_color, "\033[#ffff00m" ); } from += 8; } else if (( !strncasecmp( from, "", 8 )) || ( !strncasecmp( from, "", 7 )) || ( !strncasecmp( from, "", 7 )) || ( !strncasecmp( from, "", 7 )) || ( !strncasecmp( from, "", 8 )) || ( !strncasecmp( from, "", 7 )) || ( !strncasecmp( from, "", 9 )) || ( !strncasecmp( from, "", 9 )) || ( !strncasecmp( from, "", 6 )) || ( !strncasecmp( from, "", 9 ))) { if ( show_html ) { cptr = get_last_color( colors ); strcat( to, cptr ); to += strlen( cptr ); } while( *from != '>' ) { from++; } from++; } else if ( !strncasecmp( from, "", 3 )) { if ( show_html ) { strcat( to, YAHOO_STYLE_ITALICON ); to += strlen( YAHOO_STYLE_ITALICON ); } from += 3; } else if ( !strncasecmp( from, "", 4 )) { if ( show_html ) { strcat( to, YAHOO_STYLE_ITALICOFF ); to += strlen( YAHOO_STYLE_ITALICOFF ); } from += 4; } else if ( !strncasecmp( from, "", 3 )) { if ( show_html ) { strcat( to, YAHOO_STYLE_BOLDON ); to += strlen( YAHOO_STYLE_BOLDON ); } from += 3; } else if ( !strncasecmp( from, "", 4 )) { if ( show_html ) { strcat( to, YAHOO_STYLE_BOLDOFF ); to += strlen( YAHOO_STYLE_BOLDOFF ); } from += 4; } else if ( !strncasecmp( from, "", 7 )) { /* skip ending font tags */ from += 7; } else if ( !strncasecmp( from, "", 6 )) { /* skip ending alt tags */ from += 6; } else if ( !strncasecmp( from, "", 6 )) { /* skip ending url tags */ *(to++) = ')'; from += 6; } else if (( !strncasecmp( from, "' )) { ptr++; } if (( *ptr ) && ( *(from+4) == '=' )) { /* remember this sound so we can play it */ if ( recv_sound ) { free( recv_sound ); recv_sound = NULL; } if (( ptr - from ) < sizeof( tmp )) { strncpy( tmp2, from + 5, ptr - from - 5 ); tmp2[ptr-from] = '\0'; recv_sound = strdup( tmp2 ); } } from = ptr; if ( *ptr ) from++; } else if ( !strncasecmp( from, "", 6 )) { /* skip ending snd tags */ from += 6; } else if ( !strncasecmp( from, "", 7 )) { /* skip ending fade tags */ from += 7; } else { *(to++) = *(from++); } ptr = strchr( from, '<' ); } my_strncat( to, from, slen ); to += strlen( from ); *to = '\0'; my_strncpy( str, tmp, slen ); } // if ( ! strchr( str, '\n' )) // strcat( str, "\n" ); /* return if no urls */ if (( ! strstr( str, "http://" )) && ( ! strstr( str, "ftp://" ))) { return; } /* return if already marked */ if ( strstr( str, YAHOO_STYLE_URLON )) return; /* return if not showing html */ if ( ! show_html ) return; memset( tmp, 0, sizeof( tmp )); from = str; to = tmp; /* search for ftp:// and http:// */ ptr2 = strstr( str, "http://" ); ptr3 = strstr( str, "ftp://" ); if ( ptr2 && ptr3 ) { ptr = ptr2 < ptr3 ? ptr2 : ptr3; } else if ( ptr2 ) { ptr = ptr2; } else if ( ptr3 ) { ptr = ptr3; } else { ptr = NULL; } while( ptr ) { len = ptr - from; strncpy( to, from, len ); to += len; *to = '\0'; from += len; my_strncat( to, YAHOO_STYLE_URLON, slen ); to += strlen( YAHOO_STYLE_URLON ); while(( *from ) && ( ! isspace( *from ))) { *(to++) = *(from++); } *to = '\0'; my_strncat( to, YAHOO_STYLE_URLOFF, slen ); to += strlen( YAHOO_STYLE_URLOFF ); /* search for ftp:// and http:// */ ptr2 = strstr( from, "http://" ); ptr3 = strstr( from, "ftp://" ); if ( ptr2 && ptr3 ) { ptr = ptr2 < ptr3 ? ptr2 : ptr3; } else if ( ptr2 ) { ptr = ptr2; } else if ( ptr3 ) { ptr = ptr3; } else { ptr = NULL; } } my_strncat( to, from, slen ); to += strlen( from ); *to = '\0'; my_strncpy( str, tmp, slen ); } /* * strip junk (like "h_addrtype != AF_INET )) { /* fixme, show an error box */ return( 0 ); } memset( &sa, 0, sizeof(sa)); memmove((void*)&sa.sin_addr.s_addr, hinfo->h_addr, hinfo->h_length ); sa.sin_family = AF_INET; if ( use_proxy ) { sa.sin_port = htons( proxy_port ); } else { sa.sin_port = htons( 80 ); } if (( sock = socket( AF_INET, SOCK_STREAM, 6 )) == -1 ) { /* fixme, error message */ if ( DBG_LEVEL > 10 ) { printf( "error in socket()\n" ); } return( 0 ); } else { if ( connect( sock, (struct sockaddr*)&sa, sizeof(sa)) == -1 ) { /* fixme, error message */ if ( DBG_LEVEL > 10 ) { printf( "error in connect()\n" ); } close(sock); return( 0 ); } } snprintf( url, sizeof(url), "GET %s HTTP/1.0\r\n" "Accept: application/xml,application/xhtml+xml,text/html,text/plain,*/*\r\n" "Accept: text/plain\r\n" "User-Agent: Gyach/%s\r\n" "Host: %s\r\n", ptr, VERSION, host ); if ( cookie ) { my_strncat( url, "Cookie: ", sizeof(url)); my_strncat( url, cookie, sizeof(url)); my_strncat( url, "\r\n", sizeof(url)); } my_strncat( url, "\r\n\r\n", sizeof(url)); write( sock, url, strlen( url )); result[0] = '\0'; tr = 0; nr = read( sock, tmp, 512 ); while(( nr > 0 ) && ( tr < 65000 )) { process_gtk_events(); tmp[nr] = '\0'; memcpy( result + tr, tmp, nr ); tr += nr; nr = read( sock, tmp, 512 ); } close( sock ); result[tr] = '\0'; ptr = strstr( result, "\r\n\r\n" ); ptr += 4; tr -= ( result - ptr ); memcpy( buf, ptr, tr ); return( tr ); } void subst_escs( char *str ) { char tmp[2048]; char *from = tmp; char *to = str; DBG( 21, "subst_escs( '%s' )\n", str ); if ( ! strchr( str, '\\' )) return; my_strncpy( tmp, str, sizeof(tmp)); while( *from ) { if (( *from == '\\' ) && ( *(from+1) == '\\' ) && ( *(from+2) == 'n' )) { *(to++) = '\\'; *(to++) = 'n'; from += 3; } else if (( *from == '\\' ) && ( *(from+1) == 'n' )) { *(to++) = '\n'; from += 2; } else if (( *from == '\\' ) && ( *(from+1) == 't' )) { *(to++) = '\t'; from += 2; } else { *(to++) = *(from++); } } *to = '\0'; } char *filter_text( char *txt ) { static char buf[513] = ""; char data[513]; char *ptr; char new_cmd[1024]; FILE *fp; DBG( 11, "filter_text( '%s' )\n", txt ); /* zero out buf every time */ buf[0] = '\0'; if ( ! filter_command ) { my_strncpy( buf, txt, sizeof(buf)); return( buf ); } /* sanity check to make sure our echo doesn't hose up */ ptr = txt; while( *ptr ) { if ( *ptr == '"' ) *ptr = '\''; ptr++; } snprintf( new_cmd, sizeof(new_cmd), "echo \"%s\" | %s", txt, filter_command ); fp = popen( new_cmd, "r" ); if ( fp ) { while(( strlen( buf ) < 512 ) && ( fgets( data, 512-strlen(buf), fp ))) { if (( strlen( buf ) + strlen( data )) < 512 ) my_strncat( buf, data, sizeof(buf)); } pclose( fp ); ptr = buf + strlen( buf ); ptr--; while(( *ptr == '\n' ) || ( *ptr == '\r' )) { *ptr = '\0'; ptr--; } if ( strlen( buf ) == 511 ) { strcpy( buf+507, "...." ); } } else { my_strncpy( buf, txt, sizeof(buf)); } return( buf ); } char *replace_args( char *str, char *args ) { static char result[1025] = ""; char zargs[1025]; char tmp[1025]; char search[3]; char *arg; char *ptr; char *end; char *ptr2; int x; DBG( 11, "replace_args( '%s', '%s' )\n", str, args ); my_strncpy( result, str, sizeof(result)); my_strncpy( zargs, args, sizeof(zargs)); if (( ! strchr( result, '$' )) && ( ! strstr( result, "%s" ))) { return( result ); } arg = zargs; for( x = 0; x < 10; x++ ) { /* find next arg */ arg = skip_whitespace( arg ); end = find_whitespace( arg ); *end = '\0'; sprintf( search, "$%d", x ); ptr2 = result; while(( ptr = strstr( ptr2, search )) != NULL ) { /* skip if escaped */ if (( ptr != result ) && ( *(ptr-1) == '\\' )) { ptr2++; continue; } my_strncpy( tmp, ptr + 2, sizeof(tmp)); /* append arg if we have room */ if (( ptr - result + strlen( arg ) + 1 ) < sizeof( result )) strcpy( ptr, arg ); /* append rest of string after arg if we have room */ strncat( ptr, tmp, sizeof( result ) - strlen( result )); ptr2 = ptr; } arg = end + 1; } ptr2 = result; while(( ptr = strstr( ptr2, "$*" )) != NULL ) { /* skip if escaped */ if (( ptr != result ) && ( *(ptr-1) == '\\' )) { ptr2++; continue; } my_strncpy( tmp, ptr + 2, sizeof(tmp)); /* append arg if we have room */ if (( ptr - result + strlen( args ) + 1 ) < sizeof( result )) strcpy( ptr, args ); /* append rest of string after arg if we have room */ strncat( ptr, tmp, sizeof( result ) - strlen( result )); ptr2 = ptr; } ptr2 = result; while(( ptr = strstr( ptr2, "%s" )) != NULL ) { /* skip if escaped */ if (( ptr != result ) && ( *(ptr-1) == '\\' )) { ptr2++; continue; } my_strncpy( tmp, ptr + 2, sizeof(tmp)); /* append arg if we have room */ if (( ptr - result + strlen( args ) + 1 ) < sizeof( result )) strcpy( ptr, args ); /* append rest of string after arg if we have room */ strncat( ptr, tmp, sizeof( result ) - strlen( result )); ptr2 = ptr; } return( result ); } #ifndef OS_WINDOWS void *fetch_avatar( void *arg ) { char buf[65535]; char tmp_avatar[128] = ""; char *avatar = (char *)arg; char filename[256]; char url[256]; int length; FILE *fp; struct stat sbuf; my_strncpy( tmp_avatar, avatar, sizeof(tmp_avatar)); lower_str( tmp_avatar ); snprintf( filename, sizeof(filename), "%s/avatars/%s.jpg", GYACH_CFG_DIR, tmp_avatar ); snprintf( url, sizeof(url), "http://avserv.cheetachat.com/avatar/%s.jpg", avatar ); free( avatar ); snprintf( buf, sizeof(buf), "%s/avatars", GYACH_CFG_DIR ); if ( stat( buf, &sbuf )) mkdir( buf, 0700 ); length = fetch_url( url, buf, NULL ); if ( length ) { if ( strstr( buf, "document has moved" )) { char *start, *end; start = strstr( buf, "com/avatar/" ); start += 11; end = strchr( start, '.' ); *end = '\0'; fetch_avatar( (void *)strdup(start)); } else if ( strstr( buf, "was not found" )) { return( NULL ); } else { fp = fopen( filename, "w" ); if ( fp ) { fwrite( buf, length, 1, fp ); fclose( fp ); #if !defined(USE_GDK_PIXBUF) && !defined(USE_GTK2) /* if we don't have gdk-pixbuf we need to convert to xpm */ snprintf( buf, sizeof(buf), "convert %s xpm:%s/avatars/%s.xpm", filename, GYACH_CFG_DIR, tmp_avatar ); system( buf ); unlink( filename ); #endif } } } return( NULL ); } void display_avatar( char *user, char *avatar ) { #if defined(USE_GDK_PIXBUF) || defined(USE_GTK2) GdkPixbuf *pixbuf; #endif GdkPixmap *st_pixmap; GdkBitmap *st_mask; GtkStyle *user_style = NULL; char filename[256]; struct stat sbuf; pthread_t av_thread; int row; if ( ! strcmp( avatar, "random" )) { return; } #if defined(USE_GDK_PIXBUF) || defined(USE_GTK2) snprintf( filename, sizeof(filename), "%s/avatars/%s.jpg", GYACH_CFG_DIR, avatar ); #else snprintf( filename, sizeof(filename), "%s/avatars/%s.xpm", GYACH_CFG_DIR, avatar ); #endif lower_str( filename ); if ( stat( filename, &sbuf )) { /* doesn't exist, so download for displaying later */ pthread_create( &av_thread, NULL, fetch_avatar, (void *)strdup(avatar)); } else { /* exists, so display */ if ( ct_can_do_pixmaps()) { ct_append_pixmap( filename ); } else { row = find_user_row( user ); if ( row >= 0 ) { user_style = gtk_widget_get_style( chat_users ); if ( user_style ) { gtk_clist_set_row_height( GTK_CLIST(chat_users), 35 ); gtk_clist_set_column_width( GTK_CLIST(chat_users), 0, 50 ); #if defined(USE_GDK_PIXBUF) || defined(USE_GTK2) #ifdef USE_GTK2 pixbuf = gdk_pixbuf_new_from_file( filename, NULL ); #else pixbuf = gdk_pixbuf_new_from_file( filename ); #endif /* consider scaling pixmaps down to 22x22 in userlist */ if ( 1 ) { GdkPixbuf *spixbuf; int width; int height; width = gdk_pixbuf_get_width( pixbuf ); height = gdk_pixbuf_get_height( pixbuf ); if ( width < height ) { width = ( 1.0 * width / height ) * 20; height = 20; } else { height = ( 1.0 * height / width ) * 20; width = 20; } spixbuf = gdk_pixbuf_scale_simple( pixbuf, width, height, GDK_INTERP_BILINEAR ); gdk_pixbuf_render_pixmap_and_mask( spixbuf, &st_pixmap, &st_mask, 0 ); gdk_pixbuf_unref( spixbuf ); gtk_clist_set_row_height( GTK_CLIST(chat_users), 22 ); gtk_clist_set_column_width( GTK_CLIST(chat_users), 0, 22 ); } else gdk_pixbuf_render_pixmap_and_mask( pixbuf, &st_pixmap, &st_mask, 0 ); gdk_pixbuf_unref( pixbuf ); #else st_pixmap = gdk_pixmap_create_from_xpm( chat_users->window, &st_mask, &user_style->bg[GTK_STATE_NORMAL], filename ); #endif gtk_clist_set_pixmap(GTK_CLIST(chat_users), row, 0, st_pixmap, st_mask ); gdk_pixmap_unref( st_pixmap ); if ( st_mask ) gdk_bitmap_unref( st_mask ); } } } } } /* endif OS_WINDOWS */ #endif /* that this version is case insensitive, submitted by Jacques Fortier */ gint clist_strcasecompare(GtkCList *clist, gconstpointer ptr1, gconstpointer ptr2) { char *text1 = NULL; char *text2 = NULL; GtkCListRow *row1 = (GtkCListRow *) ptr1; GtkCListRow *row2 = (GtkCListRow *) ptr2; switch( row1->cell[clist->sort_column].type ) { case GTK_CELL_TEXT: text1 = GTK_CELL_TEXT(row1->cell[clist->sort_column])->text; break; case GTK_CELL_PIXTEXT: text1 = GTK_CELL_PIXTEXT(row1->cell[clist->sort_column])->text; break; default: break; } switch( row2->cell[clist->sort_column].type ) { case GTK_CELL_TEXT: text2 = GTK_CELL_TEXT (row2->cell[clist->sort_column])->text; break; case GTK_CELL_PIXTEXT: text2 = GTK_CELL_PIXTEXT (row2->cell[clist->sort_column])->text; break; default: break; } if (!text2) return (text1 != NULL); if (!text1) return -1; return( strcasecmp( text1, text2 )); } void *play_sound( void *arg ) { char *sound = (char *)arg; char cmd[1024]; snprintf( cmd, sizeof(cmd), "wavplay %s > /dev/null 2>&1", sound ); system( cmd ); free( sound ); return( NULL ); } gint gstrcmp( gpointer a, gpointer b ) { if ( a && b ) { DBG( 31, "gstrcmp( '%s', '%s' )\n", (char *)a, (char *)b ); } else if ( a ) { DBG( 31, "gstrcmp( '%s', NULL )\n", (char *)a ); } else if ( b ) { DBG( 31, "gstrcmp( NULL, '%s' )\n", (char *)b ); } else { DBG( 31, "gstrcmp( NULL, NULL )\n" ); } fflush( stderr ); if (( ! a ) && ( ! b )) { DBG( 32, "RETURN gstrcmp() == 0\n" ); return( 0 ); } if ( ! a ) { DBG( 32, "RETURN gstrcmp() == -1\n" ); return( -1 ); } if ( ! b ) { DBG( 32, "RETURN gstrcmp() == 1\n" ); return( 1 ); } DBG( 32, "RETURN gstrcmp() == %d\n", strcasecmp( (char *)a, (char *)b )); return( strcasecmp( (char *)a, (char *)b )); } GList *gyach_g_list_free( GList *list ) { GList *node; if ( ! list ) return( NULL ); node = g_list_first( list ); while( node ) { free( node->data ); node = g_list_next( node ); } g_list_free( list ); return( NULL ); } GList *gyach_g_list_copy( GList *list ) { GList *result; GList *node; result = g_list_copy( list ); node = g_list_first( result ); while( node ) { node->data = strdup( node->data ); node = g_list_next( node ); } return( result ); } GList *gyach_g_list_merge( GList *main, GList *sub ) { GList *this_item; GList *found_item; this_item = sub; while( this_item ) { found_item = g_list_find_custom( main, this_item->data, (GCompareFunc)gstrcmp ); if ( ! found_item ) { g_list_append( main, strdup( this_item->data )); } this_item = g_list_next( this_item ); } gyach_g_list_free( sub ); return( main ); } void my_strncat( char *dest, char *src, int size) { strncat( dest, src, size - strlen(dest) - 1 ); dest[size-1] = '\0'; } void my_strncpy( char *dest, char *src, int size) { strncpy( dest, src, size - 1 ); dest[size-1] = '\0'; } int filename_is_sane( char *filename ) { char *ptr; char valid_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789_-."; ptr = filename; while( *ptr ) { if ( !strchr( valid_chars, *ptr )) return( 0 ); ptr++; } return( 1 ); }