/* * routines.c * * Random Useful Routines and Functions * * (c) 2002-2005 Thomas White * Part of TuxMessenger - GTK+-based MSN Messenger client * * This package 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; version 2 dated June, 1991. * * This package 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 package; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include "debug.h" char *routines_glob(const char *filename) { char *full_filename; glob_t glob_result; int glob_retval; glob_retval = glob(filename, GLOB_TILDE, NULL, &glob_result); if ( glob_retval != 0 ) { debug_print("glob() failed: "); switch ( glob_retval ) { case GLOB_NOSPACE : debug_print("GLOB_NOSPACE\n"); break; case GLOB_ABORTED : debug_print("GLOB_ABORTED\n"); break; case GLOB_NOMATCH : debug_print("GLOB_NOMATCH\n"); break; default : debug_print("Unknown!\n"); break; } return NULL; } full_filename = malloc(strlen(glob_result.gl_pathv[0])+1); strcpy(full_filename, glob_result.gl_pathv[0]); globfree(&glob_result); return full_filename; } /* TCL-style lindex using ' ' as a separator */ char *routines_lindex(char *string, unsigned int pos) { unsigned int i; unsigned int s=0; char *minibuffer; unsigned int max_output_length = strlen(string); for ( i=0; i' ) { result[p]='%'; p++; result[p]='3'; p++; result[p]='E'; } else if ( ch == '=' ) { result[p]='%'; p++; result[p]='3'; p++; result[p]='D'; } else if ( ch == '@' ) { result[p]='%'; p++; result[p]='4'; p++; result[p]='0'; } else if ( ch == '\"' ) { result[p]='%'; p++; result[p]='2'; p++; result[p]='2'; } else if ( ch == '/' ) { result[p]='%'; p++; result[p]='2'; p++; result[p]='F'; } else if ( ch == '+' ) { result[p]='%'; p++; result[p]='2'; p++; result[p]='B'; } else { result[p]=ch; } p++; } result[p]='\0'; return result; } /* extract hostname from hostname:port style string */ char *routines_hostname(const char *input) { unsigned int i, n=0; char ch='z'; char *output; /* First we must check that there is actually a colon present */ for ( i=0; i> 2; base64_output[j++] = routines_base64char(sextet); /* Second sextet */ sextet = ((base64_input[i] & 0x3) << 4) + ((base64_input[i+1] & 0xf0) >> 4); base64_output[j++] = routines_base64char(sextet); /* Third sextet */ sextet = ((base64_input[i+1] & 0x0f) << 2) + ((base64_input[i+2] & 0xc0) >> 6); base64_output[j++] = routines_base64char(sextet); /* Fourth sextet */ sextet = (base64_input[i+2] & 0x3f); base64_output[j++] = routines_base64char(sextet); } switch ((length) % 3) { case 1 : { /* One byte left over */ i = length-1; sextet = (base64_input[i] & 0xfc) >> 2; base64_output[j++] = routines_base64char(sextet); sextet = (base64_input[i] & 0x03) << 4; base64_output[j++] = routines_base64char(sextet); base64_output[j++] = '='; base64_output[j++] = '='; break; } case 2 : { /* Two bytes left over */ i = length-2; sextet = (base64_input[i] & 0xfc) >> 2; base64_output[j++] = routines_base64char(sextet); sextet = ((base64_input[i] & 0x3) << 4) + ((base64_input[i+1] & 0xf0) >> 4); base64_output[j++] = routines_base64char(sextet); sextet = (base64_input[i+1] & 0x0f) << 2; base64_output[j++] = routines_base64char(sextet); base64_output[j++] = '='; break; } } base64_output[j++] = '\0'; return base64_output; } /* Base64-encode something. Needs to have a NULL terminator. */ char *routines_base64(char *base64_input) { return routines_base64givenlength(base64_input, strlen(base64_input)+1); } /* Decode Base64 string (with terminator) and put pointer to result at "output". Return length of result. */ size_t routines_base64decode(const char *base64_input, char **output) { size_t len = 0; size_t ptr = 0; char *op = malloc(strlen(base64_input)); assert(strlen(base64_input) % 4 == 0 ); while ( ptr < strlen(base64_input) ) { op[len] = (routines_unbase64char(base64_input[ptr]) << 2) + ((routines_unbase64char(base64_input[ptr+1]) & 48) >> 4); op[len+1] = ((routines_unbase64char(base64_input[ptr+1]) & 15) << 4) + ((routines_unbase64char(base64_input[ptr+2]) & 60) >> 2); op[len+2] = ((routines_unbase64char(base64_input[ptr+2]) & 3) << 6) + routines_unbase64char(base64_input[ptr+3]); len+=3; ptr+=4; } if ( base64_input[ptr-1] == '=' ) { len--; } if ( base64_input[ptr-2] == '=' ) { len--; } *output = op; return len; } static char *routines_randomhexbyte() { int j; char *response = malloc(3); /* Taken from the "rand()" man page. */ j = 1 +(int)(256.0*rand()/(RAND_MAX+1.0)); sprintf(response, "%2hhx", j); return response; } /* Generate a GUID */ char *routines_guid() { int i, k; char *guid; guid = malloc(39); assert(guid != NULL); strcpy(guid, "{"); for ( i=0; i<4; i++ ) { char *byte; byte = routines_randomhexbyte(); strncat(guid, byte, 2); free(byte); } for ( k=0; k<3; k++ ) { strcat(guid, "-"); for ( i=0; i<2; i++ ) { char *byte; byte = routines_randomhexbyte(); strncat(guid, byte, 2); free(byte); } } /* To be a valid GUID, the version and variant fields need to be set appropriately. */ guid[15] = '4'; guid[20] = 'a'; strcat(guid, "-"); for ( i=0; i<6; i++ ) { char *byte; byte = routines_randomhexbyte(); strncat(guid, byte, 2); free(byte); } strcat(guid, "}"); /* Fix up spaces. */ for ( i=0; i<(strlen(guid)-1); i++ ) { if ( guid[i] == ' ' ) { guid[i] = '0'; } } return guid; } /* Replace triangular brackets with something Pango can handle. */ char *routines_killtriangles(const char *input) { char *output; size_t i; size_t j = 0; output = malloc(2*strlen(input)+1); for ( i=0; i<=strlen(input); i++ ) { if ( input[i] == '<' ) { output[j] = '&'; j++; output[j] = 'l'; j++; output[j] = 't'; j++; output[j] = ';'; j++; } else if ( input[i] == '>' ) { output[j] = '&'; j++; output[j] = 'g'; j++; output[j] = 't'; j++; output[j] = ';'; j++; } else { output[j] = input[i]; j++; } } return output; } /* Replace triangular brackets and ampersands with something Pango can handle. */ char *routines_killtriangles_and_ampersands(const char *input) { char *output; size_t i; size_t j = 0; output = malloc(2*strlen(input)+1); for ( i=0; i<=strlen(input); i++ ) { if ( input[i] == '<' ) { output[j] = '&'; j++; output[j] = 'l'; j++; output[j] = 't'; j++; output[j] = ';'; j++; } else if ( input[i] == '>' ) { output[j] = '&'; j++; output[j] = 'g'; j++; output[j] = 't'; j++; output[j] = ';'; j++; } else if ( input[i] == '&' ) { output[j] = '&'; j++; output[j] = 'a'; j++; output[j] = 'm'; j++; output[j] = 'p'; j++; output[j] = ';'; j++; } else { output[j] = input[i]; j++; } } return output; } char *routines_flipcolour(const char *colour) { char *flipped = malloc(7); char scratch; strncpy(flipped, colour, 6); flipped[6] = '\0'; scratch = flipped[0]; flipped[0] = flipped[4]; flipped[4] = scratch; scratch = flipped[1]; flipped[1] = flipped[5]; flipped[5] = scratch; return flipped; } char *routines_gdk_to_hashrgb(const GdkColor *colour) { char *string; if ( colour == NULL ) { return NULL; } string = malloc(8); /* RGB order */ snprintf(string, 8, "#%02hhx%02hhx%02hhx", colour->red >> 8, colour->green >> 8, colour->blue >> 8); string[7] = '\0'; return string; }