From 5d0a833af478b87f4fb815e37da0beb5a09c6067 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=A6=8C=EA=A6=AB=EA=A6=B6=EA=A6=8F=EA=A7=80=EA=A6=A6?= =?UTF-8?q?=EA=A6=BF=EA=A6=A7=EA=A6=AE=EA=A6=91=EA=A6=A9=EA=A6=AD=EA=A7=80?= Date: Sat, 10 Jul 2021 23:21:25 +0800 Subject: Use the response data to initiate client It's correct now, but the problem is, the client pushes the catalog page faster than the web server can reload to make the newly built sample URL valid. --- controller.cxx | 76 +++++++++++++++++++++++++++++--------------------- controller.hxx | 3 -- handler.c | 15 ++++++---- namatoko.pro | 3 +- registration.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++---------- 5 files changed, 128 insertions(+), 57 deletions(-) diff --git a/controller.cxx b/controller.cxx index e70a66d..6f7759f 100644 --- a/controller.cxx +++ b/controller.cxx @@ -1,55 +1,67 @@ +#include #include #include #include "controller.hxx" extern "C" { - void sign_up(char const*, char const*); - struct icclient_catalog* catalog_data(char const*); + void sign_up(char const*, char const*, void (*)(icclient_response *)); + struct icclient_catalog* catalog_data(char const*, char const*); } -Controller::Controller(QObject* parent) : - QObject{parent}, - catalog{nullptr} +static Controller* controller; +static QQmlApplicationEngine* engine; +static QICClient::Client* interchange = nullptr; +static QString* path = nullptr; +static QString* imageDir = nullptr; +static Catalog* catalog = nullptr; + +Controller::Controller(QObject* parent) : QObject{parent} { + controller = this; #ifdef __ANDROID__ QString cert{CA_BUNDLE}; - QString path{QDir{QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)}.absolutePath() - % cert.remove(0, cert.lastIndexOf("/"))}; - QFile{"assets:" % cert}.copy(path); -#endif - interchange = new Client{SAMPLEURL, IMAGE_DIR -#ifdef __ANDROID__ - , path.toLatin1().constData() + path = new QString{QDir{ + QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)}.absolutePath() + % cert.remove(0, cert.lastIndexOf("/"))}; + QFile{"assets:" % cert}.copy(*path); #endif - }; - auto engine = static_cast(parent); + engine = static_cast(parent); engine->load(QUrl{QStringLiteral("qrc:/main.qml")}); auto window = engine->rootObjects()[0]; - window->setProperty("imageDir", SAMPLEURL"/images/"); connect(window, SIGNAL(signUp(QString)), this, SIGNAL(signUp(QString))); - connect(this, &Controller::signUp, [/*this,*/ + connect(this, &Controller::signUp, [](QString const& brand) { + sign_up(brand.toLatin1().constData(), path ? path->toLatin1().constData() : nullptr, + [](icclient_response* response) { + QString brand{response->data}; + icclient_free_response(response); + QString sampleUrl{QString{SECURE_SERVER} % "/" % brand}; + imageDir = new QString{"/" % brand % "/images"}; + interchange = new Client{sampleUrl.toLatin1().constData(), + imageDir->toLatin1().constData() #ifdef __ANDROID__ - path + , path->toLatin1().constData() #endif - ](QString const& brand) { - sign_up(brand.toLatin1().constData(), -#ifdef __ANDROID__ - path.toLatin1().constData() -#else - nullptr -#endif - ); -// interchange->catalog(brand); - }); - connect(interchange, &Client::gotCatalog, [this,engine,window](QString const& response) { - catalog = new Catalog{catalog_data(response.toLatin1().constData())}; - engine->rootContext()->setContextProperty("catalog", catalog); - QMetaObject::invokeMethod(window, "pushCatalog"); + }; + delete path; + auto window = engine->rootObjects()[0]; + window->setProperty("imageDir", QString{sampleUrl % "/images/"}); + controller->connect(interchange, &Client::gotCatalog, + [window](QString const& response) { + catalog = new Catalog{ + catalog_data(response.toLatin1().constData(), + imageDir->toLatin1().constData())}; + engine->rootContext()->setContextProperty("catalog", + catalog); + QMetaObject::invokeMethod(window, "pushCatalog"); + }); + interchange->allProducts(); + }); }); } Controller::~Controller() { if (catalog) delete catalog; - delete interchange; + if (imageDir) delete imageDir; + if (interchange) delete interchange; } diff --git a/controller.hxx b/controller.hxx index b073a67..845179b 100644 --- a/controller.hxx +++ b/controller.hxx @@ -13,9 +13,6 @@ class Controller : public QObject ~Controller(); signals: void signUp(QString const& name); - private: - Client* interchange; - Catalog* catalog; }; #endif diff --git a/handler.c b/handler.c index 8e118f7..1a0ce01 100644 --- a/handler.c +++ b/handler.c @@ -3,21 +3,24 @@ #include #include -static void recurse_catalog(TidyDoc doc, TidyNode tnod, struct icclient_catalog **catalog) +static void recurse_catalog(TidyDoc doc, TidyNode tnod, const char *image_dir, + struct icclient_catalog **catalog) { for (TidyNode child = tidyGetChild(tnod); child; child = tidyGetNext(child)) { ctmbstr name = tidyNodeGetName(child); if (!name) continue; if (strcmp(name, "img")) { - recurse_catalog(doc, child, catalog); + recurse_catalog(doc, child, image_dir, catalog); continue; } - static const char *prefix = IMAGE_DIR"/thumb/"; + static const char *subdir = "/thumb/"; + char prefix[strlen(image_dir) + strlen(subdir) + 1]; size_t prefix_len = strlen(prefix); bool bail = false; for (TidyAttr attr = tidyAttrFirst(child); attr; attr = tidyAttrNext(attr)) - if (!strcmp(tidyAttrName(attr), "src") && strncmp(tidyAttrValue(attr), prefix, prefix_len)) { + if (!strcmp(tidyAttrName(attr), "src") + && strncmp(tidyAttrValue(attr), prefix, prefix_len)) { bail = true; break; } @@ -47,7 +50,7 @@ static void recurse_catalog(TidyDoc doc, TidyNode tnod, struct icclient_catalog } } -struct icclient_catalog *catalog_data(const char *response) +struct icclient_catalog *catalog_data(const char *response, const char *image_dir) { TidyDoc tdoc = tidyCreate(); TidyBuffer output = {0}; @@ -55,7 +58,7 @@ struct icclient_catalog *catalog_data(const char *response) tidySaveBuffer(tdoc, &output); struct icclient_catalog *catalog = malloc(sizeof(struct icclient_catalog)); catalog->length = 0; - recurse_catalog(tdoc, tidyGetRoot(tdoc), &catalog); + recurse_catalog(tdoc, tidyGetRoot(tdoc), image_dir, &catalog); tidyBufFree(&output); tidyRelease(tdoc); return catalog; diff --git a/namatoko.pro b/namatoko.pro index b2830b8..c01e708 100644 --- a/namatoko.pro +++ b/namatoko.pro @@ -1,8 +1,7 @@ QT += quickcontrols2 DEFINES += \ CA_BUNDLE=\\\"$$CA_BUNDLE\\\" \ - SAMPLEURL=\\\"$$SAMPLEURL\\\" \ - IMAGE_DIR=\\\"$$IMAGE_DIR\\\" + SECURE_SERVER=\\\"$$SECURE_SERVER\\\" debug: DEFINES += DEBUG HEADERS += controller.hxx SOURCES += \ diff --git a/registration.c b/registration.c index f3a6a0a..5e0fe00 100644 --- a/registration.c +++ b/registration.c @@ -1,35 +1,86 @@ +#ifdef DEBUG +#ifdef __ANDROID__ +#include +#else +#include +#endif #ifdef __EMSCRIPTEN__ -#include -#include #include #else +#include #include #endif +#include +#include +#include #ifdef __EMSCRIPTEN__ -static void cleanup(struct emscripten_fetch_t *fetch) +static void clean_up(struct emscripten_fetch_t *fetch) { free(fetch->userData); emscripten_fetch_close(fetch); } +#else + +struct container { + CURL *curl; + void (*handler)(icclient_response *); + icclient_response *response; +}; + +static size_t append(char *data, size_t size, size_t nmemb, icclient_response *response) +{ + size_t realsize = size * nmemb; + response->data = realloc(response->data, response->numBytes + realsize + 1); + memcpy(&(response->data[response->numBytes]), data, realsize); + response->numBytes += realsize; + response->data[response->numBytes] = '\0'; + return realsize; +} + +static int async(void *arg) +{ + int ret = thrd_success; + struct container *container = (struct container *)arg; + CURLcode res = curl_easy_perform(container->curl); + if (res == CURLE_OK) + container->handler(container->response); + else { + ret = thrd_error; +#ifdef DEBUG + const char *error = curl_easy_strerror(res); +#ifdef __ANDROID__ + __android_log_print(ANDROID_LOG_ERROR, "namatoko.so", "%s", error); +#else + fprintf(stderr, "%s\n", error); +#endif +#endif + } + curl_easy_cleanup(container->curl); + free(container); + curl_global_cleanup(); + return ret; +} #endif -void sign_up(const char *brand, const char *certificate) +#endif + +void sign_up(const char *brand, const char *certificate, void (*handler)(icclient_response *)) { + char *data = malloc(strlen(brand) + 1); + strcpy(data, brand); #ifdef __EMSCRIPTEN__ emscripten_fetch_attr_t attr; emscripten_fetch_attr_init(&attr); attr.attributes = EMSCRIPTEN_FETCH_LOAD_TO_MEMORY; strcpy(attr.requestMethod, "POST"); - char *data = malloc(strlen(brand) + 1); - strcpy(data, brand); attr.requestData = data; - attr.requestDataSize = strlen(data) + 1; + attr.requestDataSize = strlen(data); attr.userData = data; - attr.onsuccess = cleanup; - attr.onerror = cleanup; + attr.onsuccess = handler; + attr.onerror = clean_up; emscripten_fetch(&attr, "registration"); (void)certificate; #else @@ -41,10 +92,19 @@ void sign_up(const char *brand, const char *certificate) #ifdef DEBUG curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); #endif - curl_easy_setopt(curl, CURLOPT_POSTFIELDS, brand); - curl_easy_setopt(curl, CURLOPT_URL, SAMPLEURL"/registration"); - curl_easy_perform(curl); - curl_easy_cleanup(curl); - curl_global_cleanup(); + curl_easy_setopt(curl, CURLOPT_URL, SECURE_SERVER"/registration"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, append); + icclient_response *response = malloc(sizeof(icclient_response)); + response->data = malloc(1); + response->numBytes = 0; + response->userData = data; + curl_easy_setopt(curl, CURLOPT_WRITEDATA, response); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data); + struct container *container = malloc(sizeof(struct container)); + container->curl = curl; + container->handler = handler; + container->response = response; + thrd_t thread; + thrd_create(&thread, async, container); #endif } -- cgit v1.2.3