Skip to content
This repository has been archived by the owner on Jun 9, 2023. It is now read-only.

Commit

Permalink
add spdlog for logging, check result to avoid crash when get unexpect…
Browse files Browse the repository at this point in the history
… redirect reponse
  • Loading branch information
poor-circle committed Dec 13, 2021
1 parent 4ebb475 commit 1df7254
Show file tree
Hide file tree
Showing 10 changed files with 201 additions and 118 deletions.
9 changes: 5 additions & 4 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
{
"cmake.configureSettings": {
"CMAKE_TOOLCHAIN_FILE": "C://vcpkg//vcpkg//scripts//buildsystems//vcpkg.cmake",
"VCPKG_TARGET_TRIPLET": "x64-windows-static",
"CMAKE_TOOLCHAIN_FILE": "/root/vcpkg/scripts/buildsystems/vcpkg.cmake",
},
"C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools"

"C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools",
"files.associations": {
"thread": "cpp"
}
}
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ find_package(nlohmann_json CONFIG REQUIRED)
find_path(CPP_HTTPLIB_INCLUDE_DIRS "httplib.h")
target_include_directories(daily_reporter PRIVATE ${CPP_HTTPLIB_INCLUDE_DIRS})

find_package(spdlog CONFIG REQUIRED)
target_link_libraries(daily_reporter PRIVATE spdlog::spdlog_header_only)

set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
Expand Down
89 changes: 57 additions & 32 deletions include/config.h
Original file line number Diff line number Diff line change
@@ -1,32 +1,50 @@
#pragma once
#include<utility>
#include<string>
#include<fstream>
#include<iostream>
#include"nlohmann/json.hpp"
inline nlohmann::json& default_json()

#ifdef NDEBUG
#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_INFO
#else
#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_DEBUG
#endif

#include "spdlog/spdlog.h"

namespace
{

const inline auto set_level=[]{
#ifdef NDEBUG
spdlog::set_level(spdlog::level::info);
#else
spdlog::set_level(spdlog::level::debug);
#endif
return 0;
}();
}


#include "fmt/format.h"
#include "fmt/ranges.h"

#include <utility>
#include <string>
#include <fstream>
#include <iostream>
#include <thread>

#include "nlohmann/json.hpp"

