Changeset 13934


Ignore:
Timestamp:
Feb 2, 2013, 4:22:21 PM (8 years ago)
Author:
jordan
Message:

(libT) copyediting: indentation/whitespace in rpc-server.c

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/rpc-server.c

    r13868 r13934  
    6060    bool               isWhitelistEnabled;
    6161    tr_port            port;
    62     char *            url;
     62    char             * url;
    6363    struct in_addr     bindAddress;
    64     struct evhttp *    httpd;
    65     tr_session *      session;
    66     char *            username;
    67     char *            password;
    68     char *            whitelistStr;
    69     tr_list *          whitelist;
    70 
    71     char *            sessionId;
     64    struct evhttp    * httpd;
     65    tr_session       * session;
     66    char             * username;
     67    char             * password;
     68    char             * whitelistStr;
     69    tr_list          * whitelist;
     70
     71    char             * sessionId;
    7272    time_t             sessionIdExpiresAt;
    7373
     
    7979
    8080#define dbgmsg(...) \
    81     do { \
    82         if (tr_logGetDeepEnabled ()) \
    83             tr_logAddDeep (__FILE__, __LINE__, MY_NAME, __VA_ARGS__); \
    84     } while (0)
     81  do { \
     82    if (tr_logGetDeepEnabled ()) \
     83      tr_logAddDeep (__FILE__, __LINE__, MY_NAME, __VA_ARGS__); \
     84  } while (0)
    8585
    8686
     
    9292get_current_session_id (struct tr_rpc_server * server)
    9393{
    94     const time_t now = tr_time ();
    95 
    96     if (!server->sessionId || (now >= server->sessionIdExpiresAt))
    97     {
    98         int i;
    99         const int n = 48;
    100         const char * pool = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    101         const size_t pool_size = strlen (pool);
    102         unsigned char * buf = tr_new (unsigned char, n+1);
    103 
    104         tr_cryptoRandBuf (buf, n);
    105         for (i=0; i<n; ++i)
    106             buf[i] = pool[ buf[i] % pool_size ];
    107         buf[n] = '\0';
    108 
    109         tr_free (server->sessionId);
    110         server->sessionId = (char*) buf;
    111         server->sessionIdExpiresAt = now + (60*60); /* expire in an hour */
    112     }
    113 
    114     return server->sessionId;
     94  const time_t now = tr_time ();
     95
     96  if (!server->sessionId || (now >= server->sessionIdExpiresAt))
     97    {
     98      int i;
     99      const int n = 48;
     100      const char * pool = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
     101      const size_t pool_size = strlen (pool);
     102      unsigned char * buf = tr_new (unsigned char, n+1);
     103
     104      tr_cryptoRandBuf (buf, n);
     105      for (i=0; i<n; ++i)
     106        buf[i] = pool[ buf[i] % pool_size ];
     107      buf[n] = '\0';
     108
     109      tr_free (server->sessionId);
     110      server->sessionId = (char*) buf;
     111      server->sessionIdExpiresAt = now + (60*60); /* expire in an hour */
     112    }
     113
     114  return server->sessionId;
    115115}
    116116
     
    123123send_simple_response (struct evhttp_request * req,
    124124                      int                     code,
    125                       const char *            text)
    126 {
    127     const char *      code_text = tr_webGetResponseStr (code);
    128     struct evbuffer * body = evbuffer_new ();
    129 
    130     evbuffer_add_printf (body, "<h1>%d: %s</h1>", code, code_text);
    131     if (text)
    132         evbuffer_add_printf (body, "%s", text);
    133     evhttp_send_reply (req, code, code_text, body);
    134 
    135     evbuffer_free (body);
     125                      const char            * text)
     126{
     127  const char * code_text = tr_webGetResponseStr (code);
     128  struct evbuffer * body = evbuffer_new ();
     129
     130  evbuffer_add_printf (body, "<h1>%d: %s</h1>", code, code_text);
     131  if (text)
     132    evbuffer_add_printf (body, "%s", text);
     133  evhttp_send_reply (req, code, code_text, body);
     134
     135  evbuffer_free (body);
    136136}
    137137
    138138struct tr_mimepart
    139139{
    140     char * headers;
    141     int headers_len;
    142     char * body;
    143     int body_len;
     140  char * headers;
     141  int headers_len;
     142  char * body;
     143  int body_len;
    144144};
    145145
     
    147147tr_mimepart_free (struct tr_mimepart * p)
    148148{
    149     tr_free (p->body);
    150     tr_free (p->headers);
    151     tr_free (p);
    152 }
    153 
    154 static void
    155 extract_parts_from_multipart (const struct evkeyvalq * headers,
    156                               struct evbuffer * body,
    157                               tr_ptrArray * setme_parts)
    158 {
    159     const char * content_type = evhttp_find_header (headers, "Content-Type");
    160     const char * in = (const char*) evbuffer_pullup (body, -1);
    161     size_t inlen = evbuffer_get_length (body);
    162 
    163     const char * boundary_key = "boundary=";
    164     const char * boundary_key_begin = content_type ? strstr (content_type, boundary_key) : NULL;
    165     const char * boundary_val = boundary_key_begin ? boundary_key_begin + strlen (boundary_key) : "arglebargle";
    166     char * boundary = tr_strdup_printf ("--%s", boundary_val);
    167     const size_t boundary_len = strlen (boundary);
    168 
    169     const char * delim = tr_memmem (in, inlen, boundary, boundary_len);
    170     while (delim)
    171     {
    172         size_t part_len;
    173         const char * part = delim + boundary_len;
    174 
    175         inlen -= (part - in);
    176         in = part;
    177 
    178         delim = tr_memmem (in, inlen, boundary, boundary_len);
    179         part_len = delim ? (size_t)(delim - part) : inlen;
    180 
    181         if (part_len)
    182         {
    183             const char * rnrn = tr_memmem (part, part_len, "\r\n\r\n", 4);
    184             if (rnrn)
     149  tr_free (p->body);
     150  tr_free (p->headers);
     151  tr_free (p);
     152}
     153
     154static void
     155extract_parts_from_multipart (const struct evkeyvalq  * headers,
     156                              struct evbuffer         * body,
     157                              tr_ptrArray             * setme_parts)
     158{
     159  const char * content_type = evhttp_find_header (headers, "Content-Type");
     160  const char * in = (const char*) evbuffer_pullup (body, -1);
     161  size_t inlen = evbuffer_get_length (body);
     162
     163  const char * boundary_key = "boundary=";
     164  const char * boundary_key_begin = content_type ? strstr (content_type, boundary_key) : NULL;
     165  const char * boundary_val = boundary_key_begin ? boundary_key_begin + strlen (boundary_key) : "arglebargle";
     166  char * boundary = tr_strdup_printf ("--%s", boundary_val);
     167  const size_t boundary_len = strlen (boundary);
     168
     169  const char * delim = tr_memmem (in, inlen, boundary, boundary_len);
     170  while (delim)
     171    {
     172      size_t part_len;
     173      const char * part = delim + boundary_len;
     174
     175      inlen -= (part - in);
     176      in = part;
     177
     178      delim = tr_memmem (in, inlen, boundary, boundary_len);
     179      part_len = delim ? (size_t)(delim - part) : inlen;
     180
     181      if (part_len)
     182        {
     183          const char * rnrn = tr_memmem (part, part_len, "\r\n\r\n", 4);
     184          if (rnrn)
    185185            {
    186                 struct tr_mimepart * p = tr_new (struct tr_mimepart, 1);
    187                 p->headers_len = rnrn - part;
    188                 p->headers = tr_strndup (part, p->headers_len);
    189                 p->body_len = (part+part_len) - (rnrn + 4);
    190                 p->body = tr_strndup (rnrn+4, p->body_len);
    191                 tr_ptrArrayAppend (setme_parts, p);
     186              struct tr_mimepart * p = tr_new (struct tr_mimepart, 1);
     187              p->headers_len = rnrn - part;
     188              p->headers = tr_strndup (part, p->headers_len);
     189              p->body_len = (part+part_len) - (rnrn + 4);
     190              p->body = tr_strndup (rnrn+4, p->body_len);
     191              tr_ptrArrayAppend (setme_parts, p);
    192192            }
    193193        }
    194194    }
    195195
    196     tr_free (boundary);
     196  tr_free (boundary);
    197197}
    198198
    199199static void
    200200handle_upload (struct evhttp_request * req,
    201                struct tr_rpc_server *  server)
    202 {
    203     if (req->type != EVHTTP_REQ_POST)
    204     {
    205         send_simple_response (req, 405, NULL);
    206     }
    207     else
    208     {
    209         int i;
    210         int n;
    211         bool hasSessionId = false;
    212         tr_ptrArray parts = TR_PTR_ARRAY_INIT;
    213 
    214         const char * query = strchr (req->uri, '?');
    215         const bool paused = query && strstr (query + 1, "paused=true");
    216 
    217         extract_parts_from_multipart (req->input_headers, req->input_buffer, &parts);
    218         n = tr_ptrArraySize (&parts);
    219 
    220         /* first look for the session id */
    221         for (i=0; i<n; ++i) {
    222             struct tr_mimepart * p = tr_ptrArrayNth (&parts, i);
    223             if (tr_memmem (p->headers, p->headers_len, TR_RPC_SESSION_ID_HEADER, strlen (TR_RPC_SESSION_ID_HEADER)))
    224                 break;
    225         }
    226         if (i<n) {
    227             const struct tr_mimepart * p = tr_ptrArrayNth (&parts, i);
    228             const char * ours = get_current_session_id (server);
    229             const int ourlen = strlen (ours);
    230             hasSessionId = ourlen<=p->body_len && !memcmp (p->body, ours, ourlen);
    231         }
    232 
    233         if (!hasSessionId)
    234         {
    235             int code = 409;
    236             const char * codetext = tr_webGetResponseStr (code);
    237             struct evbuffer * body = evbuffer_new ();
    238             evbuffer_add_printf (body, "%s", "{ \"success\": false, \"msg\": \"Bad Session-Id\" }");;
    239             evhttp_send_reply (req, code, codetext, body);
    240             evbuffer_free (body);
    241         }
    242         else for (i=0; i<n; ++i)
    243         {
    244             struct tr_mimepart * p = tr_ptrArrayNth (&parts, i);
    245             int body_len = p->body_len;
    246             tr_variant top, *args;
    247             tr_variant test;
    248             bool have_source = false;
    249             char * body = p->body;
    250 
    251             if (body_len >= 2 && !memcmp (&body[body_len - 2], "\r\n", 2))
    252                 body_len -= 2;
    253 
    254             tr_variantInitDict (&top, 2);
    255             tr_variantDictAddStr (&top, TR_KEY_method, "torrent-add");
    256             args = tr_variantDictAddDict (&top, TR_KEY_arguments, 2);
    257             tr_variantDictAddBool (args, TR_KEY_paused, paused);
    258 
    259             if (tr_urlIsValid (body, body_len))
     201               struct tr_rpc_server  * server)
     202{
     203  if (req->type != EVHTTP_REQ_POST)
     204    {
     205      send_simple_response (req, 405, NULL);
     206    }
     207  else
     208    {
     209      int i;
     210      int n;
     211      bool hasSessionId = false;
     212      tr_ptrArray parts = TR_PTR_ARRAY_INIT;
     213
     214      const char * query = strchr (req->uri, '?');
     215      const bool paused = query && strstr (query + 1, "paused=true");
     216
     217      extract_parts_from_multipart (req->input_headers, req->input_buffer, &parts);
     218      n = tr_ptrArraySize (&parts);
     219
     220      /* first look for the session id */
     221      for (i=0; i<n; ++i)
     222        {
     223          struct tr_mimepart * p = tr_ptrArrayNth (&parts, i);
     224          if (tr_memmem (p->headers, p->headers_len, TR_RPC_SESSION_ID_HEADER, strlen (TR_RPC_SESSION_ID_HEADER)))
     225            break;
     226        }
     227
     228      if (i<n)
     229        {
     230          const struct tr_mimepart * p = tr_ptrArrayNth (&parts, i);
     231          const char * ours = get_current_session_id (server);
     232          const int ourlen = strlen (ours);
     233          hasSessionId = ourlen<=p->body_len && !memcmp (p->body, ours, ourlen);
     234        }
     235
     236      if (!hasSessionId)
     237        {
     238          int code = 409;
     239          const char * codetext = tr_webGetResponseStr (code);
     240          struct evbuffer * body = evbuffer_new ();
     241          evbuffer_add_printf (body, "%s", "{ \"success\": false, \"msg\": \"Bad Session-Id\" }");;
     242          evhttp_send_reply (req, code, codetext, body);
     243          evbuffer_free (body);
     244        }
     245      else for (i=0; i<n; ++i)
     246        {
     247          struct tr_mimepart * p = tr_ptrArrayNth (&parts, i);
     248          int body_len = p->body_len;
     249          tr_variant top, *args;
     250          tr_variant test;
     251          bool have_source = false;
     252          char * body = p->body;
     253
     254          if (body_len >= 2 && !memcmp (&body[body_len - 2], "\r\n", 2))
     255            body_len -= 2;
     256
     257          tr_variantInitDict (&top, 2);
     258          tr_variantDictAddStr (&top, TR_KEY_method, "torrent-add");
     259          args = tr_variantDictAddDict (&top, TR_KEY_arguments, 2);
     260          tr_variantDictAddBool (args, TR_KEY_paused, paused);
     261
     262          if (tr_urlIsValid (body, body_len))
    260263            {
    261                 tr_variantDictAddRaw (args, TR_KEY_filename, body, body_len);
    262                 have_source = true;
     264              tr_variantDictAddRaw (args, TR_KEY_filename, body, body_len);
     265              have_source = true;
    263266            }
    264             else if (!tr_variantFromBenc (&test, body, body_len))
     267          else if (!tr_variantFromBenc (&test, body, body_len))
    265268            {
    266                 char * b64 = tr_base64_encode (body, body_len, NULL);
    267                 tr_variantDictAddStr (args, TR_KEY_metainfo, b64);
    268                 tr_free (b64);
    269                 have_source = true;
     269              char * b64 = tr_base64_encode (body, body_len, NULL);
     270              tr_variantDictAddStr (args, TR_KEY_metainfo, b64);
     271              tr_free (b64);
     272              have_source = true;
    270273            }
    271274
    272             if (have_source)
     275          if (have_source)
    273276            {
    274                 struct evbuffer * json = tr_variantToBuf (&top, TR_VARIANT_FMT_JSON);
    275                 tr_rpc_request_exec_json (server->session,
    276                                           evbuffer_pullup (json, -1),
    277                                           evbuffer_get_length (json),
    278                                           NULL, NULL);
    279                 evbuffer_free (json);
     277              struct evbuffer * json = tr_variantToBuf (&top, TR_VARIANT_FMT_JSON);
     278              tr_rpc_request_exec_json (server->session,
     279                                        evbuffer_pullup (json, -1),
     280                                        evbuffer_get_length (json),
     281                                        NULL, NULL);
     282              evbuffer_free (json);
    280283            }
    281284
    282             tr_variantFree (&top);
    283         }
    284 
    285         tr_ptrArrayDestruct (&parts, (PtrArrayForeachFunc)tr_mimepart_free);
    286 
    287         /* send "success" response */
    288         {
    289             int code = HTTP_OK;
    290             const char * codetext = tr_webGetResponseStr (code);
    291             struct evbuffer * body = evbuffer_new ();
    292             evbuffer_add_printf (body, "%s", "{ \"success\": true, \"msg\": \"Torrent Added\" }");;
    293             evhttp_send_reply (req, code, codetext, body);
    294             evbuffer_free (body);
    295         }
     285          tr_variantFree (&top);
     286        }
     287
     288      tr_ptrArrayDestruct (&parts, (PtrArrayForeachFunc)tr_mimepart_free);
     289
     290      /* send "success" response */
     291      {
     292        int code = HTTP_OK;
     293        const char * codetext = tr_webGetResponseStr (code);
     294        struct evbuffer * body = evbuffer_new ();
     295        evbuffer_add_printf (body, "%s", "{ \"success\": true, \"msg\": \"Torrent Added\" }");;
     296        evhttp_send_reply (req, code, codetext, body);
     297        evbuffer_free (body);
     298      }
    296299    }
    297300}
     
    300303mimetype_guess (const char * path)
    301304{
    302     unsigned int i;
    303 
    304     const struct
    305     {
    306         const char *    suffix;
    307         const char *    mime_type;
    308     } types[] = {
    309         /* these are the ones we need for serving the web client's files... */
    310         { "css",  "text/css"                  },
    311         { "gif",  "image/gif"                 },
    312         { "html", "text/html"                 },
    313         { "ico",  "image/vnd.microsoft.icon"  },
    314         { "js",   "application/javascript"    },
    315         { "png",  "image/png"                 }
    316     };
    317     const char * dot = strrchr (path, '.');
    318 
    319     for (i = 0; dot && i < TR_N_ELEMENTS (types); ++i)
    320         if (!strcmp (dot + 1, types[i].suffix))
    321             return types[i].mime_type;
    322 
    323     return "application/octet-stream";
    324 }
    325 
    326 static void
    327 add_response (struct evhttp_request * req, struct tr_rpc_server * server,
    328               struct evbuffer * out, struct evbuffer * content)
     305  unsigned int i;
     306
     307  const struct {
     308    const char * suffix;
     309    const char * mime_type;
     310  } types[] = {
     311    /* these are the ones we need for serving the web client's files... */
     312    { "css",  "text/css"                  },
     313    { "gif",  "image/gif"                 },
     314    { "html", "text/html"                 },
     315    { "ico",  "image/vnd.microsoft.icon"  },
     316    { "js",   "application/javascript"    },
     317    { "png",  "image/png"                 }
     318  };
     319  const char * dot = strrchr (path, '.');
     320
     321  for (i = 0; dot && i < TR_N_ELEMENTS (types); ++i)
     322    if (!strcmp (dot + 1, types[i].suffix))
     323      return types[i].mime_type;
     324
     325  return "application/octet-stream";
     326}
     327
     328static void
     329add_response (struct evhttp_request * req,
     330              struct tr_rpc_server  * server,
     331              struct evbuffer       * out,
     332              struct evbuffer       * content)
    329333{
    330334#ifndef HAVE_ZLIB
    331     evbuffer_add_buffer (out, content);
     335  evbuffer_add_buffer (out, content);
    332336#else
    333     const char * key = "Accept-Encoding";
    334     const char * encoding = evhttp_find_header (req->input_headers, key);
    335     const int do_compress = encoding && strstr (encoding, "gzip");
    336 
    337     if (!do_compress)
    338     {
    339         evbuffer_add_buffer (out, content);
    340     }
    341     else
    342     {
    343         int state;
    344         struct evbuffer_iovec iovec[1];
    345         void * content_ptr = evbuffer_pullup (content, -1);
    346         const size_t content_len = evbuffer_get_length (content);
    347 
    348         if (!server->isStreamInitialized)
    349         {
    350             int compressionLevel;
    351 
    352             server->isStreamInitialized = true;
    353             server->stream.zalloc = (alloc_func) Z_NULL;
    354             server->stream.zfree = (free_func) Z_NULL;
    355             server->stream.opaque = (voidpf) Z_NULL;
    356 
    357             /* zlib's manual says: "Add 16 to windowBits to write a simple gzip header
    358              * and trailer around the compressed data instead of a zlib wrapper." */
     337  const char * key = "Accept-Encoding";
     338  const char * encoding = evhttp_find_header (req->input_headers, key);
     339  const int do_compress = encoding && strstr (encoding, "gzip");
     340
     341  if (!do_compress)
     342    {
     343      evbuffer_add_buffer (out, content);
     344    }
     345  else
     346    {
     347      int state;
     348      struct evbuffer_iovec iovec[1];
     349      void * content_ptr = evbuffer_pullup (content, -1);
     350      const size_t content_len = evbuffer_get_length (content);
     351
     352      if (!server->isStreamInitialized)
     353        {
     354          int compressionLevel;
     355
     356          server->isStreamInitialized = true;
     357          server->stream.zalloc = (alloc_func) Z_NULL;
     358          server->stream.zfree = (free_func) Z_NULL;
     359          server->stream.opaque = (voidpf) Z_NULL;
     360
     361          /* zlib's manual says: "Add 16 to windowBits to write a simple gzip header
     362           * and trailer around the compressed data instead of a zlib wrapper." */
    359363#ifdef TR_LIGHTWEIGHT
    360             compressionLevel = Z_DEFAULT_COMPRESSION;
     364          compressionLevel = Z_DEFAULT_COMPRESSION;
    361365#else
    362             compressionLevel = Z_BEST_COMPRESSION;
     366          compressionLevel = Z_BEST_COMPRESSION;
    363367#endif
    364             deflateInit2 (&server->stream, compressionLevel, Z_DEFLATED, 15+16, 8, Z_DEFAULT_STRATEGY);
    365         }
    366 
    367         server->stream.next_in = content_ptr;
    368         server->stream.avail_in = content_len;
    369 
    370         /* allocate space for the raw data and call deflate () just once --
    371          * we won't use the deflated data if it's longer than the raw data,
    372          * so it's okay to let deflate () run out of output buffer space */
    373         evbuffer_reserve_space (out, content_len, iovec, 1);
    374         server->stream.next_out = iovec[0].iov_base;
    375         server->stream.avail_out = iovec[0].iov_len;
    376         state = deflate (&server->stream, Z_FINISH);
    377 
    378         if (state == Z_STREAM_END)
    379         {
    380             iovec[0].iov_len -= server->stream.avail_out;
     368          deflateInit2 (&server->stream, compressionLevel, Z_DEFLATED, 15+16, 8, Z_DEFAULT_STRATEGY);
     369        }
     370
     371      server->stream.next_in = content_ptr;
     372      server->stream.avail_in = content_len;
     373
     374      /* allocate space for the raw data and call deflate () just once --
     375       * we won't use the deflated data if it's longer than the raw data,
     376       * so it's okay to let deflate () run out of output buffer space */
     377      evbuffer_reserve_space (out, content_len, iovec, 1);
     378      server->stream.next_out = iovec[0].iov_base;
     379      server->stream.avail_out = iovec[0].iov_len;
     380      state = deflate (&server->stream, Z_FINISH);
     381
     382      if (state == Z_STREAM_END)
     383        {
     384          iovec[0].iov_len -= server->stream.avail_out;
    381385
    382386#if 0
    383             fprintf (stderr, "compressed response is %.2f of original (raw==%zu bytes; compressed==%zu)\n",
    384                            (double)evbuffer_get_length (out)/content_len,
    385                              content_len, evbuffer_get_length (out));
     387          fprintf (stderr, "compressed response is %.2f of original (raw==%zu bytes; compressed==%zu)\n",
     388                   (double)evbuffer_get_length (out)/content_len,
     389                   content_len, evbuffer_get_length (out));
    386390#endif
    387             evhttp_add_header (req->output_headers,
    388                                "Content-Encoding", "gzip");
    389         }
    390         else
    391         {
    392             memcpy (iovec[0].iov_base, content_ptr, content_len);
    393             iovec[0].iov_len = content_len;
    394         }
    395 
    396         evbuffer_commit_space (out, iovec, 1);
    397         deflateReset (&server->stream);
     391          evhttp_add_header (req->output_headers,
     392                             "Content-Encoding", "gzip");
     393        }
     394      else
     395        {
     396          memcpy (iovec[0].iov_base, content_ptr, content_len);
     397          iovec[0].iov_len = content_len;
     398        }
     399
     400      evbuffer_commit_space (out, iovec, 1);
     401      deflateReset (&server->stream);
    398402    }
    399403#endif
     
    401405
    402406static void
    403 add_time_header (struct evkeyvalq * headers, const char * key, time_t value)
    404 {
    405     /* According to RFC 2616 this must follow RFC 1123's date format,
    406        so use gmtime instead of localtime... */
    407     char buf[128];
    408     struct tm tm = *gmtime (&value);
    409     strftime (buf, sizeof (buf), "%a, %d %b %Y %H:%M:%S GMT", &tm);
    410     evhttp_add_header (headers, key, buf);
    411 }
    412 
    413 static void
    414 evbuffer_ref_cleanup_tr_free (const void * data UNUSED, size_t datalen UNUSED, void * extra)
    415 {
    416     tr_free (extra);
    417 }
    418 
    419 static void
    420 serve_file (struct evhttp_request * req,
    421             struct tr_rpc_server *  server,
    422             const char *            filename)
    423 {
    424     if (req->type != EVHTTP_REQ_GET)
    425     {
    426         evhttp_add_header (req->output_headers, "Allow", "GET");
    427         send_simple_response (req, 405, NULL);
    428     }
    429     else
    430     {
    431         void * file;
    432         size_t file_len;
    433         struct evbuffer * content;
    434         const int error = errno;
    435 
    436         errno = 0;
    437         file_len = 0;
    438         file = tr_loadFile (filename, &file_len);
    439         content = evbuffer_new ();
    440         evbuffer_add_reference (content, file, file_len, evbuffer_ref_cleanup_tr_free, file);
    441 
    442         if (errno)
    443         {
    444             char * tmp = tr_strdup_printf ("%s (%s)", filename, tr_strerror (errno));
    445             send_simple_response (req, HTTP_NOTFOUND, tmp);
    446             tr_free (tmp);
    447         }
    448         else
    449         {
    450             struct evbuffer * out;
    451             const time_t now = tr_time ();
    452 
    453             errno = error;
    454             out = evbuffer_new ();
    455             evhttp_add_header (req->output_headers, "Content-Type", mimetype_guess (filename));
    456             add_time_header (req->output_headers, "Date", now);
    457             add_time_header (req->output_headers, "Expires", now+ (24*60*60));
    458             add_response (req, server, out, content);
    459             evhttp_send_reply (req, HTTP_OK, "OK", out);
    460 
    461             evbuffer_free (out);
    462         }
    463 
    464         evbuffer_free (content);
     407add_time_header (struct evkeyvalq  * headers,
     408                 const char        * key,
     409                 time_t              value)
     410{
     411  /* According to RFC 2616 this must follow RFC 1123's date format,
     412     so use gmtime instead of localtime... */
     413  char buf[128];
     414  struct tm tm = *gmtime (&value);
     415  strftime (buf, sizeof (buf), "%a, %d %b %Y %H:%M:%S GMT", &tm);
     416  evhttp_add_header (headers, key, buf);
     417}
     418
     419static void
     420evbuffer_ref_cleanup_tr_free (const void  * data UNUSED,
     421                              size_t        datalen UNUSED,
     422                              void        * extra)
     423{
     424  tr_free (extra);
     425}
     426
     427static void
     428serve_file (struct evhttp_request  * req,
     429            struct tr_rpc_server   * server,
     430            const char             * filename)
     431{
     432  if (req->type != EVHTTP_REQ_GET)
     433    {
     434      evhttp_add_header (req->output_headers, "Allow", "GET");
     435      send_simple_response (req, 405, NULL);
     436    }
     437  else
     438    {
     439      void * file;
     440      size_t file_len;
     441      struct evbuffer * content;
     442      const int error = errno;
     443
     444      errno = 0;
     445      file_len = 0;
     446      file = tr_loadFile (filename, &file_len);
     447      content = evbuffer_new ();
     448      evbuffer_add_reference (content, file, file_len, evbuffer_ref_cleanup_tr_free, file);
     449
     450      if (errno)
     451        {
     452          char * tmp = tr_strdup_printf ("%s (%s)", filename, tr_strerror (errno));
     453          send_simple_response (req, HTTP_NOTFOUND, tmp);
     454          tr_free (tmp);
     455        }
     456      else
     457        {
     458          struct evbuffer * out;
     459          const time_t now = tr_time ();
     460
     461          errno = error;
     462          out = evbuffer_new ();
     463          evhttp_add_header (req->output_headers, "Content-Type", mimetype_guess (filename));
     464          add_time_header (req->output_headers, "Date", now);
     465          add_time_header (req->output_headers, "Expires", now+ (24*60*60));
     466          add_response (req, server, out, content);
     467          evhttp_send_reply (req, HTTP_OK, "OK", out);
     468
     469          evbuffer_free (out);
     470        }
     471
     472      evbuffer_free (content);
    465473    }
    466474}
     
    470478                   struct tr_rpc_server *  server)
    471479{
    472     const char * webClientDir = tr_getWebClientDir (server->session);
    473 
    474     if (!webClientDir || !*webClientDir)
     480  const char * webClientDir = tr_getWebClientDir (server->session);
     481
     482  if (!webClientDir || !*webClientDir)
    475483    {
    476484        send_simple_response (req, HTTP_NOTFOUND,
    477             "<p>Couldn't find Transmission's web interface files!</p>"
    478             "<p>Users: to tell Transmission where to look, "
    479             "set the TRANSMISSION_WEB_HOME environment "
    480             "variable to the folder where the web interface's "
    481             "index.html is located.</p>"
    482             "<p>Package Builders: to set a custom default at compile time, "
    483             "#define PACKAGE_DATA_DIR in libtransmission/platform.c "
    484             "or tweak tr_getClutchDir () by hand.</p>");
    485     }
    486     else
    487     {
    488         char * pch;
    489         char * subpath;
    490 
    491         subpath = tr_strdup (req->uri + strlen (server->url) + 4);
    492         if ((pch = strchr (subpath, '?')))
    493             *pch = '\0';
    494 
    495         if (strstr (subpath, ".."))
    496         {
    497             send_simple_response (req, HTTP_NOTFOUND, "<p>Tsk, tsk.</p>");
    498         }
    499         else
    500         {
    501             char * filename = tr_strdup_printf ("%s%s%s",
    502                                  webClientDir,
    503                                  TR_PATH_DELIMITER_STR,
    504                                  subpath && *subpath ? subpath : "index.html");
    505             serve_file (req, server, filename);
    506             tr_free (filename);
    507         }
    508 
    509         tr_free (subpath);
     485          "<p>Couldn't find Transmission's web interface files!</p>"
     486          "<p>Users: to tell Transmission where to look, "
     487          "set the TRANSMISSION_WEB_HOME environment "
     488          "variable to the folder where the web interface's "
     489          "index.html is located.</p>"
     490          "<p>Package Builders: to set a custom default at compile time, "
     491          "#define PACKAGE_DATA_DIR in libtransmission/platform.c "
     492          "or tweak tr_getClutchDir () by hand.</p>");
     493    }
     494  else
     495    {
     496      char * pch;
     497      char * subpath;
     498
     499      subpath = tr_strdup (req->uri + strlen (server->url) + 4);
     500      if ((pch = strchr (subpath, '?')))
     501        *pch = '\0';
     502
     503      if (strstr (subpath, ".."))
     504        {
     505          send_simple_response (req, HTTP_NOTFOUND, "<p>Tsk, tsk.</p>");
     506        }
     507      else
     508        {
     509          char * filename = tr_strdup_printf ("%s%s%s",
     510                                              webClientDir,
     511                                              TR_PATH_DELIMITER_STR,
     512                                              subpath && *subpath ? subpath : "index.html");
     513          serve_file (req, server, filename);
     514          tr_free (filename);
     515        }
     516
     517      tr_free (subpath);
    510518    }
    511519}
     
    513521struct rpc_response_data
    514522{
    515     struct evhttp_request * req;
    516     struct tr_rpc_server  * server;
     523  struct evhttp_request * req;
     524  struct tr_rpc_server  * server;
    517525};
    518526
     
    522530                   void            * user_data)
    523531{
    524     struct rpc_response_data * data = user_data;
    525     struct evbuffer * buf = evbuffer_new ();
    526 
    527     add_response (data->req, data->server, buf, response);
    528     evhttp_add_header (data->req->output_headers,
    529                            "Content-Type", "application/json; charset=UTF-8");
    530     evhttp_send_reply (data->req, HTTP_OK, "OK", buf);
    531 
    532     evbuffer_free (buf);
    533     tr_free (data);
    534 }
    535 
    536 
    537 static void
    538 handle_rpc (struct evhttp_request * req,
    539             struct tr_rpc_server  * server)
    540 {
    541     struct rpc_response_data * data = tr_new0 (struct rpc_response_data, 1);
    542 
    543     data->req = req;
    544     data->server = server;
    545 
    546     if (req->type == EVHTTP_REQ_GET)
    547     {
    548         const char * q;
    549         if ((q = strchr (req->uri, '?')))
    550             tr_rpc_request_exec_uri (server->session, q+1, -1, rpc_response_func, data);
    551     }
    552     else if (req->type == EVHTTP_REQ_POST)
    553     {
    554         tr_rpc_request_exec_json (server->session,
    555                                   evbuffer_pullup (req->input_buffer, -1),
    556                                   evbuffer_get_length (req->input_buffer),
    557                                   rpc_response_func, data);
     532  struct rpc_response_data * data = user_data;
     533  struct evbuffer * buf = evbuffer_new ();
     534
     535  add_response (data->req, data->server, buf, response);
     536  evhttp_add_header (data->req->output_headers,
     537                     "Content-Type", "application/json; charset=UTF-8");
     538  evhttp_send_reply (data->req, HTTP_OK, "OK", buf);
     539
     540  evbuffer_free (buf);
     541  tr_free (data);
     542}
     543
     544
     545static void
     546handle_rpc (struct evhttp_request * req, struct tr_rpc_server  * server)
     547{
     548  struct rpc_response_data * data = tr_new0 (struct rpc_response_data, 1);
     549
     550  data->req = req;
     551  data->server = server;
     552
     553  if (req->type == EVHTTP_REQ_GET)
     554    {
     555      const char * q;
     556      if ((q = strchr (req->uri, '?')))
     557        tr_rpc_request_exec_uri (server->session, q+1, -1, rpc_response_func, data);
     558    }
     559  else if (req->type == EVHTTP_REQ_POST)
     560    {
     561      tr_rpc_request_exec_json (server->session,
     562                                evbuffer_pullup (req->input_buffer, -1),
     563                                evbuffer_get_length (req->input_buffer),
     564                                rpc_response_func, data);
    558565    }
    559566
     
    561568
    562569static bool
    563 isAddressAllowed (const tr_rpc_server * server,
    564                   const char *          address)
    565 {
    566     tr_list * l;
    567 
    568     if (!server->isWhitelistEnabled)
    569         return true;
    570 
    571     for (l=server->whitelist; l!=NULL; l=l->next)
    572         if (tr_wildmat (address, l->data))
    573             return true;
    574 
    575     return false;
     570isAddressAllowed (const tr_rpc_server * server, const char * address)
     571{
     572  tr_list * l;
     573
     574  if (!server->isWhitelistEnabled)
     575    return true;
     576
     577  for (l=server->whitelist; l!=NULL; l=l->next)
     578    if (tr_wildmat (address, l->data))
     579      return true;
     580
     581  return false;
    576582}
    577583
     
    579585test_session_id (struct tr_rpc_server * server, struct evhttp_request * req)
    580586{
    581     const char * ours = get_current_session_id (server);
    582     const char * theirs = evhttp_find_header (req->input_headers, TR_RPC_SESSION_ID_HEADER);
    583     const bool success =  theirs && !strcmp (theirs, ours);
    584     return success;
     587  const char * ours = get_current_session_id (server);
     588  const char * theirs = evhttp_find_header (req->input_headers, TR_RPC_SESSION_ID_HEADER);
     589  const bool success =  theirs && !strcmp (theirs, ours);
     590  return success;
    585591}
    586592
     
    588594handle_request (struct evhttp_request * req, void * arg)
    589595{
    590     struct tr_rpc_server * server = arg;
    591 
    592     if (req && req->evcon)
    593     {
    594         const char * auth;
    595         char * user = NULL;
    596         char * pass = NULL;
    597 
    598         evhttp_add_header (req->output_headers, "Server", MY_REALM);
    599 
    600         auth = evhttp_find_header (req->input_headers, "Authorization");
    601         if (auth && !evutil_ascii_strncasecmp (auth, "basic ", 6))
    602         {
    603             int    plen;
    604             char * p = tr_base64_decode (auth + 6, 0, &plen);
    605             if (p && plen && ((pass = strchr (p, ':'))))
     596  struct tr_rpc_server * server = arg;
     597
     598  if (req && req->evcon)
     599    {
     600      const char * auth;
     601      char * user = NULL;
     602      char * pass = NULL;
     603
     604      evhttp_add_header (req->output_headers, "Server", MY_REALM);
     605
     606      auth = evhttp_find_header (req->input_headers, "Authorization");
     607      if (auth && !evutil_ascii_strncasecmp (auth, "basic ", 6))
     608        {
     609          int plen;
     610          char * p = tr_base64_decode (auth + 6, 0, &plen);
     611          if (p && plen && ((pass = strchr (p, ':'))))
    606612            {
    607                 user = p;
    608                 *pass++ = '\0';
     613              user = p;
     614              *pass++ = '\0';
    609615            }
    610616        }
    611617
    612         if (!isAddressAllowed (server, req->remote_host))
    613         {
    614             send_simple_response (req, 403,
    615                 "<p>Unauthorized IP Address.</p>"
    616                 "<p>Either disable the IP address whitelist or add your address to it.</p>"
    617                 "<p>If you're editing settings.json, see the 'rpc-whitelist' and 'rpc-whitelist-enabled' entries.</p>"
    618                 "<p>If you're still using ACLs, use a whitelist instead. See the transmission-daemon manpage for details.</p>");
    619         }
    620         else if (server->isPasswordEnabled
     618      if (!isAddressAllowed (server, req->remote_host))
     619        {
     620          send_simple_response (req, 403,
     621            "<p>Unauthorized IP Address.</p>"
     622            "<p>Either disable the IP address whitelist or add your address to it.</p>"
     623            "<p>If you're editing settings.json, see the 'rpc-whitelist' and 'rpc-whitelist-enabled' entries.</p>"
     624            "<p>If you're still using ACLs, use a whitelist instead. See the transmission-daemon manpage for details.</p>");
     625        }
     626      else if (server->isPasswordEnabled
    621627                 && (!pass || !user || strcmp (server->username, user)
    622628                                     || !tr_ssha1_matches (server->password,
    623629                                                           pass)))
    624630        {
    625             evhttp_add_header (req->output_headers,
    626                                "WWW-Authenticate",
    627                                "Basic realm=\"" MY_REALM "\"");
    628             send_simple_response (req, 401, "Unauthorized User");
    629         }
    630         else if (strncmp (req->uri, server->url, strlen (server->url)))
    631         {
    632             char * location = tr_strdup_printf ("%sweb/", server->url);
    633             evhttp_add_header (req->output_headers, "Location", location);
    634             send_simple_response (req, HTTP_MOVEPERM, NULL);
    635             tr_free (location);
    636         }
    637         else if (!strncmp (req->uri + strlen (server->url), "web/", 4))
    638         {
    639             handle_web_client (req, server);
    640         }
    641         else if (!strncmp (req->uri + strlen (server->url), "upload", 6))
    642         {
    643             handle_upload (req, server);
     631          evhttp_add_header (req->output_headers,
     632                             "WWW-Authenticate",
     633                             "Basic realm=\"" MY_REALM "\"");
     634          send_simple_response (req, 401, "Unauthorized User");
     635        }
     636      else if (strncmp (req->uri, server->url, strlen (server->url)))
     637        {
     638          char * location = tr_strdup_printf ("%sweb/", server->url);
     639          evhttp_add_header (req->output_headers, "Location", location);
     640          send_simple_response (req, HTTP_MOVEPERM, NULL);
     641          tr_free (location);
     642        }
     643      else if (!strncmp (req->uri + strlen (server->url), "web/", 4))
     644        {
     645          handle_web_client (req, server);
     646        }
     647      else if (!strncmp (req->uri + strlen (server->url), "upload", 6))
     648        {
     649          handle_upload (req, server);
    644650        }
    645651#ifdef REQUIRE_SESSION_ID
    646         else if (!test_session_id (server, req))
    647         {
    648             const char * sessionId = get_current_session_id (server);
    649             char * tmp = tr_strdup_printf (
    650                 "<p>Your request had an invalid session-id header.</p>"
    651                 "<p>To fix this, follow these steps:"
    652                 "<ol><li> When reading a response, get its X-Transmission-Session-Id header and remember it"
    653                 "<li> Add the updated header to your outgoing requests"
    654                 "<li> When you get this 409 error message, resend your request with the updated header"
    655                 "</ol></p>"
    656                 "<p>This requirement has been added to help prevent "
    657                 "<a href=\"http://en.wikipedia.org/wiki/Cross-site_request_forgery\">CSRF</a> "
    658                 "attacks.</p>"
    659                 "<p><code>%s: %s</code></p>",
    660                 TR_RPC_SESSION_ID_HEADER, sessionId);
    661             evhttp_add_header (req->output_headers, TR_RPC_SESSION_ID_HEADER, sessionId);
    662             send_simple_response (req, 409, tmp);
    663             tr_free (tmp);
     652      else if (!test_session_id (server, req))
     653        {
     654          const char * sessionId = get_current_session_id (server);
     655          char * tmp = tr_strdup_printf (
     656            "<p>Your request had an invalid session-id header.</p>"
     657            "<p>To fix this, follow these steps:"
     658            "<ol><li> When reading a response, get its X-Transmission-Session-Id header and remember it"
     659            "<li> Add the updated header to your outgoing requests"
     660            "<li> When you get this 409 error message, resend your request with the updated header"
     661            "</ol></p>"
     662            "<p>This requirement has been added to help prevent "
     663            "<a href=\"http://en.wikipedia.org/wiki/Cross-site_request_forgery\">CSRF</a> "
     664            "attacks.</p>"
     665            "<p><code>%s: %s</code></p>",
     666            TR_RPC_SESSION_ID_HEADER, sessionId);
     667          evhttp_add_header (req->output_headers, TR_RPC_SESSION_ID_HEADER, sessionId);
     668          send_simple_response (req, 409, tmp);
     669          tr_free (tmp);
    664670        }
    665671#endif
    666         else if (!strncmp (req->uri + strlen (server->url), "rpc", 3))
    667         {
    668             handle_rpc (req, server);
    669         }
    670         else
    671         {
    672             send_simple_response (req, HTTP_NOTFOUND, req->uri);
    673         }
    674 
    675         tr_free (user);
     672      else if (!strncmp (req->uri + strlen (server->url), "rpc", 3))
     673        {
     674          handle_rpc (req, server);
     675        }
     676      else
     677        {
     678          send_simple_response (req, HTTP_NOTFOUND, req->uri);
     679        }
     680
     681      tr_free (user);
    676682    }
    677683}
     
    680686startServer (void * vserver)
    681687{
    682     tr_rpc_server * server  = vserver;
    683     tr_address addr;
    684 
    685     if (!server->httpd)
    686     {
    687         addr.type = TR_AF_INET;
    688         addr.addr.addr4 = server->bindAddress;
    689         server->httpd = evhttp_new (server->session->event_base);
    690         evhttp_bind_socket (server->httpd, tr_address_to_string (&addr), server->port);
    691         evhttp_set_gencb (server->httpd, handle_request, server);
    692 
     688  tr_rpc_server * server  = vserver;
     689  tr_address addr;
     690
     691  if (!server->httpd)
     692    {
     693      addr.type = TR_AF_INET;
     694      addr.addr.addr4 = server->bindAddress;
     695      server->httpd = evhttp_new (server->session->event_base);
     696      evhttp_bind_socket (server->httpd, tr_address_to_string (&addr), server->port);
     697      evhttp_set_gencb (server->httpd, handle_request, server);
    693698    }
    694699}
     
    697702stopServer (tr_rpc_server * server)
    698703{
    699     if (server->httpd)
    700     {
    701         evhttp_free (server->httpd);
    702         server->httpd = NULL;
     704  if (server->httpd)
     705    {
     706      evhttp_free (server->httpd);
     707      server->httpd = NULL;
    703708    }
    704709}
     
    707712onEnabledChanged (void * vserver)
    708713{
    709     tr_rpc_server * server = vserver;
    710 
    711     if (!server->isEnabled)
    712         stopServer (server);
    713     else
    714         startServer (server);
     714  tr_rpc_server * server = vserver;
     715
     716  if (!server->isEnabled)
     717    stopServer (server);
     718  else
     719    startServer (server);
    715720}
    716721
     
    719724                  bool            isEnabled)
    720725{
    721     server->isEnabled = isEnabled;
    722 
    723     tr_runInEventThread (server->session, onEnabledChanged, server);
     726  server->isEnabled = isEnabled;
     727
     728  tr_runInEventThread (server->session, onEnabledChanged, server);
    724729}
    725730
     
    727732tr_rpcIsEnabled (const tr_rpc_server * server)
    728733{
    729     return server->isEnabled;
     734  return server->isEnabled;
    730735}
    731736
     
    733738restartServer (void * vserver)
    734739{
    735     tr_rpc_server * server = vserver;
    736 
    737     if (server->isEnabled)
    738     {
    739         stopServer (server);
    740         startServer (server);
     740  tr_rpc_server * server = vserver;
     741
     742  if (server->isEnabled)
     743    {
     744      stopServer (server);
     745      startServer (server);
    741746    }
    742747}
     
    746751               tr_port         port)
    747752{
    748     assert (server != NULL);
    749 
    750     if (server->port != port)
    751     {
    752         server->port = port;
    753 
    754         if (server->isEnabled)
    755             tr_runInEventThread (server->session, restartServer, server);
     753  assert (server != NULL);
     754
     755  if (server->port != port)
     756    {
     757      server->port = port;
     758
     759      if (server->isEnabled)
     760        tr_runInEventThread (server->session, restartServer, server);
    756761    }
    757762}
     
    760765tr_rpcGetPort (const tr_rpc_server * server)
    761766{
    762     return server->port;
     767  return server->port;
    763768}
    764769
     
    766771tr_rpcSetUrl (tr_rpc_server * server, const char * url)
    767772{
    768     char * tmp = server->url;
    769     server->url = tr_strdup (url);
    770     dbgmsg ("setting our URL to [%s]", server->url);
    771     tr_free (tmp);
     773  char * tmp = server->url;
     774  server->url = tr_strdup (url);
     775  dbgmsg ("setting our URL to [%s]", server->url);
     776  tr_free (tmp);
    772777}
    773778
     
    775780tr_rpcGetUrl (const tr_rpc_server * server)
    776781{
    777     return server->url ? server->url : "";
     782  return server->url ? server->url : "";
    778783}
    779784
     
    781786tr_rpcSetWhitelist (tr_rpc_server * server, const char * whitelistStr)
    782787{
    783     void * tmp;
    784     const char * walk;
    785 
    786     /* keep the string */
    787     tmp = server->whitelistStr;
    788     server->whitelistStr = tr_strdup (whitelistStr);
     788  void * tmp;
     789  const char * walk;
     790
     791  /* keep the string */
     792  tmp = server->whitelistStr;
     793  server->whitelistStr = tr_strdup (whitelistStr);
     794  tr_free (tmp);
     795
     796  /* clear out the old whitelist entries */
     797  while ((tmp = tr_list_pop_front (&server->whitelist)))
    789798    tr_free (tmp);
    790799
    791     /* clear out the old whitelist entries */
    792     while ((tmp = tr_list_pop_front (&server->whitelist)))
    793         tr_free (tmp);
    794 
    795     /* build the new whitelist entries */
    796     for (walk=whitelistStr; walk && *walk;) {
    797         const char * delimiters = " ,;";
    798         const size_t len = strcspn (walk, delimiters);
    799         char * token = tr_strndup (walk, len);
    800         tr_list_append (&server->whitelist, token);
    801         if (strcspn (token, "+-") < len)
    802             tr_logAddNamedInfo (MY_NAME, "Adding address to whitelist: %s (And it has a '+' or '-'!  Are you using an old ACL by mistake?)", token);
    803         else
    804             tr_logAddNamedInfo (MY_NAME, "Adding address to whitelist: %s", token);
    805 
    806         if (walk[len]=='\0')
    807             break;
    808         walk += len + 1;
     800  /* build the new whitelist entries */
     801  for (walk=whitelistStr; walk && *walk;)
     802    {
     803      const char * delimiters = " ,;";
     804      const size_t len = strcspn (walk, delimiters);
     805      char * token = tr_strndup (walk, len);
     806      tr_list_append (&server->whitelist, token);
     807      if (strcspn (token, "+-") < len)
     808        tr_logAddNamedInfo (MY_NAME, "Adding address to whitelist: %s (And it has a '+' or '-'!  Are you using an old ACL by mistake?)", token);
     809      else
     810        tr_logAddNamedInfo (MY_NAME, "Adding address to whitelist: %s", token);
     811
     812      if (walk[len]=='\0')
     813        break;
     814
     815      walk += len + 1;
    809816    }
    810817}
     
    813820tr_rpcGetWhitelist (const tr_rpc_server * server)
    814821{
    815     return server->whitelistStr ? server->whitelistStr : "";
     822  return server->whitelistStr ? server->whitelistStr : "";
    816823}
    817824
     
    820827                           bool             isEnabled)
    821828{
    822     server->isWhitelistEnabled = isEnabled != 0;
     829  server->isWhitelistEnabled = isEnabled != 0;
    823830}
    824831
     
    826833tr_rpcGetWhitelistEnabled (const tr_rpc_server * server)
    827834{
    828     return server->isWhitelistEnabled;
     835  return server->isWhitelistEnabled;
    829836}
    830837
     
    836843tr_rpcSetUsername (tr_rpc_server * server, const char * username)
    837844{
    838     char * tmp = server->username;
    839     server->username = tr_strdup (username);
    840     dbgmsg ("setting our Username to [%s]", server->username);
    841     tr_free (tmp);
     845  char * tmp = server->username;
     846  server->username = tr_strdup (username);
     847  dbgmsg ("setting our Username to [%s]", server->username);
     848  tr_free (tmp);
    842849}
    843850
     
    845852tr_rpcGetUsername (const tr_rpc_server * server)
    846853{
    847     return server->username ? server->username : "";
     854  return server->username ? server->username : "";
    848855}
    849856
     
    852859                   const char *    password)
    853860{
    854     tr_free (server->password);
    855     if (*password != '{')
    856         server->password = tr_ssha1 (password);
    857     else
    858         server->password = strdup (password);
    859     dbgmsg ("setting our Password to [%s]", server->password);
     861  tr_free (server->password);
     862  if (*password != '{')
     863    server->password = tr_ssha1 (password);
     864  else
     865    server->password = strdup (password);
     866  dbgmsg ("setting our Password to [%s]", server->password);
    860867}
    861868
     
    863870tr_rpcGetPassword (const tr_rpc_server * server)
    864871{
    865     return server->password ? server->password : "" ;
     872  return server->password ? server->password : "" ;
    866873}
    867874
     
    869876tr_rpcSetPasswordEnabled (tr_rpc_server * server, bool isEnabled)
    870877{
    871     server->isPasswordEnabled = isEnabled;
    872     dbgmsg ("setting 'password enabled' to %d", (int)isEnabled);
     878  server->isPasswordEnabled = isEnabled;
     879  dbgmsg ("setting 'password enabled' to %d", (int)isEnabled);
    873880}
    874881
     
    876883tr_rpcIsPasswordEnabled (const tr_rpc_server * server)
    877884{
    878     return server->isPasswordEnabled;
     885  return server->isPasswordEnabled;
    879886}
    880887
     
    882889tr_rpcGetBindAddress (const tr_rpc_server * server)
    883890{
    884     tr_address addr;
    885     addr.type = TR_AF_INET;
    886     addr.addr.addr4 = server->bindAddress;
    887     return tr_address_to_string (&addr);
     891  tr_address addr;
     892  addr.type = TR_AF_INET;
     893  addr.addr.addr4 = server->bindAddress;
     894  return tr_address_to_string (&addr);
    888895}
    889896
     
    895902closeServer (void * vserver)
    896903{
    897     void * tmp;
    898     tr_rpc_server * s = vserver;
    899 
    900     stopServer (s);
    901     while ((tmp = tr_list_pop_front (&s->whitelist)))
    902         tr_free (tmp);
     904  void * tmp;
     905  tr_rpc_server * s = vserver;
     906
     907  stopServer (s);
     908  while ((tmp = tr_list_pop_front (&s->whitelist)))
     909    tr_free (tmp);
    903910#ifdef HAVE_ZLIB
    904     if (s->isStreamInitialized)
    905         deflateEnd (&s->stream);
     911  if (s->isStreamInitialized)
     912    deflateEnd (&s->stream);
    906913#endif
    907     tr_free (s->url);
    908     tr_free (s->sessionId);
    909     tr_free (s->whitelistStr);
    910     tr_free (s->username);
    911     tr_free (s->password);
    912     tr_free (s);
     914  tr_free (s->url);
     915  tr_free (s->sessionId);
     916  tr_free (s->whitelistStr);
     917  tr_free (s->username);
     918  tr_free (s->password);
     919  tr_free (s);
    913920}
    914921
     
    916923tr_rpcClose (tr_rpc_server ** ps)
    917924{
    918     tr_runInEventThread ((*ps)->session, closeServer, *ps);
    919     *ps = NULL;
     925  tr_runInEventThread ((*ps)->session, closeServer, *ps);
     926  *ps = NULL;
    920927}
    921928
     
    930937tr_rpcInit (tr_session  * session, tr_variant * settings)
    931938{
    932     tr_rpc_server * s;
    933     bool boolVal;
    934     int64_t i;
    935     const char * str;
    936     tr_quark key;
    937     tr_address address;
    938 
    939     s = tr_new0 (tr_rpc_server, 1);
    940     s->session = session;
    941 
    942     key = TR_KEY_rpc_enabled;
    943     if (!tr_variantDictFindBool (settings, key, &boolVal))
    944         missing_settings_key (key);
    945     else
    946         s->isEnabled = boolVal;
    947 
    948     key = TR_KEY_rpc_port;
    949     if (!tr_variantDictFindInt (settings, key, &i))
    950         missing_settings_key (key);
    951     else
    952         s->port = i;
    953 
    954     key = TR_KEY_rpc_url;
    955     if (!tr_variantDictFindStr (settings, key, &str, NULL))
    956         missing_settings_key (key);
    957     else
    958         s->url = tr_strdup (str);
    959 
    960     key = TR_KEY_rpc_whitelist_enabled;
    961     if (!tr_variantDictFindBool (settings, key, &boolVal))
    962         missing_settings_key (key);
    963     else
    964         tr_rpcSetWhitelistEnabled (s, boolVal);
    965 
    966     key = TR_KEY_rpc_authentication_required;
    967     if (!tr_variantDictFindBool (settings, key, &boolVal))
    968         missing_settings_key (key);
    969     else
    970         tr_rpcSetPasswordEnabled (s, boolVal);
    971 
    972     key = TR_KEY_rpc_whitelist;
    973     if (!tr_variantDictFindStr (settings, key, &str, NULL) && str)
    974         missing_settings_key (key);
    975     else
    976         tr_rpcSetWhitelist (s, str);
    977 
    978     key = TR_KEY_rpc_username;
    979     if (!tr_variantDictFindStr (settings, key, &str, NULL))
    980         missing_settings_key (key);
    981     else
    982         tr_rpcSetUsername (s, str);
    983 
    984     key = TR_KEY_rpc_password;
    985     if (!tr_variantDictFindStr (settings, key, &str, NULL))
    986         missing_settings_key (key);
    987     else
    988         tr_rpcSetPassword (s, str);
    989 
    990     key = TR_KEY_rpc_bind_address;
    991     if (!tr_variantDictFindStr (settings, key, &str, NULL)) {
    992         missing_settings_key (key);
    993         address = tr_inaddr_any;
    994     } else if (!tr_address_from_string (&address, str)) {
    995         tr_logAddNamedError (MY_NAME, _("%s is not a valid address"), str);
    996         address = tr_inaddr_any;
    997     } else if (address.type != TR_AF_INET) {
    998         tr_logAddNamedError (MY_NAME, _("%s is not an IPv4 address. RPC listeners must be IPv4"), str);
    999         address = tr_inaddr_any;
    1000     }
    1001     s->bindAddress = address.addr.addr4;
    1002 
    1003     if (s->isEnabled)
    1004     {
    1005         tr_logAddNamedInfo (MY_NAME, _("Serving RPC and Web requests on port 127.0.0.1:%d%s"), (int) s->port, s->url);
    1006         tr_runInEventThread (session, startServer, s);
    1007 
    1008         if (s->isWhitelistEnabled)
    1009             tr_logAddNamedInfo (MY_NAME, "%s", _("Whitelist enabled"));
    1010 
    1011         if (s->isPasswordEnabled)
    1012             tr_logAddNamedInfo (MY_NAME, "%s", _("Password required"));
    1013     }
    1014 
    1015     return s;
    1016 }
     939  tr_rpc_server * s;
     940  bool boolVal;
     941  int64_t i;
     942  const char * str;
     943  tr_quark key;
     944  tr_address address;
     945
     946  s = tr_new0 (tr_rpc_server, 1);
     947  s->session = session;
     948
     949  key = TR_KEY_rpc_enabled;
     950  if (!tr_variantDictFindBool (settings, key, &boolVal))
     951    missing_settings_key (key);
     952  else
     953    s->isEnabled = boolVal;
     954
     955  key = TR_KEY_rpc_port;
     956  if (!tr_variantDictFindInt (settings, key, &i))
     957    missing_settings_key (key);
     958  else
     959    s->port = i;
     960
     961  key = TR_KEY_rpc_url;
     962  if (!tr_variantDictFindStr (settings, key, &str, NULL))
     963    missing_settings_key (key);
     964  else
     965    s->url = tr_strdup (str);
     966
     967  key = TR_KEY_rpc_whitelist_enabled;
     968  if (!tr_variantDictFindBool (settings, key, &boolVal))
     969    missing_settings_key (key);
     970  else
     971    tr_rpcSetWhitelistEnabled (s, boolVal);
     972
     973  key = TR_KEY_rpc_authentication_required;
     974  if (!tr_variantDictFindBool (settings, key, &boolVal))
     975    missing_settings_key (key);
     976  else
     977    tr_rpcSetPasswordEnabled (s, boolVal);
     978
     979  key = TR_KEY_rpc_whitelist;
     980  if (!tr_variantDictFindStr (settings, key, &str, NULL) && str)
     981    missing_settings_key (key);
     982  else
     983    tr_rpcSetWhitelist (s, str);
     984
     985  key = TR_KEY_rpc_username;
     986  if (!tr_variantDictFindStr (settings, key, &str, NULL))
     987    missing_settings_key (key);
     988  else
     989    tr_rpcSetUsername (s, str);
     990
     991  key = TR_KEY_rpc_password;
     992  if (!tr_variantDictFindStr (settings, key, &str, NULL))
     993    missing_settings_key (key);
     994  else
     995    tr_rpcSetPassword (s, str);
     996
     997  key = TR_KEY_rpc_bind_address;
     998  if (!tr_variantDictFindStr (settings, key, &str, NULL))
     999    {
     1000      missing_settings_key (key);
     1001      address = tr_inaddr_any;
     1002    }
     1003  else if (!tr_address_from_string (&address, str))
     1004    {
     1005      tr_logAddNamedError (MY_NAME, _("%s is not a valid address"), str);
     1006      address = tr_inaddr_any;
     1007    }
     1008  else if (address.type != TR_AF_INET)
     1009    {
     1010      tr_logAddNamedError (MY_NAME, _("%s is not an IPv4 address. RPC listeners must be IPv4"), str);
     1011      address = tr_inaddr_any;
     1012    }
     1013  s->bindAddress = address.addr.addr4;
     1014
     1015  if (s->isEnabled)
     1016    {
     1017      tr_logAddNamedInfo (MY_NAME, _("Serving RPC and Web requests on port 127.0.0.1:%d%s"), (int) s->port, s->url);
     1018      tr_runInEventThread (session, startServer, s);
     1019
     1020      if (s->isWhitelistEnabled)
     1021        tr_logAddNamedInfo (MY_NAME, "%s", _("Whitelist enabled"));
     1022
     1023      if (s->isPasswordEnabled)
     1024        tr_logAddNamedInfo (MY_NAME, "%s", _("Password required"));
     1025    }
     1026
     1027  return s;
     1028}
Note: See TracChangeset for help on using the changeset viewer.