Beispiel #1
0
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;
	}
}
Beispiel #2
0
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;
}
Beispiel #3
0
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 );
        }
    }
}
Beispiel #4
0
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;
	}
}
Beispiel #5
0
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;
	}
}
Beispiel #6
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 );
    }
}
Beispiel #7
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);
      }
    }
}
Beispiel #8
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
    {
        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 );
    }
}
Beispiel #9
0
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);
}