Changeset 5ebff60 for protocols/purple
- Timestamp:
- 2015-02-20T22:50:54Z (10 years ago)
- Branches:
- master
- Children:
- 0b9daac, 3d45471, 7733b8c
- Parents:
- af359b4
- git-author:
- Indent <please@…> (19-02-15 05:47:20)
- git-committer:
- dequis <dx@…> (20-02-15 22:50:54)
- Location:
- protocols/purple
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
protocols/purple/ft-direct.c
raf359b4 r5ebff60 34 34 #include <purple.h> 35 35 36 struct prpl_xfer_data 37 { 36 struct prpl_xfer_data { 38 37 PurpleXfer *xfer; 39 38 file_transfer_t *ft; … … 45 44 static file_transfer_t *next_ft; 46 45 47 struct im_connection *purple_ic_by_pa( PurpleAccount *pa);46 struct im_connection *purple_ic_by_pa(PurpleAccount *pa); 48 47 49 48 /* Glorious hack: We seem to have to remind at least some libpurple plugins 50 49 that we're ready because this info may get lost if we give it too early. 51 50 So just do it ten times a second. :-/ */ 52 static gboolean prplcb_xfer_write_request_cb( gpointer data, gint fd, b_input_condition cond)51 static gboolean prplcb_xfer_write_request_cb(gpointer data, gint fd, b_input_condition cond) 53 52 { 54 53 struct prpl_xfer_data *px = data; 55 56 purple_xfer_ui_ready( px->xfer ); 57 58 return purple_xfer_get_type( px->xfer ) == PURPLE_XFER_RECEIVE; 59 } 60 61 static gboolean prpl_xfer_write_request( struct file_transfer *ft ) 62 { 63 struct prpl_xfer_data *px = ft->data; 64 px->ready_timer = b_timeout_add( 100, prplcb_xfer_write_request_cb, px ); 54 55 purple_xfer_ui_ready(px->xfer); 56 57 return purple_xfer_get_type(px->xfer) == PURPLE_XFER_RECEIVE; 58 } 59 60 static gboolean prpl_xfer_write_request(struct file_transfer *ft) 61 { 62 struct prpl_xfer_data *px = ft->data; 63 64 px->ready_timer = b_timeout_add(100, prplcb_xfer_write_request_cb, px); 65 65 return TRUE; 66 66 } 67 67 68 static gboolean prpl_xfer_write( struct file_transfer *ft, char *buffer, unsigned int len)69 { 70 struct prpl_xfer_data *px = ft->data; 71 72 px->buf = g_memdup( buffer, len);68 static gboolean prpl_xfer_write(struct file_transfer *ft, char *buffer, unsigned int len) 69 { 70 struct prpl_xfer_data *px = ft->data; 71 72 px->buf = g_memdup(buffer, len); 73 73 px->buf_len = len; 74 74 75 75 //purple_xfer_ui_ready( px->xfer ); 76 px->ready_timer = b_timeout_add( 0, prplcb_xfer_write_request_cb, px);77 76 px->ready_timer = b_timeout_add(0, prplcb_xfer_write_request_cb, px); 77 78 78 return TRUE; 79 79 } 80 80 81 static void prpl_xfer_accept( struct file_transfer *ft ) 82 { 83 struct prpl_xfer_data *px = ft->data; 84 purple_xfer_request_accepted( px->xfer, NULL ); 85 prpl_xfer_write_request( ft ); 86 } 87 88 static void prpl_xfer_canceled( struct file_transfer *ft, char *reason ) 89 { 90 struct prpl_xfer_data *px = ft->data; 91 purple_xfer_request_denied( px->xfer ); 92 } 93 94 static gboolean prplcb_xfer_new_send_cb( gpointer data, gint fd, b_input_condition cond ) 81 static void prpl_xfer_accept(struct file_transfer *ft) 82 { 83 struct prpl_xfer_data *px = ft->data; 84 85 purple_xfer_request_accepted(px->xfer, NULL); 86 prpl_xfer_write_request(ft); 87 } 88 89 static void prpl_xfer_canceled(struct file_transfer *ft, char *reason) 90 { 91 struct prpl_xfer_data *px = ft->data; 92 93 purple_xfer_request_denied(px->xfer); 94 } 95 96 static gboolean prplcb_xfer_new_send_cb(gpointer data, gint fd, b_input_condition cond) 95 97 { 96 98 PurpleXfer *xfer = data; 97 struct im_connection *ic = purple_ic_by_pa( xfer->account);98 struct prpl_xfer_data *px = g_new0( struct prpl_xfer_data, 1);99 struct im_connection *ic = purple_ic_by_pa(xfer->account); 100 struct prpl_xfer_data *px = g_new0(struct prpl_xfer_data, 1); 99 101 PurpleBuddy *buddy; 100 102 const char *who; 101 102 buddy = purple_find_buddy( xfer->account, xfer->who);103 who = buddy ? purple_buddy_get_name( buddy) : xfer->who;104 103 104 buddy = purple_find_buddy(xfer->account, xfer->who); 105 who = buddy ? purple_buddy_get_name(buddy) : xfer->who; 106 105 107 /* TODO(wilmer): After spreading some more const goodness in BitlBee, 106 108 remove the evil cast below. */ 107 px->ft = imcb_file_send_start( ic, (char*) who, xfer->filename, xfer->size);109 px->ft = imcb_file_send_start(ic, (char *) who, xfer->filename, xfer->size); 108 110 px->ft->data = px; 109 111 px->xfer = data; 110 112 px->xfer->ui_data = px; 111 113 112 114 px->ft->accept = prpl_xfer_accept; 113 115 px->ft->canceled = prpl_xfer_canceled; 114 116 px->ft->write_request = prpl_xfer_write_request; 115 117 116 118 return FALSE; 117 119 } 118 120 119 static void prplcb_xfer_new( PurpleXfer *xfer ) 120 { 121 if( purple_xfer_get_type( xfer ) == PURPLE_XFER_RECEIVE ) 122 { 121 static void prplcb_xfer_new(PurpleXfer *xfer) 122 { 123 if (purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE) { 123 124 /* This should suppress the stupid file dialog. */ 124 purple_xfer_set_local_filename( xfer, "/tmp/wtf123");125 125 purple_xfer_set_local_filename(xfer, "/tmp/wtf123"); 126 126 127 /* Sadly the xfer struct is still empty ATM so come back after 127 128 the caller is done. */ 128 b_timeout_add( 0, prplcb_xfer_new_send_cb, xfer ); 129 } 130 else 131 { 132 struct prpl_xfer_data *px = g_new0( struct prpl_xfer_data, 1 ); 133 129 b_timeout_add(0, prplcb_xfer_new_send_cb, xfer); 130 } else { 131 struct prpl_xfer_data *px = g_new0(struct prpl_xfer_data, 1); 132 134 133 px->ft = next_ft; 135 134 px->ft->data = px; 136 135 px->xfer = xfer; 137 136 px->xfer->ui_data = px; 138 139 purple_xfer_set_filename( xfer, px->ft->file_name);140 purple_xfer_set_size( xfer, px->ft->file_size);141 137 138 purple_xfer_set_filename(xfer, px->ft->file_name); 139 purple_xfer_set_size(xfer, px->ft->file_size); 140 142 141 next_ft = NULL; 143 142 } 144 143 } 145 144 146 static void prplcb_xfer_progress( PurpleXfer *xfer, double percent)147 { 148 fprintf( stderr, "prplcb_xfer_dbg 0x%p %f\n", xfer, percent);149 } 150 151 static void prplcb_xfer_dbg( PurpleXfer *xfer)152 { 153 fprintf( stderr, "prplcb_xfer_dbg 0x%p\n", xfer);154 } 155 156 static gssize prplcb_xfer_write( PurpleXfer *xfer, const guchar *buffer, gssize size)145 static void prplcb_xfer_progress(PurpleXfer *xfer, double percent) 146 { 147 fprintf(stderr, "prplcb_xfer_dbg 0x%p %f\n", xfer, percent); 148 } 149 150 static void prplcb_xfer_dbg(PurpleXfer *xfer) 151 { 152 fprintf(stderr, "prplcb_xfer_dbg 0x%p\n", xfer); 153 } 154 155 static gssize prplcb_xfer_write(PurpleXfer *xfer, const guchar *buffer, gssize size) 157 156 { 158 157 struct prpl_xfer_data *px = xfer->ui_data; 159 158 gboolean st; 160 161 fprintf( stderr, "xfer_write %d %d\n", size, px->buf_len);162 163 b_event_remove( px->ready_timer);159 160 fprintf(stderr, "xfer_write %d %d\n", size, px->buf_len); 161 162 b_event_remove(px->ready_timer); 164 163 px->ready_timer = 0; 165 166 st = px->ft->write( px->ft, (char*) buffer, size ); 167 168 if( st && xfer->bytes_remaining == size ) 169 imcb_file_finished( px->ft ); 170 164 165 st = px->ft->write(px->ft, (char *) buffer, size); 166 167 if (st && xfer->bytes_remaining == size) { 168 imcb_file_finished(px->ft); 169 } 170 171 171 return st ? size : 0; 172 172 } 173 173 174 gssize prplcb_xfer_read( PurpleXfer *xfer, guchar **buffer, gssize size)174 gssize prplcb_xfer_read(PurpleXfer *xfer, guchar **buffer, gssize size) 175 175 { 176 176 struct prpl_xfer_data *px = xfer->ui_data; 177 178 fprintf( stderr, "xfer_read %d %d\n", size, px->buf_len ); 179 180 if( px->buf ) 181 { 177 178 fprintf(stderr, "xfer_read %d %d\n", size, px->buf_len); 179 180 if (px->buf) { 182 181 *buffer = px->buf; 183 182 px->buf = NULL; 184 185 px->ft->write_request( px->ft);186 183 184 px->ft->write_request(px->ft); 185 187 186 return px->buf_len; 188 187 } 189 188 190 189 return 0; 191 190 } … … 204 203 }; 205 204 206 static gboolean prplcb_xfer_send_cb( gpointer data, gint fd, b_input_condition cond);207 208 void purple_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *handle)205 static gboolean prplcb_xfer_send_cb(gpointer data, gint fd, b_input_condition cond); 206 207 void purple_transfer_request(struct im_connection *ic, file_transfer_t *ft, char *handle) 209 208 { 210 209 PurpleAccount *pa = ic->proto_data; 211 210 struct prpl_xfer_data *px; 212 211 213 212 /* xfer_new() will pick up this variable. It's a hack but we're not 214 213 multi-threaded anyway. */ 215 214 next_ft = ft; 216 serv_send_file( purple_account_get_connection( pa ), handle, ft->file_name);217 215 serv_send_file(purple_account_get_connection(pa), handle, ft->file_name); 216 218 217 ft->write = prpl_xfer_write; 219 218 220 219 px = ft->data; 221 imcb_file_recv_start( ft);222 223 px->ready_timer = b_timeout_add( 100, prplcb_xfer_send_cb, px);224 } 225 226 static gboolean prplcb_xfer_send_cb( gpointer data, gint fd, b_input_condition cond)220 imcb_file_recv_start(ft); 221 222 px->ready_timer = b_timeout_add(100, prplcb_xfer_send_cb, px); 223 } 224 225 static gboolean prplcb_xfer_send_cb(gpointer data, gint fd, b_input_condition cond) 227 226 { 228 227 struct prpl_xfer_data *px = data; 229 230 if( px->ft->status & FT_STATUS_TRANSFERRING ) 231 { 232 fprintf( stderr, "The ft, it is ready...\n" ); 233 px->ft->write_request( px->ft ); 234 228 229 if (px->ft->status & FT_STATUS_TRANSFERRING) { 230 fprintf(stderr, "The ft, it is ready...\n"); 231 px->ft->write_request(px->ft); 232 235 233 return FALSE; 236 234 } 237 235 238 236 return TRUE; 239 237 } -
protocols/purple/ft.c
raf359b4 r5ebff60 34 34 #include <purple.h> 35 35 36 struct prpl_xfer_data 37 { 36 struct prpl_xfer_data { 38 37 PurpleXfer *xfer; 39 38 file_transfer_t *ft; … … 46 45 static file_transfer_t *next_ft; 47 46 48 struct im_connection *purple_ic_by_pa( PurpleAccount *pa);49 static gboolean prplcb_xfer_new_send_cb( gpointer data, gint fd, b_input_condition cond);50 static gboolean prpl_xfer_write_request( struct file_transfer *ft);47 struct im_connection *purple_ic_by_pa(PurpleAccount *pa); 48 static gboolean prplcb_xfer_new_send_cb(gpointer data, gint fd, b_input_condition cond); 49 static gboolean prpl_xfer_write_request(struct file_transfer *ft); 51 50 52 51 53 52 /* Receiving files (IM->UI): */ 54 static void prpl_xfer_accept( struct file_transfer *ft ) 55 { 56 struct prpl_xfer_data *px = ft->data; 57 purple_xfer_request_accepted( px->xfer, NULL ); 58 prpl_xfer_write_request( ft ); 59 } 60 61 static void prpl_xfer_canceled( struct file_transfer *ft, char *reason ) 62 { 63 struct prpl_xfer_data *px = ft->data; 64 purple_xfer_request_denied( px->xfer ); 65 } 66 67 static void prplcb_xfer_new( PurpleXfer *xfer ) 68 { 69 if( purple_xfer_get_type( xfer ) == PURPLE_XFER_RECEIVE ) 70 { 71 struct prpl_xfer_data *px = g_new0( struct prpl_xfer_data, 1 ); 72 53 static void prpl_xfer_accept(struct file_transfer *ft) 54 { 55 struct prpl_xfer_data *px = ft->data; 56 57 purple_xfer_request_accepted(px->xfer, NULL); 58 prpl_xfer_write_request(ft); 59 } 60 61 static void prpl_xfer_canceled(struct file_transfer *ft, char *reason) 62 { 63 struct prpl_xfer_data *px = ft->data; 64 65 purple_xfer_request_denied(px->xfer); 66 } 67 68 static void prplcb_xfer_new(PurpleXfer *xfer) 69 { 70 if (purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE) { 71 struct prpl_xfer_data *px = g_new0(struct prpl_xfer_data, 1); 72 73 73 xfer->ui_data = px; 74 74 px->xfer = xfer; 75 px->fn = mktemp( g_strdup( "/tmp/bitlbee-purple-ft.XXXXXX" ));75 px->fn = mktemp(g_strdup("/tmp/bitlbee-purple-ft.XXXXXX")); 76 76 px->fd = -1; 77 px->ic = purple_ic_by_pa( xfer->account);78 79 purple_xfer_set_local_filename( xfer, px->fn);80 77 px->ic = purple_ic_by_pa(xfer->account); 78 79 purple_xfer_set_local_filename(xfer, px->fn); 80 81 81 /* Sadly the xfer struct is still empty ATM so come back after 82 82 the caller is done. */ 83 b_timeout_add( 0, prplcb_xfer_new_send_cb, xfer ); 84 } 85 else 86 { 83 b_timeout_add(0, prplcb_xfer_new_send_cb, xfer); 84 } else { 87 85 struct file_transfer *ft = next_ft; 88 86 struct prpl_xfer_data *px = ft->data; 89 87 90 88 xfer->ui_data = px; 91 89 px->xfer = xfer; 92 90 93 91 next_ft = NULL; 94 92 } 95 93 } 96 94 97 static gboolean prplcb_xfer_new_send_cb( gpointer data, gint fd, b_input_condition cond)95 static gboolean prplcb_xfer_new_send_cb(gpointer data, gint fd, b_input_condition cond) 98 96 { 99 97 PurpleXfer *xfer = data; 100 struct im_connection *ic = purple_ic_by_pa( xfer->account);98 struct im_connection *ic = purple_ic_by_pa(xfer->account); 101 99 struct prpl_xfer_data *px = xfer->ui_data; 102 100 PurpleBuddy *buddy; 103 101 const char *who; 104 105 buddy = purple_find_buddy( xfer->account, xfer->who);106 who = buddy ? purple_buddy_get_name( buddy) : xfer->who;107 102 103 buddy = purple_find_buddy(xfer->account, xfer->who); 104 who = buddy ? purple_buddy_get_name(buddy) : xfer->who; 105 108 106 /* TODO(wilmer): After spreading some more const goodness in BitlBee, 109 107 remove the evil cast below. */ 110 px->ft = imcb_file_send_start( ic, (char*) who, xfer->filename, xfer->size);108 px->ft = imcb_file_send_start(ic, (char *) who, xfer->filename, xfer->size); 111 109 px->ft->data = px; 112 110 113 111 px->ft->accept = prpl_xfer_accept; 114 112 px->ft->canceled = prpl_xfer_canceled; 115 113 px->ft->write_request = prpl_xfer_write_request; 116 114 117 115 return FALSE; 118 116 } 119 117 120 gboolean try_write_to_ui( gpointer data, gint fd, b_input_condition cond)118 gboolean try_write_to_ui(gpointer data, gint fd, b_input_condition cond) 121 119 { 122 120 struct file_transfer *ft = data; … … 124 122 struct stat fs; 125 123 off_t tx_bytes; 126 124 127 125 /* If we don't have the file opened yet, there's no data so wait. */ 128 if ( px->fd < 0 || !px->ui_wants_data )126 if (px->fd < 0 || !px->ui_wants_data) { 129 127 return FALSE; 130 131 tx_bytes = lseek( px->fd, 0, SEEK_CUR ); 132 fstat( px->fd, &fs);133 134 if( fs.st_size > tx_bytes ) 135 {128 } 129 130 tx_bytes = lseek(px->fd, 0, SEEK_CUR); 131 fstat(px->fd, &fs); 132 133 if (fs.st_size > tx_bytes) { 136 134 char buf[1024]; 137 size_t n = MIN( fs.st_size - tx_bytes, sizeof( buf ) ); 138 139 if( read( px->fd, buf, n ) == n && ft->write( ft, buf, n ) ) 140 { 135 size_t n = MIN(fs.st_size - tx_bytes, sizeof(buf)); 136 137 if (read(px->fd, buf, n) == n && ft->write(ft, buf, n)) { 141 138 px->ui_wants_data = FALSE; 139 } else { 140 purple_xfer_cancel_local(px->xfer); 141 imcb_file_canceled(px->ic, ft, "Read error"); 142 142 } 143 else 144 { 145 purple_xfer_cancel_local( px->xfer ); 146 imcb_file_canceled( px->ic, ft, "Read error" ); 147 } 148 } 149 150 if( lseek( px->fd, 0, SEEK_CUR ) == px->xfer->size ) 151 { 143 } 144 145 if (lseek(px->fd, 0, SEEK_CUR) == px->xfer->size) { 152 146 /*purple_xfer_end( px->xfer );*/ 153 imcb_file_finished( px->ic, ft);154 } 155 147 imcb_file_finished(px->ic, ft); 148 } 149 156 150 return FALSE; 157 151 } 158 152 159 153 /* UI calls this when its buffer is empty and wants more data to send to the user. */ 160 static gboolean prpl_xfer_write_request( struct file_transfer *ft)161 { 162 struct prpl_xfer_data *px = ft->data; 163 154 static gboolean prpl_xfer_write_request(struct file_transfer *ft) 155 { 156 struct prpl_xfer_data *px = ft->data; 157 164 158 px->ui_wants_data = TRUE; 165 try_write_to_ui( ft, 0, 0);166 159 try_write_to_ui(ft, 0, 0); 160 167 161 return FALSE; 168 162 } … … 170 164 171 165 /* Generic (IM<>UI): */ 172 static void prplcb_xfer_destroy( PurpleXfer *xfer)166 static void prplcb_xfer_destroy(PurpleXfer *xfer) 173 167 { 174 168 struct prpl_xfer_data *px = xfer->ui_data; 175 176 g_free( px->fn ); 177 g_free( px->handle ); 178 if( px->fd >= 0 ) 179 close( px->fd ); 180 g_free( px ); 181 } 182 183 static void prplcb_xfer_progress( PurpleXfer *xfer, double percent ) 169 170 g_free(px->fn); 171 g_free(px->handle); 172 if (px->fd >= 0) { 173 close(px->fd); 174 } 175 g_free(px); 176 } 177 178 static void prplcb_xfer_progress(PurpleXfer *xfer, double percent) 184 179 { 185 180 struct prpl_xfer_data *px = xfer->ui_data; 186 187 if ( px == NULL )181 182 if (px == NULL) { 188 183 return; 189 190 if( purple_xfer_get_type( xfer ) == PURPLE_XFER_SEND ) 191 { 192 if( *px->fn ) 193 { 184 } 185 186 if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) { 187 if (*px->fn) { 194 188 char *slash; 195 196 unlink( px->fn ); 197 if( ( slash = strrchr( px->fn, '/' ) ) ) 198 { 189 190 unlink(px->fn); 191 if ((slash = strrchr(px->fn, '/'))) { 199 192 *slash = '\0'; 200 rmdir( px->fn);193 rmdir(px->fn); 201 194 } 202 195 *px->fn = '\0'; 203 196 } 204 197 205 198 return; 206 199 } 207 208 if( px->fd == -1 && percent > 0 ) 209 { 200 201 if (px->fd == -1 && percent > 0) { 210 202 /* Weeeeeeeee, we're getting data! That means the file exists 211 203 by now so open it and start sending to the UI. */ 212 px->fd = open( px->fn, O_RDONLY);213 204 px->fd = open(px->fn, O_RDONLY); 205 214 206 /* Unlink it now, because we don't need it after this. */ 215 unlink( px->fn);216 } 217 218 if ( percent < 1 )219 try_write_to_ui( px->ft, 0, 0);220 else207 unlink(px->fn); 208 } 209 210 if (percent < 1) { 211 try_write_to_ui(px->ft, 0, 0); 212 } else { 221 213 /* Another nice problem: If we have the whole file, it only 222 214 gets closed when we return. Problem: There may still be 223 215 stuff buffered and not written, we'll only see it after 224 216 the caller close()s the file. So poll the file after that. */ 225 b_timeout_add( 0, try_write_to_ui, px->ft ); 226 } 227 228 static void prplcb_xfer_cancel_remote( PurpleXfer *xfer ) 217 b_timeout_add(0, try_write_to_ui, px->ft); 218 } 219 } 220 221 static void prplcb_xfer_cancel_remote(PurpleXfer *xfer) 229 222 { 230 223 struct prpl_xfer_data *px = xfer->ui_data; 231 232 if ( px->ft )233 imcb_file_canceled( px->ic, px->ft, "Canceled by remote end");234 else224 225 if (px->ft) { 226 imcb_file_canceled(px->ic, px->ft, "Canceled by remote end"); 227 } else { 235 228 /* px->ft == NULL for sends, because of the two stages. :-/ */ 236 imcb_error( px->ic, "File transfer cancelled by remote end" ); 237 } 238 239 static void prplcb_xfer_dbg( PurpleXfer *xfer ) 240 { 241 fprintf( stderr, "prplcb_xfer_dbg 0x%p\n", xfer ); 229 imcb_error(px->ic, "File transfer cancelled by remote end"); 230 } 231 } 232 233 static void prplcb_xfer_dbg(PurpleXfer *xfer) 234 { 235 fprintf(stderr, "prplcb_xfer_dbg 0x%p\n", xfer); 242 236 } 243 237 244 238 245 239 /* Sending files (UI->IM): */ 246 static gboolean prpl_xfer_write( struct file_transfer *ft, char *buffer, unsigned int len);247 static gboolean purple_transfer_request_cb( gpointer data, gint fd, b_input_condition cond);248 249 void purple_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *handle)250 { 251 struct prpl_xfer_data *px = g_new0( struct prpl_xfer_data, 1);240 static gboolean prpl_xfer_write(struct file_transfer *ft, char *buffer, unsigned int len); 241 static gboolean purple_transfer_request_cb(gpointer data, gint fd, b_input_condition cond); 242 243 void purple_transfer_request(struct im_connection *ic, file_transfer_t *ft, char *handle) 244 { 245 struct prpl_xfer_data *px = g_new0(struct prpl_xfer_data, 1); 252 246 char *dir, *basename; 253 247 254 248 ft->data = px; 255 249 px->ft = ft; 256 257 dir = g_strdup( "/tmp/bitlbee-purple-ft.XXXXXX" ); 258 if( !mkdtemp( dir ) ) 259 { 260 imcb_error( ic, "Could not create temporary file for file transfer" ); 261 g_free( px ); 262 g_free( dir ); 250 251 dir = g_strdup("/tmp/bitlbee-purple-ft.XXXXXX"); 252 if (!mkdtemp(dir)) { 253 imcb_error(ic, "Could not create temporary file for file transfer"); 254 g_free(px); 255 g_free(dir); 263 256 return; 264 257 } 265 266 if ( ( basename = strrchr( ft->file_name, '/' ) ) )258 259 if ((basename = strrchr(ft->file_name, '/'))) { 267 260 basename++; 268 else261 } else { 269 262 basename = ft->file_name; 270 px->fn = g_strdup_printf( "%s/%s", dir, basename );271 px->f d = open( px->fn, O_WRONLY | O_CREAT, 0600);272 g_free( dir);273 274 if( px->fd < 0 ) 275 {276 imcb_error( ic, "Could not create temporary file for file transfer");277 g_free( px);278 g_free( px->fn);263 } 264 px->fn = g_strdup_printf("%s/%s", dir, basename); 265 px->fd = open(px->fn, O_WRONLY | O_CREAT, 0600); 266 g_free(dir); 267 268 if (px->fd < 0) { 269 imcb_error(ic, "Could not create temporary file for file transfer"); 270 g_free(px); 271 g_free(px->fn); 279 272 return; 280 273 } 281 274 282 275 px->ic = ic; 283 px->handle = g_strdup( handle ); 284 285 imcb_log( ic, "Due to libpurple limitations, the file has to be cached locally before proceeding with the actual file transfer. Please wait..." ); 286 287 b_timeout_add( 0, purple_transfer_request_cb, ft ); 288 } 289 290 static void purple_transfer_forward( struct file_transfer *ft ) 276 px->handle = g_strdup(handle); 277 278 imcb_log(ic, 279 "Due to libpurple limitations, the file has to be cached locally before proceeding with the actual file transfer. Please wait..."); 280 281 b_timeout_add(0, purple_transfer_request_cb, ft); 282 } 283 284 static void purple_transfer_forward(struct file_transfer *ft) 291 285 { 292 286 struct prpl_xfer_data *px = ft->data; 293 287 PurpleAccount *pa = px->ic->proto_data; 294 288 295 289 /* xfer_new() will pick up this variable. It's a hack but we're not 296 290 multi-threaded anyway. */ 297 291 next_ft = ft; 298 serv_send_file( purple_account_get_connection( pa ), px->handle, px->fn);299 } 300 301 static gboolean purple_transfer_request_cb( gpointer data, gint fd, b_input_condition cond)292 serv_send_file(purple_account_get_connection(pa), px->handle, px->fn); 293 } 294 295 static gboolean purple_transfer_request_cb(gpointer data, gint fd, b_input_condition cond) 302 296 { 303 297 file_transfer_t *ft = data; 304 298 struct prpl_xfer_data *px = ft->data; 305 306 if( ft->write == NULL ) 307 { 299 300 if (ft->write == NULL) { 308 301 ft->write = prpl_xfer_write; 309 imcb_file_recv_start( px->ic, ft);310 } 311 312 ft->write_request( ft);313 302 imcb_file_recv_start(px->ic, ft); 303 } 304 305 ft->write_request(ft); 306 314 307 return FALSE; 315 308 } 316 309 317 static gboolean prpl_xfer_write( struct file_transfer *ft, char *buffer, unsigned int len ) 318 { 319 struct prpl_xfer_data *px = ft->data; 320 321 if( write( px->fd, buffer, len ) != len ) 322 { 323 imcb_file_canceled( px->ic, ft, "Error while writing temporary file" ); 310 static gboolean prpl_xfer_write(struct file_transfer *ft, char *buffer, unsigned int len) 311 { 312 struct prpl_xfer_data *px = ft->data; 313 314 if (write(px->fd, buffer, len) != len) { 315 imcb_file_canceled(px->ic, ft, "Error while writing temporary file"); 324 316 return FALSE; 325 317 } 326 327 if( lseek( px->fd, 0, SEEK_CUR ) >= ft->file_size ) 328 { 329 close( px->fd ); 318 319 if (lseek(px->fd, 0, SEEK_CUR) >= ft->file_size) { 320 close(px->fd); 330 321 px->fd = -1; 331 332 purple_transfer_forward( ft);333 imcb_file_finished( px->ic, ft);322 323 purple_transfer_forward(ft); 324 imcb_file_finished(px->ic, ft); 334 325 px->ft = NULL; 335 } 336 else337 b_timeout_add( 0, purple_transfer_request_cb, ft );338 326 } else { 327 b_timeout_add(0, purple_transfer_request_cb, ft); 328 } 329 339 330 return TRUE; 340 331 } -
protocols/purple/purple.c
raf359b4 r5ebff60 37 37 static bee_t *local_bee; 38 38 39 static char *set_eval_display_name( set_t *set, char *value);40 41 struct im_connection *purple_ic_by_pa( PurpleAccount *pa)39 static char *set_eval_display_name(set_t *set, char *value); 40 41 struct im_connection *purple_ic_by_pa(PurpleAccount *pa) 42 42 { 43 43 GSList *i; 44 45 for ( i = purple_connections; i; i = i->next )46 if ( ((struct im_connection *)i->data)->proto_data == pa )44 45 for (i = purple_connections; i; i = i->next) { 46 if (((struct im_connection *) i->data)->proto_data == pa) { 47 47 return i->data; 48 48 } 49 } 50 49 51 return NULL; 50 52 } 51 53 52 static struct im_connection *purple_ic_by_gc( PurpleConnection *gc ) 53 { 54 return purple_ic_by_pa( purple_connection_get_account( gc ) ); 55 } 56 57 static gboolean purple_menu_cmp( const char *a, const char *b ) 58 { 59 while( *a && *b ) 60 { 61 while( *a == '_' ) a ++; 62 while( *b == '_' ) b ++; 63 if( g_ascii_tolower( *a ) != g_ascii_tolower( *b ) ) 54 static struct im_connection *purple_ic_by_gc(PurpleConnection *gc) 55 { 56 return purple_ic_by_pa(purple_connection_get_account(gc)); 57 } 58 59 static gboolean purple_menu_cmp(const char *a, const char *b) 60 { 61 while (*a && *b) { 62 while (*a == '_') { 63 a++; 64 } 65 while (*b == '_') { 66 b++; 67 } 68 if (g_ascii_tolower(*a) != g_ascii_tolower(*b)) { 64 69 return FALSE; 65 66 a ++; 67 b ++; 68 } 69 70 return ( *a == '\0' && *b == '\0' ); 71 } 72 73 static void purple_init( account_t *acc ) 74 { 75 PurplePlugin *prpl = purple_plugins_find_with_id( (char*) acc->prpl->data ); 70 } 71 72 a++; 73 b++; 74 } 75 76 return (*a == '\0' && *b == '\0'); 77 } 78 79 static void purple_init(account_t *acc) 80 { 81 PurplePlugin *prpl = purple_plugins_find_with_id((char *) acc->prpl->data); 76 82 PurplePluginProtocolInfo *pi = prpl->info->extra_info; 77 83 PurpleAccount *pa; … … 81 87 GString *help; 82 88 static gboolean dir_fixed = FALSE; 83 89 84 90 /* Layer violation coming up: Making an exception for libpurple here. 85 91 Dig in the IRC state a bit to get a username. Ideally we should 86 92 check if s/he identified but this info doesn't seem *that* important. 87 93 It's just that fecking libpurple can't *not* store this shit. 88 94 89 95 Remember that libpurple is not really meant to be used on public 90 96 servers anyway! */ 91 if( !dir_fixed ) 92 { 97 if (!dir_fixed) { 93 98 irc_t *irc = acc->bee->ui_data; 94 99 char *dir; 95 96 dir = g_strdup_printf( "%s/purple/%s", global.conf->configdir, irc->user->nick);97 purple_util_set_user_dir( dir);98 g_free( dir);99 100 101 dir = g_strdup_printf("%s/purple/%s", global.conf->configdir, irc->user->nick); 102 purple_util_set_user_dir(dir); 103 g_free(dir); 104 100 105 purple_blist_load(); 101 106 purple_prefs_load(); 102 107 dir_fixed = TRUE; 103 108 } 104 105 help = g_string_new( "" ); 106 g_string_printf( help, "BitlBee libpurple module %s (%s).\n\nSupported settings:", 107 (char*) acc->prpl->name, prpl->info->name ); 108 109 if( pi->user_splits ) 110 { 109 110 help = g_string_new(""); 111 g_string_printf(help, "BitlBee libpurple module %s (%s).\n\nSupported settings:", 112 (char *) acc->prpl->name, prpl->info->name); 113 114 if (pi->user_splits) { 111 115 GList *l; 112 g_string_append_printf( help, "\n* username: Username" ); 113 for( l = pi->user_splits; l; l = l->next ) 114 g_string_append_printf( help, "%c%s", 115 purple_account_user_split_get_separator( l->data ), 116 purple_account_user_split_get_text( l->data ) ); 117 } 118 116 g_string_append_printf(help, "\n* username: Username"); 117 for (l = pi->user_splits; l; l = l->next) { 118 g_string_append_printf(help, "%c%s", 119 purple_account_user_split_get_separator(l->data), 120 purple_account_user_split_get_text(l->data)); 121 } 122 } 123 119 124 /* Convert all protocol_options into per-account setting variables. */ 120 for( i = pi->protocol_options; i; i = i->next ) 121 { 125 for (i = pi->protocol_options; i; i = i->next) { 122 126 PurpleAccountOption *o = i->data; 123 127 const char *name; … … 127 131 GList *io = NULL; 128 132 GSList *opts = NULL; 129 130 name = purple_account_option_get_setting( o ); 131 132 switch( purple_account_option_get_type( o ) ) 133 { 133 134 name = purple_account_option_get_setting(o); 135 136 switch (purple_account_option_get_type(o)) { 134 137 case PURPLE_PREF_STRING: 135 def = g_strdup( purple_account_option_get_default_string( o ));136 137 g_string_append_printf( 138 name, purple_account_option_get_text( o),139 "string", def);140 141 break; 142 138 def = g_strdup(purple_account_option_get_default_string(o)); 139 140 g_string_append_printf(help, "\n* %s (%s), %s, default: %s", 141 name, purple_account_option_get_text(o), 142 "string", def); 143 144 break; 145 143 146 case PURPLE_PREF_INT: 144 def = g_strdup_printf( "%d", purple_account_option_get_default_int( o ));147 def = g_strdup_printf("%d", purple_account_option_get_default_int(o)); 145 148 eval = set_eval_int; 146 147 g_string_append_printf( 148 name, purple_account_option_get_text( o),149 "integer", def);150 151 break; 152 149 150 g_string_append_printf(help, "\n* %s (%s), %s, default: %s", 151 name, purple_account_option_get_text(o), 152 "integer", def); 153 154 break; 155 153 156 case PURPLE_PREF_BOOLEAN: 154 if( purple_account_option_get_default_bool( o ) ) 155 def = g_strdup( "true" ); 156 else 157 def = g_strdup( "false" ); 157 if (purple_account_option_get_default_bool(o)) { 158 def = g_strdup("true"); 159 } else { 160 def = g_strdup("false"); 161 } 158 162 eval = set_eval_bool; 159 160 g_string_append_printf( 161 name, purple_account_option_get_text( o),162 "boolean", def);163 164 break; 165 163 164 g_string_append_printf(help, "\n* %s (%s), %s, default: %s", 165 name, purple_account_option_get_text(o), 166 "boolean", def); 167 168 break; 169 166 170 case PURPLE_PREF_STRING_LIST: 167 def = g_strdup( purple_account_option_get_default_list_value( o ) ); 168 169 g_string_append_printf( help, "\n* %s (%s), %s, default: %s", 170 name, purple_account_option_get_text( o ), 171 "list", def ); 172 g_string_append( help, "\n Possible values: " ); 173 174 for( io = purple_account_option_get_list( o ); io; io = io->next ) 175 { 171 def = g_strdup(purple_account_option_get_default_list_value(o)); 172 173 g_string_append_printf(help, "\n* %s (%s), %s, default: %s", 174 name, purple_account_option_get_text(o), 175 "list", def); 176 g_string_append(help, "\n Possible values: "); 177 178 for (io = purple_account_option_get_list(o); io; io = io->next) { 176 179 PurpleKeyValuePair *kv = io->data; 177 opts = g_slist_append( opts, kv->value);180 opts = g_slist_append(opts, kv->value); 178 181 /* TODO: kv->value is not a char*, WTF? */ 179 if( strcmp( kv->value, kv->key ) != 0 ) 180 g_string_append_printf( help, "%s (%s), ", (char*) kv->value, kv->key ); 181 else 182 g_string_append_printf( help, "%s, ", (char*) kv->value ); 182 if (strcmp(kv->value, kv->key) != 0) { 183 g_string_append_printf(help, "%s (%s), ", (char *) kv->value, kv->key); 184 } else { 185 g_string_append_printf(help, "%s, ", (char *) kv->value); 186 } 183 187 } 184 g_string_truncate( help, help->len - 2);188 g_string_truncate(help, help->len - 2); 185 189 eval = set_eval_list; 186 190 eval_data = opts; 187 188 break; 189 191 192 break; 193 190 194 default: 191 195 /** No way to talk to the user right now, invent one when … … 194 198 name, purple_account_option_get_type( o ) ); 195 199 */ 196 g_string_append_printf( 197 name, purple_account_option_get_type( o ));200 g_string_append_printf(help, "\n* [%s] UNSUPPORTED (type %d)", 201 name, purple_account_option_get_type(o)); 198 202 name = NULL; 199 203 } 200 201 if( name != NULL ) 202 { 203 s = set_add( &acc->set, name, def, eval, acc ); 204 205 if (name != NULL) { 206 s = set_add(&acc->set, name, def, eval, acc); 204 207 s->flags |= ACC_SET_OFFLINE_ONLY; 205 208 s->eval_data = eval_data; 206 g_free( def);207 } 208 } 209 210 g_snprintf( help_title, sizeof( help_title ), "purple %s", (char*) acc->prpl->name);211 help_add_mem( &global.help, help_title, help->str);212 g_string_free( help, TRUE);213 214 s = set_add( &acc->set, "display_name", NULL, set_eval_display_name, acc);209 g_free(def); 210 } 211 } 212 213 g_snprintf(help_title, sizeof(help_title), "purple %s", (char *) acc->prpl->name); 214 help_add_mem(&global.help, help_title, help->str); 215 g_string_free(help, TRUE); 216 217 s = set_add(&acc->set, "display_name", NULL, set_eval_display_name, acc); 215 218 s->flags |= ACC_SET_ONLINE_ONLY; 216 217 if( pi->options & OPT_PROTO_MAIL_CHECK ) 218 { 219 s = set_add( &acc->set, "mail_notifications", "false", set_eval_bool, acc ); 219 220 if (pi->options & OPT_PROTO_MAIL_CHECK) { 221 s = set_add(&acc->set, "mail_notifications", "false", set_eval_bool, acc); 220 222 s->flags |= ACC_SET_OFFLINE_ONLY; 221 223 } 222 223 if( strcmp( prpl->info->name, "Gadu-Gadu" ) == 0 ) 224 s = set_add( &acc->set, "gg_sync_contacts", "true", set_eval_bool, acc ); 225 224 225 if (strcmp(prpl->info->name, "Gadu-Gadu") == 0) { 226 s = set_add(&acc->set, "gg_sync_contacts", "true", set_eval_bool, acc); 227 } 228 226 229 /* Go through all away states to figure out if away/status messages 227 230 are possible. */ 228 pa = purple_account_new( acc->user, (char*) acc->prpl->data ); 229 for( st = purple_account_get_status_types( pa ); st; st = st->next ) 230 { 231 PurpleStatusPrimitive prim = purple_status_type_get_primitive( st->data ); 232 233 if( prim == PURPLE_STATUS_AVAILABLE ) 234 { 235 if( purple_status_type_get_attr( st->data, "message" ) ) 231 pa = purple_account_new(acc->user, (char *) acc->prpl->data); 232 for (st = purple_account_get_status_types(pa); st; st = st->next) { 233 PurpleStatusPrimitive prim = purple_status_type_get_primitive(st->data); 234 235 if (prim == PURPLE_STATUS_AVAILABLE) { 236 if (purple_status_type_get_attr(st->data, "message")) { 236 237 acc->flags |= ACC_FLAG_STATUS_MESSAGE; 237 } 238 else if( prim != PURPLE_STATUS_OFFLINE ) 239 { 240 if( purple_status_type_get_attr( st->data, "message" ) ) 238 } 239 } else if (prim != PURPLE_STATUS_OFFLINE) { 240 if (purple_status_type_get_attr(st->data, "message")) { 241 241 acc->flags |= ACC_FLAG_AWAY_MESSAGE; 242 } 243 } 244 purple_accounts_remove( pa ); 245 } 246 247 static void purple_sync_settings( account_t *acc, PurpleAccount *pa ) 248 { 249 PurplePlugin *prpl = purple_plugins_find_with_id( pa->protocol_id ); 242 } 243 } 244 } 245 purple_accounts_remove(pa); 246 } 247 248 static void purple_sync_settings(account_t *acc, PurpleAccount *pa) 249 { 250 PurplePlugin *prpl = purple_plugins_find_with_id(pa->protocol_id); 250 251 PurplePluginProtocolInfo *pi = prpl->info->extra_info; 251 252 GList *i; 252 253 for( i = pi->protocol_options; i; i = i->next ) 254 { 253 254 for (i = pi->protocol_options; i; i = i->next) { 255 255 PurpleAccountOption *o = i->data; 256 256 const char *name; 257 257 set_t *s; 258 259 name = purple_account_option_get_setting( o);260 s = set_find( &acc->set, name);261 if ( s->value == NULL )258 259 name = purple_account_option_get_setting(o); 260 s = set_find(&acc->set, name); 261 if (s->value == NULL) { 262 262 continue; 263 264 switch( purple_account_option_get_type( o ) ) 265 {263 } 264 265 switch (purple_account_option_get_type(o)) { 266 266 case PURPLE_PREF_STRING: 267 267 case PURPLE_PREF_STRING_LIST: 268 purple_account_set_string( pa, name, set_getstr( &acc->set, name ));269 break; 270 268 purple_account_set_string(pa, name, set_getstr(&acc->set, name)); 269 break; 270 271 271 case PURPLE_PREF_INT: 272 purple_account_set_int( pa, name, set_getint( &acc->set, name ));273 break; 274 272 purple_account_set_int(pa, name, set_getint(&acc->set, name)); 273 break; 274 275 275 case PURPLE_PREF_BOOLEAN: 276 purple_account_set_bool( pa, name, set_getbool( &acc->set, name ));277 break; 278 276 purple_account_set_bool(pa, name, set_getbool(&acc->set, name)); 277 break; 278 279 279 default: 280 280 break; 281 281 } 282 282 } 283 284 if( pi->options & OPT_PROTO_MAIL_CHECK ) 285 purple_account_set_check_mail( pa, set_getbool( &acc->set, "mail_notifications" ) ); 286 } 287 288 static void purple_login( account_t *acc ) 289 { 290 struct im_connection *ic = imcb_new( acc ); 283 284 if (pi->options & OPT_PROTO_MAIL_CHECK) { 285 purple_account_set_check_mail(pa, set_getbool(&acc->set, "mail_notifications")); 286 } 287 } 288 289 static void purple_login(account_t *acc) 290 { 291 struct im_connection *ic = imcb_new(acc); 291 292 PurpleAccount *pa; 292 293 if( ( local_bee != NULL && local_bee != acc->bee ) || 294 ( global.conf->runmode == RUNMODE_DAEMON && !getenv( "BITLBEE_DEBUG" ) ) ) 295 { 296 imcb_error( ic, "Daemon mode detected. Do *not* try to use libpurple in daemon mode! " 297 "Please use inetd or ForkDaemon mode instead." ); 298 imc_logout( ic, FALSE ); 293 294 if ((local_bee != NULL && local_bee != acc->bee) || 295 (global.conf->runmode == RUNMODE_DAEMON && !getenv("BITLBEE_DEBUG"))) { 296 imcb_error(ic, "Daemon mode detected. Do *not* try to use libpurple in daemon mode! " 297 "Please use inetd or ForkDaemon mode instead."); 298 imc_logout(ic, FALSE); 299 299 return; 300 300 } 301 301 local_bee = acc->bee; 302 302 303 303 /* For now this is needed in the _connected() handlers if using 304 304 GLib event handling, to make sure we're not handling events 305 305 on dead connections. */ 306 purple_connections = g_slist_prepend( purple_connections, ic);307 308 ic->proto_data = pa = purple_account_new( acc->user, (char*) acc->prpl->data);309 purple_account_set_password( pa, acc->pass);310 purple_sync_settings( acc, pa);311 312 purple_account_set_enabled( pa, "BitlBee", TRUE);313 } 314 315 static void purple_logout( struct im_connection *ic)306 purple_connections = g_slist_prepend(purple_connections, ic); 307 308 ic->proto_data = pa = purple_account_new(acc->user, (char *) acc->prpl->data); 309 purple_account_set_password(pa, acc->pass); 310 purple_sync_settings(acc, pa); 311 312 purple_account_set_enabled(pa, "BitlBee", TRUE); 313 } 314 315 static void purple_logout(struct im_connection *ic) 316 316 { 317 317 PurpleAccount *pa = ic->proto_data; 318 319 purple_account_set_enabled( pa, "BitlBee", FALSE);320 purple_connections = g_slist_remove( purple_connections, ic);321 purple_accounts_remove( pa);322 } 323 324 static int purple_buddy_msg( struct im_connection *ic, char *who, char *message, int flags)318 319 purple_account_set_enabled(pa, "BitlBee", FALSE); 320 purple_connections = g_slist_remove(purple_connections, ic); 321 purple_accounts_remove(pa); 322 } 323 324 static int purple_buddy_msg(struct im_connection *ic, char *who, char *message, int flags) 325 325 { 326 326 PurpleConversation *conv; 327 328 if( ( conv = purple_find_conversation_with_account( PURPLE_CONV_TYPE_IM, 329 who, ic->proto_data ) ) == NULL ) 330 { 331 conv = purple_conversation_new( PURPLE_CONV_TYPE_IM, 332 ic->proto_data, who ); 333 } 334 335 purple_conv_im_send( purple_conversation_get_im_data( conv ), message ); 336 327 328 if ((conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, 329 who, ic->proto_data)) == NULL) { 330 conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, 331 ic->proto_data, who); 332 } 333 334 purple_conv_im_send(purple_conversation_get_im_data(conv), message); 335 337 336 return 1; 338 337 } 339 338 340 static GList *purple_away_states( struct im_connection *ic)339 static GList *purple_away_states(struct im_connection *ic) 341 340 { 342 341 PurpleAccount *pa = ic->proto_data; 343 342 GList *st, *ret = NULL; 344 345 for ( st = purple_account_get_status_types( pa ); st; st = st->next )346 {347 PurpleStatusPrimitive prim = purple_status_type_get_primitive( st->data );348 if( prim != PURPLE_STATUS_AVAILABLE && prim != PURPLE_STATUS_OFFLINE )349 ret = g_list_append( ret, (void*) purple_status_type_get_name( st->data ) );350 } 351 343 344 for (st = purple_account_get_status_types(pa); st; st = st->next) { 345 PurpleStatusPrimitive prim = purple_status_type_get_primitive(st->data); 346 if (prim != PURPLE_STATUS_AVAILABLE && prim != PURPLE_STATUS_OFFLINE) { 347 ret = g_list_append(ret, (void *) purple_status_type_get_name(st->data)); 348 } 349 } 350 352 351 return ret; 353 352 } 354 353 355 static void purple_set_away( struct im_connection *ic, char *state_txt, char *message)354 static void purple_set_away(struct im_connection *ic, char *state_txt, char *message) 356 355 { 357 356 PurpleAccount *pa = ic->proto_data; 358 GList *status_types = purple_account_get_status_types( pa), *st;357 GList *status_types = purple_account_get_status_types(pa), *st; 359 358 PurpleStatusType *pst = NULL; 360 359 GList *args = NULL; 361 362 for( st = status_types; st; st = st->next ) 363 { 360 361 for (st = status_types; st; st = st->next) { 364 362 pst = st->data; 365 366 if( state_txt == NULL && 367 purple_status_type_get_primitive( pst ) == PURPLE_STATUS_AVAILABLE ) 368 break; 369 370 if( state_txt != NULL && 371 g_strcasecmp( state_txt, purple_status_type_get_name( pst ) ) == 0 ) 372 break; 373 } 374 375 if( message && purple_status_type_get_attr( pst, "message" ) ) 376 { 377 args = g_list_append( args, "message" ); 378 args = g_list_append( args, message ); 379 } 380 381 purple_account_set_status_list( pa, st ? purple_status_type_get_id( pst ) : "away", 382 TRUE, args ); 383 384 g_list_free( args ); 385 } 386 387 static char *set_eval_display_name( set_t *set, char *value ) 363 364 if (state_txt == NULL && 365 purple_status_type_get_primitive(pst) == PURPLE_STATUS_AVAILABLE) { 366 break; 367 } 368 369 if (state_txt != NULL && 370 g_strcasecmp(state_txt, purple_status_type_get_name(pst)) == 0) { 371 break; 372 } 373 } 374 375 if (message && purple_status_type_get_attr(pst, "message")) { 376 args = g_list_append(args, "message"); 377 args = g_list_append(args, message); 378 } 379 380 purple_account_set_status_list(pa, st ? purple_status_type_get_id(pst) : "away", 381 TRUE, args); 382 383 g_list_free(args); 384 } 385 386 static char *set_eval_display_name(set_t *set, char *value) 388 387 { 389 388 account_t *acc = set->data; 390 389 struct im_connection *ic = acc->ic; 391 392 if( ic ) 393 imcb_log( ic, "Changing display_name not currently supported with libpurple!" ); 394 390 391 if (ic) { 392 imcb_log(ic, "Changing display_name not currently supported with libpurple!"); 393 } 394 395 395 return NULL; 396 396 } 397 397 398 398 /* Bad bad gadu-gadu, not saving buddy list by itself */ 399 static void purple_gg_buddylist_export( PurpleConnection *gc ) 400 { 401 struct im_connection *ic = purple_ic_by_gc( gc ); 402 403 if( set_getstr( &ic->acc->set, "gg_sync_contacts" ) ) 404 { 405 GList *actions = gc->prpl->info->actions( gc->prpl, gc ); 399 static void purple_gg_buddylist_export(PurpleConnection *gc) 400 { 401 struct im_connection *ic = purple_ic_by_gc(gc); 402 403 if (set_getstr(&ic->acc->set, "gg_sync_contacts")) { 404 GList *actions = gc->prpl->info->actions(gc->prpl, gc); 406 405 GList *p; 407 for( p = g_list_first(actions); p; p = p->next ) 408 { 409 if( ((PurplePluginAction*)p->data) && 410 purple_menu_cmp( ((PurplePluginAction*)p->data)->label, "Upload buddylist to Server" ) == 0) 411 { 406 for (p = g_list_first(actions); p; p = p->next) { 407 if (((PurplePluginAction *) p->data) && 408 purple_menu_cmp(((PurplePluginAction *) p->data)->label, 409 "Upload buddylist to Server") == 0) { 412 410 PurplePluginAction action; 413 411 action.plugin = gc->prpl; 414 412 action.context = gc; 415 413 action.user_data = NULL; 416 ((PurplePluginAction *)p->data)->callback(&action);414 ((PurplePluginAction *) p->data)->callback(&action); 417 415 break; 418 416 } 419 417 } 420 g_list_free( actions ); 421 } 422 } 423 424 static void purple_gg_buddylist_import( PurpleConnection *gc ) 425 { 426 struct im_connection *ic = purple_ic_by_gc( gc ); 427 428 if( set_getstr( &ic->acc->set, "gg_sync_contacts" ) ) 429 { 430 GList *actions = gc->prpl->info->actions( gc->prpl, gc ); 418 g_list_free(actions); 419 } 420 } 421 422 static void purple_gg_buddylist_import(PurpleConnection *gc) 423 { 424 struct im_connection *ic = purple_ic_by_gc(gc); 425 426 if (set_getstr(&ic->acc->set, "gg_sync_contacts")) { 427 GList *actions = gc->prpl->info->actions(gc->prpl, gc); 431 428 GList *p; 432 for( p = g_list_first(actions); p; p = p->next ) 433 { 434 if( ((PurplePluginAction*)p->data) && 435 purple_menu_cmp( ((PurplePluginAction*)p->data)->label, "Download buddylist from Server" ) == 0 ) 436 { 429 for (p = g_list_first(actions); p; p = p->next) { 430 if (((PurplePluginAction *) p->data) && 431 purple_menu_cmp(((PurplePluginAction *) p->data)->label, 432 "Download buddylist from Server") == 0) { 437 433 PurplePluginAction action; 438 434 action.plugin = gc->prpl; 439 435 action.context = gc; 440 436 action.user_data = NULL; 441 ((PurplePluginAction *)p->data)->callback(&action);437 ((PurplePluginAction *) p->data)->callback(&action); 442 438 break; 443 439 } 444 440 } 445 g_list_free( actions);446 } 447 } 448 449 static void purple_add_buddy( struct im_connection *ic, char *who, char *group)441 g_list_free(actions); 442 } 443 } 444 445 static void purple_add_buddy(struct im_connection *ic, char *who, char *group) 450 446 { 451 447 PurpleBuddy *pb; 452 448 PurpleGroup *pg = NULL; 453 454 if( group && !( pg = purple_find_group( group ) ) ) 455 { 456 pg = purple_group_new( group ); 457 purple_blist_add_group( pg, NULL ); 458 } 459 460 pb = purple_buddy_new( (PurpleAccount*) ic->proto_data, who, NULL ); 461 purple_blist_add_buddy( pb, NULL, pg, NULL ); 462 purple_account_add_buddy( (PurpleAccount*) ic->proto_data, pb ); 463 464 purple_gg_buddylist_export( ((PurpleAccount*)ic->proto_data)->gc ); 465 } 466 467 static void purple_remove_buddy( struct im_connection *ic, char *who, char *group ) 449 450 if (group && !(pg = purple_find_group(group))) { 451 pg = purple_group_new(group); 452 purple_blist_add_group(pg, NULL); 453 } 454 455 pb = purple_buddy_new((PurpleAccount *) ic->proto_data, who, NULL); 456 purple_blist_add_buddy(pb, NULL, pg, NULL); 457 purple_account_add_buddy((PurpleAccount *) ic->proto_data, pb); 458 459 purple_gg_buddylist_export(((PurpleAccount *) ic->proto_data)->gc); 460 } 461 462 static void purple_remove_buddy(struct im_connection *ic, char *who, char *group) 468 463 { 469 464 PurpleBuddy *pb; 470 471 pb = purple_find_buddy( (PurpleAccount*) ic->proto_data, who ); 472 if( pb != NULL ) 473 { 465 466 pb = purple_find_buddy((PurpleAccount *) ic->proto_data, who); 467 if (pb != NULL) { 474 468 PurpleGroup *group; 475 476 group = purple_buddy_get_group( pb);477 purple_account_remove_buddy( (PurpleAccount*) ic->proto_data, pb, group);478 479 purple_blist_remove_buddy( pb);480 } 481 482 purple_gg_buddylist_export( ((PurpleAccount*)ic->proto_data)->gc);483 } 484 485 static void purple_add_permit( struct im_connection *ic, char *who)469 470 group = purple_buddy_get_group(pb); 471 purple_account_remove_buddy((PurpleAccount *) ic->proto_data, pb, group); 472 473 purple_blist_remove_buddy(pb); 474 } 475 476 purple_gg_buddylist_export(((PurpleAccount *) ic->proto_data)->gc); 477 } 478 479 static void purple_add_permit(struct im_connection *ic, char *who) 486 480 { 487 481 PurpleAccount *pa = ic->proto_data; 488 489 purple_privacy_permit_add( pa, who, FALSE);490 } 491 492 static void purple_add_deny( struct im_connection *ic, char *who)482 483 purple_privacy_permit_add(pa, who, FALSE); 484 } 485 486 static void purple_add_deny(struct im_connection *ic, char *who) 493 487 { 494 488 PurpleAccount *pa = ic->proto_data; 495 496 purple_privacy_deny_add( pa, who, FALSE);497 } 498 499 static void purple_rem_permit( struct im_connection *ic, char *who)489 490 purple_privacy_deny_add(pa, who, FALSE); 491 } 492 493 static void purple_rem_permit(struct im_connection *ic, char *who) 500 494 { 501 495 PurpleAccount *pa = ic->proto_data; 502 503 purple_privacy_permit_remove( pa, who, FALSE);504 } 505 506 static void purple_rem_deny( struct im_connection *ic, char *who)496 497 purple_privacy_permit_remove(pa, who, FALSE); 498 } 499 500 static void purple_rem_deny(struct im_connection *ic, char *who) 507 501 { 508 502 PurpleAccount *pa = ic->proto_data; 509 510 purple_privacy_deny_remove( pa, who, FALSE);511 } 512 513 static void purple_get_info( struct im_connection *ic, char *who)514 { 515 serv_get_info( purple_account_get_connection( ic->proto_data ), who);516 } 517 518 static void purple_keepalive( struct im_connection *ic)519 { 520 } 521 522 static int purple_send_typing( struct im_connection *ic, char *who, int flags)503 504 purple_privacy_deny_remove(pa, who, FALSE); 505 } 506 507 static void purple_get_info(struct im_connection *ic, char *who) 508 { 509 serv_get_info(purple_account_get_connection(ic->proto_data), who); 510 } 511 512 static void purple_keepalive(struct im_connection *ic) 513 { 514 } 515 516 static int purple_send_typing(struct im_connection *ic, char *who, int flags) 523 517 { 524 518 PurpleTypingState state = PURPLE_NOT_TYPING; 525 519 PurpleAccount *pa = ic->proto_data; 526 527 if ( flags & OPT_TYPING )520 521 if (flags & OPT_TYPING) { 528 522 state = PURPLE_TYPING; 529 else if( flags & OPT_THINKING )523 } else if (flags & OPT_THINKING) { 530 524 state = PURPLE_TYPED; 531 532 serv_send_typing( purple_account_get_connection( pa ), who, state ); 533 525 } 526 527 serv_send_typing(purple_account_get_connection(pa), who, state); 528 534 529 return 1; 535 530 } 536 531 537 static void purple_chat_msg( struct groupchat *gc, char *message, int flags)532 static void purple_chat_msg(struct groupchat *gc, char *message, int flags) 538 533 { 539 534 PurpleConversation *pc = gc->data; 540 541 purple_conv_chat_send( purple_conversation_get_chat_data( pc ), message);542 } 543 544 struct groupchat *purple_chat_with( struct im_connection *ic, char *who)535 536 purple_conv_chat_send(purple_conversation_get_chat_data(pc), message); 537 } 538 539 struct groupchat *purple_chat_with(struct im_connection *ic, char *who) 545 540 { 546 541 /* No, "of course" this won't work this way. Or in fact, it almost … … 551 546 PurpleConvChat *pcc; 552 547 struct groupchat *gc; 553 548 554 549 gc = imcb_chat_new( ic, "BitlBee-libpurple groupchat" ); 555 550 gc->data = pc = purple_conversation_new( PURPLE_CONV_TYPE_CHAT, pa, "BitlBee-libpurple groupchat" ); 556 551 pc->ui_data = gc; 557 552 558 553 pcc = PURPLE_CONV_CHAT( pc ); 559 554 purple_conv_chat_add_user( pcc, ic->acc->user, "", 0, TRUE ); … … 561 556 //purple_conv_chat_add_user( pcc, who, "", 0, TRUE ); 562 557 */ 563 558 564 559 /* There went my nice afternoon. :-( */ 565 560 566 561 PurpleAccount *pa = ic->proto_data; 567 PurplePlugin *prpl = purple_plugins_find_with_id( pa->protocol_id);562 PurplePlugin *prpl = purple_plugins_find_with_id(pa->protocol_id); 568 563 PurplePluginProtocolInfo *pi = prpl->info->extra_info; 569 PurpleBuddy *pb = purple_find_buddy( (PurpleAccount*) ic->proto_data, who);564 PurpleBuddy *pb = purple_find_buddy((PurpleAccount *) ic->proto_data, who); 570 565 PurpleMenuAction *mi; 571 566 GList *menu; 567 572 568 void (*callback)(PurpleBlistNode *, gpointer); /* FFFFFFFFFFFFFUUUUUUUUUUUUUU */ 573 574 if ( !pb || !pi || !pi->blist_node_menu )569 570 if (!pb || !pi || !pi->blist_node_menu) { 575 571 return NULL; 576 577 menu = pi->blist_node_menu( &pb->node ); 578 while( menu )579 {572 } 573 574 menu = pi->blist_node_menu(&pb->node); 575 while (menu) { 580 576 mi = menu->data; 581 if( purple_menu_cmp( mi->label, "initiate chat" ) || 582 purple_menu_cmp( mi->label, "initiate conference" ) ) 583 break; 577 if (purple_menu_cmp(mi->label, "initiate chat") || 578 purple_menu_cmp(mi->label, "initiate conference")) { 579 break; 580 } 584 581 menu = menu->next; 585 582 } 586 587 if ( menu == NULL )583 584 if (menu == NULL) { 588 585 return NULL; 589 586 } 587 590 588 /* Call the fucker. */ 591 callback = (void *) mi->callback;592 callback( &pb->node, menu->data);593 589 callback = (void *) mi->callback; 590 callback(&pb->node, menu->data); 591 594 592 return NULL; 595 593 } 596 594 597 void purple_chat_invite( struct groupchat *gc, char *who, char *message)595 void purple_chat_invite(struct groupchat *gc, char *who, char *message) 598 596 { 599 597 PurpleConversation *pc = gc->data; 600 PurpleConvChat *pcc = PURPLE_CONV_CHAT( pc);601 602 serv_chat_invite( purple_account_get_connection( gc->ic->proto_data),603 purple_conv_chat_get_id( pcc ),604 605 who);606 } 607 608 void purple_chat_kick( struct groupchat *gc, char *who, const char *message)598 PurpleConvChat *pcc = PURPLE_CONV_CHAT(pc); 599 600 serv_chat_invite(purple_account_get_connection(gc->ic->proto_data), 601 purple_conv_chat_get_id(pcc), 602 message && *message ? message : "Please join my chat", 603 who); 604 } 605 606 void purple_chat_kick(struct groupchat *gc, char *who, const char *message) 609 607 { 610 608 PurpleConversation *pc = gc->data; 611 char *str = g_strdup_printf( "kick %s %s", who, message ); 612 purple_conversation_do_command( pc, str, NULL, NULL ); 613 g_free( str ); 614 } 615 616 void purple_chat_leave( struct groupchat *gc ) 609 char *str = g_strdup_printf("kick %s %s", who, message); 610 611 purple_conversation_do_command(pc, str, NULL, NULL); 612 g_free(str); 613 } 614 615 void purple_chat_leave(struct groupchat *gc) 617 616 { 618 617 PurpleConversation *pc = gc->data; 619 620 purple_conversation_destroy( pc ); 621 } 622 623 struct groupchat *purple_chat_join( struct im_connection *ic, const char *room, const char *nick, const char *password, set_t **sets ) 618 619 purple_conversation_destroy(pc); 620 } 621 622 struct groupchat *purple_chat_join(struct im_connection *ic, const char *room, const char *nick, const char *password, 623 set_t **sets) 624 624 { 625 625 PurpleAccount *pa = ic->proto_data; 626 PurplePlugin *prpl = purple_plugins_find_with_id( pa->protocol_id);626 PurplePlugin *prpl = purple_plugins_find_with_id(pa->protocol_id); 627 627 PurplePluginProtocolInfo *pi = prpl->info->extra_info; 628 628 GHashTable *chat_hash; 629 629 PurpleConversation *conv; 630 630 GList *info, *l; 631 632 if( !pi->chat_info || !pi->chat_info_defaults || 633 !( info = pi->chat_info( purple_account_get_connection( pa ) ) ) ) 634 { 635 imcb_error( ic, "Joining chatrooms not supported by this protocol" ); 631 632 if (!pi->chat_info || !pi->chat_info_defaults || 633 !(info = pi->chat_info(purple_account_get_connection(pa)))) { 634 imcb_error(ic, "Joining chatrooms not supported by this protocol"); 636 635 return NULL; 637 636 } 638 639 if ( ( conv = purple_find_conversation_with_account( PURPLE_CONV_TYPE_CHAT, room, pa ) ) )640 purple_conversation_destroy( conv);641 642 chat_hash = pi->chat_info_defaults( purple_account_get_connection( pa ), room ); 643 644 for( l = info; l; l = l->next ) 645 {637 638 if ((conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, room, pa))) { 639 purple_conversation_destroy(conv); 640 } 641 642 chat_hash = pi->chat_info_defaults(purple_account_get_connection(pa), room); 643 644 for (l = info; l; l = l->next) { 646 645 struct proto_chat_entry *pce = l->data; 647 648 if( strcmp( pce->identifier, "handle" ) == 0 ) 649 g_hash_table_replace( chat_hash, "handle", g_strdup( nick ) ); 650 else if( strcmp( pce->identifier, "password" ) == 0 ) 651 g_hash_table_replace( chat_hash, "password", g_strdup( password ) ); 652 else if( strcmp( pce->identifier, "passwd" ) == 0 ) 653 g_hash_table_replace( chat_hash, "passwd", g_strdup( password ) ); 654 } 655 656 serv_join_chat( purple_account_get_connection( pa ), chat_hash ); 657 646 647 if (strcmp(pce->identifier, "handle") == 0) { 648 g_hash_table_replace(chat_hash, "handle", g_strdup(nick)); 649 } else if (strcmp(pce->identifier, "password") == 0) { 650 g_hash_table_replace(chat_hash, "password", g_strdup(password)); 651 } else if (strcmp(pce->identifier, "passwd") == 0) { 652 g_hash_table_replace(chat_hash, "passwd", g_strdup(password)); 653 } 654 } 655 656 serv_join_chat(purple_account_get_connection(pa), chat_hash); 657 658 658 return NULL; 659 659 } 660 660 661 void purple_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *handle);661 void purple_transfer_request(struct im_connection *ic, file_transfer_t *ft, char *handle); 662 662 663 663 static void purple_ui_init(); … … 666 666 { 667 667 static GHashTable *ret; 668 669 if( ret == NULL ) 670 { 668 669 if (ret == NULL) { 671 670 ret = g_hash_table_new(g_str_hash, g_str_equal); 672 g_hash_table_insert( ret, "name", "BitlBee");673 g_hash_table_insert( ret, "version", BITLBEE_VERSION);674 } 675 671 g_hash_table_insert(ret, "name", "BitlBee"); 672 g_hash_table_insert(ret, "version", BITLBEE_VERSION); 673 } 674 676 675 return ret; 677 676 } 678 677 679 static PurpleCoreUiOps bee_core_uiops = 678 static PurpleCoreUiOps bee_core_uiops = 680 679 { 681 680 NULL, … … 686 685 }; 687 686 688 static void prplcb_conn_progress( PurpleConnection *gc, const char *text, size_t step, size_t step_count)689 { 690 struct im_connection *ic = purple_ic_by_gc( gc);691 692 imcb_log( ic, "%s", text);693 } 694 695 static void prplcb_conn_connected( PurpleConnection *gc)696 { 697 struct im_connection *ic = purple_ic_by_gc( gc);687 static void prplcb_conn_progress(PurpleConnection *gc, const char *text, size_t step, size_t step_count) 688 { 689 struct im_connection *ic = purple_ic_by_gc(gc); 690 691 imcb_log(ic, "%s", text); 692 } 693 694 static void prplcb_conn_connected(PurpleConnection *gc) 695 { 696 struct im_connection *ic = purple_ic_by_gc(gc); 698 697 const char *dn; 699 698 set_t *s; 700 701 imcb_connected( ic ); 702 703 if( ( dn = purple_connection_get_display_name( gc ) ) && 704 ( s = set_find( &ic->acc->set, "display_name" ) ) ) 705 { 706 g_free( s->value ); 707 s->value = g_strdup( dn ); 699 700 imcb_connected(ic); 701 702 if ((dn = purple_connection_get_display_name(gc)) && 703 (s = set_find(&ic->acc->set, "display_name"))) { 704 g_free(s->value); 705 s->value = g_strdup(dn); 708 706 } 709 707 710 708 // user list needs to be requested for Gadu-Gadu 711 purple_gg_buddylist_import( gc);712 713 if ( gc->flags & PURPLE_CONNECTION_HTML )709 purple_gg_buddylist_import(gc); 710 711 if (gc->flags & PURPLE_CONNECTION_HTML) { 714 712 ic->flags |= OPT_DOES_HTML; 715 } 716 717 static void prplcb_conn_disconnected( PurpleConnection *gc ) 718 { 719 struct im_connection *ic = purple_ic_by_gc( gc ); 720 721 if( ic != NULL ) 722 { 723 imc_logout( ic, !gc->wants_to_die ); 724 } 725 } 726 727 static void prplcb_conn_notice( PurpleConnection *gc, const char *text ) 728 { 729 struct im_connection *ic = purple_ic_by_gc( gc ); 730 731 if( ic != NULL ) 732 imcb_log( ic, "%s", text ); 733 } 734 735 static void prplcb_conn_report_disconnect_reason( PurpleConnection *gc, PurpleConnectionError reason, const char *text ) 736 { 737 struct im_connection *ic = purple_ic_by_gc( gc ); 738 713 } 714 } 715 716 static void prplcb_conn_disconnected(PurpleConnection *gc) 717 { 718 struct im_connection *ic = purple_ic_by_gc(gc); 719 720 if (ic != NULL) { 721 imc_logout(ic, !gc->wants_to_die); 722 } 723 } 724 725 static void prplcb_conn_notice(PurpleConnection *gc, const char *text) 726 { 727 struct im_connection *ic = purple_ic_by_gc(gc); 728 729 if (ic != NULL) { 730 imcb_log(ic, "%s", text); 731 } 732 } 733 734 static void prplcb_conn_report_disconnect_reason(PurpleConnection *gc, PurpleConnectionError reason, const char *text) 735 { 736 struct im_connection *ic = purple_ic_by_gc(gc); 737 739 738 /* PURPLE_CONNECTION_ERROR_NAME_IN_USE means concurrent login, 740 739 should probably handle that. */ 741 if( ic != NULL ) 742 imcb_error( ic, "%s", text ); 740 if (ic != NULL) { 741 imcb_error(ic, "%s", text); 742 } 743 743 } 744 744 … … 755 755 }; 756 756 757 static void prplcb_blist_update( PurpleBuddyList *list, PurpleBlistNode *node ) 758 { 759 if( node->type == PURPLE_BLIST_BUDDY_NODE ) 760 { 761 PurpleBuddy *bud = (PurpleBuddy*) node; 762 PurpleGroup *group = purple_buddy_get_group( bud ); 763 struct im_connection *ic = purple_ic_by_pa( bud->account ); 757 static void prplcb_blist_update(PurpleBuddyList *list, PurpleBlistNode *node) 758 { 759 if (node->type == PURPLE_BLIST_BUDDY_NODE) { 760 PurpleBuddy *bud = (PurpleBuddy *) node; 761 PurpleGroup *group = purple_buddy_get_group(bud); 762 struct im_connection *ic = purple_ic_by_pa(bud->account); 764 763 PurpleStatus *as; 765 764 int flags = 0; 766 767 if ( ic == NULL )765 766 if (ic == NULL) { 768 767 return; 769 770 if( bud->server_alias ) 771 imcb_rename_buddy( ic, bud->name, bud->server_alias ); 772 else if( bud->alias ) 773 imcb_rename_buddy( ic, bud->name, bud->alias ); 774 775 if( group ) 776 imcb_add_buddy( ic, bud->name, purple_group_get_name( group ) ); 777 778 flags |= purple_presence_is_online( bud->presence ) ? OPT_LOGGED_IN : 0; 779 flags |= purple_presence_is_available( bud->presence ) ? 0 : OPT_AWAY; 780 781 as = purple_presence_get_active_status( bud->presence ); 782 783 imcb_buddy_status( ic, bud->name, flags, purple_status_get_name( as ), 784 purple_status_get_attr_string( as, "message" ) ); 785 786 imcb_buddy_times( ic, bud->name, 787 purple_presence_get_login_time( bud->presence ), 788 purple_presence_get_idle_time( bud->presence ) ); 789 } 790 } 791 792 static void prplcb_blist_new( PurpleBlistNode *node ) 793 { 794 if( node->type == PURPLE_BLIST_BUDDY_NODE ) 795 { 796 PurpleBuddy *bud = (PurpleBuddy*) node; 797 struct im_connection *ic = purple_ic_by_pa( bud->account ); 798 799 if( ic == NULL ) 768 } 769 770 if (bud->server_alias) { 771 imcb_rename_buddy(ic, bud->name, bud->server_alias); 772 } else if (bud->alias) { 773 imcb_rename_buddy(ic, bud->name, bud->alias); 774 } 775 776 if (group) { 777 imcb_add_buddy(ic, bud->name, purple_group_get_name(group)); 778 } 779 780 flags |= purple_presence_is_online(bud->presence) ? OPT_LOGGED_IN : 0; 781 flags |= purple_presence_is_available(bud->presence) ? 0 : OPT_AWAY; 782 783 as = purple_presence_get_active_status(bud->presence); 784 785 imcb_buddy_status(ic, bud->name, flags, purple_status_get_name(as), 786 purple_status_get_attr_string(as, "message")); 787 788 imcb_buddy_times(ic, bud->name, 789 purple_presence_get_login_time(bud->presence), 790 purple_presence_get_idle_time(bud->presence)); 791 } 792 } 793 794 static void prplcb_blist_new(PurpleBlistNode *node) 795 { 796 if (node->type == PURPLE_BLIST_BUDDY_NODE) { 797 PurpleBuddy *bud = (PurpleBuddy *) node; 798 struct im_connection *ic = purple_ic_by_pa(bud->account); 799 800 if (ic == NULL) { 800 801 return; 801 802 imcb_add_buddy( ic, bud->name, NULL ); 803 804 prplcb_blist_update( NULL, node ); 805 } 806 } 807 808 static void prplcb_blist_remove( PurpleBuddyList *list, PurpleBlistNode *node ) 802 } 803 804 imcb_add_buddy(ic, bud->name, NULL); 805 806 prplcb_blist_update(NULL, node); 807 } 808 } 809 810 static void prplcb_blist_remove(PurpleBuddyList *list, PurpleBlistNode *node) 809 811 { 810 812 /* 811 812 813 814 815 816 817 818 819 820 821 813 PurpleBuddy *bud = (PurpleBuddy*) node; 814 815 if( node->type == PURPLE_BLIST_BUDDY_NODE ) 816 { 817 struct im_connection *ic = purple_ic_by_pa( bud->account ); 818 819 if( ic == NULL ) 820 return; 821 822 imcb_remove_buddy( ic, bud->name, NULL ); 823 } 822 824 */ 823 825 } … … 832 834 }; 833 835 834 void prplcb_conv_new( PurpleConversation *conv ) 835 { 836 if( conv->type == PURPLE_CONV_TYPE_CHAT ) 837 { 838 struct im_connection *ic = purple_ic_by_pa( conv->account ); 836 void prplcb_conv_new(PurpleConversation *conv) 837 { 838 if (conv->type == PURPLE_CONV_TYPE_CHAT) { 839 struct im_connection *ic = purple_ic_by_pa(conv->account); 839 840 struct groupchat *gc; 840 841 gc = imcb_chat_new( ic, conv->name ); 842 if( conv->title != NULL ) 843 { 844 imcb_chat_name_hint( gc, conv->title ); 845 imcb_chat_topic( gc, NULL, conv->title, 0 ); 841 842 gc = imcb_chat_new(ic, conv->name); 843 if (conv->title != NULL) { 844 imcb_chat_name_hint(gc, conv->title); 845 imcb_chat_topic(gc, NULL, conv->title, 0); 846 846 } 847 847 848 848 conv->ui_data = gc; 849 849 gc->data = conv; 850 850 851 851 /* libpurple brokenness: Whatever. Show that we join right away, 852 852 there's no clear "This is you!" signaling in _add_users so 853 853 don't even try. */ 854 imcb_chat_add_buddy( gc, gc->ic->acc->user);855 } 856 } 857 858 void prplcb_conv_free( PurpleConversation *conv)854 imcb_chat_add_buddy(gc, gc->ic->acc->user); 855 } 856 } 857 858 void prplcb_conv_free(PurpleConversation *conv) 859 859 { 860 860 struct groupchat *gc = conv->ui_data; 861 862 imcb_chat_free( gc);863 } 864 865 void prplcb_conv_add_users( PurpleConversation *conv, GList *cbuddies, gboolean new_arrivals)861 862 imcb_chat_free(gc); 863 } 864 865 void prplcb_conv_add_users(PurpleConversation *conv, GList *cbuddies, gboolean new_arrivals) 866 866 { 867 867 struct groupchat *gc = conv->ui_data; 868 868 GList *b; 869 870 for( b = cbuddies; b; b = b->next ) 871 { 869 870 for (b = cbuddies; b; b = b->next) { 872 871 PurpleConvChatBuddy *pcb = b->data; 873 874 imcb_chat_add_buddy( gc, pcb->name);875 } 876 } 877 878 void prplcb_conv_del_users( PurpleConversation *conv, GList *cbuddies)872 873 imcb_chat_add_buddy(gc, pcb->name); 874 } 875 } 876 877 void prplcb_conv_del_users(PurpleConversation *conv, GList *cbuddies) 879 878 { 880 879 struct groupchat *gc = conv->ui_data; 881 880 GList *b; 882 883 for( b = cbuddies; b; b = b->next ) 884 imcb_chat_remove_buddy( gc, b->data, "" ); 885 } 886 887 void prplcb_conv_chat_msg( PurpleConversation *conv, const char *who, const char *message, PurpleMessageFlags flags, time_t mtime ) 881 882 for (b = cbuddies; b; b = b->next) { 883 imcb_chat_remove_buddy(gc, b->data, ""); 884 } 885 } 886 887 void prplcb_conv_chat_msg(PurpleConversation *conv, const char *who, const char *message, PurpleMessageFlags flags, 888 time_t mtime) 888 889 { 889 890 struct groupchat *gc = conv->ui_data; 890 891 PurpleBuddy *buddy; 891 892 892 893 /* ..._SEND means it's an outgoing message, no need to echo those. */ 893 if ( flags & PURPLE_MESSAGE_SEND )894 if (flags & PURPLE_MESSAGE_SEND) { 894 895 return; 895 896 buddy = purple_find_buddy( conv->account, who ); 897 if( buddy != NULL ) 898 who = purple_buddy_get_name( buddy ); 899 900 imcb_chat_msg( gc, who, (char*) message, 0, mtime ); 901 } 902 903 static void prplcb_conv_im( PurpleConversation *conv, const char *who, const char *message, PurpleMessageFlags flags, time_t mtime ) 904 { 905 struct im_connection *ic = purple_ic_by_pa( conv->account ); 896 } 897 898 buddy = purple_find_buddy(conv->account, who); 899 if (buddy != NULL) { 900 who = purple_buddy_get_name(buddy); 901 } 902 903 imcb_chat_msg(gc, who, (char *) message, 0, mtime); 904 } 905 906 static void prplcb_conv_im(PurpleConversation *conv, const char *who, const char *message, PurpleMessageFlags flags, 907 time_t mtime) 908 { 909 struct im_connection *ic = purple_ic_by_pa(conv->account); 906 910 PurpleBuddy *buddy; 907 911 908 912 /* ..._SEND means it's an outgoing message, no need to echo those. */ 909 if ( flags & PURPLE_MESSAGE_SEND )913 if (flags & PURPLE_MESSAGE_SEND) { 910 914 return; 911 912 buddy = purple_find_buddy( conv->account, who ); 913 if( buddy != NULL ) 914 who = purple_buddy_get_name( buddy ); 915 916 imcb_buddy_msg( ic, (char*) who, (char*) message, 0, mtime ); 915 } 916 917 buddy = purple_find_buddy(conv->account, who); 918 if (buddy != NULL) { 919 who = purple_buddy_get_name(buddy); 920 } 921 922 imcb_buddy_msg(ic, (char *) who, (char *) message, 0, mtime); 917 923 } 918 924 919 925 /* No, this is not a ui_op but a signal. */ 920 static void prplcb_buddy_typing( PurpleAccount *account, const char *who, gpointer null)926 static void prplcb_buddy_typing(PurpleAccount *account, const char *who, gpointer null) 921 927 { 922 928 PurpleConversation *conv; 923 929 PurpleConvIm *im; 924 930 int state; 925 926 if ( ( conv = purple_find_conversation_with_account( PURPLE_CONV_TYPE_IM, who, account ) ) == NULL )931 932 if ((conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, who, account)) == NULL) { 927 933 return; 928 934 } 935 929 936 im = PURPLE_CONV_IM(conv); 930 switch( purple_conv_im_get_typing_state( im ) ) 931 { 937 switch (purple_conv_im_get_typing_state(im)) { 932 938 case PURPLE_TYPING: 933 939 state = OPT_TYPING; … … 939 945 state = 0; 940 946 } 941 942 imcb_buddy_typing( purple_ic_by_pa( account ), who, state);943 } 944 945 static PurpleConversationUiOps bee_conv_uiops = 947 948 imcb_buddy_typing(purple_ic_by_pa(account), who, state); 949 } 950 951 static PurpleConversationUiOps bee_conv_uiops = 946 952 { 947 953 prplcb_conv_new, /* create_conversation */ … … 962 968 }; 963 969 964 struct prplcb_request_action_data 965 { 970 struct prplcb_request_action_data { 966 971 void *user_data, *bee_data; 967 972 PurpleRequestActionCb yes, no; … … 969 974 }; 970 975 971 static void prplcb_request_action_yes( void *data)976 static void prplcb_request_action_yes(void *data) 972 977 { 973 978 struct prplcb_request_action_data *pqad = data; 974 975 if( pqad->yes ) 976 pqad->yes( pqad->user_data, pqad->yes_i ); 977 g_free( pqad ); 978 } 979 980 static void prplcb_request_action_no( void *data ) 979 980 if (pqad->yes) { 981 pqad->yes(pqad->user_data, pqad->yes_i); 982 } 983 g_free(pqad); 984 } 985 986 static void prplcb_request_action_no(void *data) 981 987 { 982 988 struct prplcb_request_action_data *pqad = data; 983 984 if( pqad->no ) 985 pqad->no( pqad->user_data, pqad->no_i ); 986 g_free( pqad ); 987 } 988 989 static void *prplcb_request_action( const char *title, const char *primary, const char *secondary, 990 int default_action, PurpleAccount *account, const char *who, 991 PurpleConversation *conv, void *user_data, size_t action_count, 992 va_list actions ) 993 { 994 struct prplcb_request_action_data *pqad; 989 990 if (pqad->no) { 991 pqad->no(pqad->user_data, pqad->no_i); 992 } 993 g_free(pqad); 994 } 995 996 static void *prplcb_request_action(const char *title, const char *primary, const char *secondary, 997 int default_action, PurpleAccount *account, const char *who, 998 PurpleConversation *conv, void *user_data, size_t action_count, 999 va_list actions) 1000 { 1001 struct prplcb_request_action_data *pqad; 995 1002 int i; 996 1003 char *q; 997 998 pqad = g_new0( struct prplcb_request_action_data, 1 ); 999 1000 for( i = 0; i < action_count; i ++ ) 1001 { 1004 1005 pqad = g_new0(struct prplcb_request_action_data, 1); 1006 1007 for (i = 0; i < action_count; i++) { 1002 1008 char *caption; 1003 1009 void *fn; 1004 1005 caption = va_arg( actions, char* ); 1006 fn = va_arg( actions, void* ); 1007 1008 if( strstr( caption, "Accept" ) || strstr( caption, "OK" ) ) 1009 { 1010 1011 caption = va_arg(actions, char*); 1012 fn = va_arg(actions, void*); 1013 1014 if (strstr(caption, "Accept") || strstr(caption, "OK")) { 1010 1015 pqad->yes = fn; 1011 1016 pqad->yes_i = i; 1012 } 1013 else if( strstr( caption, "Reject" ) || strstr( caption, "Cancel" ) ) 1014 { 1017 } else if (strstr(caption, "Reject") || strstr(caption, "Cancel")) { 1015 1018 pqad->no = fn; 1016 1019 pqad->no_i = i; 1017 1020 } 1018 1021 } 1019 1022 1020 1023 pqad->user_data = user_data; 1021 1024 1022 1025 /* TODO: IRC stuff here :-( */ 1023 q = g_strdup_printf( "Request: %s\n\n%s\n\n%s", title, primary, secondary);1024 pqad->bee_data = query_add( local_bee->ui_data, purple_ic_by_pa( account), q,1025 prplcb_request_action_yes, prplcb_request_action_no, g_free, pqad);1026 1027 g_free( q);1028 1026 q = g_strdup_printf("Request: %s\n\n%s\n\n%s", title, primary, secondary); 1027 pqad->bee_data = query_add(local_bee->ui_data, purple_ic_by_pa(account), q, 1028 prplcb_request_action_yes, prplcb_request_action_no, g_free, pqad); 1029 1030 g_free(q); 1031 1029 1032 return pqad; 1030 1033 } … … 1033 1036 static void prplcb_request_test() 1034 1037 { 1035 1038 fprintf( stderr, "bla\n" ); 1036 1039 } 1037 1040 */ … … 1048 1051 }; 1049 1052 1050 static void prplcb_privacy_permit_added( PurpleAccount *account, const char *name ) 1051 { 1052 struct im_connection *ic = purple_ic_by_pa( account ); 1053 1054 if( !g_slist_find_custom( ic->permit, name, (GCompareFunc) ic->acc->prpl->handle_cmp ) ) 1055 ic->permit = g_slist_prepend( ic->permit, g_strdup( name ) ); 1056 } 1057 1058 static void prplcb_privacy_permit_removed( PurpleAccount *account, const char *name ) 1059 { 1060 struct im_connection *ic = purple_ic_by_pa( account ); 1053 static void prplcb_privacy_permit_added(PurpleAccount *account, const char *name) 1054 { 1055 struct im_connection *ic = purple_ic_by_pa(account); 1056 1057 if (!g_slist_find_custom(ic->permit, name, (GCompareFunc) ic->acc->prpl->handle_cmp)) { 1058 ic->permit = g_slist_prepend(ic->permit, g_strdup(name)); 1059 } 1060 } 1061 1062 static void prplcb_privacy_permit_removed(PurpleAccount *account, const char *name) 1063 { 1064 struct im_connection *ic = purple_ic_by_pa(account); 1061 1065 void *n; 1062 1063 n = g_slist_find_custom( ic->permit, name, (GCompareFunc) ic->acc->prpl->handle_cmp ); 1064 ic->permit = g_slist_remove( ic->permit, n ); 1065 } 1066 1067 static void prplcb_privacy_deny_added( PurpleAccount *account, const char *name ) 1068 { 1069 struct im_connection *ic = purple_ic_by_pa( account ); 1070 1071 if( !g_slist_find_custom( ic->deny, name, (GCompareFunc) ic->acc->prpl->handle_cmp ) ) 1072 ic->deny = g_slist_prepend( ic->deny, g_strdup( name ) ); 1073 } 1074 1075 static void prplcb_privacy_deny_removed( PurpleAccount *account, const char *name ) 1076 { 1077 struct im_connection *ic = purple_ic_by_pa( account ); 1066 1067 n = g_slist_find_custom(ic->permit, name, (GCompareFunc) ic->acc->prpl->handle_cmp); 1068 ic->permit = g_slist_remove(ic->permit, n); 1069 } 1070 1071 static void prplcb_privacy_deny_added(PurpleAccount *account, const char *name) 1072 { 1073 struct im_connection *ic = purple_ic_by_pa(account); 1074 1075 if (!g_slist_find_custom(ic->deny, name, (GCompareFunc) ic->acc->prpl->handle_cmp)) { 1076 ic->deny = g_slist_prepend(ic->deny, g_strdup(name)); 1077 } 1078 } 1079 1080 static void prplcb_privacy_deny_removed(PurpleAccount *account, const char *name) 1081 { 1082 struct im_connection *ic = purple_ic_by_pa(account); 1078 1083 void *n; 1079 1080 n = g_slist_find_custom( ic->deny, name, (GCompareFunc) ic->acc->prpl->handle_cmp);1081 ic->deny = g_slist_remove( ic->deny, n);1084 1085 n = g_slist_find_custom(ic->deny, name, (GCompareFunc) ic->acc->prpl->handle_cmp); 1086 ic->deny = g_slist_remove(ic->deny, n); 1082 1087 } 1083 1088 … … 1090 1095 }; 1091 1096 1092 static void prplcb_debug_print( PurpleDebugLevel level, const char *category, const char *arg_s)1093 { 1094 fprintf( stderr, "DEBUG %s: %s", category, arg_s);1097 static void prplcb_debug_print(PurpleDebugLevel level, const char *category, const char *arg_s) 1098 { 1099 fprintf(stderr, "DEBUG %s: %s", category, arg_s); 1095 1100 } 1096 1101 … … 1100 1105 }; 1101 1106 1102 static guint prplcb_ev_timeout_add( guint interval, GSourceFunc func, gpointer udata)1103 { 1104 return b_timeout_add( interval, (b_event_handler) func, udata);1105 } 1106 1107 static guint prplcb_ev_input_add( int fd, PurpleInputCondition cond, PurpleInputFunction func, gpointer udata)1108 { 1109 return b_input_add( fd, cond | B_EV_FLAG_FORCE_REPEAT, (b_event_handler) func, udata);1110 } 1111 1112 static gboolean prplcb_ev_remove( guint id)1113 { 1114 b_event_remove( (gint) id);1107 static guint prplcb_ev_timeout_add(guint interval, GSourceFunc func, gpointer udata) 1108 { 1109 return b_timeout_add(interval, (b_event_handler) func, udata); 1110 } 1111 1112 static guint prplcb_ev_input_add(int fd, PurpleInputCondition cond, PurpleInputFunction func, gpointer udata) 1113 { 1114 return b_input_add(fd, cond | B_EV_FLAG_FORCE_REPEAT, (b_event_handler) func, udata); 1115 } 1116 1117 static gboolean prplcb_ev_remove(guint id) 1118 { 1119 b_event_remove((gint) id); 1115 1120 return TRUE; 1116 1121 } 1117 1122 1118 static PurpleEventLoopUiOps glib_eventloops = 1123 static PurpleEventLoopUiOps glib_eventloops = 1119 1124 { 1120 1125 prplcb_ev_timeout_add, … … 1124 1129 }; 1125 1130 1126 static void *prplcb_notify_email( 1127 const char *to, const char *url)1128 { 1129 struct im_connection *ic = purple_ic_by_gc( gc);1130 1131 imcb_log( ic, "Received e-mail from %s for %s: %s <%s>", from, to, subject, url);1132 1131 static void *prplcb_notify_email(PurpleConnection *gc, const char *subject, const char *from, 1132 const char *to, const char *url) 1133 { 1134 struct im_connection *ic = purple_ic_by_gc(gc); 1135 1136 imcb_log(ic, "Received e-mail from %s for %s: %s <%s>", from, to, subject, url); 1137 1133 1138 return NULL; 1134 1139 } 1135 1140 1136 static void *prplcb_notify_userinfo( PurpleConnection *gc, const char *who, PurpleNotifyUserInfo *user_info)1137 { 1138 struct im_connection *ic = purple_ic_by_gc( gc);1139 GString *info = g_string_new( "");1140 GList *l = purple_notify_user_info_get_entries( user_info);1141 static void *prplcb_notify_userinfo(PurpleConnection *gc, const char *who, PurpleNotifyUserInfo *user_info) 1142 { 1143 struct im_connection *ic = purple_ic_by_gc(gc); 1144 GString *info = g_string_new(""); 1145 GList *l = purple_notify_user_info_get_entries(user_info); 1141 1146 char *key; 1142 1147 const char *value; 1143 1148 int n; 1144 1145 while( l ) 1146 { 1149 1150 while (l) { 1147 1151 PurpleNotifyUserInfoEntry *e = l->data; 1148 1149 switch( purple_notify_user_info_entry_get_type( e ) ) 1150 { 1152 1153 switch (purple_notify_user_info_entry_get_type(e)) { 1151 1154 case PURPLE_NOTIFY_USER_INFO_ENTRY_PAIR: 1152 1155 case PURPLE_NOTIFY_USER_INFO_ENTRY_SECTION_HEADER: 1153 key = g_strdup( purple_notify_user_info_entry_get_label( e ) ); 1154 value = purple_notify_user_info_entry_get_value( e ); 1155 1156 if( key ) 1157 { 1158 strip_html( key ); 1159 g_string_append_printf( info, "%s: ", key ); 1160 1161 if( value ) 1162 { 1163 n = strlen( value ) - 1; 1164 while( g_ascii_isspace( value[n] ) ) 1165 n --; 1166 g_string_append_len( info, value, n + 1 ); 1156 key = g_strdup(purple_notify_user_info_entry_get_label(e)); 1157 value = purple_notify_user_info_entry_get_value(e); 1158 1159 if (key) { 1160 strip_html(key); 1161 g_string_append_printf(info, "%s: ", key); 1162 1163 if (value) { 1164 n = strlen(value) - 1; 1165 while (g_ascii_isspace(value[n])) { 1166 n--; 1167 } 1168 g_string_append_len(info, value, n + 1); 1167 1169 } 1168 g_string_append_c( info, '\n');1169 g_free( key);1170 g_string_append_c(info, '\n'); 1171 g_free(key); 1170 1172 } 1171 1173 1172 1174 break; 1173 1175 case PURPLE_NOTIFY_USER_INFO_ENTRY_SECTION_BREAK: 1174 g_string_append( info, "------------------------\n");1175 break; 1176 } 1177 1176 g_string_append(info, "------------------------\n"); 1177 break; 1178 } 1179 1178 1180 l = l->next; 1179 1181 } 1180 1181 imcb_log( ic, "User %s info:\n%s", who, info->str);1182 g_string_free( info, TRUE);1183 1182 1183 imcb_log(ic, "User %s info:\n%s", who, info->str); 1184 g_string_free(info, TRUE); 1185 1184 1186 return NULL; 1185 1187 } … … 1187 1189 static PurpleNotifyUiOps bee_notify_uiops = 1188 1190 { 1189 1190 1191 1192 1193 1194 1195 1191 NULL, 1192 prplcb_notify_email, 1193 NULL, 1194 NULL, 1195 NULL, 1196 NULL, 1197 prplcb_notify_userinfo, 1196 1198 }; 1197 1199 1198 static void *prplcb_account_request_authorize( PurpleAccount *account, const char *remote_user, 1199 const char *id, const char *alias, const char *message, gboolean on_list, 1200 PurpleAccountRequestAuthorizationCb authorize_cb, PurpleAccountRequestAuthorizationCb deny_cb, void *user_data ) 1201 { 1202 struct im_connection *ic = purple_ic_by_pa( account ); 1200 static void *prplcb_account_request_authorize(PurpleAccount *account, const char *remote_user, 1201 const char *id, const char *alias, const char *message, gboolean on_list, 1202 PurpleAccountRequestAuthorizationCb authorize_cb, 1203 PurpleAccountRequestAuthorizationCb deny_cb, void *user_data) 1204 { 1205 struct im_connection *ic = purple_ic_by_pa(account); 1203 1206 char *q; 1204 1205 if( alias ) 1206 q = g_strdup_printf( "%s (%s) wants to add you to his/her contact " 1207 "list. (%s)", alias, remote_user, message ); 1208 else 1209 q = g_strdup_printf( "%s wants to add you to his/her contact " 1210 "list. (%s)", remote_user, message ); 1211 1212 imcb_ask_with_free( ic, q, user_data, authorize_cb, deny_cb, NULL ); 1213 g_free( q ); 1214 1207 1208 if (alias) { 1209 q = g_strdup_printf("%s (%s) wants to add you to his/her contact " 1210 "list. (%s)", alias, remote_user, message); 1211 } else { 1212 q = g_strdup_printf("%s wants to add you to his/her contact " 1213 "list. (%s)", remote_user, message); 1214 } 1215 1216 imcb_ask_with_free(ic, q, user_data, authorize_cb, deny_cb, NULL); 1217 g_free(q); 1218 1215 1219 return NULL; 1216 1220 } … … 1229 1233 static void purple_ui_init() 1230 1234 { 1231 purple_connections_set_ui_ops( &bee_conn_uiops ); 1232 purple_blist_set_ui_ops( &bee_blist_uiops ); 1233 purple_conversations_set_ui_ops( &bee_conv_uiops ); 1234 purple_request_set_ui_ops( &bee_request_uiops ); 1235 purple_privacy_set_ui_ops( &bee_privacy_uiops ); 1236 purple_notify_set_ui_ops( &bee_notify_uiops ); 1237 purple_accounts_set_ui_ops( &bee_account_uiops ); 1238 purple_xfers_set_ui_ops( &bee_xfer_uiops ); 1239 1240 if( getenv( "BITLBEE_DEBUG" ) ) 1241 purple_debug_set_ui_ops( &bee_debug_uiops ); 1235 purple_connections_set_ui_ops(&bee_conn_uiops); 1236 purple_blist_set_ui_ops(&bee_blist_uiops); 1237 purple_conversations_set_ui_ops(&bee_conv_uiops); 1238 purple_request_set_ui_ops(&bee_request_uiops); 1239 purple_privacy_set_ui_ops(&bee_privacy_uiops); 1240 purple_notify_set_ui_ops(&bee_notify_uiops); 1241 purple_accounts_set_ui_ops(&bee_account_uiops); 1242 purple_xfers_set_ui_ops(&bee_xfer_uiops); 1243 1244 if (getenv("BITLBEE_DEBUG")) { 1245 purple_debug_set_ui_ops(&bee_debug_uiops); 1246 } 1242 1247 } 1243 1248 … … 1248 1253 GString *help; 1249 1254 char *dir; 1250 1251 if( B_EV_IO_READ != PURPLE_INPUT_READ || 1252 B_EV_IO_WRITE != PURPLE_INPUT_WRITE ) 1253 { 1255 1256 if (B_EV_IO_READ != PURPLE_INPUT_READ || 1257 B_EV_IO_WRITE != PURPLE_INPUT_WRITE) { 1254 1258 /* FIXME FIXME FIXME FIXME FIXME :-) */ 1255 exit( 1 ); 1256 } 1257 1258 dir = g_strdup_printf( "%s/purple", global.conf->configdir ); 1259 purple_util_set_user_dir( dir ); 1260 g_free( dir ); 1261 1262 purple_debug_set_enabled( FALSE ); 1263 purple_core_set_ui_ops( &bee_core_uiops ); 1264 purple_eventloop_set_ui_ops( &glib_eventloops ); 1265 if( !purple_core_init( "BitlBee") ) 1266 { 1259 exit(1); 1260 } 1261 1262 dir = g_strdup_printf("%s/purple", global.conf->configdir); 1263 purple_util_set_user_dir(dir); 1264 g_free(dir); 1265 1266 purple_debug_set_enabled(FALSE); 1267 purple_core_set_ui_ops(&bee_core_uiops); 1268 purple_eventloop_set_ui_ops(&glib_eventloops); 1269 if (!purple_core_init("BitlBee")) { 1267 1270 /* Initializing the core failed. Terminate. */ 1268 fprintf( stderr, "libpurple initialization failed.\n");1271 fprintf(stderr, "libpurple initialization failed.\n"); 1269 1272 abort(); 1270 1273 } 1271 1272 if( proxytype != PROXY_NONE ) 1273 { 1274 1275 if (proxytype != PROXY_NONE) { 1274 1276 PurpleProxyInfo *pi = purple_global_proxy_get_info(); 1275 switch( proxytype ) 1276 { 1277 switch (proxytype) { 1277 1278 case PROXY_SOCKS4: 1278 purple_proxy_info_set_type( pi, PURPLE_PROXY_SOCKS4);1279 purple_proxy_info_set_type(pi, PURPLE_PROXY_SOCKS4); 1279 1280 break; 1280 1281 case PROXY_SOCKS5: 1281 purple_proxy_info_set_type( pi, PURPLE_PROXY_SOCKS5);1282 purple_proxy_info_set_type(pi, PURPLE_PROXY_SOCKS5); 1282 1283 break; 1283 1284 case PROXY_HTTP: 1284 purple_proxy_info_set_type( pi, PURPLE_PROXY_HTTP);1285 break; 1286 } 1287 purple_proxy_info_set_host( pi, proxyhost);1288 purple_proxy_info_set_port( pi, proxyport);1289 purple_proxy_info_set_username( pi, proxyuser);1290 purple_proxy_info_set_password( pi, proxypass);1291 } 1292 1293 purple_set_blist( purple_blist_new());1294 1285 purple_proxy_info_set_type(pi, PURPLE_PROXY_HTTP); 1286 break; 1287 } 1288 purple_proxy_info_set_host(pi, proxyhost); 1289 purple_proxy_info_set_port(pi, proxyport); 1290 purple_proxy_info_set_username(pi, proxyuser); 1291 purple_proxy_info_set_password(pi, proxypass); 1292 } 1293 1294 purple_set_blist(purple_blist_new()); 1295 1295 1296 /* No, really. So far there were ui_ops for everything, but now suddenly 1296 1297 one needs to use signals for typing notification stuff. :-( */ 1297 purple_signal_connect( 1298 &funcs, PURPLE_CALLBACK(prplcb_buddy_typing), NULL);1299 purple_signal_connect( 1300 &funcs, PURPLE_CALLBACK(prplcb_buddy_typing), NULL);1301 purple_signal_connect( 1302 &funcs, PURPLE_CALLBACK(prplcb_buddy_typing), NULL);1303 1304 memset( &funcs, 0, sizeof( funcs ));1298 purple_signal_connect(purple_conversations_get_handle(), "buddy-typing", 1299 &funcs, PURPLE_CALLBACK(prplcb_buddy_typing), NULL); 1300 purple_signal_connect(purple_conversations_get_handle(), "buddy-typed", 1301 &funcs, PURPLE_CALLBACK(prplcb_buddy_typing), NULL); 1302 purple_signal_connect(purple_conversations_get_handle(), "buddy-typing-stopped", 1303 &funcs, PURPLE_CALLBACK(prplcb_buddy_typing), NULL); 1304 1305 memset(&funcs, 0, sizeof(funcs)); 1305 1306 funcs.login = purple_login; 1306 1307 funcs.init = purple_init; … … 1327 1328 funcs.chat_join = purple_chat_join; 1328 1329 funcs.transfer_request = purple_transfer_request; 1329 1330 help = g_string_new( "BitlBee libpurple module supports the following IM protocols:\n");1331 1330 1331 help = g_string_new("BitlBee libpurple module supports the following IM protocols:\n"); 1332 1332 1333 /* Add a protocol entry to BitlBee's structures for every protocol 1333 supported by this libpurple instance. */ 1334 for( prots = purple_plugins_get_protocols(); prots; prots = prots->next ) 1335 { 1334 supported by this libpurple instance. */ 1335 for (prots = purple_plugins_get_protocols(); prots; prots = prots->next) { 1336 1336 PurplePlugin *prot = prots->data; 1337 1337 struct prpl *ret; 1338 1338 1339 1339 /* If we already have this one (as a native module), don't 1340 1340 add a libpurple duplicate. */ 1341 if ( find_protocol( prot->info->id ) )1341 if (find_protocol(prot->info->id)) { 1342 1342 continue; 1343 1344 ret = g_memdup( &funcs, sizeof( funcs ) ); 1343 } 1344 1345 ret = g_memdup(&funcs, sizeof(funcs)); 1345 1346 ret->name = ret->data = prot->info->id; 1346 if ( strncmp( ret->name, "prpl-", 5 ) == 0 )1347 if (strncmp(ret->name, "prpl-", 5) == 0) { 1347 1348 ret->name += 5; 1348 register_protocol( ret ); 1349 1350 g_string_append_printf( help, "\n* %s (%s)", ret->name, prot->info->name ); 1351 1349 } 1350 register_protocol(ret); 1351 1352 g_string_append_printf(help, "\n* %s (%s)", ret->name, prot->info->name); 1353 1352 1354 /* libpurple doesn't define a protocol called OSCAR, but we 1353 1355 need it to be compatible with normal BitlBee. */ 1354 if( g_strcasecmp( prot->info->id, "prpl-aim" ) == 0 ) 1355 { 1356 ret = g_memdup( &funcs, sizeof( funcs ) ); 1356 if (g_strcasecmp(prot->info->id, "prpl-aim") == 0) { 1357 ret = g_memdup(&funcs, sizeof(funcs)); 1357 1358 ret->name = "oscar"; 1358 1359 ret->data = prot->info->id; 1359 register_protocol( ret);1360 } 1361 } 1362 1363 g_string_append( 1364 1365 "(create an account using that protocol first!)");1366 1360 register_protocol(ret); 1361 } 1362 } 1363 1364 g_string_append(help, "\n\nFor used protocols, more information about available " 1365 "settings can be found using \x02help purple <protocol name>\x02 " 1366 "(create an account using that protocol first!)"); 1367 1367 1368 /* Add a simple dynamically-generated help item listing all 1368 1369 the supported protocols. */ 1369 help_add_mem( &global.help, "purple", help->str);1370 g_string_free( help, TRUE);1371 } 1370 help_add_mem(&global.help, "purple", help->str); 1371 g_string_free(help, TRUE); 1372 }
Note: See TracChangeset
for help on using the changeset viewer.