コード例 #1
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);
      }
    }
}
コード例 #2
0
ファイル: rpc-server.c プロジェクト: liesen/transmission-horn
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 );
    }
}