hrev47162 adds 1 changeset to branch 'master' old head: 5153d5ee572a2b75142a2a4233c10726e3049a2d new head: e08beebef9784529c2c3324e77a390fad20b2c04 overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=e08beeb+%5E5153d5e ---------------------------------------------------------------------------- e08beeb: 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. [ Stephan Aßmus <superstippi@xxxxxx> ] ---------------------------------------------------------------------------- Revision: hrev47162 Commit: e08beebef9784529c2c3324e77a390fad20b2c04 URL: http://cgit.haiku-os.org/haiku/commit/?id=e08beeb Author: Stephan Aßmus <superstippi@xxxxxx> Date: Wed Apr 23 22:17:49 2014 UTC ---------------------------------------------------------------------------- 4 files changed, 233 insertions(+), 62 deletions(-) src/apps/haikudepot/Model.cpp | 19 ++ src/apps/haikudepot/Model.h | 3 + src/apps/haikudepot/WebAppInterface.cpp | 267 +++++++++++++++++++++------- src/apps/haikudepot/WebAppInterface.h | 6 + ---------------------------------------------------------------------------- diff --git a/src/apps/haikudepot/Model.cpp b/src/apps/haikudepot/Model.cpp index 440907f..d8d0624 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. @@ -617,6 +618,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) { // See if there is a cached icon file diff --git a/src/apps/haikudepot/Model.h b/src/apps/haikudepot/Model.h index 6a4041f..b3a5798 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 4e6306c..f45cadc 100644 --- a/src/apps/haikudepot/WebAppInterface.cpp +++ b/src/apps/haikudepot/WebAppInterface.cpp @@ -10,19 +10,137 @@ #include <File.h> #include <HttpHeaders.h> #include <HttpRequest.h> +#include <Message.h> #include <Url.h> #include <UrlContext.h> #include <UrlProtocolListener.h> #include <UrlProtocolRoster.h> +#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<const BHttpResult&>( + 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 5635f47..f5e2a28 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; };