static void display_text_cb(enum stk_agent_result result, void *user_data) { struct ofono_stk *stk = user_data; gboolean confirm; /* * There are four possible paths for DisplayText with immediate * response flag set: * 1. Agent drops off the bus. In that case regular removal * semantics apply and the agent is removed. * * 2. A new SIM command arrives. In this case the agent is * canceled and a new command is processed. This function is * not called in this case. * * 3. The session is ended by the SIM. This case is ignored, * and will result in either case 1, 2 or 4 occurring. * * 4. Agent reports an error or success. This function is called * with the result. * * NOTE: If the agent reports a TERMINATE result, the agent will * be removed. Since the response has been already sent, there * is no way to signal the end of session to the SIM. Hence * it is assumed that immediate response flagged commands will * only occur at the end of session. */ if (stk->immediate_response) { if (stk->session_agent) session_agent_remove(stk); return; } switch (result) { case STK_AGENT_RESULT_OK: send_simple_response(stk, STK_RESULT_TYPE_SUCCESS); break; case STK_AGENT_RESULT_BACK: send_simple_response(stk, STK_RESULT_TYPE_GO_BACK); break; case STK_AGENT_RESULT_TIMEOUT: confirm = (stk->pending_cmd->qualifier & (1 << 7)) != 0; send_simple_response(stk, confirm ? STK_RESULT_TYPE_NO_RESPONSE : STK_RESULT_TYPE_SUCCESS); break; case STK_AGENT_RESULT_TERMINATE: default: send_simple_response(stk, STK_RESULT_TYPE_USER_TERMINATED); break; } }
static void default_agent_notify(gpointer user_data) { struct ofono_stk *stk = user_data; if (stk->current_agent == stk->default_agent && agent_called(stk)) send_simple_response(stk, STK_RESULT_TYPE_USER_TERMINATED); stk->default_agent = NULL; stk->current_agent = stk->session_agent; }
static void serve_file( struct evhttp_request * req, struct tr_rpc_server * server, const char * filename ) { if( req->type != EVHTTP_REQ_GET ) { evhttp_add_header( req->output_headers, "Allow", "GET" ); send_simple_response( req, 405, NULL ); } else { size_t content_len; uint8_t * content; const int error = errno; errno = 0; content_len = 0; content = tr_loadFile( filename, &content_len ); if( errno ) { send_simple_response( req, HTTP_NOTFOUND, filename ); } else { struct evbuffer * out; errno = error; out = tr_getBuffer( ); evhttp_add_header( req->output_headers, "Content-Type", mimetype_guess( filename ) ); add_response( req, server, out, content, content_len ); evhttp_send_reply( req, HTTP_OK, "OK", out ); tr_releaseBuffer( out ); tr_free( content ); } } }
static void request_selection_cb(enum stk_agent_result result, uint8_t id, void *user_data) { struct ofono_stk *stk = user_data; switch (result) { case STK_AGENT_RESULT_OK: { static struct ofono_error error = { .type = OFONO_ERROR_TYPE_FAILURE }; struct stk_response rsp; memset(&rsp, 0, sizeof(rsp)); rsp.result.type = STK_RESULT_TYPE_SUCCESS; rsp.select_item.item_id = id; if (stk_respond(stk, &rsp, stk_command_cb)) stk_command_cb(&error, stk); break; } case STK_AGENT_RESULT_BACK: send_simple_response(stk, STK_RESULT_TYPE_GO_BACK); break; case STK_AGENT_RESULT_TIMEOUT: send_simple_response(stk, STK_RESULT_TYPE_NO_RESPONSE); break; case STK_AGENT_RESULT_TERMINATE: default: send_simple_response(stk, STK_RESULT_TYPE_USER_TERMINATED); break; } }
static void session_agent_notify(gpointer user_data) { struct ofono_stk *stk = user_data; ofono_debug("Session Agent removed"); if (stk->current_agent == stk->session_agent && agent_called(stk)) { ofono_debug("Sending Terminate response for session agent"); send_simple_response(stk, STK_RESULT_TYPE_USER_TERMINATED); } stk->session_agent = NULL; stk->current_agent = stk->default_agent; if (stk->remove_agent_source) { g_source_remove(stk->remove_agent_source); stk->remove_agent_source = 0; } }
static void handle_clutch( struct evhttp_request * req, struct tr_rpc_server * server ) { const char * clutchDir = tr_getClutchDir( server->session ); assert( !strncmp( req->uri, "/transmission/web/", 18 ) ); if( !clutchDir || !*clutchDir ) { send_simple_response( req, HTTP_NOTFOUND, "<p>Couldn't find Transmission's web interface files!</p>" "<p>Users: to tell Transmission where to look, " "set the TRANSMISSION_WEB_HOME environmental " "variable to the folder where the web interface's " "index.html is located.</p>" "<p>Package Builders: to set a custom default at compile time, " "#define PACKAGE_DATA_DIR in libtransmission/platform.c " "or tweak tr_getClutchDir() by hand.</p>" ); } else { char * pch; char * subpath; char * filename; subpath = tr_strdup( req->uri + 18 ); if(( pch = strchr( subpath, '?' ))) *pch = '\0'; filename = tr_strdup_printf( "%s%s%s", clutchDir, TR_PATH_DELIMITER_STR, subpath && *subpath ? subpath : "index.html" ); serve_file( req, server, filename ); tr_free( filename ); tr_free( subpath ); } }
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 ); } }
void ofono_stk_proactive_command_notify(struct ofono_stk *stk, int length, const unsigned char *pdu) { struct ofono_error error = { .type = OFONO_ERROR_TYPE_FAILURE }; struct stk_response rsp; int err; gboolean respond = TRUE; /* * Depending on the hardware we may have received a new * command before we managed to send a TERMINAL RESPONSE to * the previous one. 3GPP says in the current revision only * one command can be executing at any time, so assume that * the previous one is being cancelled and the card just * expects a response to the new one. */ stk_proactive_command_cancel(stk); stk->pending_cmd = stk_command_new_from_pdu(pdu, length); if (!stk->pending_cmd) { ofono_error("Can't parse proactive command"); /* * Nothing we can do, we'd need at least Command Details * to be able to respond with an error. */ return; } switch (stk->pending_cmd->status) { case STK_PARSE_RESULT_OK: break; case STK_PARSE_RESULT_MISSING_VALUE: send_simple_response(stk, STK_RESULT_TYPE_MINIMUM_NOT_MET); return; case STK_PARSE_RESULT_DATA_NOT_UNDERSTOOD: send_simple_response(stk, STK_RESULT_TYPE_DATA_NOT_UNDERSTOOD); return; case STK_PARSE_RESULT_TYPE_NOT_UNDERSTOOD: default: send_simple_response(stk, STK_RESULT_TYPE_COMMAND_NOT_UNDERSTOOD); return; } /* * In case no agent is registered, we should reject commands destined * to the Agent with a NOT_CAPABLE error. */ if (stk->current_agent == NULL) { switch (stk->pending_cmd->type) { case STK_COMMAND_TYPE_SELECT_ITEM: case STK_COMMAND_TYPE_DISPLAY_TEXT: case STK_COMMAND_TYPE_GET_INKEY: case STK_COMMAND_TYPE_GET_INPUT: case STK_COMMAND_TYPE_PLAY_TONE: send_simple_response(stk, STK_RESULT_TYPE_NOT_CAPABLE); return; default: break; } } memset(&rsp, 0, sizeof(rsp)); switch (stk->pending_cmd->type) { case STK_COMMAND_TYPE_MORE_TIME: respond = handle_command_more_time(stk->pending_cmd, &rsp, stk); break; case STK_COMMAND_TYPE_SEND_SMS: respond = handle_command_send_sms(stk->pending_cmd, &rsp, stk); break; case STK_COMMAND_TYPE_SETUP_IDLE_MODE_TEXT: respond = handle_command_set_idle_text(stk->pending_cmd, &rsp, stk); break; case STK_COMMAND_TYPE_TIMER_MANAGEMENT: respond = handle_command_timer_mgmt(stk->pending_cmd, &rsp, stk); break; case STK_COMMAND_TYPE_POLL_INTERVAL: respond = handle_command_poll_interval(stk->pending_cmd, &rsp, stk); break; case STK_COMMAND_TYPE_SETUP_MENU: respond = handle_command_set_up_menu(stk->pending_cmd, &rsp, stk); break; case STK_COMMAND_TYPE_SELECT_ITEM: respond = handle_command_select_item(stk->pending_cmd, &rsp, stk); break; case STK_COMMAND_TYPE_DISPLAY_TEXT: respond = handle_command_display_text(stk->pending_cmd, &rsp, stk); break; default: rsp.result.type = STK_RESULT_TYPE_COMMAND_NOT_UNDERSTOOD; break; } if (respond == FALSE) return; err = stk_respond(stk, &rsp, stk_command_cb); if (err) stk_command_cb(&error, stk); }