Changeset 6804
- Timestamp:
- Sep 26, 2008, 3:40:24 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/libtransmission/rpc-server.c
r6801 r6804 38 38 struct tr_rpc_server 39 39 { 40 unsigned int 41 unsigned int 42 uint16_t 43 struct evhttp * 44 tr_handle * 45 char * 46 char * 47 char * 40 unsigned int isEnabled : 1; 41 unsigned int isPasswordEnabled : 1; 42 uint16_t port; 43 struct evhttp * httpd; 44 tr_handle * session; 45 char * username; 46 char * password; 47 char * acl; 48 48 }; 49 49 50 50 #define dbgmsg( fmt... ) tr_deepLog( __FILE__, __LINE__, MY_NAME, ## fmt ) 51 52 /** 53 *** 54 **/ 55 56 static void 57 send_simple_response( struct evhttp_request * req, 58 int code, 59 const char * text ) 60 { 61 const char * code_text = tr_webGetResponseStr( code ); 62 struct evbuffer * body = evbuffer_new( ); 63 64 evbuffer_add_printf( body, "<h1>%s</h1>", code_text ); 65 if( text ) 66 evbuffer_add_printf( body, "<h2>%s</h2>", text ); 67 evhttp_send_reply( req, code, code_text, body ); 68 evbuffer_free( body ); 69 } 51 70 52 71 static const char* … … 68 87 } 69 88 70 71 /**** 72 ***** ACL UTILITIES 73 ****/ 74 75 static int 76 isAddressAllowed( const tr_rpc_server * server, 77 const char * address ) 78 { 79 const char * acl; 80 81 for( acl=server->acl; acl && *acl; ) 82 { 83 const char * delimiter = strchr( acl, ',' ); 84 const int len = delimiter ? delimiter-acl : (int)strlen( acl ); 85 char * token = tr_strndup( acl, len ); 86 const int match = tr_wildmat( address, token+1 ); 87 tr_free( token ); 88 if( match ) 89 return *acl == '+'; 90 if( !delimiter ) 91 break; 92 acl = delimiter + 1; 93 } 94 95 return 0; 96 } 97 98 /** 99 *** 100 **/ 101 102 static void 103 send_simple_response( struct evhttp_request * req, int code, const char * text ) 104 { 105 const char * code_text = tr_webGetResponseStr( code ); 106 struct evbuffer * body = evbuffer_new( ); 107 evbuffer_add_printf( body, "<h1>%s</h1>", code_text ); 108 if( text ) 109 evbuffer_add_printf( body, "<h2>%s</h2>", text ); 110 evhttp_send_reply( req, code, code_text, body ); 111 evbuffer_free( body ); 112 } 113 114 static void 115 handle_upload( struct evhttp_request * req, struct tr_rpc_server * server ) 89 static void 90 handle_upload( struct evhttp_request * req, 91 struct tr_rpc_server * server ) 116 92 { 117 93 if( req->type != EVHTTP_REQ_POST ) … … 121 97 else 122 98 { 123 124 const char * content_type = evhttp_find_header( req->input_headers,"Content-Type" );99 const char * content_type = evhttp_find_header( req->input_headers, 100 "Content-Type" ); 125 101 126 102 const char * query = strchr( req->uri, '?' ); 127 const int paused = query && strstr( query+1, "paused=true" );103 const int paused = query && strstr( query + 1, "paused=true" ); 128 104 129 105 const char * in = (const char *) EVBUFFER_DATA( req->input_buffer ); 130 size_t inlen = EVBUFFER_LENGTH( req->input_buffer );106 size_t inlen = EVBUFFER_LENGTH( req->input_buffer ); 131 107 132 108 const char * boundary_key = "boundary="; 133 const char * boundary_key_begin = strstr( content_type, boundary_key ); 134 const char * boundary_val = boundary_key_begin ? boundary_key_begin + strlen( boundary_key ) : "arglebargle"; 135 136 char * boundary = tr_strdup_printf( "--%s", boundary_val ); 109 const char * boundary_key_begin = strstr( content_type, 110 boundary_key ); 111 const char * boundary_val = 112 boundary_key_begin ? boundary_key_begin + 113 strlen( boundary_key ) : "arglebargle"; 114 115 char * boundary = tr_strdup_printf( "--%s", boundary_val ); 137 116 const size_t boundary_len = strlen( boundary ); 138 117 … … 163 142 body_len = part_len - ( body - text ); 164 143 if( body_len >= 2 165 166 144 && !memcmp( &body[body_len - 2], "\r\n", 2 ) ) 145 body_len -= 2; 167 146 168 147 tr_bencInitDict( &top, 2 ); … … 190 169 191 170 /* use xml here because json responses to file uploads is trouble. 192 * see http://www.malsup.com/jquery/form/#sample7 for details */ 193 evhttp_add_header(req->output_headers, "Content-Type", "text/xml; charset=UTF-8" ); 171 * see http://www.malsup.com/jquery/form/#sample7 for details */ 172 evhttp_add_header( req->output_headers, "Content-Type", 173 "text/xml; charset=UTF-8" ); 194 174 send_simple_response( req, HTTP_OK, NULL ); 195 175 } … … 200 180 { 201 181 unsigned int i; 202 const struct { 203 const char * suffix; 204 const char * mime_type; 182 183 const struct 184 { 185 const char * suffix; 186 const char * mime_type; 205 187 } types[] = { 206 188 /* these are just the ones we need for serving clutch... */ 207 { "css", "text/css"},208 { "gif", "image/gif"},209 { "html", "text/html" },210 { "ico", "image/vnd.microsoft.icon"},211 { "js", "application/javascript"},212 { "png", "image/png"}189 { "css", "text/css" }, 190 { "gif", "image/gif" }, 191 { "html", "text/html" }, 192 { "ico", "image/vnd.microsoft.icon" }, 193 { "js", "application/javascript" }, 194 { "png", "image/png" } 213 195 }; 214 196 const char * dot = strrchr( path, '.' ); 215 197 216 for( i =0; dot && i<TR_N_ELEMENTS(types); ++i )217 if( !strcmp( dot +1, types[i].suffix ) )198 for( i = 0; dot && i < TR_N_ELEMENTS( types ); ++i ) 199 if( !strcmp( dot + 1, types[i].suffix ) ) 218 200 return types[i].mime_type; 219 201 … … 222 204 223 205 static void 224 serve_file( struct evhttp_request * req, const char * path ) 206 serve_file( struct evhttp_request * req, 207 const char * path ) 225 208 { 226 209 if( req->type != EVHTTP_REQ_GET ) 227 210 { 228 evhttp_add_header( req->output_headers, "Allow", "GET");211 evhttp_add_header( req->output_headers, "Allow", "GET" ); 229 212 send_simple_response( req, 405, NULL ); 230 213 } … … 239 222 { 240 223 struct evbuffer * buf = evbuffer_new( ); 241 evbuffer_read(buf, fd, INT_MAX ); 242 evhttp_add_header(req->output_headers, "Content-Type", mimetype_guess( path ) ); 224 evbuffer_read( buf, fd, INT_MAX ); 225 evhttp_add_header( req->output_headers, "Content-Type", 226 mimetype_guess( 227 path ) ); 243 228 evhttp_send_reply( req, HTTP_OK, "OK", buf ); 244 evbuffer_free( buf);229 evbuffer_free( buf ); 245 230 close( fd ); 246 231 } … … 249 234 250 235 static void 251 handle_clutch( struct evhttp_request * req, struct tr_rpc_server * server ) 252 { 253 const char * uri; 236 handle_clutch( struct evhttp_request * req, 237 struct tr_rpc_server * server ) 238 { 239 const char * uri; 254 240 struct evbuffer * buf = evbuffer_new( ); 255 241 256 242 assert( !strncmp( req->uri, "/transmission/web/", 18 ) ); 257 243 258 evbuffer_add_printf( buf, "%s%s", tr_getClutchDir( server->session ), TR_PATH_DELIMITER_STR ); 244 evbuffer_add_printf( buf, "%s%s", tr_getClutchDir( 245 server->session ), TR_PATH_DELIMITER_STR ); 259 246 uri = req->uri + 18; 260 if( ( *uri=='?') || (*uri=='\0') )247 if( ( *uri == '?' ) || ( *uri == '\0' ) ) 261 248 evbuffer_add_printf( buf, "index.html" ); 262 else { 249 else 250 { 263 251 const char * pch = strchr( uri, '?' ); 264 252 if( pch ) 265 evbuffer_add_printf( buf, "%*.*s", (int)(pch-uri), (int)(pch-uri), uri ); 253 evbuffer_add_printf( buf, "%*.*s", (int)( pch - uri ), 254 (int)( pch - uri ), uri ); 266 255 else 267 256 evbuffer_add_printf( buf, "%s", uri ); 268 257 } 269 258 270 259 if( strstr( (const char *)EVBUFFER_DATA( buf ), ".." ) ) 271 260 send_simple_response( req, 401, NULL ); … … 277 266 278 267 static void 279 handle_rpc( struct evhttp_request * req, struct tr_rpc_server * server ) 280 { 281 int len = 0; 282 char * response; 268 handle_rpc( struct evhttp_request * req, 269 struct tr_rpc_server * server ) 270 { 271 int len = 0; 272 char * response = NULL; 283 273 struct evbuffer * buf; 284 274 … … 286 276 { 287 277 const char * q; 288 if( ( q = strchr( req->uri, '?' )))278 if( ( q = strchr( req->uri, '?' ) ) ) 289 279 response = tr_rpc_request_exec_uri( server->session, 290 280 q + 1, … … 295 285 { 296 286 response = tr_rpc_request_exec_json( server->session, 297 EVBUFFER_DATA( req->input_buffer ), 298 EVBUFFER_LENGTH( req->input_buffer ), 287 EVBUFFER_DATA( req-> 288 input_buffer ), 289 EVBUFFER_LENGTH( req-> 290 input_buffer ), 299 291 &len ); 300 292 } … … 302 294 buf = evbuffer_new( ); 303 295 evbuffer_add( buf, response, len ); 304 evhttp_add_header( req->output_headers, "Content-Type", "application/json; charset=UTF-8" ); 296 evhttp_add_header( req->output_headers, "Content-Type", 297 "application/json; charset=UTF-8" ); 305 298 evhttp_send_reply( req, HTTP_OK, "OK", buf ); 306 299 evbuffer_free( buf ); 307 300 } 308 301 309 static void 310 handle_request( struct evhttp_request * req, void * arg ) 302 static int 303 isAddressAllowed( const tr_rpc_server * server, 304 const char * address ) 305 { 306 const char * acl; 307 308 for( acl = server->acl; acl && *acl; ) 309 { 310 const char * delimiter = strchr( acl, ',' ); 311 const int len = delimiter ? delimiter - acl : (int)strlen( acl ); 312 char * token = tr_strndup( acl, len ); 313 const int match = tr_wildmat( address, token + 1 ); 314 tr_free( token ); 315 if( match ) 316 return *acl == '+'; 317 if( !delimiter ) 318 break; 319 acl = delimiter + 1; 320 } 321 322 return 0; 323 } 324 325 static void 326 handle_request( struct evhttp_request * req, 327 void * arg ) 311 328 { 312 329 struct tr_rpc_server * server = arg; 313 330 314 if (req && req->evcon )331 if( req && req->evcon ) 315 332 { 316 333 const char * auth; 317 char * user = NULL;318 char * pass = NULL;334 char * user = NULL; 335 char * pass = NULL; 319 336 320 337 evhttp_add_header( req->output_headers, "Server", MY_REALM ); 321 338 322 339 auth = evhttp_find_header( req->input_headers, "Authorization" ); 323 340 324 341 if( auth && !strncasecmp( auth, "basic ", 6 ) ) 325 342 { 326 int plen;343 int plen; 327 344 char * p = tr_base64_decode( auth + 6, 0, &plen ); 328 if( p && plen && (( pass = strchr( p, ':' )))) { 345 if( p && plen && ( ( pass = strchr( p, ':' ) ) ) ) 346 { 329 347 user = p; 330 348 *pass++ = '\0'; … … 336 354 send_simple_response( req, 401, "Unauthorized IP Address" ); 337 355 } 338 else if( server->isPasswordEnabled && ( !pass 339 || !user 340 || strcmp( server->username, user ) 341 || strcmp( server->password, pass ) ) ) 356 else if( server->isPasswordEnabled && ( !pass 357 || !user 358 || strcmp( server->username, 359 user ) 360 || strcmp( server->password, 361 pass ) ) ) 342 362 { 343 363 evhttp_add_header( req->output_headers, 344 "WWW-Authenticate", "Basic realm=\"" MY_REALM "\"" ); 364 "WWW-Authenticate", 365 "Basic realm=\"" MY_REALM "\"" ); 345 366 send_simple_response( req, 401, "Unauthorized User" ); 346 367 } 347 else if( !strcmp( req->uri, "/transmission/web" ) || 348 !strcmp( req->uri, "/transmission/clutch" ) || 349 !strcmp( req->uri, "/" ) ) 350 { 351 evhttp_add_header( req->output_headers, "Location", "/transmission/web/" ); 368 else if( !strcmp( req->uri, "/transmission/web" ) 369 || !strcmp( req->uri, "/transmission/clutch" ) 370 || !strcmp( req->uri, "/" ) ) 371 { 372 evhttp_add_header( req->output_headers, "Location", 373 "/transmission/web/" ); 352 374 send_simple_response( req, HTTP_MOVEPERM, NULL ); 353 375 } … … 537 559 return s; 538 560 } 561
Note: See TracChangeset
for help on using the changeset viewer.