From e08beebef9784529c2c3324e77a390fad20b2c04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Thu, 24 Apr 2014 00:17:49 +0200 Subject: [PATCH] HaikuDepot: Work on retrieving more pkg info * Simple, incomplete JSON string-builder. * Not yet using the new bulk information method of the web-app. * Not yet parsing the reply and doing anything with it, consequently commented out. * What works is generating a JSON command and receiving the reply. --- src/apps/haikudepot/Model.cpp | 19 ++ src/apps/haikudepot/Model.h | 3 + src/apps/haikudepot/WebAppInterface.cpp | 267 ++++++++++++++++++------ src/apps/haikudepot/WebAppInterface.h | 6 + 4 files changed, 233 insertions(+), 62 deletions(-) diff --git a/src/apps/haikudepot/Model.cpp b/src/apps/haikudepot/Model.cpp index 440907f35d..d8d0624435 100644 --- a/src/apps/haikudepot/Model.cpp +++ b/src/apps/haikudepot/Model.cpp @@ -609,6 +609,7 @@ Model::_PopulateAllPackagesThread(bool fromCacheOnly) if (package.Get() == NULL) continue; +// _PopulatePackageInfo(package, fromCacheOnly); _PopulatePackageIcon(package, fromCacheOnly); // TODO: Average user rating. It needs to be shown in the // list view, so without the user clicking the package. @@ -616,6 +617,24 @@ Model::_PopulateAllPackagesThread(bool fromCacheOnly) } +void +Model::_PopulatePackageInfo(const PackageInfoRef& package, bool fromCacheOnly) +{ + if (fromCacheOnly) + return; + + // Retrieve info from web-app + WebAppInterface interface; + BMessage info; + + status_t status = interface.RetrievePackageInfo(package->Title(), info); + if (status == B_OK) { + // TODO: Parse message... + info.PrintToStream(); + } +} + + void Model::_PopulatePackageIcon(const PackageInfoRef& package, bool fromCacheOnly) { diff --git a/src/apps/haikudepot/Model.h b/src/apps/haikudepot/Model.h index 6a4041fd0e..b3a579862f 100644 --- a/src/apps/haikudepot/Model.h +++ b/src/apps/haikudepot/Model.h @@ -93,6 +93,9 @@ private: static int32 _PopulateAllPackagesEntry(void* cookie); void _PopulateAllPackagesThread(bool fromCacheOnly); + void _PopulatePackageInfo( + const PackageInfoRef& package, + bool fromCacheOnly); void _PopulatePackageIcon( const PackageInfoRef& package, bool fromCacheOnly); diff --git a/src/apps/haikudepot/WebAppInterface.cpp b/src/apps/haikudepot/WebAppInterface.cpp index 4e6306ccaa..f45cadc145 100644 --- a/src/apps/haikudepot/WebAppInterface.cpp +++ b/src/apps/haikudepot/WebAppInterface.cpp @@ -10,19 +10,137 @@ #include #include #include +#include #include #include #include #include +#include "List.h" #include "PackageInfo.h" +class JsonBuilder { +public: + JsonBuilder() + : + fString("{"), + fInList(false) + { + } + + JsonBuilder& AddObject() + { + fString << '{'; + fInList = false; + return *this; + } + + JsonBuilder& AddObject(const char* name) + { + _StartName(name); + + fString << "\":{"; + fInList = false; + return *this; + } + + JsonBuilder& EndObject() + { + fString << '}'; + fInList = true; + return *this; + } + + JsonBuilder& AddArray(const char* name) + { + _StartName(name); + + fString << "\":["; + + fInList = false; + + return *this; + } + + JsonBuilder& EndArray() + { + fString << ']'; + fInList = true; + return *this; + } + + JsonBuilder& AddValue(const char* name, const char* value) + { + _StartName(name); + + // TODO: Escape value + + fString << "\":\""; + fString << value; + fString << "\""; + + fInList = true; + + return *this; + } + + JsonBuilder& AddValue(const char* name, int value) + { + _StartName(name); + + fString << "\":"; + fString << value; + + fInList = true; + + return *this; + } + + JsonBuilder& AddValue(const char* name, bool value) + { + _StartName(name); + + fString << "\":"; + if (value) + fString << "true"; + else + fString << "false"; + + fInList = true; + + return *this; + } + + const BString& End() + { + fString << "}\n"; + return fString; + } + +private: + void _StartName(const char* name) + { + if (fInList) + fString << ",\""; + else + fString << '"'; + + fString << name; + } + +private: + BString fString; + bool fInList; +}; + + class ProtocolListener : public BUrlProtocolListener { public: ProtocolListener() : - fDownloadIO(NULL) + fDownloadIO(NULL), + fDebug(false) { } @@ -38,18 +156,23 @@ public: virtual void ResponseStarted(BUrlRequest* caller) { -// printf("ResponseStarted(%p)\n", caller); + if (fDebug) + printf("ResponseStarted(%p)\n", caller); } virtual void HeadersReceived(BUrlRequest* caller) { -// printf("HeadersReceived(%p)\n", caller); + if (fDebug) + printf("HeadersReceived(%p)\n", caller); } virtual void DataReceived(BUrlRequest* caller, const char* data, off_t position, ssize_t size) { -// printf("DataReceived(%p): %ld bytes\n", caller, size); + if (fDebug) { + printf("DataReceived(%p): %ld bytes\n", caller, size); + printf("%.*s", (int)size, data); + } if (fDownloadIO != NULL) fDownloadIO->Write(data, size); @@ -65,12 +188,14 @@ public: virtual void UploadProgress(BUrlRequest* caller, ssize_t bytesSent, ssize_t bytesTotal) { -// printf("UploadProgress(%p): %ld/%ld\n", caller, bytesSent, bytesTotal); + if (fDebug) + printf("UploadProgress(%p): %ld/%ld\n", caller, bytesSent, bytesTotal); } virtual void RequestCompleted(BUrlRequest* caller, bool success) { -// printf("RequestCompleted(%p): %d\n", caller, success); + if (fDebug) + printf("RequestCompleted(%p): %d\n", caller, success); } virtual void DebugMessage(BUrlRequest* caller, @@ -84,11 +209,22 @@ public: fDownloadIO = downloadIO; } + void SetDebug(bool debug) + { + fDebug = debug; + } + private: BDataIO* fDownloadIO; + bool fDebug; }; +int +WebAppInterface::fRequestIndex = 0; + + + WebAppInterface::WebAppInterface() { } @@ -108,62 +244,69 @@ WebAppInterface::SetAuthorization(const BString& username, } -//void -//WebAppInterface::_TestGetPackage() -//{ -// BUrl url("https://depot.haiku-os.org/api/v1/pkg"); -// -// ProtocolListener listener; -// BUrlContext context; -// BHttpHeaders headers; -// -// // Authentication -// if (!fUsername.IsEmpty() && !fPassword.IsEmpty()) { -// BString plain; -// plain << fUsername << ':' << fPassword; -// -// char base64[1024]; -// ssize_t base64Size = encode_base64(base64, plain, plain.Length(), -// false); -// -// if (base64Size > 0 && base64Size <= (ssize_t)sizeof(base64)) { -// base64[base64Size] = '\0'; -// -// BString authorization("Basic "); -// authorization << base64; -// -// headers.AddHeader("Authorization", authorization); -// } -// } -// // Content-Type -// headers.AddHeader("Content-Type", "application/json"); -// -// BHttpRequest request(url, true, "HTTP", &listener, &context); -// request.SetMethod(B_HTTP_POST); -// request.SetHeaders(headers); -// -// BMallocIO* data = new BMallocIO(); -// -// BString jsonString -// = "{" -// "\"jsonrpc\":\"2.0\"," -// "\"id\":4143431," -// "\"method\":\"getPkg\"," -// "\"params\":[{" -// "\"name\":\"apr\"," -// "\"architectureCode\":\"x86\"," -// "\"versionType\":\"NONE\"" -// "}]" -// "}" -// ; -// -// data->WriteAt(0, jsonString.String(), jsonString.Length()); -// data->Seek(0, SEEK_SET); -// request.AdoptInputData(data); -// -// thread_id thread = request.Run(); -// wait_for_thread(thread, NULL); -//} +status_t +WebAppInterface::RetrievePackageInfo(const BString& packageName, + BMessage& message) +{ + BUrl url("https://depot.haiku-os.org/api/v1/pkg"); + + ProtocolListener listener; + BUrlContext context; + BHttpHeaders headers; + // Content-Type + headers.AddHeader("Content-Type", "application/json"); + + BHttpRequest request(url, true, "HTTP", &listener, &context); + + // Authentication + if (!fUsername.IsEmpty() && !fPassword.IsEmpty()) { + request.SetUserName(fUsername); + request.SetPassword(fPassword); + } + + request.SetMethod(B_HTTP_POST); + request.SetHeaders(headers); + + BString jsonString = JsonBuilder() + .AddValue("jsonrpc", "2.0") + .AddValue("id", ++fRequestIndex) + .AddValue("method", "getPkg") + .AddArray("params") + .AddObject() + .AddValue("name", packageName) + .AddValue("architectureCode", "x86_gcc2") + .AddValue("naturalLanguageCode", "en") + .AddValue("versionType", "NONE") + .EndObject() + .EndArray() + .End(); + + printf("Sending JSON:\n%s\n", jsonString.String()); + + BMemoryIO* data = new BMemoryIO( + jsonString.String(), jsonString.Length() - 1); + + request.AdoptInputData(data, jsonString.Length() - 1); + + BMallocIO replyData; + listener.SetDownloadIO(&replyData); +// listener.SetDebug(true); + + thread_id thread = request.Run(); + wait_for_thread(thread, NULL); + + const BHttpResult& result = dynamic_cast( + request.Result()); + + int32 statusCode = result.StatusCode(); + + if (statusCode == 200) + return B_OK; + + printf("Response code: %ld\n", statusCode); + + return B_ERROR; +} status_t diff --git a/src/apps/haikudepot/WebAppInterface.h b/src/apps/haikudepot/WebAppInterface.h index 5635f47f56..f5e2a28dd7 100644 --- a/src/apps/haikudepot/WebAppInterface.h +++ b/src/apps/haikudepot/WebAppInterface.h @@ -11,6 +11,7 @@ class BDataIO; +class BMessage; class WebAppInterface { @@ -21,6 +22,10 @@ public: void SetAuthorization(const BString& username, const BString& password); + status_t RetrievePackageInfo( + const BString& packageName, + BMessage& message); + status_t RetrievePackageIcon( const BString& packageName, BDataIO* stream); @@ -28,6 +33,7 @@ public: private: BString fUsername; BString fPassword; + static int fRequestIndex; };