inline nlohmann::json &default_json()
{
static nlohmann::json default_json =
{
{"user_agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36 Edg/92.0.902.84"},
{"form_data","{\"formData\":[{\"name\":\"select_1582538796361\",\"title\":\"\\u4ECA\\u65E5\\u4F53\\u6E29 Body temperature today \\uFF08\\u2103\\uFF09\",\"value\":{\"stringValue\":\"37.3\\u4EE5\\u4E0B Below 37.3 degree celsius\"},\"hide\":false},{\"name\":\"select_1582538846920\",\"title\":\"\\u662F\\u5426\\u51FA\\u73B0\\u53D1\\u70ED\\u6216\\u54B3\\u55FD\\u6216\\u80F8\\u95F7\\u6216\\u547C\\u5438\\u56F0\\u96BE\\u7B49\\u75C7\\u72B6\\uFF1FDo you have sypmtoms such as fever, coughing, chest tightness or breath difficulties?\",\"value\":{\"stringValue\":\"\\u5426 No\"},\"hide\":false},{\"name\":\"select_1584240106785\",\"title\":\"\\u5B66\\u751F\\u672C\\u4EBA\\u662F\\u5426\\u586B\\u5199\",\"value\":{\"stringValue\":\"\\u662F\"},\"hide\":false},{\"name\":\"select_1582538939790\",\"title\":\"Can you hereby declare that all the information provided is all true and accurate and there is no concealment, false information or omission. \\u672C\\u4EBA\\u662F\\u5426\\u627F\\u8BFA\\u6240\\u586B\\u62A5\\u7684\\u5168\\u90E8\\u5185\\u5BB9\\u5747\\u5C5E\\u5B9E\\u3001\\u51C6\\u786E\\uFF0C\\u4E0D\\u5B58\\u5728\\u4EFB\\u4F55\\u9690\\u7792\\u548C\\u4E0D\\u5B9E\\u7684\\u60C5\\u51B5\\uFF0C\\u66F4\\u65E0\\u9057\\u6F0F\\u4E4B\\u5904\\u3002\",\"value\":{\"stringValue\":\"\\u662F Yes\"},\"hide\":false},{\"name\":\"input_1582538924486\",\"title\":\"\\u5907\\u6CE8 Notes\",\"value\":{\"stringValue\":\"\"},\"hide\":false},{\"name\":\"datetime_1611146487222\",\"title\":\"\\u6253\\u5361\\u65F6\\u95F4\\uFF08\\u65E0\\u9700\\u586B\\u5199\\uFF0C\\u4FDD\\u5B58\\u540E\\u4F1A\\u81EA\\u52A8\\u66F4\\u65B0\\uFF09\",\"value\":{\"dateValue\":\"\"},\"hide\":false}],\"playerId\":\"owner\"}" },
{"report_retry",{
{"duration",10},
{"counts",3}
}},
{"mail",{
{"address",""},
{"smtp_password",""},
{"reporter_name","HAL-9000"}
}},
{"xmu",{
{"ID",""},
{"password",""}
}}
};
{
{"user_agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36 Edg/92.0.902.84"},
{"form_data", "{\"formData\":[{\"name\":\"select_1582538796361\",\"title\":\"\\u4ECA\\u65E5\\u4F53\\u6E29 Body temperature today \\uFF08\\u2103\\uFF09\",\"value\":{\"stringValue\":\"37.3\\u4EE5\\u4E0B Below 37.3 degree celsius\"},\"hide\":false},{\"name\":\"select_1582538846920\",\"title\":\"\\u662F\\u5426\\u51FA\\u73B0\\u53D1\\u70ED\\u6216\\u54B3\\u55FD\\u6216\\u80F8\\u95F7\\u6216\\u547C\\u5438\\u56F0\\u96BE\\u7B49\\u75C7\\u72B6\\uFF1FDo you have sypmtoms such as fever, coughing, chest tightness or breath difficulties?\",\"value\":{\"stringValue\":\"\\u5426 No\"},\"hide\":false},{\"name\":\"select_1584240106785\",\"title\":\"\\u5B66\\u751F\\u672C\\u4EBA\\u662F\\u5426\\u586B\\u5199\",\"value\":{\"stringValue\":\"\\u662F\"},\"hide\":false},{\"name\":\"select_1582538939790\",\"title\":\"Can you hereby declare that all the information provided is all true and accurate and there is no concealment, false information or omission. \\u672C\\u4EBA\\u662F\\u5426\\u627F\\u8BFA\\u6240\\u586B\\u62A5\\u7684\\u5168\\u90E8\\u5185\\u5BB9\\u5747\\u5C5E\\u5B9E\\u3001\\u51C6\\u786E\\uFF0C\\u4E0D\\u5B58\\u5728\\u4EFB\\u4F55\\u9690\\u7792\\u548C\\u4E0D\\u5B9E\\u7684\\u60C5\\u51B5\\uFF0C\\u66F4\\u65E0\\u9057\\u6F0F\\u4E4B\\u5904\\u3002\",\"value\":{\"stringValue\":\"\\u662F Yes\"},\"hide\":false},{\"name\":\"input_1582538924486\",\"title\":\"\\u5907\\u6CE8 Notes\",\"value\":{\"stringValue\":\"\"},\"hide\":false},{\"name\":\"datetime_1611146487222\",\"title\":\"\\u6253\\u5361\\u65F6\\u95F4\\uFF08\\u65E0\\u9700\\u586B\\u5199\\uFF0C\\u4FDD\\u5B58\\u540E\\u4F1A\\u81EA\\u52A8\\u66F4\\u65B0\\uFF09\",\"value\":{\"dateValue\":\"\"},\"hide\":false}],\"playerId\":\"owner\"}"},
{"report_retry", {{"duration", 100}, {"counts", 10}}},
{"mail", {{"address", ""}, {"smtp_password", ""}, {"reporter_name", "HAL-9000"}}},
{"xmu", {{"ID", ""}, {"password", ""}}}};
return default_json;
}
inline nlohmann::json& init_json()
inline nlohmann::json &init_json()
{
static auto j = default_json();
std::ifstream file("report_setting.json");
Expand All @@ -37,7 +55,7 @@ inline nlohmann::json& init_json()
j.update(user_json);
return j;
}
inline nlohmann::json& get_json()
inline nlohmann::json &get_json()
{
static nlohmann::json j = init_json();
return j;
Expand All @@ -46,7 +64,7 @@ inline std::string get_user_agent()
{
return get_json().at("user_agent").get<std::string>();
}
inline std::string get_form_data()
inline std::string get_form_data()
{
return get_json().at("form_data").get<std::string>();
}
Expand All @@ -60,21 +78,21 @@ inline int get_report_retry_counts()
}
inline std::pair<std::string, std::string> get_user_info()
{
auto& j = get_json().at("xmu");
return { j.at("ID").get<std::string>(),j.at("password").get<std::string>() };
auto &j = get_json().at("xmu");
return {j.at("ID").get<std::string>(), j.at("password").get<std::string>()};
}
inline bool is_send_mail()
{
return get_json().at("mail").at("address").get<std::string>() != "";
}
inline std::pair<std::string, std::string> get_mail_info()
{
auto& j = get_json().at("mail");
return { j.at("address").get<std::string>(), j.at("smtp_password").get<std::string>() };
auto &j = get_json().at("mail");
return {j.at("address").get<std::string>(), j.at("smtp_password").get<std::string>()};
}
inline std::string get_reporter_name()
{
return get_json().at("mail").at("reporter_name").get<std::string>();
return get_json().at("mail").at("reporter_name").get<std::string>();
}
inline bool check_config()
{
Expand All @@ -97,8 +115,15 @@ inline bool check_config()
}
}
}
catch (const std::exception& e){}
catch (const std::exception &e)
{
}
std::ofstream s("report_setting.json");
s << default_json().dump(4);
return false;
}
template<typename T>
inline void rand_sleep(T duration)
{
std::this_thread::sleep_for((duration/duration.count())*(rand()%duration.count()));
}
10 changes: 5 additions & 5 deletions include/login.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#pragma once

