/*Software License Copyright(C) 2024[liuyingjie] License Terms Usage Rights Any individual or entity is free to use, copy, and distribute the binary form of this software without modification to the source code, without the need to disclose the source code. If the source code is modified, the modifications must be open - sourced under the same license.This means that the modifications must be disclosed and accompanied by a copy of this license. Future Versions Updates From this version onwards, all future releases will be governed by the terms of the latest version of the license.This license will automatically be nullified and replaced by the new version. Users must comply with the terms of the new license issued in future releases. Liability and Disclaimer This software is provided “as is”, without any express or implied warranties, including but not limited to the warranties of merchantability, fitness for a particular purpose, and non - infringement.In no event shall the author or copyright holder be liable for any claims, damages, or other liabilities, whether in an action of contract, tort, or otherwise, arising from, out of, or in connection with the software or the use or other dealings in the software. Contact Information If you have any questions, please contact us: 1585346868@qq.com Or visit our website fwlua.com. */ #include "net/http_parser.h" #if USE_NET_HTTP_WEBSITE #include "util/file.h" #include "util/strutils.h" network::http::parser::parser() { m_method = network::http::ALL; } network::http::parser::~parser() { } const ylib::json& ylib::network::http::parser::json() { return m_json_param; } std::string ylib::network::http::parser::text() { return m_data.to_string(); } bool network::http::parser::init(const std::string &url,const network::http::method& method,const ylib::buffer &data, const std::string &content_type) { m_url = url; m_data = data; m_content_type = content_type; m_method = method; /*解析URL*/ parse_url(m_url,m_url_param); switch (m_method) { case network::http::GET: break; case network::http::POST: { if(content_type.find("application/x-www-form-urlencoded") != -1) { parse_url(m_data.to_string(),m_body_param); } else if(content_type.find("application/json") != -1) { parse_json(); } else if(content_type.find("multipart/form-data") !=-1) { parse_form(); } } break; default: break; } return true; } bool network::http::parser::url_param(const std::string &name, std::string &value) { return read_url_param(m_url_param,name,value); } bool ylib::network::http::parser::url_param_exist(const std::string& name) { return m_url_param.find(name) != m_url_param.end(); } std::vector network::http::parser::url_param_names() { std::vector names; for_iter(iter,m_url_param) names.push_back(iter->first); return names; } bool network::http::parser::body_param(const std::string &name, std::string &value) { if(m_method == POST) { if(m_content_type.find("application/x-www-form-urlencoded") != -1) { return read_url_param(m_body_param,name,value); } else if(m_content_type.find("application/json") != -1) { if(!m_json_param.exist(name)) return false; if(m_json_param[name].is_number()){ value = std::to_string(m_json_param[name].to()); }else{ value = m_json_param[name].to(); } return true; } return false; } return false; } bool ylib::network::http::parser::body_param_exist(const std::string& name) { if (m_method == POST) { if (m_content_type.find("application/x-www-form-urlencoded") != -1) { return m_body_param.find(name) != m_body_param.end(); } else if (m_content_type.find("application/json") != -1) { return m_json_param.exist(name); } } return false; } std::vector network::http::parser::body_param_names() { std::vector names; if(m_method == POST) { if (m_content_type.find("application/x-www-form-urlencoded") != -1) { for_iter(iter,m_body_param) names.push_back(iter->first); } else if (m_content_type.find("application/json") != -1) { return m_json_param.keys(); } } return names; } network::http::form_parser *network::http::parser::form() { return &m_form; } void network::http::parser::parse_url(const std::string &url, std::map &map) { map.clear(); auto ps = strutils::split(url,'&'); for(size_t i=0;i(pi[0],pi[1])); } } void network::http::parser::parse_json() { m_json_param.parse(m_data.to_string()); } void network::http::parser::parse_form() { m_form.parse(&m_data); } bool network::http::parser::read_url_param(const std::map &map, const std::string &name, std::string &value) { auto iter = map.find(name); if(iter == map.end()) return false; value = iter->second; return true; } network::http::form_parser::form_parser() { } network::http::form_parser::~form_parser() { } std::vector network::http::form_parser::names() { std::vector result; for_iter(iter,m_infos) result.push_back(iter->first); return result; } bool network::http::form_parser::get(const std::string &name, form_info &info) { auto iter = m_infos.find(name); if(iter == m_infos.end()) return false; info = iter->second; return true; } bool network::http::form_parser::write_file(const std::string &name, const std::string &filepath) { auto iter = m_infos.find(name); if(iter == m_infos.end()) return false; return ylib::file::write(filepath,(const char*)m_data->data()+iter->second.start,iter->second.length); } bool network::http::form_parser::parse(buffer *data) { this->m_data = data; std::vector starts; std::vector lengths; parse_count(starts,lengths); for(size_t i=0;i &starts, std::vector &lengths) { ylib::buffer cut_flag; { int32 curr_idx = 0; while (char c = getchar(curr_idx++)) { if (c == '\r' && getchar(curr_idx) == '\n') { curr_idx++; break; } else cut_flag.append(c); } } auto idxVct = m_data->find_list(cut_flag); for (size_t i = 0; i < idxVct.size(); i++) { size_t startIdx = idxVct[i] + cut_flag.length() + 2; if (i + 1 != idxVct.size()) { starts.push_back((uint32)startIdx); lengths.push_back((uint32)(idxVct[i + 1] - idxVct[i] - cut_flag.length() - 2)); } } } void network::http::form_parser::parse_form(uint32 start,uint32 length) { auto parse_paraminfo_secondkv=[](const ylib::buffer& buf)->ylib::KeyValue { ylib::KeyValue kv; buffer cutV; cutV.resize(1); cutV[0] = '='; auto cdIdx = buf.find(cutV, 0); if (cdIdx == -1) return kv; kv.name = buf.sub(0, cdIdx).to_string(); kv.value = buf.sub(cdIdx + 2, buf.length() - 3 - cdIdx).to_string(); return kv; }; ylib::buffer form_data(m_data->data()+start,length); ylib::buffer fh; ylib::buffer fh2; ylib::buffer cs_ln; fh.resize(2); fh2.resize(2); cs_ln.resize(2); fh[0] = ';'; fh[1] = ' '; fh2[0] = ':'; fh2[1] = ' '; cs_ln[0] = '\r'; cs_ln[1] = '\n'; auto div = form_data.find_list(cs_ln); if (div.size() == -1) return; form_info forminfo; //数据 if (div.size() == 3) { forminfo.start = div[1] + 2+start; forminfo.length = div[div.size() - 1] - 2 - div[1]; } else if (div.size() > 3) { forminfo.start = div[2] + 2+start; forminfo.length = div[div.size() - 1] - 2 - div[2]; auto ContentType = form_data.sub(div[0] + 2, div[1] - 2 - div[0]); // Content-Type auto cdIdx = ContentType.find(fh2); if (cdIdx == -1) return; forminfo.content_type = ContentType.sub(cdIdx + 2, ContentType.length() - 2 - cdIdx); } else return; //配置项 auto info = form_data.sub(div[0]); std::string t = info; auto info_vct = info.find_list(fh); if (info_vct.size() == 0) return; // Content-Disposition auto contentDisposition = info.sub(info_vct[0]); auto cdIdx = contentDisposition.find(fh2); if (cdIdx == -1) return; forminfo.disposition = contentDisposition.sub(cdIdx + 2, contentDisposition.length() - 2 - cdIdx); if (info_vct.size() == 1) { auto kv = parse_paraminfo_secondkv(info.sub(info_vct[0] + 2, info.length() - info_vct[0] - 2)); if (kv.name == "name") forminfo.name = kv.value; else if (kv.name == "filename") forminfo.filename = kv.value; } else { for (size_t i = 0; i < info_vct.size(); i++) { ylib::buffer info_sub; if (info_vct.size() == i + 1) info_sub = info.sub(info_vct[i] + 2, info.length() - info_vct[i] - 2); else info_sub = info.sub(info_vct[i] + 2, info_vct[i + 1] - info_vct[i] - 2); auto kv = parse_paraminfo_secondkv(info_sub); if (kv.name == "name") forminfo.name = kv.value; else if (kv.name == "filename") forminfo.filename = kv.value; } } m_infos.insert(std::pair(forminfo.name,forminfo)); } char network::http::form_parser::getchar(size_t index) { if (index + 1 > m_data->length()) throw 0; return *(m_data->data() + index); } #endif