?? simple.c
字號(hào):
#include <assert.h>#include <string.h>#include <errno.h>#include <glib.h>#include "internal.h"#include "account.h"#include "accountopt.h"#include "debug.h"#include "multi.h"#include "notify.h"#include "prpl.h"#include "request.h"#include "server.h"#include "util.h"#ifdef NO_FORK#include <shlwapi.h>#endif#include "simple.h"static GaimPlugin *my_protocol = NULL;typedef enum{ /* GAIM <-> GAG */ SIMPLE_IM = 0x00, SIMPLE_PRESENCE = 0x01, SIMPLE_HELLO = 0x02, /* GAIM --> GAG */ SIMPLE_LOGIN = 0x40, SIMPLE_LOGOUT = 0x41, SIMPLE_ADD_BUDDY = 0x42, SIMPLE_REMOVE_BUDDY = 0x43, SIMPLE_SHUTDOWN = 0x44, /* GAG --> GAIM */ SIMPLE_ERROR = 0x80, SIMPLE_LOGIN_STATUS = 0x81} gag_command_t;/* In the parent Read from gag using FD_GAG_TO_GAIM Write to gag using FD_GAIM_TO_GAG*/#ifdef NO_FORKstatic int gagfd = 0;#define FD_GAG_TO_GAIM gagfd#define FD_GAIM_TO_GAG gagfd#elsestatic int gaimtogag[2];static int gagtogaim[2];#define FD_GAG_TO_GAIM gagtogaim[0]#define FD_GAIM_TO_GAG gaimtogag[1]#endifstatic int gaginitialized = 0;static intisAccountNameUnsafe(char *accountName){ /* There's an open-ended minefield to be explored here. * This is just a first attempt to keep gaim and gag * from blowing apart because some user typed in * "bad stuff (tm)". */ if (g_strrstr(accountName,"<")!=NULL) {return 1;} if (g_strrstr(accountName,">")!=NULL) {return 1;} if (g_strrstr(accountName," ")!=NULL) {return 1;} if (g_strrstr(accountName,":")!=NULL) { if ( ! ( g_str_has_prefix(accountName,"sip:") || g_str_has_prefix(accountName,"sips:") ) ) return 1; } return 0; }char *buildSIPURI(char *accountName){ if (g_str_has_prefix(accountName,"sip:")) {return g_strdup(accountName);} if (g_str_has_prefix(accountName,"sips:")) {return g_strdup(accountName);} return g_strconcat("sip:",accountName,NULL);}static void sippy_get_string( char* buf, int bufSize ){ int len; int length; len = read( FD_GAG_TO_GAIM, &length, sizeof(length) ); assert( len == sizeof(length) ); if ( length+1 >= bufSize ) { assert(0); } if (length) { len = read( FD_GAG_TO_GAIM, buf, length ); assert( len == length ); } buf[length]=0;}static void sippy_get_int( int* i ){ int len; int length; len = read( FD_GAG_TO_GAIM, &length, sizeof(length) ); assert( len == sizeof(length) ); if ( length != sizeof(int) ) { assert(0); } len = read( FD_GAG_TO_GAIM, i, length ); assert( len == length );}static void sippy_get_bool( unsigned char* i ){ int len; int length; len = read( FD_GAG_TO_GAIM, &length, sizeof(length) ); assert( len == sizeof(length) ); if ( length != sizeof(char) ) { assert(0); } len = read( FD_GAG_TO_GAIM, i, length ); assert( len == length );}static void sippy_send_bool( const unsigned char b ){ int len; int l; assert( FD_GAIM_TO_GAG ); len=sizeof(b); l=write( FD_GAIM_TO_GAG, &len, sizeof(len) ); assert( l == sizeof(len) ); l=write( FD_GAIM_TO_GAG, &b, len ); assert( l == len );}static void sippy_send_string( const char* buf ){ int len; int l; assert( FD_GAIM_TO_GAG ); /*RjS - Gaim gives us NULLs instead of empty strings sometimes */ len=(buf==NULL?0:strlen(buf)); l=write( FD_GAIM_TO_GAG, &len, sizeof(len) ); assert( l == sizeof(len) ); if (len>0) { l=write( FD_GAIM_TO_GAG, buf, len ); assert( l == len ); }}static void sippy_send_command( const gag_command_t command ){ int l; assert( FD_GAIM_TO_GAG ); l=write( FD_GAIM_TO_GAG, &command, sizeof(command) ); assert( l == sizeof(command) );}static const char *sippy_list_icon(GaimAccount *a, GaimBuddy *b){ return "sippy";}static voidsippy_recv_cb(gpointer data, gint source, GaimInputCondition condition){ GaimConnection *gc = data; int len; int command; static char buf[4096]; static char bufFrom[4096]; static char bufTo[4096]; len = read( FD_GAG_TO_GAIM, &command, sizeof(command ) ); if ( len == -1 ) { int err = errno; gaim_debug(GAIM_DEBUG_INFO,"sippy","err=%d\n",err); /* something really bad happened */ assert(0); } if ( len == 0 ) { /* not ready */ return; } assert( len == sizeof(command) ); switch ( command ) { case SIMPLE_IM: { gaim_debug(GAIM_DEBUG_INFO,"sippy","got an IM messages from gag\n"); sippy_get_string( bufTo, sizeof(bufTo) ); sippy_get_string( bufFrom, sizeof(bufFrom) ); sippy_get_string( buf, sizeof(buf) ); gaim_debug(GAIM_DEBUG_INFO,"sippy","got an IM from=%s to=%s data=%s\n",bufFrom,bufTo,buf); serv_got_im(gc,bufFrom,buf,0,time(NULL)); } break; case SIMPLE_LOGIN_STATUS: { unsigned char success; int sipCode; /* bool success, int sipCode, data message */ sippy_get_bool( &success ); sippy_get_int( &sipCode ); sippy_get_string( buf, sizeof(buf) ); gaim_debug(GAIM_DEBUG_INFO,"sippy","got a LOGIN_STATUS status=%d msg=%s\n",sipCode,buf); if (gaim_connection_get_state(gc) != GAIM_CONNECTED) { if (success) { gaim_connection_update_progress(gc,_("Connecting"),1,2); gaim_connection_set_state(gc, GAIM_CONNECTED); } else { gaim_connection_error(gc, _(buf)); } } } break; case SIMPLE_PRESENCE: /* uri aor, bool available, Data status */ { unsigned char open; int lastReportedUCStatus; gaim_debug(GAIM_DEBUG_INFO,"sippy","got a PRES messages from gag\n"); sippy_get_string( bufFrom, sizeof(bufFrom) ); sippy_get_bool( &open ); sippy_get_string( buf, sizeof(buf) ); gaim_debug(GAIM_DEBUG_INFO,"sippy","got a PRES messages from gag from=%s open=%d, msg=%s\n",bufFrom,open,buf); { struct simple_connection_cache *sc_cache = gc->proto_data; struct simple_friend_cache *sf; sf = g_hash_table_lookup(sc_cache->friends,bufFrom); if (!sf) { sf = simple_friend_cache_new(); g_hash_table_insert(sc_cache->friends,g_strdup(bufFrom),sf); } if (sf->status_string) { g_free(sf->status_string); } sf->status_string = g_strdup(buf); lastReportedUCStatus = (sf->status_int ^= 2); } /* AFAICT, there is a half-done change to the use of * the last argument to serv_got_update that is messing * up Yahoo as well as us. The code above the prpl abstraction * claims the integer is ours to do with as we please, but they * use the lowest order bit to mean available or not. * * Other code looks for changes to this integer - if it has * not changed it shortcuts all the GUI updates. So... * We're going to game gaim for now by toggling the second * lowest order bit each time we call this function. * * TODO: This was true in the gaim 0.71 code - need to review to * see if this is still appropriate. */ serv_got_update(gc, bufFrom, (int)open, 0, 0, 0, lastReportedUCStatus); } break; case SIMPLE_HELLO: /* bool ok */ { unsigned char ok; sippy_get_bool( &ok ); gaim_debug(GAIM_DEBUG_INFO,"sippy","got a HELLO ok=%d\n",ok); } case SIMPLE_ERROR: { gaim_debug(GAIM_DEBUG_INFO,"sippy","got an ERROR messages from gag\n"); sippy_get_string( buf, sizeof(buf) ); gaim_debug(GAIM_DEBUG_INFO,"sippy","gag ERROR %s\n",buf); gaim_request_action(gc, _("SIP Error"), _("SIP Error"), buf, 0, NULL, 1, _("Okay"), 0); } break; default: assert(0); }}static voidsippy_add_buddy(GaimConnection *gc, GaimBuddy *who, GaimGroup *dontCare){ if (!gaginitialized) {return;} gaim_debug(GAIM_DEBUG_INFO,"sippy","sending ADD BUDDY to gag us=%s them=%s\n",gc->account->username,who->name); sippy_send_command( SIMPLE_ADD_BUDDY ); sippy_send_string( gc->account->username ); sippy_send_string( who->name );}static voidsippy_logout(GaimConnection *gc){ if (!gaginitialized) {return;} gaim_debug(GAIM_DEBUG_INFO,"sippy","sending LOGOUT to gag aor=%s\n",gc->account->username); sippy_send_command( SIMPLE_LOGOUT ); sippy_send_string( gc->account->username ); gaim_debug(GAIM_DEBUG_INFO,"sippy","Removing gag's gaim_input\n"); gaim_input_remove(gc->inpa);}static voidsippy_remove_buddy(GaimConnection *gc, GaimBuddy *who, GaimGroup *group){ if (!gaginitialized) {return;} gaim_debug(GAIM_DEBUG_INFO,"sippy","sending REMOVE BUDDY to gag us=%s them=%s\n",gc->account->username,who->name); sippy_send_command( SIMPLE_REMOVE_BUDDY ); sippy_send_string( gc->account->username ); sippy_send_string( who->name );}static gboolean sippy_unload_plugin(GaimPlugin *plugin){ if (gaginitialized) { gaim_debug(GAIM_DEBUG_INFO,"sippy","sending SHUTDOWN to gag\n"); sippy_send_command( SIMPLE_SHUTDOWN ); } return 1;}static voidinit_gag(GaimConnection *gc){ char sanity_check_buffer[8]; int sane;#ifdef NO_FORK char gag_path[256]; DWORD gag_path_size = 240;#endif gaim_debug(GAIM_DEBUG_INFO,"sippy","Initializing Gag\n"); #ifdef NO_FORK { int listenfd; int status; int shell_exec_status; struct sockaddr_in us; struct sockaddr_in them; size_t addr_len = sizeof(them); char buffer[1024]; memset((void *)&us, 0, sizeof(struct sockaddr_in)); memset((void *)&them, 0, sizeof(struct sockaddr_in)); us.sin_family = AF_INET; us.sin_port = 0xBEEF; inet_aton("127.0.0.1", &(us.sin_addr)); listenfd = socket(PF_INET, SOCK_STREAM, 0); if (listenfd < 0) { /* We're single threaded, so strerror is safe */ snprintf(buffer, sizeof(buffer), "Unable to start the SIP engine - " "Could not create loopback socket; err = %d (%s)", errno, strerror(errno)); gaim_connection_error(gc, buffer); return; } status = bind (listenfd, (struct sockaddr*)&us, sizeof(struct sockaddr)); if (status != 0) { /* We're single threaded, so strerror is safe */ snprintf(buffer, sizeof(buffer), "Unable to start the SIP engine - " "Could not bind to loopback socket; err = %d (%s)", errno, strerror(errno)); gaim_connection_error(gc, buffer); return; } status = listen(listenfd, 1); if (status != 0) { /* We're single threaded, so strerror is safe */ snprintf(buffer, sizeof(buffer), "Unable to start the SIP engine - " "Could not listen on loopback socket; err = %d (%s)", errno, strerror(errno)); gaim_connection_error(gc, buffer); return; } /* Start SIP engine */ /* First, check in the directory into which Gaim is installed */ SHRegGetUSValue ("SOFTWARE\\gaim", NULL, NULL, (LPVOID)gag_path, &gag_path_size, TRUE, NULL, 0); strcat(gag_path, "\\gag.exe");
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -