📄 wap-appl.c.backup
字号:
static Octstr *get_referer_url(const WSPMachine *sm){ return sm ? sm->referer_url : NULL;}/* * Return the reply from an HTTP request to the phone via a WSP session. */static void return_session_reply(long server_transaction_id, long status, List *headers, Octstr *body, long session_id){ WAPEvent *e; e = wap_event_create(S_MethodResult_Req); e->u.S_MethodResult_Req.server_transaction_id = server_transaction_id; e->u.S_MethodResult_Req.status = status; e->u.S_MethodResult_Req.response_headers = headers; e->u.S_MethodResult_Req.response_body = body; e->u.S_MethodResult_Req.session_id = session_id; wsp_session_dispatch_event(e);}/* * Return the reply from an HTTP request to the phone via connectionless * WSP. */static void return_unit_reply(WAPAddrTuple *tuple, long transaction_id, long status, List *headers, Octstr *body){ WAPEvent *e; e = wap_event_create(S_Unit_MethodResult_Req); e->u.S_Unit_MethodResult_Req.addr_tuple = wap_addr_tuple_duplicate(tuple); e->u.S_Unit_MethodResult_Req.transaction_id = transaction_id; e->u.S_Unit_MethodResult_Req.status = status; e->u.S_Unit_MethodResult_Req.response_headers = headers; e->u.S_Unit_MethodResult_Req.response_body = body; wsp_unit_dispatch_event(e);}/* * Return an HTTP reply back to the phone. */static void return_reply(int status, Octstr *content_body, List *headers, long sdu_size, WAPEvent *orig_event, long session_id, Octstr *url, int x_wap_tod, List *request_headers){ struct content content; int converted; WSPMachine *sm; content.url = url; content.body = content_body; if (status < 0) { error(0, "WSP: http lookup failed, oops."); content.charset = octstr_create(""); /* smart WSP error messaging?! */ if (wsp_smart_errors) { Octstr *referer_url; status = HTTP_OK; content.type = octstr_create("text/vnd.wap.wml"); /* * check if a referer for this URL exists and * get back to the previous page in this case */ if ((referer_url = get_referer_url(find_session_machine_by_id(session_id)))) { content.body = error_requesting_back(url, referer_url); debug("wap.wsp",0,"WSP: returning smart error WML deck for referer URL"); } /* * if there is no referer to retun to, check if we have a * device-home defined and return to that, otherwise simply * drop an error wml deck. */ else if (device_home != NULL) { content.body = error_requesting_back(url, device_home); debug("wap.wsp",0,"WSP: returning smart error WML deck for device-home URL"); } else { content.body = error_requesting(url); debug("wap.wsp",0,"WSP: returning smart error WML deck"); } /* * if we did not connect at all there is no content in * the headers list, so create for the upcoming transformation */ if (headers == NULL) headers = http_create_empty_headers(); converted = convert_content(&content); if (converted == 1) http_header_mark_transformation(headers, content.body, content.type); } else { status = HTTP_BAD_GATEWAY; content.type = octstr_create("text/plain"); content.charset = octstr_create(""); content.body = octstr_create(""); } } else { http_header_get_content_type(headers, &content.type, &content.charset); alog("<%s> (%s, charset='%s') %d", octstr_get_cstr(url), octstr_get_cstr(content.type), octstr_get_cstr(content.charset), status);#ifdef ENABLE_COOKIES if (session_id != -1) if (get_cookies(headers, find_session_machine_by_id(session_id)) == -1) error(0, "WSP: Failed to extract cookies");#endif converted = convert_content(&content); if (converted < 0) { warning(0, "WSP: All converters for `%s' failed.", octstr_get_cstr(content.type)); /* Don't change status; just send the client what we did get. */ } if (converted == 1) { http_header_mark_transformation(headers, content.body, content.type); /* * set referer URL to WSPMachine, but only if this was a converted * content-type, like .wml */ if (session_id != -1) { debug("wap.wsp.http",0,"WSP: Setting Referer URL to <%s>", octstr_get_cstr(url)); if ((sm = find_session_machine_by_id(session_id)) != NULL) { set_referer_url(url, sm); } else { error(0,"WSP: Failed to find session machine for ID %ld", session_id); } } } } if (headers == NULL) headers = http_create_empty_headers(); http_remove_hop_headers(headers); http_header_remove_all(headers, "X-WAP.TOD"); if (x_wap_tod) add_x_wap_tod(headers); if (content.body == NULL) content.body = octstr_create(""); /* * Deal with otherwise wap-aware servers that return text/html error * messages if they report an error. * (Normally we leave the content type alone even if the client doesn't * claim to accept it, because the server might know better than the * gateway.) */ if (http_status_class(status) != HTTP_STATUS_SUCCESSFUL && !http_type_accepted(request_headers, octstr_get_cstr(content.type))) { warning(0, "WSP: Content type <%s> not supported by client," " deleting body.", octstr_get_cstr(content.type)); octstr_destroy(content.body); content.body = octstr_create(""); octstr_destroy(content.type); content.type = octstr_create("text/plain"); http_header_mark_transformation(headers, content.body, content.type); } /* * If the response is too large to be sent to the client, * suppress it and inform the client. */ if (octstr_len(content.body) > sdu_size && sdu_size > 0) { /* * Only change the status if it indicated success. * If it indicated an error, then that information is * more useful to the client than our "Bad Gateway" would be. * The too-large body is probably an error page in html. */ if (http_status_class(status) == HTTP_STATUS_SUCCESSFUL) status = HTTP_BAD_GATEWAY; warning(0, "WSP: Entity at %s too large (size %ld B, limit %lu B)", octstr_get_cstr(url), octstr_len(content.body), sdu_size); octstr_destroy(content.body); content.body = octstr_create(""); http_header_mark_transformation(headers, content.body, content.type); } if (orig_event->type == S_MethodInvoke_Ind) { return_session_reply(orig_event->u.S_MethodInvoke_Ind.server_transaction_id, status, headers, content.body, session_id); } else { return_unit_reply(orig_event->u.S_Unit_MethodInvoke_Ind.addr_tuple, orig_event->u.S_Unit_MethodInvoke_Ind.transaction_id, status, headers, content.body); } octstr_destroy(content.type); /* body was re-used above */ octstr_destroy(content.charset); octstr_destroy(url); /* same as content.url */ counter_decrease(fetches);}/* * This thread receives replies from HTTP layer and sends them back to * the phone. */static void return_replies_thread(void *arg){ Octstr *body; struct request_data *p; int status; Octstr *final_url; List *headers; while (run_status == running) { p = http_receive_result(caller, &status, &final_url, &headers, &body); if (p == NULL) break; return_reply(status, body, headers, p->client_SDU_size, p->event, p->session_id, p->url, p->x_wap_tod, p->request_headers); wap_event_destroy(p->event); http_destroy_headers(p->request_headers); gw_free(p); octstr_destroy(final_url); }}/* * This WML deck is returned when the user asks for the URL "kannel:alive". */#define HEALTH_DECK \ "<?xml version=\"1.0\"?>" \ "<!DOCTYPE wml PUBLIC \"-//WAPFORUM//DTD 1.1//EN\" " \ "\"http://www.wapforum.org/DTD/wml_1.1.xml\">" \ "<wml><card id=\"health\"><p>Ok</p></card></wml>"static void start_fetch(WAPEvent *event) { int ret; long client_SDU_size; /* 0 means no limit */ Octstr *url; Octstr *referer_url; List *session_headers; List *request_headers; List *actual_headers; List *resp_headers; WAPAddrTuple *addr_tuple; long session_id; Octstr *content_body; Octstr *method; /* type of request, normally a get or a post */ Octstr *request_body; int x_wap_tod; /* X-WAP.TOD header was present in request */ Octstr *magic_url; struct request_data *p; counter_increase(fetches); if (event->type == S_MethodInvoke_Ind) { struct S_MethodInvoke_Ind *p; p = &event->u.S_MethodInvoke_Ind; session_headers = p->session_headers; request_headers = p->request_headers; url = octstr_duplicate(p->request_uri); addr_tuple = p->addr_tuple; session_id = p->session_id; client_SDU_size = p->client_SDU_size; request_body = octstr_duplicate(p->request_body); method = p->method; } else { struct S_Unit_MethodInvoke_Ind *p; p = &event->u.S_Unit_MethodInvoke_Ind; session_headers = NULL; request_headers = p->request_headers; url = octstr_duplicate(p->request_uri); addr_tuple = p->addr_tuple; session_id = -1; client_SDU_size = 0; /* No limit */ request_body = octstr_duplicate(p->request_body); method = p->method; } wsp_http_map_url(&url); actual_headers = list_create(); if (session_headers != NULL) http_header_combine(actual_headers, session_headers); if (request_headers != NULL) http_header_combine(actual_headers, request_headers); http_remove_hop_headers(actual_headers); x_wap_tod = http_header_remove_all(actual_headers, "X-WAP.TOD"); add_accept_headers(actual_headers); add_charset_headers(actual_headers); add_network_info(actual_headers, addr_tuple); add_client_sdu_size(actual_headers, client_SDU_size); add_via(actual_headers); #ifdef ENABLE_COOKIES if ((session_id != -1) && (set_cookies(actual_headers, find_session_machine_by_id(session_id)) == -1)) error(0, "WSP: Failed to add cookies");#endif /* set referer URL to HTTP header from WSPMachine */ if (session_id != -1) { if ((referer_url = get_referer_url(find_session_machine_by_id(session_id))) != NULL) { add_referer_url(actual_headers, referer_url); } } add_kannel_version(actual_headers); add_session_id(actual_headers, session_id); http_header_pack(actual_headers); magic_url = octstr_imm("kannel:alive"); if (octstr_str_compare(method, "GET") == 0 && octstr_compare(url, magic_url) == 0) { ret = HTTP_OK; resp_headers = list_create(); http_header_add(resp_headers, "Content-Type", "text/vnd.wap.wml"); content_body = octstr_create(HEALTH_DECK); octstr_destroy(request_body); return_reply(ret, content_body, resp_headers, client_SDU_size, event, session_id, url, x_wap_tod, actual_headers); wap_event_destroy(event); http_destroy_headers(actual_headers); } else if (octstr_str_compare(method, "GET") == 0 || octstr_str_compare(method, "POST") == 0 || octstr_str_compare(method, "HEAD") == 0) { if (request_body != NULL && (octstr_str_compare(method, "GET") == 0 || octstr_str_compare(method, "HEAD") == 0)) { octstr_destroy(request_body); request_body = NULL; } p = gw_malloc(sizeof(*p)); p->client_SDU_size = client_SDU_size; p->event = event; p->session_id = session_id; p->url = url; p->x_wap_tod = x_wap_tod; p->request_headers = actual_headers; http_start_request(caller, http_name2method(method), url, actual_headers, request_body, 0, p, NULL); octstr_destroy(request_body); } else { error(0, "WSP: Method %s not supported.", octstr_get_cstr(method)); content_body = octstr_create(""); resp_headers = http_create_empty_headers(); ret = HTTP_NOT_IMPLEMENTED; octstr_destroy(request_body); return_reply(ret, content_body, resp_headers, client_SDU_size, event, session_id, url, x_wap_tod, actual_headers); wap_event_destroy(event); http_destroy_headers(actual_headers); }}/* Shut up WMLScript compiler status/trace messages. */static void dev_null(const char *data, size_t len, void *context) { /* nothing */}static Octstr *convert_wml_to_wmlc(struct content *content) { Octstr *wmlc; int ret; ret = wml_compile(content->body, content->charset, &wmlc); if (ret == 0) return wmlc; warning(0, "WSP: WML compilation failed."); return NULL;}static Octstr *convert_wmlscript_to_wmlscriptc(struct content *content) { WsCompilerParams params; WsCompilerPtr compiler; WsResult result; unsigned char *result_data; size_t result_size; Octstr *wmlscriptc; memset(¶ms, 0, sizeof(params)); params.use_latin1_strings = 0; params.print_symbolic_assembler = 0; params.print_assembler = 0; params.meta_name_cb = NULL; params.meta_name_cb_context = NULL; params.meta_http_equiv_cb = NULL; params.meta_http_equiv_cb_context = NULL; params.stdout_cb = dev_null; params.stderr_cb = dev_null; compiler = ws_create(¶ms); if (compiler == NULL) { panic(0, "WSP: could not create WMLScript compiler"); exit(1); } result = ws_compile_data(compiler, octstr_get_cstr(content->url), octstr_get_cstr(content->body), octstr_len(content->body), &result_data, &result_size); if (result != WS_OK) { warning(0, "WSP: WMLScript compilation failed: %s", ws_result_to_string(result)); wmlscriptc = NULL; } else { wmlscriptc = octstr_create_from_data(result_data, result_size); } return wmlscriptc;}/* The interface for capability negotiation is a bit different from * the negotiation at WSP level, to make it easier to program. * The application layer gets a list of requested capabilities, * basically a straight decoding of the WSP level capabilities. * It replies with a list of all capabilities it wants to set or * refuse. (Refuse by setting cap->data to NULL). Any capabilities * it leaves out are considered "unknown; don't care". The WSP layer * will either process those itself, or refuse them. * * At the WSP level, not sending a reply to a capability means accepting * what the client proposed. If the application layer wants this to * happen, it should set cap->data to NULL and cap->accept to 1. * (The WSP layer does not try to guess what kind of reply would be * identical to what the client proposed, because the format of the * reply is often different from the format of the request, and this * is likely to be true for unknown capabilities too.) */static List *negotiate_capabilities(List *req_caps) { /* Currently we don't know or care about any capabilities, * though it is likely that "Extended Methods" will be * the first. */ return list_create();}/*********************************************************************** * The following code implements the map-url mechanism */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -