diff options
author | ꦌꦫꦶꦏ꧀ꦦꦿꦧꦮꦑꦩꦭ꧀ <erik@darapsa.co.id> | 2021-07-10 23:21:25 +0800 |
---|---|---|
committer | ꦌꦫꦶꦏ꧀ꦦꦿꦧꦮꦑꦩꦭ꧀ <erik@darapsa.co.id> | 2021-07-10 23:21:25 +0800 |
commit | 5d0a833af478b87f4fb815e37da0beb5a09c6067 (patch) | |
tree | 00a1e021aea50625d0c57ddeb4321af47a3c0641 | |
parent | 873f8a55d01ecbd11c957d140eaf2a0bb30ae51f (diff) |
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.
-rw-r--r-- | controller.cxx | 76 | ||||
-rw-r--r-- | controller.hxx | 3 | ||||
-rw-r--r-- | handler.c | 15 | ||||
-rw-r--r-- | namatoko.pro | 3 | ||||
-rw-r--r-- | 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 <icclient.h> #include <QtQml> #include <qicclient/admin.hxx> #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<QQmlApplicationEngine*>(parent); + engine = static_cast<QQmlApplicationEngine*>(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 @@ -3,21 +3,24 @@ #include <tidybuffio.h> #include <icclient.h> -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 <android/log.h> +#else +#include <stdio.h> +#endif #ifdef __EMSCRIPTEN__ -#include <stdlib.h> -#include <string.h> #include <emscripten/fetch.h> #else +#include <threads.h> #include <curl/curl.h> #endif +#include <stdlib.h> +#include <string.h> +#include <icclient/typedefs.h> #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 } |