#include<optional>
#include<string_view>
#include<memory>
#include <optional>
#include <string_view>
#include <memory>

#include<httplib.h>
std::unique_ptr<httplib::Client> login(const std::string_view src_url,std::optional<std::string_view> login_check_path = {});
#include <httplib.h>
std::unique_ptr<httplib::Client> login(const std::string_view src_url, std::optional<std::string_view> login_check_path = {});
6 changes: 3 additions & 3 deletions include/mail.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#pragma once

#include<string_view>
#include<optional>
#include <string_view>
#include <optional>

//send default null message means success
void send_daily_report_mail(std::string_view title, std::string_view context="");
void send_daily_report_mail(std::string_view title, std::string_view context = "");
4 changes: 2 additions & 2 deletions include/report.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#pragma once

#include<string>
#include<optional>
#include <string>
#include <optional>

std::optional<std::string> report_now();
105 changes: 79 additions & 26 deletions src/login.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
#include <exception>

#include "httplib.h"
#include "fmt/format.h"
#include "nlohmann/json.hpp"
#include "openssl/aes.h"

#include "config.h"
Expand All @@ -25,7 +23,7 @@ vector<unsigned char> rndstr(size_t len)
ret.push_back(random_chars[rnd(e)]);
return ret;
}
void PKCS7Padding(vector<unsigned char>& str)
void PKCS7Padding(vector<unsigned char> &str)
{
unsigned char remain = 16 - str.size() % 16;
for (size_t i = 0; i < remain; ++i)
Expand All @@ -46,10 +44,10 @@ string aes_128_encryption(string_view raw_info, string_view aes_key)
{
throw invalid_argument("aes_key error!");
}
AES_set_encrypt_key((unsigned char*)aes_key.data(), 128, &enc_key);
AES_set_encrypt_key((unsigned char *)aes_key.data(), 128, &enc_key);
auto in = addlen(raw_info), iv = rndstr(16);
dec_out.resize(in.size());
AES_cbc_encrypt(in.data(), (unsigned char*)dec_out.data(), in.size(), &enc_key, iv.data(), AES_ENCRYPT);
AES_cbc_encrypt(in.data(), (unsigned char *)dec_out.data(), in.size(), &enc_key, iv.data(), AES_ENCRYPT);
return httplib::detail::base64_encode(dec_out);
}
auto parseHTML(string_view s, string_view pattern)
Expand Down Expand Up @@ -78,62 +76,117 @@ pair<string, string> url_parse(const string_view url)
{
if (*iter == '/' && pre != '/' && (iter + 1 == url.end() || *(iter + 1) != '/'))
{
return { string(url.substr(0, iter - url.begin())) ,string(url.substr(iter - url.begin(), url.end() - iter)) };
return {string(url.substr(0, iter - url.begin())), string(url.substr(iter - url.begin(), url.end() - iter))};
}
pre = *iter;
}
return { "","" };
return {"", ""};
}
unique_ptr<httplib::Client> login(const string_view src_url, optional<string_view> login_check_path = {})
{
auto host = "https://ids.xmu.edu.cn"s;
auto path = "/authserver/login?service="s.append(src_url);
auto headers = httplib::Headers{ {"User-Agent",get_user_agent()} };
auto headers = httplib::Headers{{"User-Agent", get_user_agent()}};
httplib::Client cli(host.data());
cli.set_keep_alive(true);
cli.enable_server_certificate_verification(false);
auto res = cli.Get(path.data(), headers);
if (!res)
{
SPDLOG_ERROR("failed to open the XMU Universal login URL:{}",path);
return {};
auto [username, password] = get_user_info();
}

SPDLOG_DEBUG("Headers:{}",res.value().headers);
SPDLOG_DEBUG("Body:{}",res.value().body);
SPDLOG_DEBUG("Status:{}",res.value().status);
SPDLOG_DEBUG("Cookie for try to login:{}", res->get_header_value("Set-Cookie"));

headers.emplace("Cookie", res->get_header_value("Set-Cookie"));
res = cli.Post
(
path.data(), headers,
httplib::Params
{
{ "dllt", "userNamePasswordLogin"},
{ "execution", "e1s1" },
{ "_eventId","submit" },
{ "rmShown","1" },
{ "lt", string(get_lt(res->body)) },
{ "username",username },
{ "password",aes_128_encryption(password,get_aeskey(res->body)) }
}
);
rand_sleep(500ms);
auto [username, password] = get_user_info();

SPDLOG_INFO("Login username:{}",username);
SPDLOG_DEBUG("Login password:{}",password);

auto params = httplib::Params
{
{"dllt", "userNamePasswordLogin"},
{"execution", "e1s1"},
{"_eventId", "submit"},
{"rmShown", "1"},
{"lt", string(get_lt(res->body))},
{"username", username},
{"password", aes_128_encryption(password, get_aeskey(res->body))}
};

SPDLOG_DEBUG("URL:{}",path);
SPDLOG_DEBUG("Headers:{}",headers);
SPDLOG_DEBUG("Params:{}",params);

res = cli.Post(path.data(), headers, params);
if (!res)
{
SPDLOG_ERROR("failed to login when post username and password.");
return {};
}

SPDLOG_DEBUG("Headers:{}",res.value().headers);
SPDLOG_DEBUG("Body:{}",res.value().body);
SPDLOG_DEBUG("Status:{}",res.value().status);

auto location=res->get_header_value("Location");
if (location.empty())
{
SPDLOG_DEBUG("failed to get the redirect-location");
}
tie(host, path) = url_parse(res->get_header_value("Location"));
SPDLOG_DEBUG("redirect host:{} path:{}",host, path);

auto cli2 = make_unique<httplib::Client>(host.data());
cli2->set_keep_alive(true);
cli2->enable_server_certificate_verification(false);
res = cli2->Get(path.data(),headers);
res = cli2->Get(path.data(), headers);
if (!res)
{
SPDLOG_ERROR("failed to login when redirect.");
SPDLOG_ERROR("Host:{} Path:{}",host,path);
SPDLOG_ERROR("Headers:{}",headers);
return {};
}

SPDLOG_DEBUG("response headers: {}",res->headers);
rand_sleep(500ms);

auto [iter, iterend] = res->headers.equal_range("Set-Cookie");
for (; iter != iterend; ++iter)
{
if (iter->second.find("SAAS_U") != string::npos)
{
cli2->set_default_headers({ {"User-Agent",get_user_agent()},{ "Cookie", iter->second } });
cli2->set_default_headers({{"User-Agent", get_user_agent()}, {"Cookie", iter->second}});
if (login_check_path.has_value())
{
res = cli2->Get(string(login_check_path.value()).data());
if (!res || res->status != 200)
if (!res)
{
SPDLOG_ERROR("login check failed! SAAS_U:{}",iter->second);
return {};
}
if (res->status != 200)
{
SPDLOG_ERROR("login check failed! SAAS_U:{}",iter->second);
SPDLOG_ERROR("login check result:");
SPDLOG_ERROR("Headers:{}",res.value().headers);
SPDLOG_ERROR("Body:{}",res.value().body);
SPDLOG_ERROR("Status:{}",res.value().status);
return {};
}
}
SPDLOG_INFO("login succeed! {}",iter->second);
return cli2;
}
}

SPDLOG_ERROR("Can't found the cookie called SAAS_U for saving the login status!");
return {};
}
Loading

0 comments on commit 1df7254

Please sign in to comment.