MSFilter *set_CODECFilter(RtpProfile *profile, int pt, int mode){ PayloadType *payload; switch(mode){ case MEDIA_API_DECODER: payload = rtp_profile_get_payload(profile, pt); if(payload == NULL){ api_error("media_api: undefined payload in URL\n"); return NULL; } return ms_decoder_new_with_string_id(payload->mime_type); //Commented this to include the new RtpProfile /*if(pt != -1) return ms_decoder_new_with_pt(pt); *else return ms_copy_new(); */ case MEDIA_API_ENCODER: payload = rtp_profile_get_payload(profile, pt); if(payload == NULL){ api_error("media_api: undefined payload in URL\n"); return NULL; } return ms_encoder_new_with_string_id(payload->mime_type); /*if(pt != -1) return ms_encoder_new_with_pt(pt); *else return ms_copy_new(); */ } }
void start( const ::roast::windows::window &w, bool fullscreen, int adapter_no, const device_mode::_<_DeviceModeN> &device_mode) { ::D3D10_DRIVER_TYPE d3d_driver_type = common_device_mode_2_d3d_device_type<_DeviceModeN>::value; /////////////////////////////////////////////////////////// ::DXGI_SWAP_CHAIN_DESC scdesc; ::ZeroMemory( &scdesc, sizeof(scdesc) ); scdesc.BufferCount = 1; scdesc.BufferDesc.Width = w.get_height(); scdesc.BufferDesc.Height = w.get_width(); scdesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; scdesc.BufferDesc.RefreshRate.Numerator = 60; scdesc.BufferDesc.RefreshRate.Denominator = 1; scdesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; scdesc.OutputWindow = w.get_hwnd(); scdesc.SampleDesc.Count = 1; scdesc.SampleDesc.Quality = 0; scdesc.Windowed = (fullscreen ? FALSE : TRUE); /////////////////////////////////////////////////////////// // Create Device ::HRESULT hr = ::D3D10CreateDeviceAndSwapChain( NULL, d3d_driver_type, NULL, 0, D3D10_SDK_VERSION, &scdesc, m_swapchain.get_ptrptr(), &m_if ); if ( hr != D3D_OK ){ throw api_error(start__D3D10CreateDeviceAndSwapChain__Failed, "D3D10CreateDeviceAndSwapChain() Failed.", hr); } // GetBuffer m_swapchain->GetBuffer( 0, __uuidof(::ID3D10Texture2D), (void**)m_backbuf.get_ptrptr() ); // CreateRenderTargetView hr = m_if->CreateRenderTargetView( m_backbuf, NULL, m_view.get_ptrptr() ); if ( hr != D3D_OK ){ throw api_error(start__CreateRenderTargetView__Failed, "ID3D10Device::CreateRenderTargetView() Failed.", hr); } m_backbuf->Release(); // OMSetRenderTargets m_if->OMSetRenderTargets( 1, m_view.get_ptrptr(), NULL ); // RSSetViewports ::D3D10_VIEWPORT vp; vp.Width = scdesc.BufferDesc.Width; vp.Height = scdesc.BufferDesc.Height; vp.MinDepth = 0.0f; vp.MaxDepth = 1.0f; vp.TopLeftX = 0; vp.TopLeftY = 0; m_if->RSSetViewports( 1, &vp ); }
int api_notification_list(ONION_FUNC_PROTO_STR) { const char * userid = onion_request_get_query(req, "userid"); const char * appkey = onion_request_get_query(req, "appkey"); const char * sessid = onion_request_get_query(req, "sessid"); if (userid == NULL || sessid == NULL || appkey == NULL) { return api_error(p, req, res, API_RT_WRONGPARAM); } struct userec *ue = getuser(userid); if (ue == 0) { return api_error(p, req, res, API_RT_NOSUCHUSER); } int r = check_user_session(ue, sessid, appkey); if (r != API_RT_SUCCESSFUL) { free(ue); return api_error(p, req, res, r); } struct json_object *obj = json_tokener_parse("{\"errcode\": 0, \"notifications\": []}"); struct json_object *noti_array = json_object_object_get(obj, "notifications"); NotifyItemList allNotifyItems = parse_notification(ue->userid); struct json_object * item = NULL; struct NotifyItem * currItem; struct boardmem *b; for (currItem = (struct NotifyItem *)allNotifyItems; currItem != NULL; currItem = currItem->next) { item = json_object_new_object(); json_object_object_add(item, "board", json_object_new_string(currItem->board)); json_object_object_add(item, "noti_time", json_object_new_int64(currItem->noti_time)); json_object_object_add(item, "from_userid", json_object_new_string(currItem->from_userid)); json_object_object_add(item, "title", json_object_new_string(currItem->title_utf)); json_object_object_add(item, "type", json_object_new_int(currItem->type)); b = getboardbyname(currItem->board); json_object_object_add(item, "secstr", json_object_new_string(b->header.sec1)); json_object_array_add(noti_array, item); } free_notification(allNotifyItems); api_set_json_header(res); onion_response_write0(res, json_object_to_json_string(obj)); json_object_put(obj); free(ue); return OCS_PROCESSED; }
/// Constructs a new api_error with the message in the SQLite database. /// /// \param database_ The SQLite database. /// \param api_function_ The name of the SQLite C API function that caused the /// error. /// /// \return A new api_error with the retrieved message. sqlite::api_error sqlite::api_error::from_database(database& database_, const std::string& api_function_) { ::sqlite3* c_db = database_c_gate(database_).c_database(); return api_error(api_function_, ::sqlite3_errmsg(c_db)); }
int media_flow_setup_fd(MediaFlow *flow, CallMember* csource, CallMember *cdestination, int direction){ GList *source, *destination; char *dir; FlowDirections *fd = (FlowDirections *) g_malloc(sizeof(FlowDirections)); if(direction == MEDIA_FLOW_DUPLEX) dir = "DUPLEX"; else if(direction == MEDIA_FLOW_HALF_DUPLEX) dir = "HALF_DUPLEX"; api_trace("media_flow_setup_fd: setting up %s flow for %s , %s",dir, csource->name, cdestination->name); source = g_list_find_custom(flow->members, csource, &find); destination =g_list_find_custom(flow->members, cdestination, &find); if(source == NULL){ api_error("media_flow_setup_fd: Invalid source %s specified", csource->name); } if(destination == NULL){ api_error("media_flow_setup_fd: Invalid destination %s specified", cdestination->name); //ERROR handling to be done here } fd->source = (Members*)source->data; fd->destination = (Members*)destination->data; fd->type = direction; flow->flowDirections = g_list_append(flow->flowDirections, fd); return 1; }
int api_notification_del(ONION_FUNC_PROTO_STR) { const char * userid = onion_request_get_query(req, "userid"); const char * appkey = onion_request_get_query(req, "appkey"); const char * sessid = onion_request_get_query(req, "sessid"); if (userid == NULL || sessid == NULL || appkey == NULL) { return api_error(p, req, res, API_RT_WRONGPARAM); } const char * type = onion_request_get_query(req, "type"); const char * board = onion_request_get_query(req, "board"); const char * aid_str = onion_request_get_query(req, "aid"); if (type == NULL && (board == NULL || aid_str == NULL)) { return api_error(p, req, res, API_RT_WRONGPARAM); } struct userec *ue = getuser(userid); if (ue == 0) { return api_error(p, req, res, API_RT_NOSUCHUSER); } int r = check_user_session(ue, sessid, appkey); if (r != API_RT_SUCCESSFUL) { free(ue); return api_error(p, req, res, r); } if ((type != NULL) && (strcasecmp(type, "delall") == 0)) { del_all_notification(ue->userid); } else { del_post_notification(ue->userid, board, atoi(aid_str)); } free(ue); return api_error(p, req, res, API_RT_SUCCESSFUL); }
// returns false for failure DLLEXPORT bool patch_setup(unsigned long client_thread_id, const Patch & patch, bool use_injection) { g_use_injection = use_injection; g_patch = patch; g_message[0] = '\0'; g_patch_hhook = SetWindowsHookEx(WH_GETMESSAGE, patch_GetMsgProc, g_hinstance, client_thread_id); if(g_patch_hhook == 0) { api_error("Failed to install hook in client"); return false; } return true; }
void present() { ::HRESULT hr = m_swapchain->Present(0,0); if ( hr != D3D_OK ) throw api_error(present__Present_Failed,"IDXGISwapChain::Present() Failed.", hr); }
/* Thread actions: - Write login.cfg to client directory - Start the client executable with CreateProcess() - WaitForInputIdle() - call patch_setup() in Injection DLL - Post a message to the client thread (param: this thread id) - Wait for a message with GetMessage() */ unsigned LaunchThread::run() { // Calculate CRC of client executable. unsigned int checksum, length; CCrc crc; begin_stage(STAGE_CRC); if(!crc.GetCrc(m_client_path, &checksum, &length)) { crtl_error("Cannot read client executable"); error_stage(STAGE_CRC); return 0; } done_stage(STAGE_CRC); // Load Ignition.cfg Patch patch; // Lookup CRC to find patch information. // First try Ignition.cfg begin_stage(STAGE_IGNITIONCFG); if(!patch.load(m_config.get_ignition_cfg(), checksum, length)) { crtl_error("Cannot get patch from Ignition.cfg"); //error_stage(STAGE_IGNITIONCFG); // If not found, also try ilpatch.cfg begin_stage(STAGE_ILPATCHCFG); if(!patch.load("ilpatch.cfg", checksum, length)) { sprintf(m_message_buf, "This client verion is not supported.\n" "(No patch information for selected client.)\n" "Checksum: %08x Length: %x", checksum, length); m_message = m_message_buf; error_stage(STAGE_ILPATCHCFG); return 0; } else done_stage(STAGE_ILPATCHCFG); } else { done_stage(STAGE_IGNITIONCFG); skipped_stage(STAGE_ILPATCHCFG); } // Write login.cfg to client directory. string login_cfg(m_config.get_client_dir()); login_cfg += "\\login.cfg"; begin_stage(STAGE_LOGINCFG); FILE * fp = fopen(login_cfg.c_str(), "wt"); if(fp == NULL) { crtl_error("Cannot write login.cfg"); error_stage(STAGE_LOGINCFG); return 0; } fprintf(fp, "; login.cfg\n; created by Injection Launcher\n"); fprintf(fp, "LoginServer=%s\n", m_address); fclose(fp); //patch uo.cfg with username and password for login if(strcmp(m_username, "") != 0) // no username so skip this { string RememberAcctPW("on"); string AcctID(m_username); string AcctPassword(ILaunchConfig::crypt_pw(m_password)); if(AcctPassword == "") RememberAcctPW = "off"; string uo_cfg(m_config.get_client_dir()); uo_cfg += "\\uo.cfg"; FILE * ifp = fopen(uo_cfg.c_str(), "rt"); if(ifp == NULL) { crtl_error("Cannot read uo.cfg"); error_stage(STAGE_LOGINCFG); return 0; } string uo_cfg_tmp(uo_cfg); uo_cfg_tmp += ".tmp"; FILE * ofp = fopen(uo_cfg_tmp.c_str(), "wt"); if(ofp == NULL) { crtl_error("Cannot write uo.cfg.tmp"); error_stage(STAGE_LOGINCFG); return 0; } char buf[100]; while(fgets(buf, 100, ifp) != NULL) { // strip out our fields if(strncmp(buf,"AcctID",6) == 0) {} else if(strncmp(buf,"AcctPassword",12) == 0) {} else if(strncmp(buf,"RememberAcctPW",14) == 0) {} else fputs(buf, ofp); } // build new config strings string AcctID_str("AcctID="); AcctID_str += AcctID+"\n"; string AcctPassword_str("AcctPassword="******"\n"; string RememberAcctPW_str("RememberAcctPW="); RememberAcctPW_str += RememberAcctPW+"\n"; // write our new config strings fputs(AcctID_str.c_str(), ofp); fputs(AcctPassword_str.c_str(), ofp); fputs(RememberAcctPW_str.c_str(), ofp); fclose(ofp); fclose(ifp); // delete orig uo.cfg remove(uo_cfg.c_str()); // rename uo.cfg.tmp to uo.cfg rename(uo_cfg_tmp.c_str(), uo_cfg.c_str()); } done_stage(STAGE_LOGINCFG); // Load injection.dll to patch client begin_stage(STAGE_LOADINJECTION); HMODULE hmodule = LoadLibrary("injection.dll"); if(hmodule == 0) { api_error("Failed to load injection.dll in launcher"); error_stage(STAGE_LOADINJECTION); return 0; } patch_setup_t patch_setup = reinterpret_cast<patch_setup_t>(GetProcAddress(hmodule, "patch_setup")); patch_getmessage_t patch_getmessage = reinterpret_cast<patch_getmessage_t>(GetProcAddress(hmodule, "patch_getmessage")); if(patch_setup == 0 || patch_getmessage == 0) { api_error("Failed to find function in injection.dll"); error_stage(STAGE_LOADINJECTION); return 0; } done_stage(STAGE_LOADINJECTION); STARTUPINFO si; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); PROCESS_INFORMATION pi; // Run the client executable begin_stage(STAGE_STARTCLIENT); if(CreateProcess(m_client_path, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi) == 0) { api_error("Failed to execute client"); error_stage(STAGE_STARTCLIENT); return 0; } if(WaitForInputIdle(pi.hProcess, INFINITE) != 0) { api_error("Failed waiting for client window to open"); error_stage(STAGE_STARTCLIENT); return 0; } done_stage(STAGE_STARTCLIENT); begin_stage(STAGE_PATCHCLIENT); if(!patch_setup(pi.dwThreadId, patch, m_config.get_use_injection())) { m_message = patch_getmessage(); error_stage(STAGE_PATCHCLIENT); return 0; } // Post a message to the client thread if(PostThreadMessage(pi.dwThreadId, WM_USER, GetCurrentThreadId(), 0) == 0) { api_error("Failed posting message to client"); error_stage(STAGE_PATCHCLIENT); return 0; } MSG msg; // Wait for a message back from the client thread if(GetMessage(&msg, NULL, WM_USER, WM_USER) == -1) { api_error("Failed waiting for message from client"); error_stage(STAGE_PATCHCLIENT); return 0; } if(msg.wParam != 0) { TerminateProcess(pi.hProcess, 0xffffffff); m_message = patch_getmessage(); error_stage(STAGE_PATCHCLIENT); return 0; } m_message = "Success"; done_stage(STAGE_PATCHCLIENT); CloseHandle(pi.hThread); CloseHandle(pi.hProcess); return 1; }
static LRESULT WINAPI patch_GetMsgProc(int code, WPARAM wparam, LPARAM lparam) { if(code == HC_ACTION) { DWORD error = 0; MSG * msg = reinterpret_cast<MSG *>(lparam); DWORD launching_thread = msg->wParam; // Apply the patch const PatchElement * elem = g_patch.get_elements(); int num_elements = g_patch.get_num_elements(); char Tmp[1024]; wsprintf(Tmp,"num_elements1=%d\n",num_elements); OutputDebugString(Tmp); for(int i = 0; i < num_elements; i++) { DWORD oldProtect; if(VirtualProtect(reinterpret_cast<LPVOID>(elem->m_address), elem->m_length, PAGE_READWRITE, &oldProtect) == 0) { api_error("Failed to patch (page protection)"); error = 1; break; } CopyMemory(reinterpret_cast<unsigned char *>(elem->m_address), elem->m_buffer, elem->m_length); elem++; } // Load Injection DLL (unless disabled) if(error == 0 && g_use_injection) { HINSTANCE hmodule = LoadLibrary("injection.dll"); if(hmodule == NULL) api_error("Failed to load injection.dll in client"); else { // find entry points in injection.dll install_func_t install_func = reinterpret_cast<install_func_t>( GetProcAddress(hmodule, "Install")); geterrortext_func_t geterrortext_func = reinterpret_cast<geterrortext_func_t>( GetProcAddress(hmodule, "GetErrorText")); if(install_func == NULL) { api_error("Failed to find Install function in injection.dll"); error = 1; } else if(geterrortext_func == NULL) { api_error("Failed to find GetErrorText function in injection.dll"); error = 1; } else { // Attempt to install Injection // NOTE: the checksum and length parameters are not needed int err = install_func(0, 0); if(err != 0) { strcpy(g_message, geterrortext_func(err)); error = 1; } } } } // Post a message to the launching thread (param: success/failure) PostThreadMessage(launching_thread, WM_USER, error, GetLastError()); UnhookWindowsHookEx(g_patch_hhook); } return CallNextHookEx(g_patch_hhook, code, wparam, lparam); }
static int api_mail_do_post(ONION_FUNC_PROTO_STR, int mode) { const char * userid = onion_request_get_query(req, "userid"); const char * appkey = onion_request_get_query(req, "appkey"); const char * sessid = onion_request_get_query(req, "sessid"); const char * token = onion_request_get_query(req, "token"); const char * to_userid = onion_request_get_query(req, "to_userid"); const char * title = onion_request_get_query(req, "title"); const char * backup = onion_request_get_query(req, "backup"); if(!userid || !appkey || !sessid || !title || !to_userid || !token) return api_error(p, req, res, API_RT_WRONGPARAM); struct userec *ue = getuser(userid); if(!ue) return api_error(p, req, res, API_RT_NOSUCHUSER); struct userec currentuser; memcpy(¤tuser, ue, sizeof(currentuser)); free(ue); int r = check_user_session(¤tuser, sessid, appkey); if(r != API_RT_SUCCESSFUL) { return api_error(p, req, res, r); } if(HAS_PERM(PERM_DENYMAIL)) { return api_error(p, req, res, API_RT_MAILNOPPERM); } int uent_index = get_user_utmp_index(sessid); struct user_info *ui = &(shm_utmp->uinfo[uent_index]); if(strcmp(ui->token, token) != 0) { return api_error(p, req, res, API_RT_WRONGTOKEN); } // 更新 token 和来源 IP getrandomstr_r(ui->token, TOKENLENGTH+1); const char * fromhost = onion_request_get_header(req, "X-Real-IP"); memset(ui->from, 0, 20); strncpy(ui->from, fromhost, 20); if(check_user_maxmail(currentuser)) { return api_error(p, req, res, API_RT_MAILFULL); } struct userec *to_user = getuser(to_userid); if(!to_user) { return api_error(p, req, res, API_RT_NOSUCHUSER); } if(inoverride(currentuser.userid, to_user->userid, "rejects")) { free(to_user); return api_error(p, req, res, API_RT_INUSERBLIST); } const char * data = onion_request_get_post(req, "content"); char filename[80]; sprintf(filename, "bbstmpfs/tmp/%s_%s.tmp", currentuser.userid, ui->token); char * data2 = strdup(data); while(strstr(data2, "[ESC]") != NULL) data2 = string_replace(data2, "[ESC]", "\033"); char * data_gbk = (char *)malloc(strlen(data2)*2); u2g(data2, strlen(data2), data_gbk, strlen(data2)*2); f_write(filename, data_gbk); free(data2); int mark=0; // 文件标记 //if(insertattachments(filename, data_gbk, currentuser->userid)>0) //mark |= FH_ATTACHED; free(data_gbk); char * title_tmp = (char *)malloc(strlen(title)*2); u2g(title, strlen(title), title_tmp, strlen(title)*2); char title_gbk[80], title_tmp2[80]; strncpy(title_gbk, title_tmp[0]==0 ? "No Subject" : title_tmp, 80); snprintf(title_tmp2, 80, "{%s} %s", to_user->userid, title); free(title_tmp); r = do_mail_post(to_user->userid, title, filename, currentuser.userid, currentuser.username, fromhost, 0, mark); if(backup && strcasecmp(backup, "true")==0) { do_mail_post_to_sent_box(currentuser.userid, title_tmp2, filename, currentuser.userid, currentuser.username, fromhost, 0, mark); } unlink(filename); free(to_user); if(r<0) { return api_error(p, req, res, API_RT_MAILINNERR); } api_set_json_header(res); onion_response_printf(res, "{ \"errcode\":0, \"token\":\"%s\" }", ui->token); return OCS_PROCESSED; }
int api_mail_list(ONION_FUNC_PROTO_STR) { const char * str_startnum = onion_request_get_query(req, "startnum"); const char * str_count = onion_request_get_query(req, "count"); const char * userid = onion_request_get_query(req, "userid"); const char * appkey = onion_request_get_query(req, "appkey"); const char * sessid = onion_request_get_query(req, "sessid"); const char * box_type = onion_request_get_query(req, "box_type"); if(!userid || !appkey || !sessid) return api_error(p, req, res, API_RT_WRONGPARAM); struct userec *ue = getuser(userid); if(!ue) return api_error(p, req, res, API_RT_NOSUCHUSER); int r = check_user_session(ue, sessid, appkey); if(r != API_RT_SUCCESSFUL) { free(ue); return api_error(p, req, res, r); } int startnum = (str_startnum) ? atoi(str_startnum) : 999999; int count = (str_count) ? atoi(str_count) : 20; char mail_dir[80]; int box_type_i = (box_type != NULL && box_type[0] == '1') ? API_MAIL_SENT_BOX : API_MAIL_RECIEVE_BOX; if(box_type_i == API_MAIL_RECIEVE_BOX) setmailfile(mail_dir, ue->userid, ".DIR"); else setsentmailfile(mail_dir, ue->userid, ".DIR"); int total = file_size_s(mail_dir) / sizeof(struct fileheader); if(!total) { free(ue); return api_error(p, req, res, API_RT_MAILEMPTY); } FILE *fp = fopen(mail_dir, "r"); if(fp==0) { free(ue); return api_error(p, req, res, API_RT_MAILDIRERR); } if(startnum == 0 || startnum > total-count+1) startnum = total - count + 1; if(startnum <= 0) startnum = 1; struct fileheader x; int i; struct bmy_article mail_list[count]; memset(mail_list, 0, sizeof(struct bmy_article) * count); fseek(fp, (startnum - 1) * sizeof(struct fileheader), SEEK_SET); for(i=0; i<count; ++i) { if(fread(&x, sizeof(x), 1, fp) <= 0) break; mail_list[i].sequence_num = i + startnum; mail_list[i].mark = x.accessed; strncpy(mail_list[i].author, fh2owner(&x), sizeof(mail_list[i].author)); mail_list[i].filetime = x.filetime; g2u(x.title, strlen(x.title), mail_list[i].title, sizeof(mail_list[i].title)); } fclose(fp); char *s = bmy_mail_array_to_json_string(mail_list, count, 0, ue); api_set_json_header(res); onion_response_write0(res, s); free(s); free(ue); return OCS_PROCESSED; }
static int api_mail_get_content(ONION_FUNC_PROTO_STR, int mode) { const char * userid = onion_request_get_query(req, "userid"); const char * sessid = onion_request_get_query(req, "sessid"); const char * appkey = onion_request_get_query(req, "appkey"); const char * str_num = onion_request_get_query(req, "num"); const char * box_type = onion_request_get_query(req, "box_type"); if(!userid || !sessid || !appkey || !str_num) return api_error(p, req, res, API_RT_WRONGPARAM); struct userec * ue = getuser(userid); if(ue == 0) return api_error(p, req, res, API_RT_WRONGPARAM); if(check_user_session(ue, sessid, appkey) != API_RT_SUCCESSFUL) { free(ue); return api_error(p, req, res, API_RT_WRONGSESS); } char mail_dir[80]; struct fileheader fh; int box_type_i = (box_type != NULL && box_type[0] == '1') ? API_MAIL_SENT_BOX : API_MAIL_RECIEVE_BOX; if(box_type_i == API_MAIL_RECIEVE_BOX) setmailfile(mail_dir, ue->userid, ".DIR"); else setsentmailfile(mail_dir, ue->userid, ".DIR"); FILE *fp = fopen(mail_dir, "r"); if(fp==0) { free(ue); return api_error(p, req, res, API_RT_MAILINNERR); } int total = file_size_s(mail_dir) / sizeof(struct fileheader); int num = atoi(str_num); if(num<=0) num = 1; if(num>total) num = total; fseek(fp, (num-1)*sizeof(struct fileheader), SEEK_SET); if(fread(&fh, sizeof(fh), 1, fp) <= 0) { fclose(fp); free(ue); return api_error(p, req, res, API_RT_MAILINNERR); } fclose(fp); char title_utf[240]; g2u(fh.title, strlen(fh.title), title_utf, 240); struct attach_link *attach_link_list = NULL; char * mail_content_utf8 = parse_mail(ue->userid, fh.filetime, mode, &attach_link_list); if(!mail_content_utf8) { // 文件不存在 free(ue); free_attach_link_list(attach_link_list); return api_error(p, req, res, API_RT_MAILEMPTY); } char * mail_json_str = (char *)malloc(strlen(mail_content_utf8) + 512); if(!mail_json_str) { free(ue); free(mail_content_utf8); free_attach_link_list(attach_link_list); return api_error(p, req, res, API_RT_NOTENGMEM); } memset(mail_json_str, 0, strlen(mail_content_utf8)+512); sprintf(mail_json_str, "{\"errcode\": 0, \"attach\":[]}"); struct json_object * jp = json_tokener_parse(mail_json_str); if(!jp) { free(ue); free(mail_content_utf8); free_attach_link_list(attach_link_list); free(mail_json_str); return api_error(p, req, res, API_RT_NOTENGMEM); } json_object_object_add(jp, "content", json_object_new_string(mail_content_utf8)); json_object_object_add(jp, "title", json_object_new_string(title_utf)); if(attach_link_list) { struct json_object * attach_array = json_object_object_get(jp, "attach"); char at_buf[320]; struct attach_link * alp = attach_link_list; while(alp) { memset(at_buf, 0, 320); sprintf(at_buf, "{\"link\": \"%s\", \"size\": %d}", alp->link, alp->size); json_object_array_add(attach_array, json_tokener_parse(at_buf)); alp=alp->next; } } char * api_output = strdup(json_object_to_json_string(jp)); free(ue); free(mail_content_utf8); free_attach_link_list(attach_link_list); free(mail_json_str); json_object_put(jp); api_set_json_header(res); onion_response_write0(res, api_output); free(api_output); return OCS_PROCESSED; }