gboolean gtr_dbus_add_torrent( const char * filename ) { /* FIXME: why is this static? */ static gboolean handled = FALSE; #ifdef HAVE_DBUS_GLIB char * payload; gsize file_length; char * file_contents = NULL; /* If it's a file, load its contents and send them over the wire... * it might be a temporary file that's going to disappear. */ if( g_file_get_contents( filename, &file_contents, &file_length, NULL ) ) payload = tr_base64_encode( file_contents, file_length, NULL ); else if( gtr_is_supported_url( filename ) || gtr_is_magnet_link( filename ) ) payload = tr_strdup( filename ); else payload = NULL; if( payload != NULL ) { GError * err = NULL; DBusGConnection * conn; DBusGProxy * proxy = NULL; if(( conn = dbus_g_bus_get( DBUS_BUS_SESSION, &err ))) proxy = dbus_g_proxy_new_for_name (conn, VALUE_SERVICE_NAME, VALUE_SERVICE_OBJECT_PATH, VALUE_SERVICE_INTERFACE ); else if( err ) g_message( "err: %s", err->message ); if( proxy ) dbus_g_proxy_call( proxy, "AddMetainfo", &err, G_TYPE_STRING, payload, G_TYPE_INVALID, G_TYPE_BOOLEAN, &handled, G_TYPE_INVALID ); if( err ) g_message( "err: %s", err->message ); if( proxy ) g_object_unref( proxy ); if( conn ) dbus_g_connection_unref( conn ); tr_free( payload ); } g_free( file_contents ); #endif return handled; }
static int test_base64( void ) { char *in, *out; int len; /* base64 */ out = tr_base64_encode( "YOYO!", -1, &len ); check_streq ("WU9ZTyE=", out); check_int_eq (8, len); in = tr_base64_decode( out, -1, &len ); check_streq ("YOYO!", in); check_int_eq (5, len); tr_free( in ); tr_free( out ); out = tr_base64_encode( NULL, 0, &len ); check( out == NULL ); check_int_eq (0, len); return 0; }
static void handle_upload (struct evhttp_request * req, struct tr_rpc_server * server) { if (req->type != EVHTTP_REQ_POST) { send_simple_response (req, 405, NULL); } else { int i; int n; bool hasSessionId = false; tr_ptrArray parts = TR_PTR_ARRAY_INIT; const char * query = strchr (req->uri, '?'); const bool paused = query && strstr (query + 1, "paused=true"); extract_parts_from_multipart (req->input_headers, req->input_buffer, &parts); n = tr_ptrArraySize (&parts); /* first look for the session id */ for (i=0; i<n; ++i) { struct tr_mimepart * p = tr_ptrArrayNth (&parts, i); if (tr_memmem (p->headers, p->headers_len, TR_RPC_SESSION_ID_HEADER, strlen (TR_RPC_SESSION_ID_HEADER))) break; } if (i<n) { const struct tr_mimepart * p = tr_ptrArrayNth (&parts, i); const char * ours = get_current_session_id (server); const size_t ourlen = strlen (ours); hasSessionId = ourlen <= p->body_len && memcmp (p->body, ours, ourlen) == 0; } if (!hasSessionId) { int code = 409; const char * codetext = tr_webGetResponseStr (code); struct evbuffer * body = evbuffer_new (); evbuffer_add_printf (body, "%s", "{ \"success\": false, \"msg\": \"Bad Session-Id\" }");; evhttp_send_reply (req, code, codetext, body); evbuffer_free (body); } else for (i=0; i<n; ++i) { struct tr_mimepart * p = tr_ptrArrayNth (&parts, i); size_t body_len = p->body_len; tr_variant top, *args; tr_variant test; bool have_source = false; char * body = p->body; if (body_len >= 2 && memcmp (&body[body_len - 2], "\r\n", 2) == 0) body_len -= 2; tr_variantInitDict (&top, 2); tr_variantDictAddStr (&top, TR_KEY_method, "torrent-add"); args = tr_variantDictAddDict (&top, TR_KEY_arguments, 2); tr_variantDictAddBool (args, TR_KEY_paused, paused); if (tr_urlIsValid (body, body_len)) { tr_variantDictAddRaw (args, TR_KEY_filename, body, body_len); have_source = true; } else if (!tr_variantFromBenc (&test, body, body_len)) { char * b64 = tr_base64_encode (body, body_len, NULL); tr_variantDictAddStr (args, TR_KEY_metainfo, b64); tr_free (b64); have_source = true; } if (have_source) tr_rpc_request_exec_json (server->session, &top, NULL, NULL); tr_variantFree (&top); } tr_ptrArrayDestruct (&parts, (PtrArrayForeachFunc)tr_mimepart_free); /* send "success" response */ { int code = HTTP_OK; const char * codetext = tr_webGetResponseStr (code); struct evbuffer * body = evbuffer_new (); evbuffer_add_printf (body, "%s", "{ \"success\": true, \"msg\": \"Torrent Added\" }");; evhttp_send_reply (req, code, codetext, body); evbuffer_free (body); } } }
static void handle_upload( struct evhttp_request * req, struct tr_rpc_server * server ) { if( req->type != EVHTTP_REQ_POST ) { send_simple_response( req, 405, NULL ); } else { const char * content_type = evhttp_find_header( req->input_headers, "Content-Type" ); const char * query = strchr( req->uri, '?' ); const int paused = query && strstr( query + 1, "paused=true" ); const char * in = (const char *) EVBUFFER_DATA( req->input_buffer ); size_t inlen = EVBUFFER_LENGTH( req->input_buffer ); const char * boundary_key = "boundary="; const char * boundary_key_begin = strstr( content_type, boundary_key ); const char * boundary_val = boundary_key_begin ? boundary_key_begin + strlen( boundary_key ) : "arglebargle"; char * boundary = tr_strdup_printf( "--%s", boundary_val ); const size_t boundary_len = strlen( boundary ); const char * delim = tr_memmem( in, inlen, boundary, boundary_len ); while( delim ) { size_t part_len; const char * part = delim + boundary_len; inlen -= ( part - in ); in = part; delim = tr_memmem( in, inlen, boundary, boundary_len ); part_len = delim ? (size_t)( delim - part ) : inlen; if( part_len ) { char * text = tr_strndup( part, part_len ); if( strstr( text, "filename=\"" ) ) { const char * body = strstr( text, "\r\n\r\n" ); if( body ) { char * b64; size_t body_len; tr_benc top, *args; struct evbuffer * json = tr_getBuffer( ); body += 4; /* walk past the \r\n\r\n */ body_len = part_len - ( body - text ); if( body_len >= 2 && !memcmp( &body[body_len - 2], "\r\n", 2 ) ) body_len -= 2; tr_bencInitDict( &top, 2 ); args = tr_bencDictAddDict( &top, "arguments", 2 ); tr_bencDictAddStr( &top, "method", "torrent-add" ); b64 = tr_base64_encode( body, body_len, NULL ); tr_bencDictAddStr( args, "metainfo", b64 ); tr_bencDictAddInt( args, "paused", paused ); tr_bencSaveAsJSON( &top, json ); tr_rpc_request_exec_json( server->session, EVBUFFER_DATA( json ), EVBUFFER_LENGTH( json ), NULL, NULL ); tr_releaseBuffer( json ); tr_free( b64 ); tr_bencFree( &top ); } } tr_free( text ); } } tr_free( boundary ); /* use xml here because json responses to file uploads is trouble. * see http://www.malsup.com/jquery/form/#sample7 for details */ evhttp_add_header( req->output_headers, "Content-Type", "text/xml; charset=UTF-8" ); send_simple_response( req, HTTP_OK, NULL ); } }