From 3bf3fdee409a746fe59047a30bd674e63542351b Mon Sep 17 00:00:00 2001 From: rexbu Date: Sat, 17 Mar 2018 15:37:49 +0800 Subject: [PATCH] update --- 3rdparty/cJSON/.DS_Store => .DS_Store | Bin 6148 -> 6148 bytes {basic => 3rdparty}/.DS_Store | Bin 6148 -> 6148 bytes 3rdparty/Android.mk | 2 +- 3rdparty/README.md | 5 - 3rdparty/cJSON/Android.mk | 13 - 3rdparty/libzip/Android.mk | 2 +- 3rdparty/libzip/Application.mk | 3 - Android.mk | 2 +- Application.mk | 3 + basic/Android.mk | 42 +- basic/JSON.cpp | 28 +- basic/JSON.h | 1 - basic/McHttp.cpp | 71 +- basic/McHttp.h | 3 +- basic/McReference.h | 1 - basic/ThreadPool.h | 2 +- basic/android/McDevice.cpp | 16 +- basic/android/McResource.cpp | 2 +- basic/cJSON.h | 149 --- basic/ios/McDevice.mm | 48 +- basic/ios/McHttp.mm | 225 ---- basic/ios/McZip.mm | 354 ----- basic/ios/SFHFKeychainUtils.h | 41 + basic/ios/SFHFKeychainUtils.m | 438 ++++++ bs/Android.mk | 3 +- bs/bs.h | 1 + bs/bs_dnscache.c | 59 +- bs/bs_dnscache.h | 10 +- 3rdparty/cJSON/cJSON.c => bs/bs_json.c | 2 +- 3rdparty/cJSON/cJSON.h => bs/bs_json.h | 0 bs/bs_sign.h | 1 + bs/bs_socket.c | 85 +- bs/bs_socket.h | 2 + bs/bs_url.c | 441 +++--- bs/bs_url.h | 11 +- model/.DS_Store | Bin 6148 -> 6148 bytes model/async/Android.mk | 4 - model/p2p/.DS_Store | Bin 6148 -> 0 bytes model/utp/.DS_Store | Bin 6148 -> 0 bytes native/Android.mk | 14 + native/NativeLoad.cpp | 132 ++ src/.gitignore | 32 + src/Android.mk | 56 + src/Me.h | 36 + src/MeACL.cpp | 146 ++ src/MeACL.h | 54 + src/MeCallback.cpp | 73 + src/MeCallback.h | 42 + src/MeCloud.cpp | 249 ++++ src/MeCloud.h | 91 ++ src/MeDevice.cpp | 101 ++ src/MeDevice.h | 31 + src/MeDownloadFile.cpp | 40 + src/MeDownloadFile.h | 32 + src/MeError.h | 21 + src/MeFile.cpp | 137 ++ src/MeFile.h | 82 ++ src/MeHttpFileCallback.cpp | 74 + src/MeHttpFileCallback.h | 49 + src/MeJoinQuery.cpp | 305 +++++ src/MeJoinQuery.h | 65 + src/MeObject.cpp | 488 +++++++ src/MeObject.h | 115 ++ src/MeQuery.cpp | 315 +++++ src/MeQuery.h | 120 ++ src/MeRole.cpp | 25 + src/MeRole.h | 27 + src/MeSMS.cpp | 21 + src/MeSMS.h | 19 + src/MeTimeStat.cpp | 62 + src/MeTimeStat.h | 29 + src/MeUploadFile.cpp | 128 ++ src/MeUploadFile.h | 51 + src/MeUser.cpp | 194 +++ src/MeUser.h | 58 + src/README.md | 1 + src/android/GetAuthInfomationCallback.cpp | 40 + src/android/GetAuthInfomationCallback.h | 27 + src/android/MeAndroidCallback.cpp | 145 ++ src/android/MeAndroidCallback.h | 43 + src/android/MeAndroidHttpFileCallBack.cpp | 210 +++ src/android/MeAndroidHttpFileCallBack.h | 47 + src/android/UpLoadFileCallBack.cpp | 31 + src/android/UpLoadFileCallBack.h | 22 + src/android/android_mecloud.cpp | 1486 +++++++++++++++++++++ src/ios/MeCrypt.h | 21 + src/ios/MeCrypt.mm | 60 + src/ios/MeDownloadFile.mm | 19 + src/ios/MeHeader.h | 24 + src/ios/MeIOSACL.h | 61 + src/ios/MeIOSACL.mm | 102 ++ src/ios/MeIOSCallback.h | 29 + src/ios/MeIOSCallback.mm | 32 + src/ios/MeIOSException.h | 23 + src/ios/MeIOSException.mm | 35 + src/ios/MeIOSFile.h | 23 + src/ios/MeIOSFile.mm | 53 + src/ios/MeIOSHttpDataCallback.h | 31 + src/ios/MeIOSHttpDataCallback.mm | 40 + src/ios/MeIOSHttpFileCallback.h | 32 + src/ios/MeIOSHttpFileCallback.mm | 60 + src/ios/MeIOSJSONObject.h | 68 + src/ios/MeIOSJSONObject.mm | 204 +++ src/ios/MeIOSJoinQuery.h | 48 + src/ios/MeIOSJoinQuery.mm | 100 ++ src/ios/MeIOSNetManager.h | 109 ++ src/ios/MeIOSNetManager.mm | 371 +++++ src/ios/MeIOSObject.h | 43 + src/ios/MeIOSObject.mm | 134 ++ src/ios/MeIOSQuery.h | 102 ++ src/ios/MeIOSQuery.mm | 203 +++ src/ios/MeIOSRole.h | 23 + src/ios/MeIOSRole.mm | 40 + src/ios/MeIOSUser.h | 32 + src/ios/MeIOSUser.mm | 91 ++ src/ios/MeObject.mm | 17 + src/ios/MeQuery.mm | 22 + src/ios/MeUploadFile.mm | 31 + src/ios/MeUser.mm | 44 + src/setup.sh | 41 + 120 files changed, 8941 insertions(+), 1063 deletions(-) rename 3rdparty/cJSON/.DS_Store => .DS_Store (91%) rename {basic => 3rdparty}/.DS_Store (82%) delete mode 100644 3rdparty/README.md delete mode 100644 3rdparty/cJSON/Android.mk delete mode 100755 3rdparty/libzip/Application.mk create mode 100755 Application.mk delete mode 100644 basic/cJSON.h delete mode 100644 basic/ios/McHttp.mm delete mode 100644 basic/ios/McZip.mm create mode 100755 basic/ios/SFHFKeychainUtils.h create mode 100755 basic/ios/SFHFKeychainUtils.m rename 3rdparty/cJSON/cJSON.c => bs/bs_json.c (99%) rename 3rdparty/cJSON/cJSON.h => bs/bs_json.h (100%) delete mode 100644 model/p2p/.DS_Store delete mode 100644 model/utp/.DS_Store create mode 100644 native/Android.mk create mode 100644 native/NativeLoad.cpp create mode 100644 src/.gitignore create mode 100644 src/Android.mk create mode 100644 src/Me.h create mode 100644 src/MeACL.cpp create mode 100644 src/MeACL.h create mode 100644 src/MeCallback.cpp create mode 100644 src/MeCallback.h create mode 100644 src/MeCloud.cpp create mode 100644 src/MeCloud.h create mode 100644 src/MeDevice.cpp create mode 100644 src/MeDevice.h create mode 100644 src/MeDownloadFile.cpp create mode 100644 src/MeDownloadFile.h create mode 100644 src/MeError.h create mode 100644 src/MeFile.cpp create mode 100644 src/MeFile.h create mode 100644 src/MeHttpFileCallback.cpp create mode 100644 src/MeHttpFileCallback.h create mode 100644 src/MeJoinQuery.cpp create mode 100644 src/MeJoinQuery.h create mode 100644 src/MeObject.cpp create mode 100644 src/MeObject.h create mode 100644 src/MeQuery.cpp create mode 100644 src/MeQuery.h create mode 100644 src/MeRole.cpp create mode 100644 src/MeRole.h create mode 100644 src/MeSMS.cpp create mode 100644 src/MeSMS.h create mode 100644 src/MeTimeStat.cpp create mode 100644 src/MeTimeStat.h create mode 100644 src/MeUploadFile.cpp create mode 100644 src/MeUploadFile.h create mode 100644 src/MeUser.cpp create mode 100644 src/MeUser.h create mode 100644 src/README.md create mode 100644 src/android/GetAuthInfomationCallback.cpp create mode 100644 src/android/GetAuthInfomationCallback.h create mode 100644 src/android/MeAndroidCallback.cpp create mode 100644 src/android/MeAndroidCallback.h create mode 100644 src/android/MeAndroidHttpFileCallBack.cpp create mode 100644 src/android/MeAndroidHttpFileCallBack.h create mode 100644 src/android/UpLoadFileCallBack.cpp create mode 100644 src/android/UpLoadFileCallBack.h create mode 100644 src/android/android_mecloud.cpp create mode 100644 src/ios/MeCrypt.h create mode 100644 src/ios/MeCrypt.mm create mode 100644 src/ios/MeDownloadFile.mm create mode 100644 src/ios/MeHeader.h create mode 100644 src/ios/MeIOSACL.h create mode 100644 src/ios/MeIOSACL.mm create mode 100644 src/ios/MeIOSCallback.h create mode 100644 src/ios/MeIOSCallback.mm create mode 100644 src/ios/MeIOSException.h create mode 100644 src/ios/MeIOSException.mm create mode 100644 src/ios/MeIOSFile.h create mode 100644 src/ios/MeIOSFile.mm create mode 100644 src/ios/MeIOSHttpDataCallback.h create mode 100644 src/ios/MeIOSHttpDataCallback.mm create mode 100644 src/ios/MeIOSHttpFileCallback.h create mode 100644 src/ios/MeIOSHttpFileCallback.mm create mode 100644 src/ios/MeIOSJSONObject.h create mode 100644 src/ios/MeIOSJSONObject.mm create mode 100644 src/ios/MeIOSJoinQuery.h create mode 100644 src/ios/MeIOSJoinQuery.mm create mode 100644 src/ios/MeIOSNetManager.h create mode 100644 src/ios/MeIOSNetManager.mm create mode 100644 src/ios/MeIOSObject.h create mode 100644 src/ios/MeIOSObject.mm create mode 100644 src/ios/MeIOSQuery.h create mode 100644 src/ios/MeIOSQuery.mm create mode 100644 src/ios/MeIOSRole.h create mode 100644 src/ios/MeIOSRole.mm create mode 100644 src/ios/MeIOSUser.h create mode 100644 src/ios/MeIOSUser.mm create mode 100644 src/ios/MeObject.mm create mode 100644 src/ios/MeQuery.mm create mode 100644 src/ios/MeUploadFile.mm create mode 100644 src/ios/MeUser.mm create mode 100755 src/setup.sh diff --git a/3rdparty/cJSON/.DS_Store b/.DS_Store similarity index 91% rename from 3rdparty/cJSON/.DS_Store rename to .DS_Store index 5008ddfcf53c02e82d7eee2e57c38e5672ef89f6..368ea93fad15abd9af95bae05114e0cdf4da1e56 100644 GIT binary patch delta 261 zcmZoMXfc=|#>B`mF;Q%yo}wr_0|Nsi1A_nqLn1>FLkUA=S#VL_#Kh(GAPEizW1wIP zLjkg6PJUiGL=yumLlRJ?m?4uP8KezKh6yNBj3&m)kjsz{G%b}O2Tg{JArELy3DBG} zhSZeeAjHu~2NHo+1YW5HK<@2y8yc=*G7B0%I2AW_AvK4xj>{$am(+{342+ UKzW7)kiy9(Jj$D6L{=~Z05sDNYXATM diff --git a/basic/.DS_Store b/3rdparty/.DS_Store similarity index 82% rename from basic/.DS_Store rename to 3rdparty/.DS_Store index b0a2f31016805585e1be8cd55f0ae445c5b0b403..44190e1b981cd3864a2e5da04737c29d0a010da3 100644 GIT binary patch delta 104 zcmZoMXfc=|#>CJzu~2NHo}wrt0|NsP3otNbG8B{r7v<&T=cP|9R2KwEurcHSg_9Vn xK$4rKncuK%c3`e&+RV)<`|JB%mC!)7n%S7 delta 365 zcmZoMXfc=|#>B)qu~2NHo}wr-0|Nsi1A_nqLq0<$LrPM4aY0hf#*NDv>p?Q?42cYR z3@Hpn$g=rKK$(+C1v#0;B?bo98JU<_SlQS)IJh{tc)4POGxE!WOA<>;i=7gSqCvcX z#FC68C_5xSKL^fEObW|PEsqxvan8>xNzBYkEdp!KOi2YQsgDWI%uC5Hcgio#ODP5$ z6bzB!;Naxoj2Doot~N0>)lo1pF|O57s5Un@0J4qEYHK+;#8nM#Jri;(tEy{i>t+I7 z3j~ZnUxEQYl!j5WfDAN$mIW8(3FYMHr30lv+L(bslh07Ran2i-&Fmcf9Khh)xbZvl aWPTA{5s)z;H4P9NY|G{lkqyif8(09Kpjz($ diff --git a/3rdparty/Android.mk b/3rdparty/Android.mk index 55ca333..6571161 100644 --- a/3rdparty/Android.mk +++ b/3rdparty/Android.mk @@ -1 +1 @@ -include $(all-subdir-makefiles) \ No newline at end of file +include $(all-subdir-makefiles) diff --git a/3rdparty/README.md b/3rdparty/README.md deleted file mode 100644 index 53d5aab..0000000 --- a/3rdparty/README.md +++ /dev/null @@ -1,5 +0,0 @@ -## libzip -from julienr/libzip-android - -## libzipp -from ctabin/libzippp diff --git a/3rdparty/cJSON/Android.mk b/3rdparty/cJSON/Android.mk deleted file mode 100644 index b5f493d..0000000 --- a/3rdparty/cJSON/Android.mk +++ /dev/null @@ -1,13 +0,0 @@ -LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_CFLAGS += -D__ANDROID__ -g -#APP_PLATFORM := android-19 - -LOCAL_SRC_FILES += \ - cJSON.c - -#LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -llog -LOCAL_MODULE := cjson - -include $(BUILD_STATIC_LIBRARY) diff --git a/3rdparty/libzip/Android.mk b/3rdparty/libzip/Android.mk index f7fb928..15d332f 100755 --- a/3rdparty/libzip/Android.mk +++ b/3rdparty/libzip/Android.mk @@ -3,7 +3,7 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_CPP_EXTENSION := .cpp .cc -LIBZIP_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.c) +LIBZIP_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.c $(LOCAL_PATH)/*.cpp) LOCAL_C_INCLUDES := $(LOCAL_PATH)/ LOCAL_SRC_FILES := $(LIBZIP_SRC_FILES:$(LOCAL_PATH)/%=%) LOCAL_MODULE := zip diff --git a/3rdparty/libzip/Application.mk b/3rdparty/libzip/Application.mk deleted file mode 100755 index ab3d773..0000000 --- a/3rdparty/libzip/Application.mk +++ /dev/null @@ -1,3 +0,0 @@ -# NDK_TOOLCHAIN_VERSION := 4.9 -# APP_STL := gnustl_static -# APP_ABI := armeabi-v7a diff --git a/Android.mk b/Android.mk index 55ca333..6571161 100644 --- a/Android.mk +++ b/Android.mk @@ -1 +1 @@ -include $(all-subdir-makefiles) \ No newline at end of file +include $(all-subdir-makefiles) diff --git a/Application.mk b/Application.mk new file mode 100755 index 0000000..b970743 --- /dev/null +++ b/Application.mk @@ -0,0 +1,3 @@ +# NDK_TOOLCHAIN_VERSION := 4.9 +APP_STL := gnustl_static +APP_ABI := armeabi-v7a \ No newline at end of file diff --git a/basic/Android.mk b/basic/Android.mk index 412b108..349953d 100644 --- a/basic/Android.mk +++ b/basic/Android.mk @@ -1,14 +1,13 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) -LOCAL_CFLAGS += -D__ANDROID__ -g +LOCAL_CFLAGS += -D__ANDROID__ -g -DDEBUG #APP_PLATFORM := android-19 LOCAL_C_INCLUDES = \ - $(LOCAL_PATH)/../3rdparty/cJSON \ $(LOCAL_PATH)/../3rdparty/libzip \ - $(LOCAL_PATH)/../3rdparty/libzippp \ - $(LOCAL_PATH)/../bs + $(LOCAL_PATH)/../bs \ + $(LOCAL_PATH)/ SRCFILES = $(wildcard $(LOCAL_PATH)/*.cpp $(LOCAL_PATH)/*/*.cpp) SRCS = $(patsubst $(LOCAL_PATH)/%, ./%,$(SRCFILES)) @@ -16,15 +15,32 @@ SRCS = $(patsubst $(LOCAL_PATH)/%, ./%,$(SRCFILES)) LOCAL_SRC_FILES += \ $(SRCS) -LOCAL_STATIC_LIBRARIES := \ - libbs \ - libcjson \ - libzippp \ - libzip +#LOCAL_SHARED_LIBRARIES := libnative +#LOCAL_LDLIBS := -llog -landroid -lz -ldl + +LOCAL_MODULE := basic_d + +include $(BUILD_STATIC_LIBRARY) + +include $(CLEAR_VARS) + +LOCAL_CFLAGS += -D__ANDROID__ -g +#APP_PLATFORM := android-19 + +LOCAL_C_INCLUDES = \ + $(LOCAL_PATH)/../3rdparty/libzip \ + $(LOCAL_PATH)/../bs \ + $(LOCAL_PATH)/ + +SRCFILES = $(wildcard $(LOCAL_PATH)/*.cpp $(LOCAL_PATH)/*/*.cpp) +SRCS = $(patsubst $(LOCAL_PATH)/%, ./%,$(SRCFILES)) + +LOCAL_SRC_FILES += \ + $(SRCS) -LOCAL_SHARED_LIBRARIES := libnative -LOCAL_LDLIBS := -llog -landroid -lz -ldl +#LOCAL_SHARED_LIBRARIES := libnative +#LOCAL_LDLIBS := -llog -landroid -lz -ldl -LOCAL_MODULE := MobileCross +LOCAL_MODULE := basic_r -include $(BUILD_SHARED_LIBRARY) +include $(BUILD_STATIC_LIBRARY) \ No newline at end of file diff --git a/basic/JSON.cpp b/basic/JSON.cpp index 1ec1239..1f2145a 100644 --- a/basic/JSON.cpp +++ b/basic/JSON.cpp @@ -8,6 +8,7 @@ #include "JSON.h" #include "McZip.h" +#include using namespace mc; @@ -326,8 +327,7 @@ double JSONObject::doubleValue(const char* name, double dv){ cJSON* json = cJSON_GetObjectItem(m_root, name); if (json != NULL && json->type==cJSON_Number) { return json->valuedouble; - } - else{ + } else { return dv; } } @@ -336,13 +336,13 @@ bool_t JSONObject::boolValue(const char* name){ cJSON* json = cJSON_GetObjectItem(m_root, name); if (json != NULL && json->type==cJSON_True) { return BS_TRUE; + } else if (json != NULL && json->type==cJSON_Number) { + if (json->valueint != 0) { + return BS_TRUE; + } } - else if(json != NULL && json->type==cJSON_True){ - return BS_FALSE; - } - else{ - return BS_NOTBOOL; - } + + return BS_FALSE; } const char* JSONObject::stringValue(const char* name){ @@ -400,17 +400,21 @@ map JSONObject::stringdict() { cJSON* obj = m_root->child; while (obj!=NULL) { std::string s = obj->string; - if (obj->type == cJSON_False || obj->type == cJSON_True || obj->type == cJSON_Number) { + if (obj->type == cJSON_Number) { char temp[64]; - if (obj->valueint == 0) { - sprintf(temp, "%f", obj->valuedouble); - } else { + if (fabs((obj->valueint) - obj->valuedouble) <= DBL_EPSILON) { sprintf(temp, "%d", obj->valueint); + } else { + sprintf(temp, "%f", obj->valuedouble); } string s(temp); ks[obj->string] = s; } else if (obj->type == cJSON_String) { ks[obj->string] = obj->valuestring; + } else if (obj->type == cJSON_False) { + ks[obj->string] = "false"; + } else if (obj->type == cJSON_True) { + ks[obj->string] = "true"; } obj = obj->next; diff --git a/basic/JSON.h b/basic/JSON.h index df1b53c..03676b1 100644 --- a/basic/JSON.h +++ b/basic/JSON.h @@ -14,7 +14,6 @@ #include #include #include "bs.h" -#include "cJSON.h" using namespace std; // 只支持Ojbect和Array类型拷贝 diff --git a/basic/McHttp.cpp b/basic/McHttp.cpp index 585ceec..d4a7dc8 100644 --- a/basic/McHttp.cpp +++ b/basic/McHttp.cpp @@ -143,17 +143,12 @@ void HttpSession::http(const char *url, const char *method, const char *body, ui http_set_body(h->http, body, length); h->http_callback = callback; + display_http_log(h->http->req.mem); + void **para = (void **) malloc(sizeof(void *) * 2); para[0] = h; para[1] = this; ((ThreadPool *) m_thread_pool)->add(thread_http, para); - -#if DEBUG - if (http_show_log) { - info_log("%s", h->http->req.mem); - } -#else -#endif } void HttpSession::download(const char *url, const char *path, HttpFileCallback *callback) { @@ -168,6 +163,8 @@ void HttpSession::download(const char *url, const char *path, HttpFileCallback * http_add_newline(h->http); snprintf(h->path, sizeof(h->path), "%s", path); h->file_callback = callback; + + display_http_log(h->http->req.mem); pthread_t download_thread; pthread_create(&download_thread, NULL, thread_down, h); @@ -187,13 +184,14 @@ void HttpSession::upload(const char *url, const char *path, vectorhttp); snprintf(h->path, sizeof(h->path), "%s", path); h->file_callback = callback; + + display_http_log(h->http->req.mem); pthread_t upload_thread; pthread_create(&upload_thread, NULL, thread_up_file, h); } -void -HttpSession::upload(const char *url, uint8_t *data, int size, vector > auths, +void HttpSession::upload(const char *url, uint8_t *data, int size, vector > auths, HttpFileCallback *callback) { mc_http_data_t *h = bs_new(mc_http_data); h->http = http_create(url, "PUT"); @@ -208,11 +206,12 @@ HttpSession::upload(const char *url, uint8_t *data, int size, vectorhttp->body_size = (uint32_t) size; h->file_callback = callback; - + + display_http_log(h->http->req.mem); + void **para = (void **) malloc(sizeof(void *) * 2); para[0] = h; para[1] = this; - pthread_t post_data_thread; pthread_create(&post_data_thread, NULL, thread_post_data, para); } @@ -233,20 +232,14 @@ void HttpSession::postData(const char *url, uint8_t *data, int size, HttpFileCal mc_http_data_set(h, data, size); h->http->body_size = (uint32_t) size; h->file_callback = callback; + + display_http_log(h->http->req.mem); void **para = (void **) malloc(sizeof(void *) * 2); para[0] = h; para[1] = this; - pthread_t post_data_thread; pthread_create(&post_data_thread, NULL, thread_post_data, para); - -#if DEBUG - if (http_show_log) { - info_log("%s", h->http->req.mem); - } -#else -#endif } void HttpSession::addHttpHeader(const char *key, const char *value) { @@ -284,6 +277,15 @@ void HttpSession::clearCookie() { m_headers.erase(cookie); } +void HttpSession::display_http_log(const char *log) { +#if DEBUG + if (http_show_log) { + info_log("%s", log); + } +#else +#endif +} + #pragma --mark "http回调及线程" void *thread_http(void *para) { void **arg = (void **) para; @@ -297,9 +299,9 @@ void *thread_http(void *para) { // http->http会在http_perform中被删除 free(arg); + bs_delete(http->http); bs_delete(http); bs_delete(res); - return NULL; } @@ -325,8 +327,9 @@ void *thread_down(void *para) { down->file_callback->done(res->response_code, res->response_code, res->body); } // http->http会在http_perform中被删除 + bs_delete(down->http); bs_delete(down); - + bs_delete(res); return NULL; } @@ -339,9 +342,9 @@ void *thread_up_file(void *para) { thread_http_response(res, NULL); up->file_callback->done(res->response_code, res->response_code, res->body); } - // http->http会在http_perform中被删除 + bs_delete(up->http); bs_delete(up); - + bs_delete(res); return NULL; } @@ -355,21 +358,23 @@ void *thread_post_data(void *para) { thread_http_response(res, (HttpSession *) arg[1]); up->file_callback->done(res->response_code, res->response_code, res->body); } - // http->http会在http_perform中被删除 free(arg); + bs_delete(up->http); bs_delete(up); bs_delete(res); return NULL; } void thread_http_response(http_res_t *res, HttpSession *session) { - if (res->response_code < 0) { - const char *error = "http connect error!"; + if (res->response_code <= 0) { + const char *error = "网络连接失败,请稍后再试"; if (res->response_code == BS_TIMEOUT) { - error = "http time-out"; + error = "网络连接超时,请稍后再试"; } res->body = (char *)error; + session->display_http_log(res->body); + return; } else { if (session != NULL) { res->cookie = bs_strrstr(res->response.mem, "\r\nSet-Cookie"); @@ -380,15 +385,5 @@ void thread_http_response(http_res_t *res, HttpSession *session) { } } -#if DEBUG - if (session->http_show_log) { - if (res->response_code == HTTP_OK) { - JSONObject response(res->body); - info_log("%s", response.toString()); - } else { - info_log("%s", res->response.mem); - } - } -#else -#endif + session->display_http_log(res->response.mem); } diff --git a/basic/McHttp.h b/basic/McHttp.h index cff4c06..9fe6d88 100644 --- a/basic/McHttp.h +++ b/basic/McHttp.h @@ -62,9 +62,10 @@ class HttpSession{ const char* cookie(); static void setTimeout(uint32_t timeout); static void showLog(bool show); + void display_http_log(const char *log); static uint32_t http_timeout; // 过期时间 - static bool http_show_log; // 展示日志 + static bool http_show_log; // 展示日志 protected: void setOpt(void* curl, http_method_t method, const char* body, uint32_t length); map m_headers; diff --git a/basic/McReference.h b/basic/McReference.h index fab435a..47f2e3f 100644 --- a/basic/McReference.h +++ b/basic/McReference.h @@ -32,7 +32,6 @@ namespace mc { bool unLock(){ if (m_is_reference && m_referencecount<=0) { - err_log("unlock error! referencecount[%d]", m_referencecount); return false; } diff --git a/basic/ThreadPool.h b/basic/ThreadPool.h index a72b338..191cc28 100644 --- a/basic/ThreadPool.h +++ b/basic/ThreadPool.h @@ -41,7 +41,7 @@ class ThreadPool{ static ThreadPool* shareInstance(); static void destroyInstance(); - ThreadPool(int thread_num = 2); + ThreadPool(int thread_num = 20); ~ThreadPool(); void add(void* (*run)(void*),void* arg); diff --git a/basic/android/McDevice.cpp b/basic/android/McDevice.cpp index 8973b70..b276c54 100644 --- a/basic/android/McDevice.cpp +++ b/basic/android/McDevice.cpp @@ -9,9 +9,8 @@ #include #include #include "bs.h" -#include "McDevice.h" -#include "McFile.h" -#include "MeDevice.h" +#include "../McDevice.h" +#include "../McFile.h" using namespace std; @@ -27,7 +26,7 @@ void mc::mc_set_device(JNIEnv *env, jobject thiz, jobject context) { jclass deviceClass = env->FindClass("com/rex/utils/DeviceUtil"); const char *s = NULL; - jmethodID method = env->GetStaticMethodID(deviceClass, "getDeviceId", + jmethodID method = env->GetStaticMethodID(deviceClass, "deviceId", "(Landroid/content/Context;)Ljava/lang/String;"); jstring deviceid = (jstring) env->CallStaticObjectMethod(deviceClass, method, context); if (deviceid != NULL) { @@ -64,15 +63,6 @@ void mc::mc_set_device(JNIEnv *env, jobject thiz, jobject context) { fclose(fp); debug_log("PackageName: %s", package); g_packagename = package; - // method = env->GetStaticMethodID(deviceClass, "getPackageName", "(Landroid/content/Context;)Ljava/lang/String;"); - // deviceid = (jstring)env->CallStaticObjectMethod(deviceClass, method, context); - // if (deviceid!=NULL) - // { - // s = env->GetStringUTFChars(deviceid, NULL); - // debug_log("PackageName: %s", s); - // g_package_name = s; - // env->ReleaseStringUTFChars(deviceid, s); - // } method = env->GetStaticMethodID(deviceClass, "getDeviceModel", "()Ljava/lang/String;"); deviceid = (jstring) env->CallStaticObjectMethod(deviceClass, method, context); diff --git a/basic/android/McResource.cpp b/basic/android/McResource.cpp index b11d626..c856063 100644 --- a/basic/android/McResource.cpp +++ b/basic/android/McResource.cpp @@ -9,7 +9,7 @@ #include #include #include -#include "McFile.h" +#include "../McFile.h" extern JavaVM* g_jvm; diff --git a/basic/cJSON.h b/basic/cJSON.h deleted file mode 100644 index 8c55086..0000000 --- a/basic/cJSON.h +++ /dev/null @@ -1,149 +0,0 @@ -/* - Copyright (c) 2009 Dave Gamble - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - */ - -#ifndef cJSON__h -#define cJSON__h - -#ifdef __cplusplus -extern "C" -{ -#endif - - /* cJSON Types: */ -#define cJSON_False 0 -#define cJSON_True 1 -#define cJSON_NULL 2 -#define cJSON_Number 3 -#define cJSON_String 4 -#define cJSON_Array 5 -#define cJSON_Object 6 - -#define cJSON_IsReference 256 -#define cJSON_StringIsConst 512 - - /* The cJSON structure: */ - typedef struct cJSON { - struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ - struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ - - int type; /* The type of the item, as above. */ - - char *valuestring; /* The item's string, if type==cJSON_String */ - int valueint; /* The item's number, if type==cJSON_Number */ - double valuedouble; /* The item's number, if type==cJSON_Number */ - - char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ - } cJSON; - - typedef struct cJSON_Hooks { - void *(*malloc_fn)(size_t sz); - void (*free_fn)(void *ptr); - } cJSON_Hooks; - - /* Supply malloc, realloc and free functions to cJSON */ - extern void cJSON_InitHooks(cJSON_Hooks* hooks); - - - /* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */ - extern cJSON *cJSON_Parse(const char *value); - /* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */ - extern char *cJSON_Print(cJSON *item); - /* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */ - extern char *cJSON_PrintUnformatted(cJSON *item); - /* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */ - extern char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt); - /* Delete a cJSON entity and all subentities. */ - extern void cJSON_Delete(cJSON *c); - - /* Returns the number of items in an array (or object). */ - extern int cJSON_GetArraySize(cJSON *array); - /* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */ - extern cJSON *cJSON_GetArrayItem(cJSON *array,int item); - /* Get item "string" from object. Case insensitive. */ - extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string); - - /* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ - extern const char *cJSON_GetErrorPtr(void); - - /* These calls create a cJSON item of the appropriate type. */ - extern cJSON *cJSON_CreateNull(void); - extern cJSON *cJSON_CreateTrue(void); - extern cJSON *cJSON_CreateFalse(void); - extern cJSON *cJSON_CreateBool(int b); - extern cJSON *cJSON_CreateNumber(double num); - extern cJSON *cJSON_CreateString(const char *string); - extern cJSON *cJSON_CreateArray(void); - extern cJSON *cJSON_CreateObject(void); - - /* These utilities create an Array of count items. */ - extern cJSON *cJSON_CreateIntArray(const int *numbers,int count); - extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count); - extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count); - extern cJSON *cJSON_CreateStringArray(const char **strings,int count); - - /* Append item to the specified array/object. */ - extern void cJSON_AddItemToArray(cJSON *array, cJSON *item); - extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item); - extern void cJSON_AddItemToObjectCS(cJSON *object,const char *string,cJSON *item); /* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object */ - /* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ - extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); - extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item); - - /* Remove/Detatch items from Arrays/Objects. */ - extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which); - extern void cJSON_DeleteItemFromArray(cJSON *array,int which); - extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string); - extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string); - - /* Update array items. */ - extern void cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem); /* Shifts pre-existing items to the right. */ - extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem); - extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); - - /* Duplicate a cJSON item */ - extern cJSON *cJSON_Duplicate(cJSON *item,int recurse); - /* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will - need to be released. With recurse!=0, it will duplicate any children connected to the item. - The item->next and ->prev pointers are always zero on return from Duplicate. */ - - /* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ - extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated); - - extern void cJSON_Minify(char *json); - - /* Macros for creating things quickly. */ -#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull()) -#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue()) -#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse()) -#define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b)) -#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n)) -#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s)) - - /* When assigning an integer value, it needs to be propagated to valuedouble too. */ -#define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val)) -#define cJSON_SetNumberValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val)) - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/basic/ios/McDevice.mm b/basic/ios/McDevice.mm index 4ec3dec..ba4a716 100644 --- a/basic/ios/McDevice.mm +++ b/basic/ios/McDevice.mm @@ -15,28 +15,52 @@ #include #include #include "McDevice.h" +#include "SFHFKeychainUtils.h" #include #define KEYCHAIN_SERVICE_NAME @"visioninsdk.com.visionin.rex" #define KEYCHAIN_ACCOUNT_UUID @"keychain_account_uuid.com.visionin.rex" +// 该方式已经失效 +//const char* mc::device_id() +//{ +// NSString *UUID = [[NSUserDefaults standardUserDefaults] objectForKey:KEYCHAIN_SERVICE_NAME]; +// if (!UUID || [UUID isEqualToString:@""]) { +// +// NSString *domain = KEYCHAIN_SERVICE_NAME; +// NSString *key = KEYCHAIN_ACCOUNT_UUID; +// NSString *identifier = [SecureUDID UDIDForDomain:[domain stringByAppendingString:@"uuid"] usingKey:[key stringByAppendingString:@"uuid"]]; +// //本地没有,创建UUID +// UUID = identifier; +// if (identifier && ![identifier isEqualToString:@""]) { +// [[NSUserDefaults standardUserDefaults] setObject:identifier forKey:KEYCHAIN_SERVICE_NAME]; +// } +// } +// +// NSString *format = [UUID stringByReplacingOccurrencesOfString:@"-" withString:@""]; +// return [format UTF8String]; +//} const char* mc::device_id() { - NSString *UUID = [[NSUserDefaults standardUserDefaults] objectForKey:KEYCHAIN_SERVICE_NAME]; - if (!UUID || [UUID isEqualToString:@""]) { + NSString *UUID = [SFHFKeychainUtils getPasswordForUsername:KEYCHAIN_ACCOUNT_UUID andServiceName:KEYCHAIN_SERVICE_NAME error:nil]; + if (!UUID) { + CFUUIDRef puuid = CFUUIDCreate(nil); + CFStringRef uuidString = CFUUIDCreateString(nil, puuid); + NSString *result = (NSString *)CFBridgingRelease(CFStringCreateCopy(NULL, uuidString)); + CFRelease(puuid); + CFRelease(uuidString); - NSString *domain = KEYCHAIN_SERVICE_NAME; - NSString *key = KEYCHAIN_ACCOUNT_UUID; - NSString *identifier = [SecureUDID UDIDForDomain:[domain stringByAppendingString:@"uuid"] usingKey:[key stringByAppendingString:@"uuid"]]; - //本地没有,创建UUID - UUID = identifier; - if (identifier && ![identifier isEqualToString:@""]) { - [[NSUserDefaults standardUserDefaults] setObject:identifier forKey:KEYCHAIN_SERVICE_NAME]; + NSError *error; + + UUID = [result stringByReplacingOccurrencesOfString:@"-" withString:@""]; + BOOL saved = [SFHFKeychainUtils storeUsername:KEYCHAIN_ACCOUNT_UUID andPassword:UUID + forServiceName:KEYCHAIN_SERVICE_NAME updateExisting:YES error:&error]; + if (!saved) { + info_log("Keychain保存UUID时出错"); } } - - NSString *format = [UUID stringByReplacingOccurrencesOfString:@"-" withString:@""]; - return [format UTF8String]; + + return [UUID UTF8String]; } const char* mc::system_version(){ diff --git a/basic/ios/McHttp.mm b/basic/ios/McHttp.mm deleted file mode 100644 index 9972439..0000000 --- a/basic/ios/McHttp.mm +++ /dev/null @@ -1,225 +0,0 @@ -/** - * file : Http.mm - * author : bushaofeng - * create : 2016-08-25 17:20 - * func : - * history: - */ - -#include "McHttp.h" -#import -using namespace mc; - -void* http_header_init(void* p){ - http_header_t* h = (http_header_t*)p; - string_init(&h->first); - string_init(&h->second); - return h; -} -void http_header_set(http_header_t* header, const char* key, const char* value){ - header->first.append(&header->first, key); - header->second.append(&header->second, value); -} -void http_header_destroy(void* p){ - http_header_t* h = (http_header_t*)p; - - string_destroy(&h->first); - string_destroy(&h->second); -} - -#pragma --mark "NSURLSession回调" -@interface McURLSessionDelegate : NSObject -@property(nonatomic, assign)DownCallback* downloadCallback; -@property(nonatomic, assign)HttpCallback* httpCallback; -@property(nonatomic, retain)NSMutableData* responseData; -@end - -#pragma --mark "IOSEnv" -namespace mc { - -class IOSEnv{ -public: - IOSEnv(){ - m_session_config = [NSURLSessionConfiguration defaultSessionConfiguration]; - m_delegate_queue = [[NSOperationQueue alloc] init]; - } - NSURLSessionConfiguration* m_session_config; - NSOperationQueue* m_delegate_queue; -}; - -} - -#pragma --mark "HttpSession" - -HttpSession::HttpSession(){ - vector_init(&m_headers); - m_interval = 60; - m_iosenv = new IOSEnv(); - -// if (m_config!=NULL) { -// NSMutableDictionary* dict = [[NSMutableDictionary alloc] init]; -// for (int i=0; iheaderCount(); i++) { -// http_header_t* header = m_config->header(i); -// [dict setObject:[NSString stringWithUTF8String:header->second.mem] forKey:[NSString stringWithUTF8String:header->first.mem]]; -// } -// [m_session_config setHTTPAdditionalHeaders:dict]; -// } -} - -void HttpSession::addHttpHeader(const char* key, const char* value){ - http_header_t header; - http_header_init(&header); - http_header_set(&header, key, value); - vector_add(&m_headers, header); -} - -void HttpSession::get(const char* curl, HttpCallback* callback){ - http(curl, "GET", NULL, 0, callback); -} - -void HttpSession::post(const char* url, const char* body, uint32_t length, HttpCallback* callback){ - http(url, "POST", body, length, callback); -} - -void HttpSession::put(const char* url, const char* body, uint32_t length, HttpCallback* callback){ - http(url, "PUT", body, length, callback); -} - -void HttpSession::del(const char* url, HttpCallback* callback){ - http(url, "DELETE", NULL, 0, callback); -} - -void HttpSession::http(const char* curl, const char* method, const char* body, uint32_t length, HttpCallback* callback){ - NSString* url = [NSString stringWithUTF8String:curl]; - NSURL *nsurl = [[NSURL alloc] initWithString:[url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; - NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:nsurl cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:m_interval]; - //[requet addValue:appKey forHTTPHeaderField:@"X-MeCloud-AppKey"]; - [request setHTTPMethod:[NSString stringWithUTF8String:method]]; - for (int i=0; isecond.mem] forHTTPHeaderField:[NSString stringWithUTF8String:header->first.mem]]; - } - if (body!=NULL) { - [request setHTTPBody:[NSData dataWithBytes:body length:length]]; - } - - McURLSessionDelegate* delegate = [[McURLSessionDelegate alloc] init]; - delegate.httpCallback = callback; - NSURLSession* httpSession = [NSURLSession sessionWithConfiguration:m_iosenv->m_session_config delegate:delegate delegateQueue:m_iosenv->m_delegate_queue]; - - NSURLSessionDataTask* task = [httpSession dataTaskWithRequest:request]; - [task resume]; -} - -void HttpSession::download(const char* url, DownCallback* callback){ - NSURL *nsurl = [[NSURL alloc] initWithString:[NSString stringWithUTF8String:url]]; - NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:nsurl]; - [request setHTTPMethod:@"GET"]; - for (int i=0; isecond.mem] forHTTPHeaderField:[NSString stringWithUTF8String:header->first.mem]]; - } - - McURLSessionDelegate* delegate = [[McURLSessionDelegate alloc] init]; - delegate.downloadCallback = callback; - NSURLSession* downloadSession = [NSURLSession sessionWithConfiguration:m_iosenv->m_session_config delegate:delegate delegateQueue:m_iosenv->m_delegate_queue]; - NSURLSessionDownloadTask* task = [downloadSession downloadTaskWithRequest:request]; - - [task resume]; -} - -HttpSession::~HttpSession(){ - delete m_iosenv; - for (int i=0; iprogress(bytesWritten, totalBytesWritten, totalBytesExpectedToWrite); - } -} -/** - * 下载完成后被调用的方法(iOS7和iOS8都必须实现) - */ -- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{ - if (_downloadCallback!=NULL) - { - _downloadCallback->done(200, BS_SUCCESS, [[location path] UTF8String]); - } - - session = nil; - downloadTask = nil; - _responseData = nil; -} -/** - * 3.断点续传的时候被调用的方法。(一般上面都不用写,iOS8可以不实现) - */ -- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes -{ - -} - -// 1. http回调请求 --(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler -{ - //注意:需要使用completionHandler回调告诉系统应该如何处理服务器返回的数据 - //默认是取消的 - /* - 59 NSURLSessionResponseCancel = 0, 默认的处理方式,取消 - 60 NSURLSessionResponseAllow = 1, 接收服务器返回的数据 - 61 NSURLSessionResponseBecomeDownload = 2,变成一个下载请求 - 62 NSURLSessionResponseBecomeStream 变成一个流 - 63 */ - completionHandler(NSURLSessionResponseAllow); -} - -//2.接收到服务器返回数据的时候会调用该方法,如果数据较大那么该方法可能会调用多次 --(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data -{ - //拼接服务器返回的数据 - [self.responseData appendData:data]; -} - -//3.当请求完成(成功|失败)的时候会调用该方法,如果请求失败,则error有值 --(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error -{ - if (error!=nil) { - NSLog(@"Mc HTTP Error: %@", error); - if (_httpCallback!=NULL) - { - _httpCallback->done((int)error.code, BS_INVALID, (char*)[error.domain UTF8String]); - } - } - else if (_httpCallback!=NULL) - { - NSString* string = [[NSString alloc] initWithData:_responseData encoding:NSUTF8StringEncoding]; - // callback->done(200, BS_SUCCESS, (char*)[data bytes]); - _httpCallback->done(200, BS_SUCCESS, (char*)string.UTF8String); - } - - session = nil; - task = nil; - _responseData = nil; -} - -@end diff --git a/basic/ios/McZip.mm b/basic/ios/McZip.mm deleted file mode 100644 index af7178d..0000000 --- a/basic/ios/McZip.mm +++ /dev/null @@ -1,354 +0,0 @@ -/** - * file : McZip.mm - * author : bushaofeng - * create : 2016-08-25 17:20 - * func : - * history: - */ - -#include "McZip.h" -#include "unzip.h" -#include "zip.h" -#import "zlib.h" -#import "zconf.h" -#include "Common.h" -#import - -using namespace mc; -static NSDate* _dateWithMSDOSFormat(UInt32 msdosDateTime); - -bool Zip::unzip(const char* upath, const char* udestination, ZipCallback* callback, bool overwrite , - const char* upassword, ZipArchiveCallback* delegate){ - NSString* path = [NSString stringWithUTF8String:upath]; - NSString* destination = [NSString stringWithUTF8String:udestination]; - NSString* password = nil; - if (upassword!=NULL) { - password = [NSString stringWithUTF8String:upassword]; - } - - zipFile zip = unzOpen((const char*)[path UTF8String]); - if (zip == NULL) - { - const char* err = "failed to open zip file"; - err_log("%s: %s", err, upath); - if (callback) { - callback->complete(NULL, false, err); - } - - return false; - } - - NSDictionary * fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil]; - unsigned long long fileSize = [fileAttributes[NSFileSize] unsignedLongLongValue]; - unsigned long long currentPosition = 0; - - unz_global_info globalInfo = {0ul, 0ul}; - unzGetGlobalInfo(zip, &globalInfo); - - // Begin unzipping - if (unzGoToFirstFile(zip) != UNZ_OK) - { - const char* err = "failed to open first file in zip file"; - err_log("%s", err); - if (callback) - { - callback->complete(nil, NO, err); - } - return NO; - } - - BOOL success = YES; - BOOL canceled = NO; - int ret = 0; - int crc_ret =0; - unsigned char buffer[4096] = {0}; - NSFileManager *fileManager = [NSFileManager defaultManager]; - NSMutableSet *directoriesModificationDates = [[NSMutableSet alloc] init]; - - if (delegate!=NULL) { - delegate->willUnzip(upath, globalInfo); - delegate->progress(currentPosition, fileSize); - } - - uint32_t currentFileNumber = 0; - do { - @autoreleasepool { - if ([password length] == 0) { - ret = unzOpenCurrentFile(zip); - } else { - ret = unzOpenCurrentFilePassword(zip, [password cStringUsingEncoding:NSASCIIStringEncoding]); - } - - if (ret != UNZ_OK) { - success = NO; - break; - } - - // Reading data and write to file - unz_file_info fileInfo; - memset(&fileInfo, 0, sizeof(unz_file_info)); - - ret = unzGetCurrentFileInfo(zip, &fileInfo, NULL, 0, NULL, 0, NULL, 0); - if (ret != UNZ_OK) { - success = NO; - unzCloseCurrentFile(zip); - break; - } - - currentPosition += fileInfo.compressed_size; - - // Message delegate - if (delegate != NULL) { - if(!delegate->shouldUnzip(currentFileNumber, globalInfo.number_entry, upath, fileInfo)){ - success = NO; - canceled = YES; - break; - } - delegate->willUnzip(currentFileNumber, globalInfo.number_entry, upath, fileInfo); - delegate->progress(currentPosition, fileSize); - } - - char *filename = (char *)malloc(fileInfo.size_filename + 1); - if (filename == NULL) - { - return NO; - } - - unzGetCurrentFileInfo(zip, &fileInfo, filename, fileInfo.size_filename + 1, NULL, 0, NULL, 0); - filename[fileInfo.size_filename] = '\0'; - - // - // Determine whether this is a symbolic link: - // - File is stored with 'version made by' value of UNIX (3), - // as per http://www.pkware.com/documents/casestudies/APPNOTE.TXT - // in the upper byte of the version field. - // - BSD4.4 st_mode constants are stored in the high 16 bits of the - // external file attributes (defacto standard, verified against libarchive) - // - // The original constants can be found here: - // http://minnie.tuhs.org/cgi-bin/utree.pl?file=4.4BSD/usr/include/sys/stat.h - // - const uLong ZipUNIXVersion = 3; - const uLong BSD_SFMT = 0170000; - const uLong BSD_IFLNK = 0120000; - - BOOL fileIsSymbolicLink = NO; - if (((fileInfo.version >> 8) == ZipUNIXVersion) && BSD_IFLNK == (BSD_SFMT & (fileInfo.external_fa >> 16))) { - fileIsSymbolicLink = NO; - } - - // Check if it contains directory - NSString *strPath = @(filename); - BOOL isDirectory = NO; - if (filename[fileInfo.size_filename-1] == '/' || filename[fileInfo.size_filename-1] == '\\') { - isDirectory = YES; - } - free(filename); - - // Contains a path - if ([strPath rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@"/\\"]].location != NSNotFound) { - strPath = [strPath stringByReplacingOccurrencesOfString:@"\\" withString:@"/"]; - } - - NSString *fullPath = [destination stringByAppendingPathComponent:strPath]; - NSError *err = nil; - NSDate *modDate = _dateWithMSDOSFormat(fileInfo.dosDate); - NSDictionary *directoryAttr = @{NSFileCreationDate: modDate, NSFileModificationDate: modDate}; - - if (isDirectory) { - [fileManager createDirectoryAtPath:fullPath withIntermediateDirectories:YES attributes:directoryAttr error:&err]; - } else { - [fileManager createDirectoryAtPath:[fullPath stringByDeletingLastPathComponent] withIntermediateDirectories:YES attributes:directoryAttr error:&err]; - } - if (nil != err) { - err_log("MeZip Error: %s", [err.localizedDescription UTF8String]); - } - - if(!fileIsSymbolicLink) - [directoriesModificationDates addObject: @{@"path": fullPath, @"modDate": modDate}]; - - if ([fileManager fileExistsAtPath:fullPath] && !isDirectory && !overwrite) { - //FIXME: couldBe CRC Check? - unzCloseCurrentFile(zip); - ret = unzGoToNextFile(zip); - continue; - } - - if (!fileIsSymbolicLink) { - FILE *fp = fopen((const char*)[fullPath UTF8String], "wb"); - while (fp) { - int readBytes = unzReadCurrentFile(zip, buffer, 4096); - - if (readBytes > 0) { - fwrite(buffer, readBytes, 1, fp ); - } else { - break; - } - } - - if (fp) { - if ([[[fullPath pathExtension] lowercaseString] isEqualToString:@"zip"]) { - NSLog(@"Unzipping nested .zip file: %@", [fullPath lastPathComponent]); - if (unzip([fullPath UTF8String], [[fullPath stringByDeletingLastPathComponent] UTF8String], NULL, overwrite, upassword)) { - [[NSFileManager defaultManager] removeItemAtPath:fullPath error:nil]; - } - } - - fclose(fp); - - // Set the original datetime property - if (fileInfo.dosDate != 0) { - NSDate *orgDate = _dateWithMSDOSFormat(fileInfo.dosDate); - NSDictionary *attr = @{NSFileModificationDate: orgDate}; - - if (attr) { - if ([fileManager setAttributes:attr ofItemAtPath:fullPath error:nil] == NO) { - // Can't set attributes - NSLog(@"[SSZipArchive] Failed to set attributes - whilst setting modification date"); - } - } - } - - // Set the original permissions on the file - uLong permissions = fileInfo.external_fa >> 16; - if (permissions != 0) { - // Store it into a NSNumber - NSNumber *permissionsValue = @(permissions); - - // Retrieve any existing attributes - NSMutableDictionary *attrs = [[NSMutableDictionary alloc] initWithDictionary:[fileManager attributesOfItemAtPath:fullPath error:nil]]; - - // Set the value in the attributes dict - attrs[NSFilePosixPermissions] = permissionsValue; - - // Update attributes - if ([fileManager setAttributes:attrs ofItemAtPath:fullPath error:nil] == NO) { - // Unable to set the permissions attribute - NSLog(@"[SSZipArchive] Failed to set attributes - whilst setting permissions"); - } - -#if !__has_feature(objc_arc) - [attrs release]; -#endif - } - } - } - else - { - // Assemble the path for the symbolic link - NSMutableString* destinationPath = [NSMutableString string]; - int bytesRead = 0; - while((bytesRead = unzReadCurrentFile(zip, buffer, 4096)) > 0) - { - buffer[bytesRead] = (int)0; - [destinationPath appendString:@((const char*)buffer)]; - } - - // Create the symbolic link (making sure it stays relative if it was relative before) - int symlinkError = symlink([destinationPath cStringUsingEncoding:NSUTF8StringEncoding], - [fullPath cStringUsingEncoding:NSUTF8StringEncoding]); - - if(symlinkError != 0) - { - NSLog(@"Failed to create symbolic link at \"%@\" to \"%@\". symlink() error code: %d", fullPath, destinationPath, errno); - } - } - - crc_ret = unzCloseCurrentFile( zip ); - if (crc_ret == UNZ_CRCERROR) { - //CRC ERROR - success = NO; - break; - } - ret = unzGoToNextFile( zip ); - - // Message delegate - if (delegate!=NULL) { - delegate->didUnzip(currentFileNumber, (uint32_t)globalInfo.number_entry, upath, fileInfo); - delegate->didUnzip(currentFileNumber, (uint32_t)globalInfo.number_entry, upath, [fullPath UTF8String]); - } - - currentFileNumber++; - if (callback!=NULL) - { - callback->progress([strPath UTF8String], fileInfo, currentFileNumber, globalInfo.number_entry); - } - } - } while(ret == UNZ_OK && ret != UNZ_END_OF_LIST_OF_FILE); - - // Close - unzClose(zip); - - // The process of decompressing the .zip archive causes the modification times on the folders - // to be set to the present time. So, when we are done, they need to be explicitly set. - // set the modification date on all of the directories. - NSError * err = nil; - for (NSDictionary * d in directoriesModificationDates) { - if (![[NSFileManager defaultManager] setAttributes:@{NSFileModificationDate: d[@"modDate"]} ofItemAtPath:d[@"path"] error:&err]) { - NSLog(@"[SSZipArchive] Set attributes failed for directory: %@.", d[@"path"]); - } - if (err) { - NSLog(@"[SSZipArchive] Error setting directory file modification date attribute: %@",err.localizedDescription); - } - } - -#if !__has_feature(objc_arc) - [directoriesModificationDates release]; -#endif - - // Message delegate - if (success && delegate!=NULL) { - delegate->didUnzip(upath, globalInfo, udestination); - delegate->progress(fileSize, fileSize); - } - - const char *retErr = NULL; - if (crc_ret == UNZ_CRCERROR) - { - retErr = "crc check failed for file"; - } - - if (callback!=NULL) { - callback->complete(upath, success, retErr); - } - - return success; -} - -NSDate* _dateWithMSDOSFormat(UInt32 msdosDateTime){ - static const UInt32 kYearMask = 0xFE000000; - static const UInt32 kMonthMask = 0x1E00000; - static const UInt32 kDayMask = 0x1F0000; - static const UInt32 kHourMask = 0xF800; - static const UInt32 kMinuteMask = 0x7E0; - static const UInt32 kSecondMask = 0x1F; - - static NSCalendar *gregorian; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ -#if defined(__IPHONE_8_0) || defined(__MAC_10_10) - gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]; -#else - gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; -#endif - }); - - NSDateComponents *components = [[NSDateComponents alloc] init]; - - //NSAssert(0xFFFFFFFF == (kYearMask | kMonthMask | kDayMask | kHourMask | kMinuteMask | kSecondMask), @"[SSZipArchive] MSDOS date masks don't add up"); - - [components setYear:1980 + ((msdosDateTime & kYearMask) >> 25)]; - [components setMonth:(msdosDateTime & kMonthMask) >> 21]; - [components setDay:(msdosDateTime & kDayMask) >> 16]; - [components setHour:(msdosDateTime & kHourMask) >> 11]; - [components setMinute:(msdosDateTime & kMinuteMask) >> 5]; - [components setSecond:(msdosDateTime & kSecondMask) * 2]; - - NSDate *date = [NSDate dateWithTimeInterval:0 sinceDate:[gregorian dateFromComponents:components]]; - -#if !__has_feature(objc_arc) - [components release]; -#endif - - return date; -} diff --git a/basic/ios/SFHFKeychainUtils.h b/basic/ios/SFHFKeychainUtils.h new file mode 100755 index 0000000..9ccff0f --- /dev/null +++ b/basic/ios/SFHFKeychainUtils.h @@ -0,0 +1,41 @@ +// +// SFHFKeychainUtils.h +// +// Created by Buzz Andersen on 10/20/08. +// Based partly on code by Jonathan Wight, Jon Crosby, and Mike Malone. +// Copyright 2008 Sci-Fi Hi-Fi. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#import + + +@interface SFHFKeychainUtils : NSObject { + +} + ++ (NSString *) getPasswordForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error; ++ (BOOL) storeUsername: (NSString *) username andPassword: (NSString *) password forServiceName: (NSString *) serviceName updateExisting: (BOOL) updateExisting error: (NSError **) error; ++ (BOOL) deleteItemForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error; + +@end \ No newline at end of file diff --git a/basic/ios/SFHFKeychainUtils.m b/basic/ios/SFHFKeychainUtils.m new file mode 100755 index 0000000..eeca64b --- /dev/null +++ b/basic/ios/SFHFKeychainUtils.m @@ -0,0 +1,438 @@ +// +// SFHFKeychainUtils.m +// +// Created by Buzz Andersen on 10/20/08. +// Based partly on code by Jonathan Wight, Jon Crosby, and Mike Malone. +// Copyright 2008 Sci-Fi Hi-Fi. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#import "SFHFKeychainUtils.h" +#import + +static NSString *SFHFKeychainUtilsErrorDomain = @"SFHFKeychainUtilsErrorDomain"; + +#if __IPHONE_OS_VERSION_MIN_REQUIRED < 30000 && TARGET_IPHONE_SIMULATOR +@interface SFHFKeychainUtils (PrivateMethods) ++ (SecKeychainItemRef) getKeychainItemReferenceForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error; +@end +#endif + +@implementation SFHFKeychainUtils + +#if __IPHONE_OS_VERSION_MIN_REQUIRED < 30000 && TARGET_IPHONE_SIMULATOR + ++ (NSString *) getPasswordForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error { + if (!username || !serviceName) { + *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil]; + return nil; + } + + SecKeychainItemRef item = [SFHFKeychainUtils getKeychainItemReferenceForUsername: username andServiceName: serviceName error: error]; + + if (*error || !item) { + return nil; + } + + // from Advanced Mac OS X Programming, ch. 16 + UInt32 length; + char *password; + SecKeychainAttribute attributes[8]; + SecKeychainAttributeList list; + + attributes[0].tag = kSecAccountItemAttr; + attributes[1].tag = kSecDescriptionItemAttr; + attributes[2].tag = kSecLabelItemAttr; + attributes[3].tag = kSecModDateItemAttr; + + list.count = 4; + list.attr = attributes; + + OSStatus status = SecKeychainItemCopyContent(item, NULL, &list, &length, (void **)&password); + + if (status != noErr) { + *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil]; + return nil; + } + + NSString *passwordString = nil; + + if (password != NULL) { + char passwordBuffer[1024]; + + if (length > 1023) { + length = 1023; + } + strncpy(passwordBuffer, password, length); + + passwordBuffer[length] = '\0'; + passwordString = [NSString stringWithCString:passwordBuffer]; + } + + SecKeychainItemFreeContent(&list, password); + + CFRelease(item); + + return passwordString; +} + ++ (void) storeUsername: (NSString *) username andPassword: (NSString *) password forServiceName: (NSString *) serviceName updateExisting: (BOOL) updateExisting error: (NSError **) error { + if (!username || !password || !serviceName) { + *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil]; + return; + } + + OSStatus status = noErr; + + SecKeychainItemRef item = [SFHFKeychainUtils getKeychainItemReferenceForUsername: username andServiceName: serviceName error: error]; + + if (*error && [*error code] != noErr) { + return; + } + + *error = nil; + + if (item) { + status = SecKeychainItemModifyAttributesAndData(item, + NULL, + strlen([password UTF8String]), + [password UTF8String]); + + CFRelease(item); + } + else { + status = SecKeychainAddGenericPassword(NULL, + strlen([serviceName UTF8String]), + [serviceName UTF8String], + strlen([username UTF8String]), + [username UTF8String], + strlen([password UTF8String]), + [password UTF8String], + NULL); + } + + if (status != noErr) { + *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil]; + } +} + ++ (void) deleteItemForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error { + if (!username || !serviceName) { + *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: 2000 userInfo: nil]; + return; + } + + *error = nil; + + SecKeychainItemRef item = [SFHFKeychainUtils getKeychainItemReferenceForUsername: username andServiceName: serviceName error: error]; + + if (*error && [*error code] != noErr) { + return; + } + + OSStatus status; + + if (item) { + status = SecKeychainItemDelete(item); + + CFRelease(item); + } + + if (status != noErr) { + *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil]; + } +} + ++ (SecKeychainItemRef) getKeychainItemReferenceForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error { + if (!username || !serviceName) { + *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil]; + return nil; + } + + *error = nil; + + SecKeychainItemRef item; + + OSStatus status = SecKeychainFindGenericPassword(NULL, + strlen([serviceName UTF8String]), + [serviceName UTF8String], + strlen([username UTF8String]), + [username UTF8String], + NULL, + NULL, + &item); + + if (status != noErr) { + if (status != errSecItemNotFound) { + *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil]; + } + + return nil; + } + + return item; +} + +#else + ++ (NSString *) getPasswordForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error { + if (!username || !serviceName) { + if (error != nil) { + *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil]; + } + return nil; + } + + if (error != nil) { + *error = nil; + } + + // Set up a query dictionary with the base query attributes: item type (generic), username, and service + + NSArray *keys = [[[NSArray alloc] initWithObjects: (NSString *) kSecClass, kSecAttrAccount, kSecAttrService, nil] autorelease]; + NSArray *objects = [[[NSArray alloc] initWithObjects: (NSString *) kSecClassGenericPassword, username, serviceName, nil] autorelease]; + + NSMutableDictionary *query = [[[NSMutableDictionary alloc] initWithObjects: objects forKeys: keys] autorelease]; + + // First do a query for attributes, in case we already have a Keychain item with no password data set. + // One likely way such an incorrect item could have come about is due to the previous (incorrect) + // version of this code (which set the password as a generic attribute instead of password data). + + NSDictionary *attributeResult = NULL; + NSMutableDictionary *attributeQuery = [query mutableCopy]; + [attributeQuery setObject: (id) kCFBooleanTrue forKey:(id) kSecReturnAttributes]; + OSStatus status = SecItemCopyMatching((CFDictionaryRef) attributeQuery, (CFTypeRef *) &attributeResult); + + [attributeResult release]; + [attributeQuery release]; + + if (status != noErr) { + // No existing item found--simply return nil for the password + if (error != nil && status != errSecItemNotFound) { + //Only return an error if a real exception happened--not simply for "not found." + *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil]; + } + + return nil; + } + + // We have an existing item, now query for the password data associated with it. + + NSData *resultData = nil; + NSMutableDictionary *passwordQuery = [query mutableCopy]; + [passwordQuery setObject: (id) kCFBooleanTrue forKey: (id) kSecReturnData]; + + status = SecItemCopyMatching((CFDictionaryRef) passwordQuery, (CFTypeRef *) &resultData); + + [resultData autorelease]; + [passwordQuery release]; + + if (status != noErr) { + if (status == errSecItemNotFound) { + // We found attributes for the item previously, but no password now, so return a special error. + // Users of this API will probably want to detect this error and prompt the user to + // re-enter their credentials. When you attempt to store the re-entered credentials + // using storeUsername:andPassword:forServiceName:updateExisting:error + // the old, incorrect entry will be deleted and a new one with a properly encrypted + // password will be added. + if (error != nil) { + *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -1999 userInfo: nil]; + } + } + else { + // Something else went wrong. Simply return the normal Keychain API error code. + if (error != nil) { + *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil]; + } + } + + return nil; + } + + NSString *password = nil; + + if (resultData) { + password = [[NSString alloc] initWithData: resultData encoding: NSUTF8StringEncoding]; + } + else { + // There is an existing item, but we weren't able to get password data for it for some reason, + // Possibly as a result of an item being incorrectly entered by the previous code. + // Set the -1999 error so the code above us can prompt the user again. + if (error != nil) { + *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -1999 userInfo: nil]; + } + } + + return [password autorelease]; +} + ++ (BOOL) storeUsername: (NSString *) username andPassword: (NSString *) password forServiceName: (NSString *) serviceName updateExisting: (BOOL) updateExisting error: (NSError **) error +{ + if (!username || !password || !serviceName) + { + if (error != nil) + { + *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil]; + } + return NO; + } + + // See if we already have a password entered for these credentials. + NSError *getError = nil; + NSString *existingPassword = [SFHFKeychainUtils getPasswordForUsername: username andServiceName: serviceName error:&getError]; + + if ([getError code] == -1999) + { + // There is an existing entry without a password properly stored (possibly as a result of the previous incorrect version of this code. + // Delete the existing item before moving on entering a correct one. + + getError = nil; + + [self deleteItemForUsername: username andServiceName: serviceName error: &getError]; + + if ([getError code] != noErr) + { + if (error != nil) + { + *error = getError; + } + return NO; + } + } + else if ([getError code] != noErr) + { + if (error != nil) + { + *error = getError; + } + return NO; + } + + if (error != nil) + { + *error = nil; + } + + OSStatus status = noErr; + + if (existingPassword) + { + // We have an existing, properly entered item with a password. + // Update the existing item. + + if (![existingPassword isEqualToString:password] && updateExisting) + { + //Only update if we're allowed to update existing. If not, simply do nothing. + + NSArray *keys = [[[NSArray alloc] initWithObjects: (NSString *) kSecClass, + kSecAttrService, + kSecAttrLabel, + kSecAttrAccount, + nil] autorelease]; + + NSArray *objects = [[[NSArray alloc] initWithObjects: (NSString *) kSecClassGenericPassword, + serviceName, + serviceName, + username, + nil] autorelease]; + + NSDictionary *query = [[[NSDictionary alloc] initWithObjects: objects forKeys: keys] autorelease]; + + status = SecItemUpdate((CFDictionaryRef) query, (CFDictionaryRef) [NSDictionary dictionaryWithObject: [password dataUsingEncoding: NSUTF8StringEncoding] forKey: (NSString *) kSecValueData]); + } + } + else + { + // No existing entry (or an existing, improperly entered, and therefore now + // deleted, entry). Create a new entry. + + NSArray *keys = [[[NSArray alloc] initWithObjects: (NSString *) kSecClass, + kSecAttrService, + kSecAttrLabel, + kSecAttrAccount, + kSecValueData, + nil] autorelease]; + + NSArray *objects = [[[NSArray alloc] initWithObjects: (NSString *) kSecClassGenericPassword, + serviceName, + serviceName, + username, + [password dataUsingEncoding: NSUTF8StringEncoding], + nil] autorelease]; + + NSDictionary *query = [[[NSDictionary alloc] initWithObjects: objects forKeys: keys] autorelease]; + + status = SecItemAdd((CFDictionaryRef) query, NULL); + } + + if (status != noErr) + { + // Something went wrong with adding the new item. Return the Keychain error code. + if (error != nil) { + *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil]; + } + + return NO; + } + + return YES; +} + ++ (BOOL) deleteItemForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error +{ + if (!username || !serviceName) + { + if (error != nil) + { + *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil]; + } + return NO; + } + + if (error != nil) + { + *error = nil; + } + + NSArray *keys = [[[NSArray alloc] initWithObjects: (NSString *) kSecClass, kSecAttrAccount, kSecAttrService, kSecReturnAttributes, nil] autorelease]; + NSArray *objects = [[[NSArray alloc] initWithObjects: (NSString *) kSecClassGenericPassword, username, serviceName, kCFBooleanTrue, nil] autorelease]; + + NSDictionary *query = [[[NSDictionary alloc] initWithObjects: objects forKeys: keys] autorelease]; + + OSStatus status = SecItemDelete((CFDictionaryRef) query); + + if (status != noErr) + { + if (error != nil) { + *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil]; + } + + return NO; + } + + return YES; +} + +#endif + +@end diff --git a/bs/Android.mk b/bs/Android.mk index f47e1a8..25e8936 100644 --- a/bs/Android.mk +++ b/bs/Android.mk @@ -19,7 +19,8 @@ LOCAL_SRC_FILES += \ bs_common.c \ bs_object.c \ bs_string.c \ - bs_data.c + bs_data.c \ + bs_json.c # bs_time里的signal函数在r10里不支持 #When you use the ndk r10, android-21 is used by default but it's not fully retro-compatible with devices running former Android versions. In your case, signal can't be found on your device (but it would run properly on Lollipop). #When using the NDK, you should use the platform (APP_PLATFORM:=android-XX) that corresponds to your android:minSdkVersion. diff --git a/bs/bs.h b/bs/bs.h index e1420c3..6af68e5 100644 --- a/bs/bs.h +++ b/bs/bs.h @@ -29,4 +29,5 @@ #include "bs_object.h" #include "bs_string.h" #include "bs_data.h" +#include "bs_json.h" #endif diff --git a/bs/bs_dnscache.c b/bs/bs_dnscache.c index 8d72480..e70bb67 100644 --- a/bs/bs_dnscache.c +++ b/bs/bs_dnscache.c @@ -9,12 +9,6 @@ #include "bs_dnscache.h" #include -typedef struct bs_dns{ - struct bs_dns *next; - struct in_addr in_addr_ip; - char *hostname; -}bs_dns; - typedef bs_dns *bs_dns_pr; pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; @@ -36,7 +30,7 @@ void dns_root_create() { m_root->next = NULL; } -struct in_addr* dns_cache_lookup(const char *hostname) { +bs_dns* dns_cache_lookup(const char *hostname) { if (pthread_mutex_lock(&mutex) != 0){ fprintf(stdout, "lock error!\n"); } @@ -49,7 +43,7 @@ struct in_addr* dns_cache_lookup(const char *hostname) { while (dns) { if (strcmp(dns->hostname, hostname) == 0) { pthread_mutex_unlock(&mutex); - return &dns->in_addr_ip; + return dns; } dns = dns->next; } @@ -83,7 +77,8 @@ void dns_cache_store(struct in_addr in_addr_ip, const char *hostname) { // 存储dns信息时候需要加锁,处理线程安全 bs_dns_pr node = (bs_dns_pr)malloc(sizeof(bs_dns)); dns_pre->next = node; - node->in_addr_ip = in_addr_ip; + node->in_addr_ip = (struct in_addr *)malloc(sizeof(struct in_addr)); + memcpy(node->in_addr_ip, &in_addr_ip, sizeof(struct in_addr)); node->next = NULL; int len = (int)strlen(hostname) + 1; @@ -92,13 +87,53 @@ void dns_cache_store(struct in_addr in_addr_ip, const char *hostname) { return; } memcpy(node->hostname, hostname, len); - printf(""); } // 解锁 pthread_mutex_unlock(&mutex); } +void dns_cache_ipv6_store(struct in6_addr in_addr_ip, const char *hostname) { + if (pthread_mutex_lock(&mutex) != 0){ + fprintf(stdout, "lock error!\n"); + } + if (dns_cache_empty()) { + dns_root_create(); + } + + int cacheCount = 0; + bs_dns_pr dns_pre = m_root; + bs_dns_pr dns_next = dns_pre->next; + while (dns_next) { + cacheCount++; + dns_pre = dns_next; + dns_next = dns_next->next; + if (strcmp(hostname, dns_pre->hostname) == 0) { + pthread_mutex_unlock(&mutex); + return; + } + } + + if (cacheCount < BS_HOST_CACHE_COUNT) { + // 存储dns信息时候需要加锁,处理线程安全 + bs_dns_pr node = (bs_dns_pr)malloc(sizeof(bs_dns)); + dns_pre->next = node; + node->in_addr_ip6 = (struct in6_addr *)malloc(sizeof(struct in6_addr)); + memcpy(node->in_addr_ip6, &in_addr_ip, sizeof(struct in6_addr)); + node->next = NULL; + + int len = (int)strlen(hostname) + 1; + if (!(node->hostname = (char*)malloc(sizeof(char) * len))) { + pthread_mutex_unlock(&mutex); + return; + } + memcpy(node->hostname, hostname, len); + } + + // 解锁 + pthread_mutex_unlock(&mutex); +} + void dns_cache_remove(const char *hostname) { if (pthread_mutex_lock(&mutex) != 0){ fprintf(stdout, "lock error!\n"); @@ -114,6 +149,8 @@ void dns_cache_remove(const char *hostname) { if (strcmp(dns_next->hostname, hostname)) { dns_pre = dns_next->next; free(dns_next->hostname); + free(dns_next->in_addr_ip); + free(dns_next->in_addr_ip6); free(dns_next); pthread_mutex_unlock(&mutex); return; @@ -140,6 +177,8 @@ void dns_cache_clear() { bs_dns_pr node = dns; dns = node->next; free(node->hostname); + free(node->in_addr_ip); + free(node->in_addr_ip6); free(node); } diff --git a/bs/bs_dnscache.h b/bs/bs_dnscache.h index 59e2e44..5525416 100644 --- a/bs/bs_dnscache.h +++ b/bs/bs_dnscache.h @@ -11,8 +11,16 @@ #include "bs_type.h" -struct in_addr* dns_cache_lookup(const char *hostname); +typedef struct bs_dns { + struct bs_dns *next; + struct in_addr *in_addr_ip; + struct in6_addr *in_addr_ip6; + char *hostname; +} bs_dns; + +bs_dns* dns_cache_lookup(const char *hostname); void dns_cache_store(struct in_addr in_addr_ip, const char *hostname); +void dns_cache_ipv6_store(struct in6_addr in_addr_ip, const char *hostname); void dns_cache_remove(const char *hostname); void dns_cache_clear(); diff --git a/3rdparty/cJSON/cJSON.c b/bs/bs_json.c similarity index 99% rename from 3rdparty/cJSON/cJSON.c rename to bs/bs_json.c index 95921cf..5f24403 100644 --- a/3rdparty/cJSON/cJSON.c +++ b/bs/bs_json.c @@ -30,7 +30,7 @@ #include #include #include -#include "cJSON.h" +#include "bs_json.h" static const char *ep; diff --git a/3rdparty/cJSON/cJSON.h b/bs/bs_json.h similarity index 100% rename from 3rdparty/cJSON/cJSON.h rename to bs/bs_json.h diff --git a/bs/bs_sign.h b/bs/bs_sign.h index 5d0ad53..e57d2e9 100644 --- a/bs/bs_sign.h +++ b/bs/bs_sign.h @@ -13,6 +13,7 @@ extern "C"{ #endif #define BS_MD5_STRLEN 32 + /* typedef struct{ diff --git a/bs/bs_socket.c b/bs/bs_socket.c index 7a73deb..0f113b3 100644 --- a/bs/bs_socket.c +++ b/bs/bs_socket.c @@ -9,17 +9,47 @@ #include "bs_type.h" #include "bs_dnscache.h" -#define dns_cache_list "{\"n01.me-yun.com\": \"47.94.254.214\", \"wyh1111.oss-cn-hangzhou.aliyuncs.com\": \"120.27.176.249\"}" -static int socket_create(int sock_type, int is_nonblock); +int socket_udp(bool_t is_nonblock); +int socket_tcp(bool_t is_nonblock); +static int socket_create(int family, int sock_type, int is_nonblock); static int sockaddr_create(struct sockaddr_in* addr, in_addr_t s_addr, int port); +state_t bs_tcp_sock_connect(int *sock, const char *ip, int port, bool_t is_nonblock) { + state_t status = BS_SUCCESS; + struct addrinfo hints, *res; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + hints.ai_protocol = 0; + char portStr[8]; + snprintf(portStr, 8, "%d", port); + int retryTimes = 3; + while (retryTimes > 0) { + // 偶尔DNS会解析失败,现在给一个重试机制,默认为重试3次 + retryTimes -= 1; + status = getaddrinfo(ip, portStr, &hints, &res); + if (status == 0) { + *sock = socket_create(res->ai_family, SOCK_STREAM, is_nonblock); + bs_sock_ignore_sigpipe(*sock); + status = connect(*sock, res->ai_addr, res->ai_addrlen); + break; + } else { + printf("ERROR: getaddrinfo error: %s\n", gai_strerror(status)); + } + } + + freeaddrinfo(res); + return status; +} + int socket_udp(bool_t is_nonblock){ - return socket_create(SOCK_DGRAM, is_nonblock); + return socket_create(AF_INET, SOCK_DGRAM, is_nonblock); } int socket_tcp(bool_t is_nonblock){ - return socket_create(SOCK_STREAM, is_nonblock); + return socket_create(AF_INET, SOCK_STREAM, is_nonblock); } state_t bs_sock_keepalive(int sock){ @@ -59,6 +89,25 @@ state_t bs_sock_bind(int sock, int port){ return BS_SUCCESS; } +state_t bs_sock_connect(int sock, const char* ip, int port){ + state_t st; + struct sockaddr_in addr; + + st = bs_sock_addr(&addr, ip, port); + if(st != BS_SUCCESS){ + return st; + } + + st = connect(sock, (struct sockaddr*)&addr, sizeof(struct sockaddr_in)); + // if(st==0){ + // return BS_SUCCESS; + // } + // + // return errno; + + return st; +} + state_t bs_sock_addr(struct sockaddr_in* addr, const char* ip, int port){ struct hostent* host = NULL; struct in_addr *currentIp; @@ -67,7 +116,7 @@ state_t bs_sock_addr(struct sockaddr_in* addr, const char* ip, int port){ if ((host=gethostbyname(ip))==NULL){ return BS_HOSTERR; } - + currentIp = (struct in_addr *)host->h_addr; dns_cache_store(*currentIp, ip); } @@ -80,25 +129,6 @@ state_t bs_sock_addr(struct sockaddr_in* addr, const char* ip, int port){ return BS_SUCCESS; } -state_t bs_sock_connect(int sock, const char* ip, int port){ - state_t st; - struct sockaddr_in addr; - - st = bs_sock_addr(&addr, ip, port); - if(st != BS_SUCCESS){ - return st; - } - - st = connect(sock, (struct sockaddr*)&addr, sizeof(struct sockaddr_in)); -// if(st==0){ -// return BS_SUCCESS; -// } -// -// return errno; - - return st; -} - void bs_sock_ignore_sigpipe(int sock) { const int set = 1; #ifdef __ANDROID__ @@ -221,10 +251,10 @@ static int sockaddr_create(struct sockaddr_in* addr, in_addr_t s_addr, int port) return BS_SUCCESS; } -static int socket_create(int sock_type, int is_nonblock){ +static int socket_create(int family, int sock_type, int is_nonblock){ int sock; - if((sock = socket(AF_INET, sock_type, 0)) == -1){ + if((sock = socket(family, sock_type, 0)) == -1){ return -1; } @@ -237,8 +267,7 @@ static int socket_create(int sock_type, int is_nonblock){ if(is_nonblock){ socket_unblock(sock); - } - else{ + } else{ socket_block(sock); } diff --git a/bs/bs_socket.h b/bs/bs_socket.h index e43fd4c..4c3170c 100644 --- a/bs/bs_socket.h +++ b/bs/bs_socket.h @@ -37,6 +37,8 @@ typedef struct bs_addr_t{ int socket_udp(bool_t is_nonblock); int socket_tcp(bool_t is_nonblock); +state_t bs_tcp_sock_connect(int *sock, const char* ip, int port, bool_t is_nonblock); +//state_t bs_udp_sock_connect(int *sock, const char* ip, int port, bool_t is_nonblock); state_t socket_unblock(int sock); state_t socket_block(int sock); state_t bs_sock_keepalive(int sock); diff --git a/bs/bs_url.c b/bs/bs_url.c index ba67800..d2bf3fd 100644 --- a/bs/bs_url.c +++ b/bs/bs_url.c @@ -1,8 +1,8 @@ /** - * file : bs_url.c - * author : bushaofeng - * create : 2014-10-06 23:05 - * func : + * file : bs_url.c + * author : bushaofeng + * create : 2014-10-06 23:05 + * func : * history: */ @@ -52,24 +52,24 @@ void http_destroy(void* p){ state_t url_parse(url_t* url, const char* url_str){ int i; char port[8] = {0}; - + if(url==NULL || url_str==NULL){ return BS_INVALID; } - + char* start; char* end; - + url->url.set(&url->url, url_str, (uint32_t)strlen(url_str)); start = (char*)url_str; - + // protocal end = strstr(start, "://"); if(end != NULL){ url->protocal.set(&url->protocal, start, (uint32_t)(end-start)); start = end+3; } - + // host/port end = strchr(start, '/'); if(end != NULL){ @@ -86,7 +86,7 @@ state_t url_parse(url_t* url, const char* url_str){ } start = end; } - + url->path.set(&url->path, start, (uint32_t)strlen(url_str)-(uint32_t)(start - url_str)); // path @@ -124,6 +124,20 @@ void http_add_newline(http_t* http){ data_append(&http->req, newline, (uint32_t)strlen(newline)); } +void* http_res_init(void * p){ + http_res_t* res = (http_res_t*)p; + data_init(&res->response); + res->response_code = 0; + res->body = NULL; + res->body_size = 0; + return res; +} + +void http_res_destroy(void* p){ + http_res_t* res = (http_res_t*)p; + data_destroy(&res->response); +} + /// 设置http body void http_set_body(http_t* http, const char* body, uint32_t body_size){ char buffer[URL_SIZE]; @@ -140,207 +154,162 @@ void http_set_body(http_t* http, const char* body, uint32_t body_size){ http_res_header parse_header(const char *response) { /*获取响应头的信息*/ - struct http_res_header resp; + struct http_res_header response_header; char *header = strstr(response, "HTTP/1.1"); //获取http状态代码 if (header) - sscanf(header, "%*s %hd", &resp.status_code); + sscanf(header, "%*s %hd", &response_header.status_code); //获取返回文档类型 header = strstr(response, "Content-Type:"); if (header) - sscanf(header, "%*s %s", resp.content_type); + sscanf(header, "%*s %s", response_header.content_type); //获取返回文档长度 header = strstr(response, "Content-Length:"); if (header) - sscanf(header, "%*s %lld", &resp.content_length); - - return resp; -} - -state_t http_timeout(int sock, http_t* http) { - struct timeval timeout; - fd_set r; - FD_ZERO(&r); - FD_SET(sock,&r); - timeout.tv_sec = http->time_out; - timeout.tv_usec = 0; - int retval = select(sock+1,NULL,&r,NULL,&timeout); - return retval; + sscanf(header, "%*s %lld", &response_header.content_length); + + return response_header; } http_res_t* http_perform(http_t* http) { - int sock; - char buf[1024]; - int len = 0; + int socket; http_res_t *res = bs_new(http_res); - sock = socket_tcp(BS_TRUE); - res->response_code = connect_socket(sock, http); + res->response_code = connect_socket(&socket, http); if (res->response_code == BS_SUCCESS) { - socket_block(sock); - if (write(sock, http->req.mem, http->req.len) <= 0) { - res->response_code = BS_SENDERR; - } else { - while( (len = (int)read(sock, buf, sizeof(buf))) > 0){ - data_append(&res->response, buf, len); - } - - http_response_parse(res); + http_send_request(socket, res, http); + if (res->response_code == BS_SUCCESS) { + http_receive_response(socket, res, http); } } - close(sock); - bs_delete(http); + if (res->response_code == -1 && errno == ETIMEDOUT) { + res->response_code = BS_TIMEOUT; + } + + close(socket); return res; } http_res_t* http_download(http_t* http, const char* path, void* download, http_progress progressCallback){ - int sock; + int socket; char buf[1024]; uint64_t len = 0; - FILE *file; uint64_t hasrecieve = 0; http_res_t *res = bs_new(http_res); - - sock = socket_tcp(BS_TRUE); - res->response_code = connect_socket(sock, http); + + res->response_code = connect_socket(&socket, http); if (res->response_code == BS_SUCCESS) { - socket_block(sock); - file = fopen(path, "wb+"); - if(file == NULL){ - res->response_code = BS_CREATERR; - } else { - if(write(sock, http->req.mem, http->req.len) <= 0){ - res->response_code = BS_SENDERR; - } else { - int flag = 0; - // http response header解析 - while ((len = read(sock, buf, 1)) != 0) { - data_append(&res->response, buf, (uint32_t)len); - if (buf[0] == '\r' || buf[0] == '\n') { - flag ++; - } else { - flag = 0; + http_send_request(socket, res, http); + + if (res->response_code == BS_SUCCESS) { + // http response header解析 + http_receive_header(socket, res, http); + if (res->response_code == BS_SUCCESS) { + FILE *file = fopen(path, "wb+"); + if(file == NULL){ + res->response_code = BS_CREATERR; + } else { + // 构建请求成功后的http状态消息 + http_response_parse(res); + http_res_header res_header = parse_header(res->response.mem); + + while (hasrecieve < res_header.content_length) { + len = read(socket, buf, sizeof(buf)); + fwrite(buf, (size_t)len, 1, file); + hasrecieve += len; //更新已经下载的长度 + progressCallback(len, hasrecieve, res_header.content_length, download); // 回调下载文件的进度值 } - if (flag == 4) - break; - } - - // 构建请求成功后的http状态消息 - http_response_parse(res); - http_res_header res_header = parse_header(res->response.mem); - - while (hasrecieve < res_header.content_length) { - len = read(sock, buf, sizeof(buf)); - fwrite(buf, (size_t)len, 1, file); - hasrecieve += len; //更新已经下载的长度 - progressCallback(len, hasrecieve, res_header.content_length, download); // 回调下载文件的进度值 + fclose(file); } } - - fclose(file); } } - close(sock); - bs_delete(http); + if (res->response_code == -1 && errno == ETIMEDOUT) { + res->response_code = BS_TIMEOUT; + } + close(socket); return res; } -http_res_t* http_upload(http_t* http, const char* path, void* upload, http_progress progressCallback){ - int sock; +http_res_t* http_upload(http_t *http, const char *path, void *upload, http_progress progressCallback){ + int socket; char buf[1024]; - FILE *file; uint64_t hassend = 0; uint64_t len = 0; uint64_t contentLength = 0; http_res_t *res = bs_new(http_res); - sock = socket_tcp(BS_TRUE); - res->response_code = connect_socket(sock, http); + res->response_code = connect_socket(&socket, http); if (res->response_code == BS_SUCCESS) { - socket_block(sock); - file = fopen(path, "rb"); - if(file == NULL){ - res->response_code = BS_CREATERR; - } else { - // 获取文件的大小 - fseek (file , 0 , SEEK_END); - contentLength = ftell (file); - rewind (file); - // 上传http头 - if(write(sock, http->req.mem, http->req.len)<=0){ - res->response_code = BS_SENDERR; + http_send_request(socket, res, http); + if (res->response_code == BS_SUCCESS) { + FILE *file = fopen(path, "rb"); + if(file == NULL){ + res->response_code = BS_CREATERR; } else { - // 设置socket的缓冲区 - int sock_buf_size = 10000; - setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&sock_buf_size, sizeof(sock_buf_size)); - - //上传http文件 - while ((len = fread(buf, 1, sizeof(buf), file)) > 0) { - if (write(sock, buf, (size_t)len) <= -1) { - res->response_code = BS_SENDERR; - } else { - hassend += len; - if (hassend / len % 10 == 1 || hassend >= contentLength) { - progressCallback(len, hassend, contentLength, upload); // 回调上传文件的进度值 - } - } - } - - uint64_t read_length = 0; - if ((read_length = read(sock, buf, sizeof(buf))) > 0) { - data_append(&res->response, buf, (uint32_t)read_length); - } - - if (read_length == -1) { + // 获取文件的大小 + fseek (file , 0 , SEEK_END); + contentLength = ftell (file); + rewind (file); + } + // 设置socket的缓冲区 + int sock_buf_size = 10000; + setsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char *)&sock_buf_size, sizeof(sock_buf_size)); + + //上传http文件 + while ((len = fread(buf, 1, sizeof(buf), file)) > 0) { + if (write(socket, buf, (size_t)len) <= -1) { res->response_code = BS_SENDERR; } else { - http_response_parse(res); + hassend += len; + if (hassend / len % 10 == 1 || hassend >= contentLength) { + progressCallback(len, hassend, contentLength, upload); // 回调上传文件的进度值 + } } } + http_receive_response(socket, res, http); fclose(file); } } - close(sock); - bs_delete(http); + if (res->response_code == -1 && errno == ETIMEDOUT) { + res->response_code = BS_TIMEOUT; + } + + close(socket); return res; } -http_res_t* http_post_data(http_t* http, uint8_t* data, void* upload, http_progress progressCallback) { - int sock; +http_res_t* http_post_data(http_t *http, uint8_t *data, void *upload, http_progress progressCallback) { + int socket; char buf[1024]; uint64_t hassend = 0; uint32_t bufferSize = 1024; uint64_t len = 0; http_res_t* res = bs_new(http_res); - sock = socket_tcp(BS_TRUE); - res->response_code = connect_socket(sock, http); + res->response_code = connect_socket(&socket, http); if (res->response_code == BS_SUCCESS) { - socket_block(sock); - // 上传http头 - if (write(sock, http->req.mem, http->req.len)<=0){ - res->response_code = BS_SENDERR; - } else { + http_send_request(socket, res, http); + if (res->response_code == BS_SUCCESS) { //上传二进制数据 size_t sock_buf_size = 10000; - setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&sock_buf_size, sizeof(sock_buf_size)); + setsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char *)&sock_buf_size, sizeof(sock_buf_size)); uint64_t totalSize = http->body_size; len = bufferSize; while (hassend < totalSize) { memset(buf, 0, bufferSize); uint64_t remainSize = totalSize - hassend; len = remainSize > bufferSize ? bufferSize : remainSize; - memcpy(buf, data+hassend, len); - if (write(sock, buf, (size_t)len) <= -1) { - close(sock); - bs_delete(http); + memcpy(buf, data + hassend, len); + if (write(socket, buf, (size_t)len) <= -1) { + close(socket); res->response_code = BS_SENDERR; return res; } else { @@ -351,55 +320,83 @@ http_res_t* http_post_data(http_t* http, uint8_t* data, void* upload, http_progr } } - uint64_t read_length = 0; - while((read_length = (int)read(sock, buf, sizeof(buf))) > 0) { - data_append(&res->response, buf, (uint32_t)read_length); - if (read_length < bufferSize) { + http_receive_response(socket, res, http); + } + } + + if (res->response_code == -1 && errno == ETIMEDOUT) { + res->response_code = BS_TIMEOUT; + } + + close(socket); + return res; +} + +void http_send_request(int socket, http_res_t* http_res, http_t* http) { + socket_block(socket); + http_res->response_code = write_timeout(socket, http->time_out); + if (http_res->response_code == BS_SUCCESS) { + if (write(socket, http->req.mem, http->req.len) <= 0) { + http_res->response_code = BS_SENDERR; + } + } +} + +void http_receive_response(int socket, http_res_t *http_res, http_t *http) { + int len = 0; + int bufferSize = 1024; + int receveLength = 0; + char buf[bufferSize]; + http_receive_header(socket, http_res, http); + http_res_header res_header = parse_header(http_res->response.mem); + if (res_header.content_length > 0) { + if (http_res->response_code == BS_SUCCESS) { + while((len = (int)read(socket, buf, sizeof(buf))) > 0) { + data_append(&http_res->response, buf, len); + receveLength += len; + if (receveLength >= res_header.content_length) { break; } } - if (read_length == -1) { - res->response_code = BS_SENDERR; + if (len == -1) { + http_res->response_code = BS_SENDERR; } else { - http_response_parse(res); + http_response_parse(http_res); } } + } else { + http_response_parse(http_res); } - - close(sock); - bs_delete(http); - return res; -} - -void* http_res_init(void * p){ - http_res_t* res = (http_res_t*)p; - data_init(&res->response); - res->response_code = 0; - res->body = NULL; - res->body_size = 0; - return res; } -void http_res_destroy(void* p){ - http_res_t* res = (http_res_t*)p; - data_destroy(&res->response); +void http_receive_header(int socket, http_res_t *http_res, http_t* http) { + char buf[1024]; + int len = 0; + int flag = 0; + http_res->response_code = read_timeout(socket, http->time_out); + if (http_res->response_code == BS_SUCCESS) { + while ((len = read(socket, buf, 1)) != 0) { + data_append(&http_res->response, buf, (uint32_t)len); + if (buf[0] == '\r' || buf[0] == '\n') { + flag ++; + } else { + flag = 0; + } + + if (flag == 4) + break; + } + } } -state_t connect_socket(int sock, http_t *http) { - bs_sock_ignore_sigpipe(sock); - - int err = bs_sock_connect(sock, http->url.domain.mem, http->url.port); - if (err == -1 && errno != EINPROGRESS) { +state_t connect_socket(int *sock, http_t *http) { + int err = bs_tcp_sock_connect(sock, http->url.domain.mem, http->url.port, BS_TRUE); + if (!(err == -1 || errno == EINPROGRESS) || err == BS_HOSTERR) { return BS_CONNERR; } - - int retval = http_timeout(sock, http); - if(retval==-1 || retval == 0) { - return retval == -1 ? BS_CONNERR : BS_TIMEOUT; - } - - return BS_SUCCESS; + + return connect_timeout(*sock, http->time_out); } state_t http_response_parse(http_res_t* res){ @@ -419,6 +416,106 @@ state_t http_response_parse(http_res_t* res){ return BS_SUCCESS; } +state_t read_timeout(int socket, uint32_t wait_seconds) +{ + int ret = 0; + if (wait_seconds > 0) { + fd_set read_fdset; + struct timeval timeout; + + FD_ZERO(&read_fdset); + FD_SET(socket, &read_fdset); + + timeout.tv_sec = wait_seconds; + timeout.tv_usec = 0; + + do { + ret = select(socket + 1, &read_fdset, NULL, NULL, &timeout); //select会阻塞直到检测到事件或者超时 + // 如果select检测到可读事件发送,则此时调用read不会阻塞 + } while (ret < 0 && errno == EINTR); + + if (ret == 0) { + ret = -1; + errno = ETIMEDOUT; + } else if (ret == 1) { + return 0; + } + + } + + return ret; +} + +state_t write_timeout(int socket, uint32_t wait_seconds) +{ + int ret = 0; + if (wait_seconds > 0) { + fd_set write_fdset; + struct timeval timeout; + + FD_ZERO(&write_fdset); + FD_SET(socket, &write_fdset); + + timeout.tv_sec = wait_seconds; + timeout.tv_usec = 0; + + do { + ret = select(socket + 1, NULL, &write_fdset, NULL, &timeout); + } while (ret < 0 && errno == EINTR); + + if (ret == 0) { + ret = -1; + errno = ETIMEDOUT; + } else if (ret == 1) { + return 0; + } + } + + return ret; +} + +state_t connect_timeout(int socket, uint32_t wait_seconds) +{ + int ret; + fd_set connect_fdset; + struct timeval timeout; + FD_ZERO(&connect_fdset); + FD_SET(socket, &connect_fdset); + + timeout.tv_sec = wait_seconds; + timeout.tv_usec = 0; + + do { + /* 一旦连接建立,套接字就可写 */ + ret = select(socket + 1, NULL, &connect_fdset, NULL, &timeout); + } while (ret < 0 && errno == EINTR); + + if (ret == 0) { + errno = ETIMEDOUT; + return -1; + } else if (ret < 0) { + return -1; + } else if (ret == 1) { + /* ret返回为1,可能有两种情况,一种是连接建立成功,一种是套接字产生错误 + * 此时错误信息不会保存至errno变量中(select没出错),因此,需要调用 + * getsockopt来获取 */ + int err; + socklen_t socklen = sizeof(err); + int sockoptret = getsockopt(socket, SOL_SOCKET, SO_ERROR, &err, &socklen); + if (sockoptret == -1) { + return -1; + } + if (err == 0) { + ret = 0; + } else { + errno = err; + ret = -1; + } + } + + return ret; +} + void url_print(url_t* url){ fprintf(stdout, "protocal[%s] host[%s] domain[%s] port[%d] path[%s] query[%s]\n", url->protocal.mem, url->host.mem, url->domain.mem, url->port, url->path.mem, url->query.mem); } diff --git a/bs/bs_url.h b/bs/bs_url.h index 82db594..c87420e 100644 --- a/bs/bs_url.h +++ b/bs/bs_url.h @@ -84,6 +84,12 @@ http_res_t* http_download(http_t* http, const char* file, void* download, http_p http_res_t* http_upload(http_t* http, const char* path, void* upload, http_progress progressCallback); /// 上传二进制数据到服务器。return ==0:正确;>0:http错误码 <0:连接http失败 http_res_t* http_post_data(http_t* http, uint8_t* data, void* upload, http_progress progressCallback); +/// http request请求 +void http_send_request(int socket, http_res_t* http_res, http_t* http); +/// http response接收 +void http_receive_response(int socket, http_res_t* http_res, http_t* http); +/// http response header接收 +void http_receive_header(int socket, http_res_t *http_res, http_t* http); struct http_res_t{ data_t response; @@ -96,8 +102,11 @@ struct http_res_t{ void* http_res_init(void *p); void http_res_destroy(void *p); -state_t connect_socket(int sock, http_t *http); +state_t connect_socket(int *sock, http_t *http); state_t http_response_parse(http_res_t *res); +state_t read_timeout(int socket, uint32_t wait_seconds); +state_t write_timeout(int socket, uint32_t wait_seconds); +state_t connect_timeout(int socket, uint32_t wait_seconds); #ifdef __cplusplus } #endif diff --git a/model/.DS_Store b/model/.DS_Store index 6a0d20cf338640a20e235a0235742206b7c5d9c2..99cca4de8bb51dd35e8f0b04ffc7f52ea3699d1c 100644 GIT binary patch delta 30 kcmZoMXfc@J&&V<{z#2&OByVPAWMZGJz$mtvo#QV*0ES@*NB{r; delta 33 ncmZoMXfc@J&&WD4z#2&OB(pO!lroes6l{DT$iA7K<1aq|qUZ_A diff --git a/model/async/Android.mk b/model/async/Android.mk index b04ede1..e196e46 100644 --- a/model/async/Android.mk +++ b/model/async/Android.mk @@ -11,13 +11,9 @@ LOCAL_C_INCLUDES += \ LOCAL_SRC_FILES += \ AsyncFrame.cpp \ AsyncSocket.cpp \ - AsyncQueue.cpp \ SocketFrame.cpp #LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -llog -LOCAL_STATIC_LIBRARIES := \ - libbs \ - libbasic LOCAL_MODULE := async diff --git a/model/p2p/.DS_Store b/model/p2p/.DS_Store deleted file mode 100644 index 3f1d85a6399083ff8e0091bec9d38ab1d3f376ce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKyH3O~5S$G;aX`V9lqso@;0wa(K%$_cM{p0siExP!Q0FuFH2wx=y;gM2L5mRV zO6zgfvyMErvM~S|zs!$;5r83GG23DDh3UBZhGj7_AWE2{#u9TJ;SmoTY!CcK1$6Ir zaf%i9?Fno9cTv@|X;n`-u7~5Ce)tiLJv|VYxaBS{aK}Bbut@px-sA80`8*{v<}EqH z3eRbFcHPU~MuQW&<}_$hcK+I94?6aJ$_%S`TU!Ma-CO}zz!mt13b1CY4fhPabp>1j zSD;fszYhgnv5eRnhEE5Za0MXd3VJLfL~9a0*4>k7C6sRCQ}IMVum_Wk`oP4XvKz!msY3P?V=nvA)m ySX(z1r?s}A-_X^R*BW*y?1WNGu9o5hdN9Td?GVd|tsx^c{}Bi>c;gEEr~;oQ;7<+! diff --git a/model/utp/.DS_Store b/model/utp/.DS_Store deleted file mode 100644 index a324098ca8b199f7d363f2f5f28cfa6958493967..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKyG{c!5S$G`M9`$9bV-H89~@CYqM(5uK^}-G2NxmI-)Hb?{0+={mne5!LxUo; zE7`O5&id?;&JO@GTF=gaA%FpkqNvkh+T9uIIk``iJVu2DW;n$&mK_7_VwcYS5a)Q| zykD_3|Esc^PReS+xQcVha`Ksto(gh}2d;9CN3OZVyvgs~wfF~E;|(inGiAMMvgL;C z_pQ(dFx=6 zp8!O?MrWh1*JaH~j)h}w$Oug=m1wErPYkhi_9y2Rj +#include +#include + +#include +#include +#include +#include + +using namespace std; + +JavaVM* g_jvm = NULL; +map g_so_map; +char g_package_name[256] = {0}; + +jlong loadSo(JNIEnv *env, jclass jc, jstring so_name); +jint registerJNIMethod(JNIEnv *env, jclass jc, jlong so, jstring jclassname, jstring jfunc, jstring jsignature); +static int registerNativeMethods(JNIEnv *env, const char *className, JNINativeMethod *gMethods, int numMethods); + +jint JNI_OnLoad(JavaVM *vm, void *reserved) { + void *env = NULL; + //LOGI("JNI_OnLoad"); + if (vm->GetEnv(&env, JNI_VERSION_1_6) != JNI_OK) { + __android_log_print(ANDROID_LOG_ERROR, "NativeLoad", "ERROR: GetEnv failed"); + return -1; + } + + FILE* fp = fopen("/proc/self/cmdline", "r"); + fread(g_package_name, sizeof(g_package_name), 1, fp); + /* + if (strcmp(g_package_name, "com.visionin.demo")!=0) + { + return -1; + } + */ + fclose(fp); + + g_jvm = vm; + __android_log_print(ANDROID_LOG_ERROR, "NativeLoad", "g_jvm: %llu", (unsigned long long)g_jvm); + + JNINativeMethod method[2] = { + {"loadSo", "(Ljava/lang/String;)J", (void*)loadSo}, + {"registerJNIMethod", "(JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;)I", (void*)registerJNIMethod} + }; + registerNativeMethods((JNIEnv *)env, "com/rex/load/NativeLoad", method, 2); + + return JNI_VERSION_1_6; +} + +jlong loadSo(JNIEnv *env, jclass jc, jstring so_name){ + void *filehandle = NULL; + + const char* so = env->GetStringUTFChars(so_name, NULL); + if(so == NULL) { + __android_log_print(ANDROID_LOG_ERROR, "NativeLoad", "Error: so name is null!"); + return 0; + } + + map::iterator iter = g_so_map.find(string(so)); + if (iter == g_so_map.end()) + { + filehandle = dlopen(so, RTLD_LAZY); + if (filehandle==NULL) + { + char libpath[1024]; + snprintf(libpath, sizeof(libpath), "/data/data/%s/lib/%s", g_package_name, so); + __android_log_print(ANDROID_LOG_ERROR, "NativeLoad", "%s load error[%s]. change to load path: %s", so, dlerror(), libpath); + filehandle = dlopen(libpath, RTLD_LAZY); + if (filehandle==NULL) + { + __android_log_print(ANDROID_LOG_ERROR, "NativeLoad", "Libary %s Load Error[%s]!", so, dlerror()); + return 0; + } + } + + g_so_map[string(so)] = filehandle; + } + else{ + filehandle = iter->second; + } + + env->ReleaseStringUTFChars(so_name, so); + return (jlong)filehandle; +} + +jint registerJNIMethod(JNIEnv *env, jclass jc, jlong so, jstring jclassname, jstring jfunc, jstring jsignature){ + const char* classname = env->GetStringUTFChars(jclassname, NULL); + const char* java_func = env->GetStringUTFChars(jfunc, NULL); + const char* signature = env->GetStringUTFChars(jsignature, NULL); + //const char* native_func = env->GetStringUTFChars(jnative_func, NULL); + if(classname==NULL || java_func == NULL || signature==NULL) { + return 0; + } + + void* func = dlsym((void*)so, java_func); + if (func==NULL) + { + __android_log_print(ANDROID_LOG_ERROR, "NativeLoad", "Libary[%lld] Load Method [%s] Error!", (long long)so, java_func); + return 0; + } + + JNINativeMethod method = {java_func, signature, func}; + int st = registerNativeMethods(env, classname, &method, 1); + + env->ReleaseStringUTFChars(jclassname, classname); + env->ReleaseStringUTFChars(jfunc, java_func); + env->ReleaseStringUTFChars(jsignature, signature); + //env->ReleaseStringUTFChars(jnative_func, native_func); + + return st; +} + +static int registerNativeMethods(JNIEnv *env, const char *className, JNINativeMethod *methods, int numMethods){ + jclass clazz; + clazz = env->FindClass(className); + if (clazz == NULL) { + __android_log_print(ANDROID_LOG_ERROR, "NativeLoad", "Native registration unable to find class '%s'", className); + return JNI_FALSE; + } + if (env->RegisterNatives(clazz, methods, numMethods) < 0) { + __android_log_print(ANDROID_LOG_ERROR, "NativeLoad", "RegisterNatives failed for '%s'", className); + return JNI_FALSE; + } + return JNI_TRUE; +} diff --git a/src/.gitignore b/src/.gitignore new file mode 100644 index 0000000..259148f --- /dev/null +++ b/src/.gitignore @@ -0,0 +1,32 @@ +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app diff --git a/src/Android.mk b/src/Android.mk new file mode 100644 index 0000000..0bf242a --- /dev/null +++ b/src/Android.mk @@ -0,0 +1,56 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_CFLAGS += -D__ANDROID__ -g -DDEBUG +#APP_PLATFORM := android-19 + +SRCFILES = $(wildcard $(LOCAL_PATH)/*.cpp $(LOCAL_PATH)/*/*.cpp) +SRCS = $(patsubst $(LOCAL_PATH)/%, ./%,$(SRCFILES)) + +LOCAL_C_INCLUDES = \ + $(LOCAL_PATH)/../3rdparty/libzip \ + $(LOCAL_PATH)/../bs \ + $(LOCAL_PATH)/../basic + +LOCAL_SRC_FILES += \ + $(SRCS) + +LOCAL_SHARED_LIBRARIES := libnative +LOCAL_STATIC_LIBRARIES := \ + libasync \ + libbasic_d \ + libbs \ + libzip + +LOCAL_LDLIBS := -ldl -llog -lz +LOCAL_MODULE := MeCloud_d + +include $(BUILD_SHARED_LIBRARY) + +include $(CLEAR_VARS) + +LOCAL_CFLAGS += -D__ANDROID__ -g +#APP_PLATFORM := android-19 + +SRCFILES = $(wildcard $(LOCAL_PATH)/*.cpp $(LOCAL_PATH)/*/*.cpp) +SRCS = $(patsubst $(LOCAL_PATH)/%, ./%,$(SRCFILES)) + +LOCAL_C_INCLUDES = \ + $(LOCAL_PATH)/../3rdparty/libzip \ + $(LOCAL_PATH)/../bs \ + $(LOCAL_PATH)/../basic + +LOCAL_SRC_FILES += \ + $(SRCS) + +LOCAL_SHARED_LIBRARIES := libnative +LOCAL_STATIC_LIBRARIES := \ + libasync \ + libbasic_r \ + libbs \ + libzip + +LOCAL_LDLIBS := -ldl -llog -lz +LOCAL_MODULE := MeCloud_r + +include $(BUILD_SHARED_LIBRARY) \ No newline at end of file diff --git a/src/Me.h b/src/Me.h new file mode 100644 index 0000000..f81b828 --- /dev/null +++ b/src/Me.h @@ -0,0 +1,36 @@ +/** + * file : Me.h + * author : Rex + * create : 2016-11-01 15:00 + * func : + * history: + */ + +#ifndef __ME_H_ +#define __ME_H_ + +#include "MeCloud.h" +#include "MeObject.h" +#include "MeUser.h" +#include "MeFile.h" +#include "MeDownloadFile.h" +#include "MeUploadFile.h" +#include "MeDevice.h" +#include "MeTimeStat.h" +#include "MeQuery.h" +#include "MeCallback.h" +#include "MeRole.h" +#include "MeACL.h" +#include "MeError.h" +#include "MeHttpFileCallback.h" +#include "MeSMS.h" +#ifdef __IOS__ +#include "MeIOSObject.h" +#include "MeIOSException.h" +#include "MeIOSJSONObject.h" +#include "MeIOSNetManager.h" +#include "MeIOSRole.h" +#include "MeIOSACL.h" +#include "MeIOSUser.h" +#endif +#endif diff --git a/src/MeACL.cpp b/src/MeACL.cpp new file mode 100644 index 0000000..78c58cb --- /dev/null +++ b/src/MeACL.cpp @@ -0,0 +1,146 @@ +/** + * file : MeACL.cpp + * author : Rex + * create : 2017-07-18 17:57 + * func : + * history: + */ + +#include "MeACL.h" +#include "MeRole.h" +#include "MeUser.h" + +#define ME_ACL_WRITE_ACCSS "write" // 写权限可key +#define ME_ACL_READ_ACCSS "read" // 读权限的key +#define ME_ACL_DELETE_ACCSS "delete" // 读权限的key +#define ME_ACL_PUBLIC_IDENTIFIER "*" // 身份key +// 三面三个key请参考下面注解 +/* + 存储格式 + { + "*":{"read": true}, + "user1_id": {"write": true}, + "role:role1": {"read": true} + } +*/ + +MeACL::MeACL():JSONObject() { +} + +//全部执行深拷贝 +MeACL::MeACL(MeACL* acl):JSONObject(acl, false) { + for (map::iterator iter = acl->m_object_map.begin(); iter!=acl->m_object_map.end(); iter++) { + m_object_map[iter->first] = new JSONObject(iter->second, false); + } +} + +MeACL& MeACL::operator=(const MeACL &acl) { + if (m_root!=NULL) { + cJSON_Delete(m_root); + } + + m_root = cJSON_Duplicate(acl.getCJSON(), 1); + m_auto_destruct = true; + + clear(); + + for (map::const_iterator iter = acl.m_object_map.begin(); iter!=acl.m_object_map.end(); iter++) { + JSONObject* obj = iter->second; + m_object_map[iter->first] = new JSONObject(obj, false); + } + + return *this; +} + +#pragma --mark 公开权限 +void MeACL::setPublicReadAccess(){ + setACLAccess(ME_ACL_READ_ACCSS, ME_ACL_PUBLIC_IDENTIFIER); +} + +void MeACL::setPublicWriteAccess(){ + setACLAccess(ME_ACL_WRITE_ACCSS, ME_ACL_PUBLIC_IDENTIFIER); +} + +#pragma --mark 角色权限 +void MeACL::setRoleReadAccess(const char* role){ + setACLRoleAccess(ME_ACL_READ_ACCSS, role); +} + +void MeACL::setRoleWriteAccess(const char* role){ + setACLRoleAccess(ME_ACL_WRITE_ACCSS, role); +} + +void MeACL::setRoleDeleteAccess(const char* role) { + setACLRoleAccess(ME_ACL_DELETE_ACCSS, role); +} + +void MeACL::setRoleReadAccess(MeRole* role){ + setRoleReadAccess(role->stringValue(ME_ROLE_KEY)); +} + +void MeACL::setRoleWriteAccess(MeRole* role){ + setRoleWriteAccess(role->stringValue(ME_ROLE_KEY)); +} + +void MeACL::setRoleDeleteAccess(MeRole* role) { + setRoleDeleteAccess(role->stringValue(ME_ROLE_KEY)); +} + +void MeACL::setACLRoleAccess(const char* name, const char* role, bool access){ + char *rolename = (char *)malloc(strlen(ME_ROLE_KEY) + strlen(role) + 2); + strcpy(rolename, ME_ROLE_KEY); + strcat(rolename, ":"); + strcat(rolename, role); + setACLAccess(name, rolename); + free(rolename); +} + +#pragma --mark 用户权限 +void MeACL::setUserReadAccess(const char* userId){ + setACLAccess(ME_ACL_READ_ACCSS, userId); +} + +void MeACL::setUserWriteAccess(const char* userId){ + setACLAccess(ME_ACL_WRITE_ACCSS, userId); +} + +void MeACL::setUserDeleteAccess(const char* userId) { + setACLAccess(ME_ACL_DELETE_ACCSS, userId); +} + +void MeACL::setUserReadAccess(MeUser* user){ + setUserReadAccess(user->objectId()); +} + +void MeACL::setUserWriteAccess(MeUser* user){ + setUserWriteAccess(user->objectId()); +} + +void MeACL::setUserDeleteAccess(MeUser* user) { + setUserDeleteAccess(user->objectId()); +} + +#pragma --mark 通用接口 +void MeACL::setACLAccess(const char* name, const char* identifier, bool access){ + JSONObject *accessObject = m_object_map[identifier]; + if (!has(identifier)) { + accessObject = new JSONObject(); + m_object_map[identifier] = accessObject; + } + + accessObject->put(name, access); + put(identifier, accessObject); +} + +void MeACL::clear() { + for (map::iterator iter = m_object_map.begin(); iter!=m_object_map.end(); iter++) { + JSONObject* obj = iter->second; + delete obj; + } + + m_object_map.clear(); +} + +MeACL::~MeACL(){ + clear(); +} diff --git a/src/MeACL.h b/src/MeACL.h new file mode 100644 index 0000000..949b3f9 --- /dev/null +++ b/src/MeACL.h @@ -0,0 +1,54 @@ +/** + * file : MeACL.h + * author : Rex + * create : 2017-07-18 17:57 + * func : + * history: + */ + +#ifndef __MEACL_H_ +#define __MEACL_H_ + +#include +#include "JSON.h" + +class MeRole; +class MeUser; +#define ME_ACL_KEY "acl" + +using namespace mc; +using namespace std; +class MeACL: public JSONObject{ +public: + MeACL(); + MeACL(MeACL* acl); + ~MeACL(); + + MeACL& operator=(const MeACL &acl); + + void setPublicReadAccess(); + void setPublicWriteAccess(); + + void setRoleReadAccess(const char* role); + void setRoleWriteAccess(const char* role); + void setRoleDeleteAccess(const char* role); + void setRoleReadAccess(MeRole* role); + void setRoleWriteAccess(MeRole* role); + void setRoleDeleteAccess(MeRole* role); + + void setUserReadAccess(const char* userId); + void setUserWriteAccess(const char* userId); + void setUserDeleteAccess(const char* userId); + void setUserReadAccess(MeUser* user); + void setUserWriteAccess(MeUser* user); + void setUserDeleteAccess(MeUser* user); + +protected: + map m_object_map; + +private: + void setACLAccess(const char* name, const char* identifier, bool access=true); + void setACLRoleAccess(const char* name, const char* role, bool access=true); + void clear(); +}; +#endif diff --git a/src/MeCallback.cpp b/src/MeCallback.cpp new file mode 100644 index 0000000..971c2c9 --- /dev/null +++ b/src/MeCallback.cpp @@ -0,0 +1,73 @@ +/** + * file : MeCallback.cpp + * author : bushaofeng + * create : 2016-08-27 23:28 + * func : + * history: + */ + +#include "bs.h" +#include "MeCallback.h" +#include "MeObject.h" +#include "MeCloud.h" +#include "ThreadPool.h" + +#pragma --mark "对象回调" +void MeCallback::done(int http_code, status_t st, char* text) { + char *decrypt = NULL; + if (text && http_code == HTTP_OK) { + decrypt = MeCloud::shareInstance()->decrypt(text, (int)strlen(text)); + } else { + // 异常处理,防止崩溃 + const char* error = "服务器异常"; + decrypt = (char *)malloc(strlen(error) + 1); + memcpy(decrypt, error, strlen(error)); + } + + if (http_code != HTTP_OK) { + MeException e; + e.put("httpCode", http_code); + e.put("errMsg", text); + done(NULL, &e); + free(decrypt); + return; + } + + char *c = decrypt; + while ((*c==' ' || *c=='\n')&&(c-decrypt)copySelf(&obj); + done(m_object, NULL); + } else { + MeObject *object = new MeObject(); + object->copySelf(&obj, false); + done(object, NULL); + delete object; + } + } else if (*c=='[') { + JSONArray array(c); + uint32_t size = array.size(); + MeObject* objs = new MeObject[size]; + for (int i=0; i < size; i++) { + JSONObject d = array.jsonValue(i); + MeObject* o = &objs[i]; + o->setClassName(m_classname); + o->copySelf(&d, false); + } + done(objs, NULL, size); + delete[] objs; + } else{ + MeException e; + e.put("errCode", BS_JSONPARSE); + e.put("errMsg", "JSON Parse Error"); + e.put("info", c); + done(NULL, &e); + } + + free(decrypt); +} diff --git a/src/MeCallback.h b/src/MeCallback.h new file mode 100644 index 0000000..f46b935 --- /dev/null +++ b/src/MeCallback.h @@ -0,0 +1,42 @@ +/** + * file : MeCallback.h + * author : bushaofeng + * create : 2016-08-27 23:28 + * func : + * history: + */ + +#ifndef __MECALLBACK_H_ +#define __MECALLBACK_H_ + +#include "McBasic.h" +using namespace mc; + +class MeObject; +class MeException; + +#ifdef __IOS__ +typedef void (^MeCallbackBlock)(MeObject *obj, MeException *err, uint32_t size); +#else +typedef void (*MeCallback_func)(MeObject *obj, MeException *err, uint32_t size); +#endif + +class MeCallback: public HttpCallback, public Reference{ +public: + MeCallback(const char *classname = NULL, MeObject *obj = NULL){ + m_classname = classname; + m_object = obj; + } + + virtual void done(int http_code, status_t st, char *text); + virtual void done(MeObject* obj, MeException* err, uint32_t size = 1) = 0; + + const char* m_classname; + MeObject* m_object; +#ifdef __ANDROID__ + jboolean isEnd; +#else +#endif +}; + +#endif diff --git a/src/MeCloud.cpp b/src/MeCloud.cpp new file mode 100644 index 0000000..d661838 --- /dev/null +++ b/src/MeCloud.cpp @@ -0,0 +1,249 @@ +/** + * file : MeCloud.cpp + * author : bushaofeng + * create : 2016-08-27 01:09 + * func : + * history: + */ + +#include "bs.h" +#include "MeCloud.h" +#include + +MeCloud* MeCloud::m_instance = NULL; +const char* MeCloud::m_version = "1.0"; +bool MeCloud::m_log = false; + +#if DEBUG +char MeCloud::m_base_url[URL_SIZE] = "http://n01.me-yun.com:8000/"; +#else +char MeCloud::m_base_url[URL_SIZE] = "http://n01.me-yun.com:8000/"; +#endif + +void MeCloud::setBaseUrl(const char* url) { + snprintf(m_base_url, sizeof(m_base_url), "%s", url); +} + +void MeCloud::setTimeout(uint32_t timeout) { + HttpSession::setTimeout(timeout); +} + +void MeCloud::showLog(bool show) { + m_log = show; + HttpSession::showLog(show); +} + +void MeCloud::initialize(const char* appId, const char* appKey){ + if (m_instance==NULL) + { + m_instance = new MeCloud(appId, appKey); + } +} + +MeCloud* MeCloud::shareInstance(){ + if (m_instance==NULL) { + m_instance = new MeCloud(NULL, NULL); + + bs_log_init("stdout"); + } + return m_instance; +} + +MeCloud::MeCloud(const char* appId, const char* appKey){ + if (appId != NULL && appKey != NULL) { + m_http_session.addHttpHeader("X-MeCloud-AppId", appId); + m_http_session.addHttpHeader("X-MeCloud-AppKey", appKey); + } + m_http_session.addHttpHeader("X-MeCloud-Version", m_version); + +#if DEBUG + m_http_session.addHttpHeader("X-MeCloud-Debug", "1"); +#else +#endif +} + +void MeCloud::addHttpHeader(const char* key, const char* value) { + m_http_session.addHttpHeader(key, value); +} + +const char* MeCloud::cookie() { + return m_http_session.cookie(); +} + +// 清理cookie +void MeCloud::clearCookie() { + m_http_session.clearCookie(); +} + +// 内存需要外面释放 +char* MeCloud::crypto(const char *input, int in_size) { + Crypt crypt; + char *output; +#if DEBUG + output = (char *)malloc(in_size + 1); + memset(output, 0, in_size + 1); + memcpy(output, input, in_size + 1); +#else + int outSize = in_size * 2 + 1; + output = (char *)malloc(outSize); + crypt.crypto((char *)input, in_size, output, outSize); +#endif + return output; +} + +// 内存需要外面手动释放 +char* MeCloud::decrypt(const char *input, int in_size) { + Crypt crypt; + char *decryOutput; +#if DEBUG + decryOutput = (char *)malloc(in_size + 1); + memset(decryOutput, 0, in_size + 1); + memcpy(decryOutput, input, in_size + 1); +#else + int outSize = in_size / 2 + 1; + decryOutput = (char *)malloc(outSize); + crypt.decrypt((char *)input, in_size, decryOutput, outSize); +#endif + + return decryOutput; +} + +unsigned char* MeCloud::crypto(const unsigned char *input, int in_size) { + Crypt crypt; + int outSize = in_size + 1; + unsigned char *output = (unsigned char *)malloc(outSize); + crypt.crypto((unsigned char *)input, in_size, output, outSize); + return output; +} + +unsigned char* MeCloud::decrypt(const unsigned char *input, int in_size) { + Crypt crypt; + int outSize = in_size + 1; + unsigned char *decryOutput = (unsigned char *)malloc(outSize); + crypt.decrypt((unsigned char *)input, in_size, decryOutput, outSize); + return decryOutput; +} + +void MeCloud::get(const char* url, MeCallback* callback) { + char *newUrl = getEncodeUrl((char *)url); + m_http_session.get(url, callback); + delete newUrl; +} + +void MeCloud::get(const char* url, map param, MeCallback* callback) { + char tempUrl[URL_SIZE]; + snprintf(tempUrl, sizeof(tempUrl), "%s", url); + for (map::iterator iter = param.begin(); iter != param.end(); iter++) { + if (iter == param.begin()) { + snprintf(tempUrl, sizeof(tempUrl), "%s?%s=%s", tempUrl, iter->first.c_str(), iter->second.c_str()); + } else { + snprintf(tempUrl, sizeof(tempUrl), "%s&%s=%s", tempUrl, iter->first.c_str(), iter->second.c_str()); + } + } + + char *newUrl = getEncodeUrl((char *)tempUrl); + m_http_session.get(newUrl, callback); + delete newUrl; +} + +void MeCloud::post(const char* url, const char* body, MeCallback* callback){ + const char *content = body; + if (!content) { + content = ""; + } + + char *output = crypto(content, (int)strlen(content)); + char *newUrl = getEncodeUrl((char *)url); + m_http_session.post(newUrl, output, (uint32_t)strlen(output), callback); + delete newUrl; + free(output); +} +void MeCloud::put(const char* url, const char* body, MeCallback* callback){ + char *output = crypto(body, (int)strlen(body)); + m_http_session.put(url, output, (uint32_t)strlen(output), callback); + free(output); +} +void MeCloud::del(const char* url, MeCallback* callback){ + m_http_session.del(url, callback); +} +void MeCloud::download(const char* url, const char* path, HttpFileCallback* callback){ + m_http_session.download(url, path, callback); +} + +void MeCloud::upload(const char* url, const char* path, vector > auth, HttpFileCallback* callback){ + m_http_session.upload(url, path, auth, callback); +} + +void MeCloud::upload(const char* url, uint8_t *data, int size, vector > auth, HttpFileCallback* callback) { + m_http_session.upload(url, data, size, auth, callback); +} + +void MeCloud::postData(const char* url, uint8_t *data, int size,HttpFileCallback* callback) { + char *newUrl = getEncodeUrl((char *)url); + m_http_session.postData(url, data, size, callback); + delete newUrl; +} + +char* MeCloud::getEncodeUrl(char *oldUrl) { + char *newUrl = new char[URL_SIZE]; + memset(newUrl, 0, URL_SIZE); + sscanf(oldUrl, "%[^?]", newUrl); + if (strcmp(newUrl, oldUrl) != 0) { + char *param = bs_strrstr(oldUrl, "?") + 1; + char *cryptParam = crypto(param, strlen(param)); + snprintf(newUrl, URL_SIZE, "%s?%s", newUrl, cryptParam); + free(cryptParam); + } + return newUrl; +} + +const char* MeCloud::baseUrl(){ + return m_base_url; +} + +const char* MeCloud::restUrl(){ + snprintf(m_url, URL_SIZE, "%s%s/", m_base_url, m_version); + return m_url; +} +const char* MeCloud::classUrl(){ + snprintf(m_url, URL_SIZE, "%s%s/class/", m_base_url, m_version); + return m_url; +} +const char* MeCloud::userUrl(){ + snprintf(m_url, URL_SIZE, "%s%s/user/", m_base_url, m_version); + return m_url; +} +const char* MeCloud::fileUrl(){ + snprintf(m_url, URL_SIZE, "%s%s/file/", m_base_url, m_version); + return m_url; +} + +void MeCloud::saveJSONToCache(JSONObject *json, const char *key) { + char path[1024]; + char file_name[BS_MD5_STRLEN + 1]; + bs_sign(key, file_name); + FileManager::remove(SharedPreferences::path(file_name, path, sizeof(path))); + Crypt crypt; + const char *str = json->toString(); + int64_t crysize = crypt.encryptByCompress((byte*)str, (uint32_t)strlen(str)); + FileManager::write(path, crypt.bytes(), crysize); +} + +JSONObject* MeCloud::getJSONFromCache(const char *key) { + char file_name[BS_MD5_STRLEN + 1]; + bs_sign(key, file_name); + SharedPreferences fileContentPreference(file_name); + if (fileContentPreference.exist()) { + JSONObject *json = new JSONObject(&fileContentPreference); + return json; + } + + return NULL; +} + +void MeCloud::removeJSONFromCache(const char *key) { + char path[1024]; + char file_name[BS_MD5_STRLEN + 1]; + bs_sign(key, file_name); + FileManager::remove(SharedPreferences::path(file_name, path, sizeof(path))); +} diff --git a/src/MeCloud.h b/src/MeCloud.h new file mode 100644 index 0000000..8d8507b --- /dev/null +++ b/src/MeCloud.h @@ -0,0 +1,91 @@ +/** + * file : MeCloud.h + * author : bushaofeng + * create : 2016-08-27 01:09 + * func : + * history: + */ + +#ifndef __MECLOUD_H_ +#define __MECLOUD_H_ + +#include "McHttp.h" +#include "MeCallback.h" +#include "JSON.h" +#include +#include +#include + +using namespace mc; +class MeException: public JSONObject{ +public: + MeException(){} + MeException(const char* str):JSONObject(str){} + + int errCode(){ + return intValue("errCode"); + } + const char* errMsg(){ + return stringValue("errMsg"); + } + const char* info(){ + return stringValue("info"); + } +}; + +class MeCloud{ +public: + static void initialize(const char* appId = NULL, const char* appKey = NULL); + static MeCloud* shareInstance(); + + static void setBaseUrl(const char* url); + static void setTimeout(uint32_t timeout); + static void showLog(bool show); + inline HttpSession* httpSession(){ return &m_http_session; } + inline static bool isShowedLog(){ return m_log; } + void clearCookie(); + const char* cookie(); + + MeCloud(const char* appId, const char* appKey); + void addHttpHeader(const char* key, const char* value); + + char* crypto(const char *input, int in_size); + char* decrypt(const char *input, int in_size); + unsigned char* crypto(const unsigned char *input, int in_size); + unsigned char* decrypt(const unsigned char *input, int in_size); + + void get(const char* url, map param, MeCallback* callback = NULL); + void get(const char* url, MeCallback* callback = NULL); + void post(const char* url, const char* body, MeCallback* callback = NULL); + void put(const char* url, const char* body, MeCallback* callback = NULL); + void del(const char* url, MeCallback* callback = NULL); + void download(const char* url, const char* path, HttpFileCallback* callback = NULL); + void upload(const char* url, const char* path, vector > auth, HttpFileCallback* callback = NULL); + void upload(const char* url, uint8_t *data, int size, vector > auth, HttpFileCallback* callback = NULL); + void postData(const char* url, uint8_t *data, int size, HttpFileCallback* callback); + + char* getEncodeUrl(char *oldUrl); + + // 以下4个函数不能同时调用,第二个会把第一个抹掉 + const char* baseUrl(); + const char* restUrl(); + const char* classUrl(); + const char* userUrl(); + const char* fileUrl(); + + static const char* m_version; + static char m_base_url[URL_SIZE]; + + void saveJSONToCache(JSONObject *json, const char *key); + JSONObject* getJSONFromCache(const char *key); + void removeJSONFromCache(const char *key); + +protected: + static MeCloud* m_instance; + static bool m_log; + HttpSession m_http_session; + char m_url[URL_SIZE]; + char* m_app_id; + char* m_app_key; +}; +#endif diff --git a/src/MeDevice.cpp b/src/MeDevice.cpp new file mode 100644 index 0000000..3c95ddc --- /dev/null +++ b/src/MeDevice.cpp @@ -0,0 +1,101 @@ +/** + * file : MeDevice.cpp + * author : Rex + * create : 2017-04-04 16:57 + * func : + * history: + */ + +#include "MeDevice.h" +#include "McDevice.h" +#include "McBasic.h" + +MeDevice* MeDevice::m_current_device = NULL; + +MeDevice::MeDevice(): +MeObject("Device"){ + // 设备 +#ifdef __IOS__ + put("bundleId", mc::bundle_id()); +#else + put("package", mc::package_name()); +#endif + put("device", mc::device_version()); + put("system", mc::system_version()); + put("deviceId", mc::device_id()); + // deviceId为唯一索引 + addUniqueKey("deviceId"); + + // 回调设置 + m_object = this; + MeCallback::m_classname = MeObject::m_classname; +} + +MeDevice::MeDevice(JSONObject* obj):MeObject("Device", obj){ + // 回调设置 + m_object = this; + MeCallback::m_classname = MeObject::m_classname; +} + +#pragma --mark "注册设备与退出" +void MeDevice::login(MeCallback* callback){ + // 处理唯一索引 + char unique[512] = {0}; + for (int i=0; i 0) { + // 去掉最后一个& + unique[strlen(unique)-1] = '\0'; + snprintf(m_url, sizeof(m_url), "%s%s?%s", MeCloud::shareInstance()->classUrl(), MeObject::m_classname, unique); + } + else{ + snprintf(m_url, sizeof(m_url), "%s%s", MeCloud::shareInstance()->classUrl(), MeObject::m_classname); + } + + m_callback = callback; + MeCloud::shareInstance()->post(m_url, toString(), this); +} + +void MeDevice::logout(){ + if (m_current_device!=NULL) { + char path[1024]; + FileManager::remove(SharedPreferences::path("__CurrentDevice", path, sizeof(path)) ); + delete m_current_device; + m_current_device = NULL; + } +} + +#pragma --mark "回调" +void MeDevice::done(MeObject* obj, MeException* err, uint32_t size) { + // 写currentUser + if (err!=NULL) { + m_callback->done(obj, err, size); + return; + } + + // 存储CurrentUser + m_current_device = this; + char path[1024]; + FileManager::remove(SharedPreferences::path("__CurrentDevice", path, sizeof(path)) ); + Crypt crypt; + const char* str = toString(); + int64_t crysize = crypt.encryptByCompress((byte*)str, (uint32_t)strlen(str)); + FileManager::write(path, crypt.bytes(), crysize); + + m_callback->done(obj, err, size); +} + +MeDevice* MeDevice::currentDevice(){ + if (m_current_device == NULL) { + SharedPreferences preference("__CurrentDevice"); + if (preference.exist()) { + m_current_device = new MeDevice(&preference); + return m_current_device; + } + + return NULL; + } + + return m_current_device; +} diff --git a/src/MeDevice.h b/src/MeDevice.h new file mode 100644 index 0000000..817b12a --- /dev/null +++ b/src/MeDevice.h @@ -0,0 +1,31 @@ +/** + * file : MeDevice.h + * author : Rex + * create : 2017-04-04 16:57 + * func : + * history: + */ + +#ifndef __MEDEVICE_H_ +#define __MEDEVICE_H_ + +#include "MeObject.h" + +class MeDevice: public MeObject, public MeCallback{ +public: + MeDevice(); + MeDevice(JSONObject* obj); + + // 当前设备 + static MeDevice* currentDevice(); + // 注册设备 + void login(MeCallback* callback); + void logout(); + + virtual void done(MeObject* obj, MeException* err, uint32_t size = 1); + +protected: + static MeDevice* m_current_device; +}; + +#endif diff --git a/src/MeDownloadFile.cpp b/src/MeDownloadFile.cpp new file mode 100644 index 0000000..0927a6e --- /dev/null +++ b/src/MeDownloadFile.cpp @@ -0,0 +1,40 @@ +// +// MeDownloadFile.cpp +// MeCloud +// +// Created by super on 2017/7/31. +// Copyright © 2017年 Rex. All rights reserved. +// + +#include "MeDownloadFile.h" + +MeDownloadFile::MeDownloadFile(JSONObject* obj, const char* className): MeFile(ME_HTTPFILE_DOWNLOAD, className, obj) { + +} + +MeDownloadFile::MeDownloadFile(MeDownloadFile* file): MeFile(file) { + +} + +void MeDownloadFile::setDownloadUrl(const char *url) { + memset(m_url, 0, sizeof(m_url)); + if (strstr(url, "http://") || strstr(url, "https://")) { + snprintf(m_url, sizeof(m_url), "%s", url); + } else { + // Url + memset(m_url, 0, sizeof(m_url)); + if (has("type") && strlen(stringValue("type"))>0) { + snprintf(m_url, sizeof(m_url), "http://wyh1111.oss-cn-hangzhou.aliyuncs.com/%s.%s", url, stringValue("type")); + } else{ + snprintf(m_url, sizeof(m_url), "http://wyh1111.oss-cn-hangzhou.aliyuncs.com/%s", url); + } + } +} + +MeDownloadFile::~MeDownloadFile() { +} + +/// 下载 +void MeDownloadFile::download(HttpFileCallback* callback) { + MeCloud::shareInstance()->download(m_url, filePath(),callback); +} diff --git a/src/MeDownloadFile.h b/src/MeDownloadFile.h new file mode 100644 index 0000000..ed71d93 --- /dev/null +++ b/src/MeDownloadFile.h @@ -0,0 +1,32 @@ +// +// MeDownloadFile.hpp +// MeCloud +// +// Created by super on 2017/7/31. +// Copyright © 2017年 Rex. All rights reserved. +// + +#ifndef MeDownloadFile_h +#define MeDownloadFile_h + +#include "MeFile.h" + +using namespace mc; +class MeDownloadFile: public MeFile { +public: + + MeDownloadFile(JSONObject* obj = NULL, const char* className = "File"); + MeDownloadFile(MeDownloadFile* file); + ~MeDownloadFile(); + + void setDownloadUrl(const char *url); + + /// 下载 + void download(HttpFileCallback* callback); + +#ifdef __IOS__ + void download(MeHttpFileCallbackBlock block, MeHttpFileProgressBlock progressBlock); +#endif +}; + +#endif /* MeDownloadFile_h */ diff --git a/src/MeError.h b/src/MeError.h new file mode 100644 index 0000000..1657f14 --- /dev/null +++ b/src/MeError.h @@ -0,0 +1,21 @@ +// +// MeError.h +// MeCloud +// +// Created by super on 2017/7/20. +// Copyright © 2017年 Rex. All rights reserved. +// + +#ifndef MeError_h +#define MeError_h + +typedef enum ME_USER_CODE{ + ME_USER_SUCCESS, + ME_USERNAME_ILLEGAL, + ME_PASSWORD_ILLEGAL, + ME_PASSWORD_SAME, + ME_OLDPASSWORD_ILLEGAL, + ME_NEWPASSWORD_ILLEGAL, +}code_user; + +#endif /* MeError_h */ diff --git a/src/MeFile.cpp b/src/MeFile.cpp new file mode 100644 index 0000000..59007e5 --- /dev/null +++ b/src/MeFile.cpp @@ -0,0 +1,137 @@ +/** + * file : MeFile.cpp + * author : Rex + * create : 2016-09-20 23:46 + * func : + * history: + */ + +#include "MeFile.h" +#include + +static char g_root_path[1024]; +const char* MeFile::m_root_path = NULL; + +MeFile::MeFile(me_file_type type, const char* className, JSONObject* obj): MeObject(className, obj){ + me_type = type; +} + +MeFile::MeFile(MeFile* file): +MeObject(file){ +} + +MeFile::MeFile(MeObject *meObject, bool auth): MeObject(meObject, auth) { + me_type = ME_HTTPFILE_Default; +} + +MeFile::MeFile(const char* objectId, const char* className): MeObject(objectId, className) { + me_type = ME_HTTPFILE_Default; +} + +MeFile::~MeFile() { +} + +void MeFile::init(){ + // 文件名 +// 根据业务去求或者是下载文件类型判断下载完是不是需要解压 +// memset(m_unzip_name, 0, sizeof(m_unzip_name)); +// memset(m_unzip_path, 0, sizeof(m_unzip_path)); +// if (memcmp(m_name + strlen(m_name) - 4, ".zip", 4) == 0) { +// memcpy(m_unzip_name, m_name, strlen(m_name) - 4); +// snprintf(m_unzip_path, sizeof(m_unzip_path), "%s/%s", rootPath(), m_unzip_name); +// } +} + +void MeFile::setFilename(const char* filename) { + snprintf(m_name, sizeof(m_name), "%s", filename); + snprintf(m_path, sizeof(m_path), "%s/%s", rootPath(), m_name); +} + +const char* MeFile::getUrl(){ + if (strlen(m_url)==0) { + return NULL; + } + + return m_url; +} + +me_file_type MeFile::fileType() { + return me_type; +} + +/// 返回存储路径 +const char* MeFile::filePath(){ + return m_path; +} +/// 解压 +bool MeFile::unzip(){ + return true; + // return Zip::unzip(filePath(), rootPath(), callback); +} + +/// 解压后文件名,如果不是zip文件返回NULL +//const char* MeFile::unzipFileName(){ +// if (strlen(m_unzip_name)==0) { +// return NULL; +// } +// +// return m_unzip_name; +//} +/// 解压后文件路径,如果不是zip文件返回nil +//const char* MeFile::unzipFilePath(){ +// if (strlen(m_unzip_path)==0) { +// return NULL; +// } +// +// return m_unzip_path; +//} + +/// 根目录 +const char* MeFile::rootPath() { + if (m_root_path==NULL) { + snprintf(g_root_path, sizeof(g_root_path), "%s/__me", FileManager::rootPath()); + // 如果不存在则创建文件夹 + if (!FileManager::exist(g_root_path)) { + FileManager::mkdir(g_root_path); + } + m_root_path = g_root_path; + } + + return m_root_path; +} + +const char* MeFile::imageUrl(int width, int height) { + memset(m_image_url, 0, URL_SIZE); + if (strcmp("oss", me_platform) == 0) { + if (width > 0 && height > 0) { + Crypt crypt; + snprintf(m_image_url, URL_SIZE, "x-oss-process=image/resize,w_%d,h_%d", width, height); + char *cryptoParam = MeCloud::shareInstance()->crypto(m_image_url, (int)strlen(m_image_url)); + memset(m_image_url, 0, URL_SIZE); + snprintf(m_image_url, URL_SIZE, "%sfile/download/%s?%s", MeCloud::shareInstance()->restUrl(), objectId(), cryptoParam); + free(cryptoParam); + } else { + snprintf(m_image_url, URL_SIZE, "%sfile/download/%s", MeCloud::shareInstance()->restUrl(), objectId()); + } + } else { + memcpy(m_image_url, stringValue("url"), URL_SIZE); + } + + return m_image_url; +} + +const char* MeFile::imageUrl() { + return imageUrl(0, 0); +} + +const char* MeFile::imageCropUrl(int x, int y, int width, int height) { + memset(m_image_url, 0, URL_SIZE); + Crypt crypt; + snprintf(m_image_url, URL_SIZE, "x-oss-process=image/crop,x_%d,y_%d,w_%d,h_%d", x, y, width, height); + char *cryptoParam = MeCloud::shareInstance()->crypto(m_image_url, (int)strlen(m_image_url)); + memset(m_image_url, 0, URL_SIZE); + snprintf(m_image_url, URL_SIZE, "%sfile/download/%s?%s", MeCloud::shareInstance()->restUrl(), objectId(), cryptoParam); + free(cryptoParam); + return m_image_url; +} + diff --git a/src/MeFile.h b/src/MeFile.h new file mode 100644 index 0000000..0ca08c8 --- /dev/null +++ b/src/MeFile.h @@ -0,0 +1,82 @@ +/** + * file : MeFile.h + * author : Rex + * create : 2016-09-20 23:46 + * func : + * history: + */ + +#ifndef __MEFILE_H_ +#define __MEFILE_H_ + +#include "bs.h" +#include "MeObject.h" +#include "McHttp.h" +#include "McZip.h" +#ifdef __IOS__ +#include "MeIOSHttpFileCallBack.h" +#else +#include "MeHttpFileCallBack.h" +#endif + +typedef enum ME_HTTPFILE_TYPE{ + ME_HTTPFILE_Default, // 普通文件对象 + ME_HTTPFILE_DOWNLOAD, // 上传文件对象 + ME_HTTPFILE_UPLOAD, // 下载文件对象 +}me_file_type; + +using namespace mc; +class MeFile: public MeObject{ +public: + MeFile(me_file_type type = ME_HTTPFILE_DOWNLOAD, const char* className = "File", JSONObject* obj = NULL); + MeFile(MeFile* file); + MeFile(MeObject *meObject, bool auth = false); + MeFile(const char* objectId, const char* className = "File"); + ~MeFile(); + + void init(); + + const char* getUrl(); + + /// 返回处理文件类型(目前有上传和下载) + me_file_type fileType(); + + /// 返回存储路径 + const char* filePath(); + void setFilename(const char* filename); + + /// 解压 + bool unzip(); + + /// 解压后文件名,如果不是zip文件返回NULL +// const char* unzipFileName(); + /// 解压后文件路径,如果不是zip文件返回nil + const char* unzipFilePath(); + + /// 根目录 + static const char* rootPath(); + + // 图片文件 + const char* imageUrl(int width, int height); + + const char* imageCropUrl(int x, int y, int width, int height); + + const char* imageUrl(); + +protected: + static const char* m_root_path; + + char m_name[1024]; + char m_path[1024]; + char m_image_url[URL_SIZE]; + +// char m_unzip_name[256]; +// char m_unzip_path[1024]; + me_file_type me_type; + const char *me_platform = "oss"; + const char *me_bucket = ""; + +private: +}; + +#endif diff --git a/src/MeHttpFileCallback.cpp b/src/MeHttpFileCallback.cpp new file mode 100644 index 0000000..6c53b24 --- /dev/null +++ b/src/MeHttpFileCallback.cpp @@ -0,0 +1,74 @@ +// +// MeDownloadCallback.cpp +// MeCloud +// +// Created by super on 2017/7/24. +// Copyright © 2017年 Rex. All rights reserved. +// + +#include "MeHttpFileCallback.h" +#include "MeFile.h" +#include "bs.h" +#include "string.h" + +void MeHttpFileCallback::done(int http_code, status_t st, const char* text){ + if (http_code != HTTP_OK) { + MeException e; + e.put("httpCode", http_code); + e.put("errMsg", text); + e.put("info", text); + done(m_file, &e); + return; + } + + done(m_file, NULL); +} + +void MeHttpDataCallback::done(int http_code, status_t st, const char *text) { + char *decrypt = NULL; + if (text && http_code == HTTP_OK) { + decrypt = MeCloud::shareInstance()->decrypt(text, (int)strlen(text)); + } else { + // 异常处理,防止崩溃 + const char* error = "服务器异常"; + decrypt = (char *)malloc(strlen(error) + 1); + memcpy(decrypt, error, strlen(error)); + } + + if (http_code != HTTP_OK) { + MeException e; + e.put("httpCode", http_code); + e.put("errMsg", text); + e.put("info", text); + done(NULL, &e); + free(decrypt); + return; + } + + char* c = (char *)decrypt; + while ((*c==' ' || *c=='\n')&&(c-decrypt)copySelf(&obj, false); + done(object, NULL); + delete object; + } else if(*c=='[') { + JSONArray array(c); + uint32_t size = array.size(); + MeObject* objs = new MeObject[size]; + done(objs, NULL, size); + delete[] objs; + } else { + MeException e; + e.put("errCode", BS_JSONPARSE); + e.put("errMsg", "JSON Parse Error"); + e.put("info", c); + done(NULL, &e); + } + + free(decrypt); +} diff --git a/src/MeHttpFileCallback.h b/src/MeHttpFileCallback.h new file mode 100644 index 0000000..faa9af9 --- /dev/null +++ b/src/MeHttpFileCallback.h @@ -0,0 +1,49 @@ +// +// MeHttpFileCallback.h +// MeCloud +// +// Created by super on 2017/7/24. +// Copyright © 2017年 Rex. All rights reserved. +// + +#ifndef __MEDOWNLOADCALLBACK_H_ +#define __MEDOWNLOADCALLBACK_H_ + +#include "McBasic.h" +using namespace mc; + +class MeFile; +class MeException; +class MeObject; + +#ifdef __IOS__ +typedef void (^MeHttpFileCallbackBlock)(MeFile *obj, MeException *err, uint32_t size); +typedef void (^MeHttpFileProgressBlock)(uint64_t writen, uint64_t total_writen, uint64_t total_expect_write); +#else +typedef void (*MeHttpFileCallback_func)(MeFile *obj, MeException *err, uint32_t size); +typedef void (*MeHttpFileProgress_func)(uint64_t writen, uint64_t total_writen, uint64_t total_expect_write); +#endif + +class MeHttpFileCallback: public HttpFileCallback, public Reference{ +public: + MeHttpFileCallback(const char* classname=NULL, MeFile* file=NULL){ + m_classname = classname; + m_file = file; + } + + virtual void done(int http_code, status_t st, const char* text); + virtual void done(MeFile* file, MeException* err, uint32_t size = 1) = 0; + + const char* m_classname; + MeFile* m_file; +}; + +class MeHttpDataCallback: public HttpFileCallback, public Reference{ +public: + MeHttpDataCallback(){} + + virtual void done(int http_code, status_t st, const char* text); + virtual void done(MeObject* json, MeException* err, uint32_t size = 1) = 0; +}; + +#endif /* MeHttpFileCallback.h */ diff --git a/src/MeJoinQuery.cpp b/src/MeJoinQuery.cpp new file mode 100644 index 0000000..825f23a --- /dev/null +++ b/src/MeJoinQuery.cpp @@ -0,0 +1,305 @@ +// +// MeJoinQuery.cpp +// MeCloud +// 区别于MeQuery, MeQuery只能做单表查询,MeJoinQuery能做多表联合查询 +// Created by super on 2017/9/17. +// Copyright © 2017年 Rex. All rights reserved. +// + +#include "MeJoinQuery.h" + +MeJoinQuery::MeJoinQuery(const char *classname, bool nestQuery) { + memset(m_classname, 0, sizeof(m_classname)); + bs_strcpy(m_classname, sizeof(m_classname), classname); + m_nest_query = nestQuery; +} + +string_t *MeJoinQuery::getjoinKey(const char *key) { + string_t *joinKey = bs_new(string); + if (m_nest_query) { + string_append(joinKey, m_classname); + string_append(joinKey, "."); + string_append(joinKey, key); + } else { + string_append(joinKey, key); + } + + return joinKey; +} + +void MeJoinQuery::addSelectKey(const char *key) { + if (!m_select_keys) { + m_select_keys = new JSONObject(); + } + + string_t *joinKey = getjoinKey(key); + m_select_keys->put(joinKey->mem, 1); + bs_delete(joinKey); +} + +void MeJoinQuery::addNotSelectKey(const char *key) { + if (!m_select_keys) { + m_select_keys = new JSONObject(); + } + + string_t *joinKey = getjoinKey(key); + m_select_keys->put(joinKey->mem, 0); + bs_delete(joinKey); +} + +void MeJoinQuery::addLimit(int count) { + m_limit = count; +} + +void MeJoinQuery::addAscend(const char *key) { + if (!m_sort_keys) { + m_sort_keys = new JSONObject(); + } + + string_t *joinKey = getjoinKey(key); + m_sort_keys->put(joinKey->mem, 1); + bs_delete(joinKey); +} + +void MeJoinQuery::addDescend(const char *key) { + if (!m_sort_keys) { + m_sort_keys = new JSONObject(); + } + + string_t *joinKey = getjoinKey(key); + m_sort_keys->put(joinKey->mem, -1); + bs_delete(joinKey); +} + +void MeJoinQuery::addUnwind(const char *key) { + +} + +void MeJoinQuery::matchEqualTo(const char *key, const char *val) { + if (!m_match) { + m_match = new JSONObject(); + } + + string_t *joinKey = NULL; + if (!strcmp("_id", key)) { + joinKey = getjoinKey("_sid"); + } else { + joinKey = getjoinKey(key); + } + m_match->put(joinKey->mem, val); + bs_delete(joinKey); +} + +void MeJoinQuery::matchEqualTo(const char *key, int val) { + if (!m_match) { + m_match = new JSONObject(); + } + + string_t *joinKey = NULL; + if (!strcmp("_id", key)) { + joinKey = getjoinKey("_sid"); + } else { + joinKey = getjoinKey(key); + } + m_match->put(joinKey->mem, val); + bs_delete(joinKey); +} + +void MeJoinQuery::matchGreater(const char *key, const char *val) { + if (!m_match) { + m_match = new JSONObject(); + } + + JSONObject obj; + obj.put("$gt", val); + string_t *joinKey = NULL; + if (!strcmp("_id", key)) { + joinKey = getjoinKey("_sid"); + } else { + joinKey = getjoinKey(key); + } + m_match->put(joinKey->mem, &obj); + bs_delete(joinKey); +} + +void MeJoinQuery::matchGreater(const char *key, int val) { + if (!m_match) { + m_match = new JSONObject(); + } + + JSONObject obj; + obj.put("$gt", val); + string_t *joinKey = NULL; + if (!strcmp("_id", key)) { + joinKey = getjoinKey("_sid"); + } else { + joinKey = getjoinKey(key); + } + m_match->put(joinKey->mem, &obj); + bs_delete(joinKey); +} + +void MeJoinQuery::matchLess(const char *key, const char *val) { + if (!m_match) { + m_match = new JSONObject(); + } + + JSONObject obj; + obj.put("$lt", val); + string_t *joinKey = NULL; + if (!strcmp("_id", key)) { + joinKey = getjoinKey("_sid"); + } else { + joinKey = getjoinKey(key); + } + m_match->put(joinKey->mem, &obj); + bs_delete(joinKey); +} + +void MeJoinQuery::matchLess(const char *key, int val) { + if (!m_match) { + m_match = new JSONObject(); + } + + JSONObject obj; + obj.put("$lt", val); + string_t *joinKey = NULL; + if (!strcmp("_id", key)) { + joinKey = getjoinKey("_sid"); + } else { + joinKey = getjoinKey(key); + } + m_match->put(joinKey->mem, &obj); + bs_delete(joinKey); +} + +void +MeJoinQuery::addForeignTable(const char *fromTable, const char *foreignKey, const char *localKey, + const char *document) { + if (!m_lookup) { + m_lookup = new JSONArray(); + } + + JSONObject *lookupObject = new JSONObject(); + lookupObject->setDestruct(false); + lookupObject->put("from", fromTable); + + string_t *joinKey = NULL; + if (!strcmp("_id", localKey)) { + joinKey = getjoinKey("_sid"); + } else { + joinKey = getjoinKey(localKey); + } + lookupObject->put("localField", joinKey->mem); + bs_delete(joinKey); + + if (!strcmp("_id", foreignKey)) { + lookupObject->put("foreignField", "_sid"); + } else { + lookupObject->put("foreignField", foreignKey); + } + lookupObject->put("as", document); + m_lookup->append(lookupObject); + delete lookupObject; +} + +void MeJoinQuery::addMeJoinQuery(MeJoinQuery *joinQuery) { + if (joinQuery->m_nest_query) { + m_child_querys.push_back(joinQuery); + } +} + +void MeJoinQuery::composeQueryArray(MeJoinQuery *query, JSONArray *jsonArray) { + if (query->m_match) { + JSONObject *match = new JSONObject(); + match->setDestruct(false); + match->put("$match", query->m_match); + jsonArray->append(match); + delete match; + } + + if (query->m_sort_keys) { + JSONObject *sort = new JSONObject(); + sort->setDestruct(false); + sort->put("$sort", query->m_sort_keys); + jsonArray->append(sort); + delete sort; + } + + if (!query->m_nest_query && query->m_limit > ME_QUERY_DEFAULT_VALUE) { + JSONObject *limit = new JSONObject(); + limit->setDestruct(false); + limit->put("$limit", query->m_limit); + jsonArray->append(limit); + delete limit; + } + + if (query->m_lookup) { + for (int i = 0; i < query->m_lookup->size(); i++) { + JSONObject *lookup = new JSONObject(); + lookup->setDestruct(false); + JSONObject value = m_lookup->jsonValue(i); + lookup->put("$lookup", &(value)); + jsonArray->append(lookup); + delete lookup; + } + } + + if (query->m_select_keys) { + JSONObject *select = new JSONObject(); + select->setDestruct(false); + select->put("$project", query->m_select_keys); + jsonArray->append(select); + delete select; + } +} + +void MeJoinQuery::find(MeCallback *callback) { + // 具有parent MeJoinQuery不支持关联查询 + if (m_nest_query) { + return; + } + + JSONArray *jsonArray = new JSONArray(); + composeQueryArray(this, jsonArray); + + if (m_child_querys.size() > 0) { + vector allChildQuery; + MeJoinQuery *list = this; + MeJoinQuery *current = this; + while (current) { + for (vector::iterator iter = current->m_child_querys.begin(); + iter != current->m_child_querys.end(); iter++) { + list->next = (*iter); + composeQueryArray(*iter, jsonArray); + allChildQuery.push_back((*iter)); + } + + current = current->next; + } + } + + snprintf(m_url, sizeof(m_url), "%s%s?%s=%s", MeCloud::shareInstance()->classUrl(), m_classname, + "aggregate", jsonArray->toString()); + int k = 0; + for (int i = 0; i < strlen(m_url); ++i) { + if (m_url[i] != '\n' && m_url[i] != '\t' && m_url[i] != ' ') { + m_url[k++] = m_url[i]; + } + } + m_url[k] = '\0'; + MeCloud::shareInstance()->get(m_url, callback); + delete jsonArray; +} + +MeJoinQuery::~MeJoinQuery() { + delete m_match; + m_match = NULL; + delete m_select_keys; + m_match = NULL; + delete m_sort_keys; + m_match = NULL; + delete m_lookup; + m_match = NULL; + m_child_querys.clear(); +} diff --git a/src/MeJoinQuery.h b/src/MeJoinQuery.h new file mode 100644 index 0000000..e59defe --- /dev/null +++ b/src/MeJoinQuery.h @@ -0,0 +1,65 @@ +// +// MeJoinQuery.h +// MeCloud +// +// Created by super on 2017/9/17. +// Copyright © 2017年 Rex. All rights reserved. +// + +#ifndef MeJoinQuery_h +#define MeJoinQuery_h + +#include "MeQuery.h" +#include +#include + +class MeJoinQuery: public JSONObject { +public: + MeJoinQuery(const char *classname, bool nestQuery = false); + ~MeJoinQuery(); + + inline const char *url() { return m_url; } + + void addSelectKey(const char *key); + void addNotSelectKey(const char *key); + void addLimit(int count); + // 确保加入的先后顺序,级别越高,理解关系型中的数据库select排序顺序 + void addAscend(const char *key); + void addDescend(const char *key); + //暂时不要 + void addUnwind(const char *key); + + void matchEqualTo(const char *key, const char *val); + void matchEqualTo(const char *key, int val); + void matchGreater(const char *key, const char *val); + void matchGreater(const char *key, int val); + void matchLess(const char *key, const char *val); + void matchLess(const char *key, int val); + void addForeignTable(const char *fromTable, const char *foreignKey, const char *localKey, const char* document); + + void addMeJoinQuery(MeJoinQuery *joinQuery); + + void find(MeCallback* callback); +protected: + char m_classname[ME_CLASS_SIZE]; + char m_url[URL_SIZE]; + + // 嵌套查询 + bool m_nest_query = false; + + long m_limit = ME_QUERY_DEFAULT_VALUE; + long m_aggregate_count = ME_QUERY_DEFAULT_VALUE; + JSONObject *m_match = NULL; + JSONObject *m_select_keys = NULL; + JSONObject *m_sort_keys = NULL; + JSONArray *m_lookup = NULL; + char *unwindKey = NULL; + + MeJoinQuery *next = NULL; + vector m_child_querys; +private: + string_t* getjoinKey(const char* key); + void composeQueryArray(MeJoinQuery *query, JSONArray *jsonArray); +}; + +#endif /* MeJoinQuery_h */ diff --git a/src/MeObject.cpp b/src/MeObject.cpp new file mode 100644 index 0000000..8ebd9f6 --- /dev/null +++ b/src/MeObject.cpp @@ -0,0 +1,488 @@ +/** + * file : MeObject.cpp + * author : bushaofeng + * create : 2016-08-27 01:09 + * func : + * history: + */ + +#include "MeObject.h" +#include "MeFile.h" +#include "bs.h" +#include "MeACL.h" +#include "McDevice.h" + +#pragma --mark "构造函数" +MeObject::MeObject(){ + init(); +} + +MeObject::MeObject(const char* objectId, const char* className) { + setClassName(className); + snprintf(m_objectid, BS_UNIQUE_ID_LENGTH, "%s", objectId); + put("_id", objectId); +} + +MeObject::MeObject(MeObject* obj, bool auth): +JSONObject(obj, auth){ + assert(obj!=NULL); + if (obj->objectId()) { + snprintf(m_objectid, BS_UNIQUE_ID_LENGTH, "%s", obj->objectId()); + } else { + init(); + } + setClassName(obj->className()); + memset(m_db, 0, sizeof(m_db)); + + for (map::iterator iter = obj->m_object_map.begin(); iter!=obj->m_object_map.end(); iter++) { + m_object_map[iter->first] = new MeObject(iter->second, false); + } + + for (map::iterator iter = obj->m_array_map.begin(); iter!=obj->m_array_map.end(); iter++) { + m_array_map[iter->first] = new JSONArray(iter->second, false); + } +} + +MeObject::MeObject(const char* className, JSONObject* json){ + setClassName(className); + memset(m_db, 0, sizeof(m_db)); + if (json!=NULL) { + copy(json); + } else { + init(); + } +} + +#pragma 本地初始化objectId +void MeObject::init() { + mc::guid(m_objectid); +} + +const char* MeObject::className() { + if (strlen(m_classname) > 0) { + return m_classname; + } + + const char *localClassName = JSONObject::stringValue("_class"); + if (!localClassName) { + localClassName = ""; + } + + return localClassName; +} + +#pragma --mark "参数设置" +void MeObject::setClassName(const char* className) { + bs_strcpy(m_classname, sizeof(m_classname), className); +} + +void MeObject::setDb(const char* db) { + bs_strcpy(m_db, sizeof(m_db), db); +} + +void MeObject::addUniqueKey(const char* key) { + m_unique_key.push_back(string(key)); +} + +void MeObject::setACL(MeACL *acl) { + objectAcl = *acl; + if (stringValue("_id")==NULL) { + JSONObject::put(ME_ACL_KEY, &objectAcl); + } else{ + m_set_dirty.put(ME_ACL_KEY, &objectAcl); + } +} + +MeACL MeObject::getACL() { + MeACL acl; + JSONObject object = jsonValue("acl"); + JSONObject aclObject(object); + acl.copy(&aclObject, true); + return acl; +} + +#pragma --mark "拷贝" +void MeObject::copy(JSONObject* obj, bool auth) { + if (obj->has("_id")) { + copySelf(obj, auth); + } + else{ + JSON::copy(obj, auth); + } +} + +void MeObject::copySelf(JSONObject *obj, bool auth) { + if (!obj->has("_id") && strlen(m_objectid) < BS_UNIQUE_ID_EFFECT_LENGTH) { + return; + } + + clear(); + JSON::copy(obj, auth); + + if (obj->has("_id")) { + snprintf(m_objectid, BS_UNIQUE_ID_LENGTH, "%s", obj->stringValue("_id")); + } +} + +#pragma --mark "反序列化" +bool MeObject::deserialize(const char* path){ + JSONObject obj; + if(obj.deserialize(path)){ + copy(&obj); + return true; + } + return false; +} + +#pragma --mark "字段更新" +void MeObject::set(const char* name, MeObject* obj){ + if (stringValue("_id")==NULL) { + obj->put("_sid", obj->objectId()); + } + + MeObject *newObject = new MeObject(obj, false); + MeObject *oldObject = m_object_map[string(name)]; + if (oldObject) { + delete oldObject; + } + m_object_map[string(name)] = newObject; +} + +void MeObject::add(const char* name, MeObject* object) { + JSONArray *newArray = m_array_map[string(name)]; + if (!newArray) { + newArray = new JSONArray(); + m_array_map[string(name)] = newArray; + } + + MeObject *newObject = new MeObject(object, false); + newObject->put("_sid", object->objectId()); + newArray->append(newObject); + m_child_classname[string(newObject->objectId())] = string(newObject->className()); +} + +void MeObject::set(const char* name, JSONArray* array, const char* childClassName) { + JSONArray *newArray = m_array_map[string(name)]; + if (!newArray) { + newArray = new JSONArray(); + m_array_map[string(name)] = newArray; + } + + newArray->clear(); + for (int i = 0; i < array->size(); i++) { + JSONObject json = array->jsonValue(i); + MeObject *object = new MeObject(); + const char* id = object->objectId(); + m_child_classname[string(id)] = string(childClassName); + object->copy(&json, false); + object->put("_sid", id); + newArray->append(object); + } +} + +MeObject MeObject::objectValue(const char* key) { + map::iterator iter = m_object_map.find(string(key)); + if (iter!=m_object_map.end()) { + return *(iter->second); + } + + MeObject *childObject = new MeObject(); + JSONObject object = JSONObject::jsonValue(key); + if (!object.empty()) { + childObject->copy(&object); + m_object_map[string(key)] = childObject; + } + + return *childObject; +} + +JSONArray MeObject::arrayValue(const char* key) { + map::iterator iter = m_array_map.find(string(key)); + if (iter!=m_array_map.end()) { + return *(iter->second); + } + + return JSONObject::arrayValue(key); +} + +void MeObject::put(const char* name, const char* value){ + if (stringValue("_id") == NULL) { + JSONObject::put(name, value); + } else{ + m_set_dirty.put(name, value); + } +} + +void MeObject::put(const char* name, double value){ + if (stringValue("_id") == NULL) { + JSONObject::put(name, value); + } else{ + m_set_dirty.put(name, value); + } +} + +void MeObject::put(const char* name, float value){ + if (stringValue("_id") == NULL) { + JSONObject::put(name, value); + } else{ + m_set_dirty.put(name, value); + } +} + +void MeObject::put(const char* name, int value){ + if (stringValue("_id") == NULL) { + JSONObject::put(name, value); + } else{ + m_set_dirty.put(name, value); + } +} + +void MeObject::put(const char* name, long value){ + if (stringValue("_id") == NULL) { + JSONObject::put(name, value); + } else{ + m_set_dirty.put(name, value); + } +} + +void MeObject::put(const char* name, bool value){ + if (stringValue("_id") == NULL) { + JSONObject::put(name, value); + } else{ + m_set_dirty.put(name, value); + } +} + +#pragma --mark "字段增长" +void MeObject::increase(const char* name, int num){ + if (stringValue("_id") == NULL) { + int v = intValue(name, 0); + JSONObject::put(name, v+num); + } else{ + m_inc_dirty.put(name, num); + } +} + +void MeObject::increase(const char* name, long num){ + if (stringValue("_id") == NULL) { + long v = longValue(name, 0); + JSONObject::put(name, v+num); + } else{ + m_inc_dirty.put(name, num); + } +} + +void MeObject::increase(const char* name, float num){ + if (stringValue("_id") == NULL) { + float v = floatValue(name, 0); + JSONObject::put(name, v+num); + } else{ + m_inc_dirty.put(name, num); + } +} + +#pragma --mark "构建m_url" +void MeObject::initPostUrl() { + // 处理唯一索引 + char unique[512] = {0}; + for (int i=0; i 0) { + // 去掉最后一个& + unique[strlen(unique)-1] = '\0'; + snprintf(m_url, sizeof(m_url), "%s%s?%s", MeCloud::shareInstance()->classUrl(), m_classname, unique); + } else{ + snprintf(m_url, sizeof(m_url), "%s%s", MeCloud::shareInstance()->classUrl(), m_classname); + } +} + +#pragma --mark "保存" +void MeObject::save(MeCallback* callback){ + if (callback!=NULL) { + callback->m_object = this; + callback->m_classname = m_classname; + } + + if (m_object_map.empty() && m_array_map.empty()) { + saveData(callback); + } else { + saveNestedData(callback); + } +} + +#pragma --mark "保存非嵌套类数据" +void MeObject::saveData(MeCallback* callback) { + if (stringValue("_id") == NULL) { + initPostUrl(); + postData(callback); + } else { + putData(callback); + } +} + +void MeObject::postData(MeCallback* callback) { + // _sid为数据创造前的唯一id + put("_sid", m_objectid); + MeCloud::shareInstance()->post(m_url, toString(), callback); +} + +void MeObject::putData(MeCallback* callback) { + JSONObject *json = new JSONObject(); + if (!m_set_dirty.empty()) { + json->put("$set", &m_set_dirty); + } + + if (!m_inc_dirty.empty()>0) { + json->put("$inc", &m_inc_dirty); + } + + snprintf(m_url, sizeof(m_url), "%s%s/%s", MeCloud::shareInstance()->classUrl(), m_classname, m_objectid); + MeCloud::shareInstance()->put(m_url, json->toString(), callback); + delete json; +} + +#pragma --mark "保存嵌套类数据" +void MeObject::saveNestedData(MeCallback* callback) { + JSONArray *array = new JSONArray(); + map nestObjectMap; + for (map::iterator iter = m_object_map.begin(); iter!=m_object_map.end(); iter++) { + MeObject *obj = iter->second; + if (obj->stringValue("_id") == NULL) { + JSONObject *classObj = new JSONObject(); + classObj->setDestruct(false); + classObj->put(obj->className(), obj); + array->append(classObj); + delete classObj; + } + + nestObjectMap[iter->first] = obj->objectId(); + } + + map nestArrayMap; + for (map::iterator iter = m_array_map.begin(); iter!=m_array_map.end(); iter++) { + JSONArray *objectArray = iter->second; + JSONArray *nestArray = new JSONArray(); + for (int i = 0; i < objectArray->size(); i++) { + JSONObject item = objectArray->jsonValue(i); + const char *objectId = item.stringValue("_sid"); + const char *childClassname = m_child_classname[string(objectId)].c_str(); + if (item.stringValue("_id") == NULL) { + JSONObject *classObj = new JSONObject(); + classObj->setDestruct(false); + classObj->put(childClassname, &item); + array->append(classObj); + delete classObj; + } + + nestArray->append(objectId); + } + + nestArrayMap[iter->first] = nestArray; + } + + if (stringValue("_id") == NULL) { + initPostUrl(); + for (map::iterator iter = nestObjectMap.begin(); iter!=nestObjectMap.end(); iter++) { + JSONObject::put(iter->first.c_str(), iter->second.c_str()); + } + for (map::iterator iter = nestArrayMap.begin(); iter!=nestArrayMap.end(); iter++) { + JSONObject::put(iter->first.c_str(), iter->second); + } + postNestedData(callback, array); + } else { + for (map::iterator iter = nestObjectMap.begin(); iter!=nestObjectMap.end(); iter++) { + m_set_dirty.put(iter->first.c_str(), iter->second.c_str()); + } + for (map::iterator iter = nestArrayMap.begin(); iter!=nestArrayMap.end(); iter++) { + JSONObject::put(iter->first.c_str(), iter->second); + } + putNestedData(callback, array); + } + + delete array; + for (map::iterator iter = nestArrayMap.begin(); iter!=nestArrayMap.end(); iter++) { + JSONArray* jsonArray = iter->second; + delete jsonArray; + } + nestObjectMap.clear(); + nestArrayMap.clear(); +} + +void MeObject::postNestedData(MeCallback* callback, JSONArray *array) { + // _sid为数据创造前的唯一id + put("_sid", m_objectid); + JSONObject *json = new JSONObject(); + json->copy(this, false); + array->append(json); + + if (array->size() <= 1) { + MeCloud::shareInstance()->post(m_url, array->jsonValue(0).toString(), callback); + } else { + MeCloud::shareInstance()->post(m_url, array->toString(), callback); + } + + json->setDestruct(false); + delete json; +} + +void MeObject::putNestedData(MeCallback* callback, JSONArray *array) { + JSONObject *json = new JSONObject(); + json->setDestruct(false); + json->put("$set", &m_set_dirty); + + if (!m_inc_dirty.empty() > 0) { + json->put("$inc", &m_inc_dirty); + } + + array->append(json); + + snprintf(m_url, sizeof(m_url), "%s%s/%s", MeCloud::shareInstance()->classUrl(), m_classname, m_objectid); + if (array->size() <= 1) { + MeCloud::shareInstance()->put(m_url, array->jsonValue(0).toString(), callback); + } else { + MeCloud::shareInstance()->put(m_url, array->toString(), callback); + } + + + delete json; +} + +void MeObject::deleteObject(MeCallback* callback) { + if (stringValue("_id") != NULL) { + snprintf(m_url, sizeof(m_url), "%s%s/%s", MeCloud::shareInstance()->classUrl(), m_classname ,m_objectid); + MeCloud::shareInstance()->del(m_url, callback); + } else { + char message[] = "无效数据"; + callback->done(HTTP_OK, BS_INVALID, message); + } +} + +#pragma --mark "清空与虚构" +void MeObject::clear(){ + JSONObject::clear(); + m_set_dirty.clear(); + m_inc_dirty.clear(); + clearMap(); +} + +void MeObject::clearMap() { + for (map::iterator iter = m_object_map.begin(); iter!=m_object_map.end(); iter++) { + MeObject* obj = iter->second; + delete obj; + } + + for (map::iterator iter = m_array_map.begin(); iter!=m_array_map.end(); iter++) { + JSONArray* array = iter->second; + delete array; + } + + m_object_map.clear(); + m_array_map.clear(); + m_child_classname.clear(); +} + +MeObject::~MeObject() { + clearMap(); +} diff --git a/src/MeObject.h b/src/MeObject.h new file mode 100644 index 0000000..02f12f1 --- /dev/null +++ b/src/MeObject.h @@ -0,0 +1,115 @@ +/** + * file : MeObject.h + * author : bushaofeng + * create : 2016-08-27 01:09 + * func : + * history: + */ + +#ifndef __MEOBJECT_H_ +#define __MEOBJECT_H_ + +#include +#include +#include +#include +#include "MeCloud.h" +#include "JSON.h" +#include "MeACL.h" + +#define ME_CLASS_SIZE 64 +using namespace mc; +using namespace std; + +#define ME_TYPE_POINTER "__pointer" +class MeObject: public JSONObject{ +public: + MeObject(); // 只用于MeCallback生成MeObject数组,数组必须使用默认构造函数 + MeObject(const char* objectId, const char* className); + // 默认转移释放权限,如果不转移会深拷贝 + MeObject(MeObject* obj, bool auth = true); + MeObject(const char* className, JSONObject* obj = NULL); + ~MeObject(); + + const char* className(); + inline const char *objectId() { return m_objectid; } + inline const char *url() { return m_url; } + + void setClassName(const char* className); + void setDb(const char* db); + // 添加唯一索引, 只在post时生效 + void addUniqueKey(const char* key); + + // 权限操作 + void setACL(MeACL* acl); + MeACL getACL(); + + virtual void put(const char* name, const char* value); + virtual void put(const char* name, double value); + virtual void put(const char* name, int value); + virtual void put(const char* name, long value); + virtual void put(const char* name, float value); + virtual void put(const char* name, bool value); + // 对象嵌套 + virtual void set(const char* name, MeObject* obj); + virtual void add(const char* name, MeObject* object); + virtual void set(const char* name, JSONArray* array, const char* childClassName); + + MeObject objectValue(const char* key); + JSONArray arrayValue(const char* key); + + void increase(const char* key, int num); + void increase(const char* key, long num); + void increase(const char* key, float num); + + //谨慎使用,目前不提供该功能 + void deleteObject(MeCallback* callback); + + void save(MeCallback* callback); +#ifdef __IOS__ + void save(MeCallbackBlock block); +#endif + + // 是否转移释放权限,如果不转移则深拷贝 + virtual void copy(JSONObject* obj, bool auth= true); + void copySelf(JSONObject *obj, bool auth = true); + + virtual void clear(); + /// 从文件反序列化 + virtual bool deserialize(const char* path); + +protected: + char m_classname[ME_CLASS_SIZE]; + char m_db[ME_CLASS_SIZE]; + char m_url[URL_SIZE]; + MeACL objectAcl; // 需要new出来的对象 + + char m_objectid[BS_UNIQUE_ID_LENGTH]; + JSONObject m_set_dirty; + JSONObject m_inc_dirty; + + //TODO: 暂时只考虑了从服务器下载数据的解析 + map m_object_map; + map m_array_map; + map m_child_classname; + vector m_unique_key; + + // 存储save传进来的callback,目前只支持一个callback,一次save完成之后才能进行下次save + MeCallback* m_callback; + +private: + void init(); + + void initPostUrl(); + void saveData(MeCallback* callback); + void postData(MeCallback* callback); + void putData(MeCallback* callback); + + // 嵌套类数据 + void saveNestedData(MeCallback* callback); + void putNestedData(MeCallback* callback, JSONArray *array); + void postNestedData(MeCallback* callback, JSONArray *array); + void clearMap(); +}; + +#endif diff --git a/src/MeQuery.cpp b/src/MeQuery.cpp new file mode 100644 index 0000000..0f3f718 --- /dev/null +++ b/src/MeQuery.cpp @@ -0,0 +1,315 @@ +/** + * file : MeQuery.cpp + * author : bushaofeng + * create : 2016-08-27 01:09 + * func : + * history: + */ + +#include "MeQuery.h" + +MeAggregateObject::MeAggregateObject(const char* className) { + bs_strcpy(m_classname, sizeof(m_classname), className); +} + +MeAggregateObject::MeAggregateObject(MeAggregateObject *aggregateObject) { + bs_strcpy(m_classname, sizeof(m_classname), aggregateObject->m_classname); + if (m_root!=NULL) { + cJSON_Delete(m_root); + } + + m_root = cJSON_Duplicate(aggregateObject->getCJSON(), 1); + m_keyValue = aggregateObject->m_keyValue; + m_distinct_keyValue = aggregateObject->m_distinct_keyValue; + m_method = aggregateObject->m_method; + m_auto_destruct = true; +} + +MeAggregateObject::MeAggregateObject(const MeAggregateObject &aggregateObject) { + bs_strcpy(m_classname, sizeof(m_classname), aggregateObject.m_classname); + if (m_root!=NULL) { + cJSON_Delete(m_root); + } + + m_root = cJSON_Duplicate(aggregateObject.getCJSON(), 1); + m_keyValue = aggregateObject.m_keyValue; + m_distinct_keyValue = aggregateObject.m_distinct_keyValue; + m_method = aggregateObject.m_method; +} + +MeAggregateObject::~MeAggregateObject() { +} + +void MeAggregateObject::whereEqualTo(const char* key, const char* val) { + put(key, val); +} + +void MeAggregateObject::whereEqualTo(const char* key, int val) { + put(key, val); +} + +void MeAggregateObject::whereNotEqualTo(const char* key, const char* val) { + JSONObject obj; + obj.put("$ne", val); + put(key, &obj); +} + +void MeAggregateObject::whereNotEqualTo(const char* key, int val) { + put(key, val); +} + +void MeAggregateObject::whereGreater(const char *key, const char *val) { + JSONObject obj; + obj.put("$gt", val); + put(key, &obj); +} + +void MeAggregateObject::whereGreater(const char *key, int val) { + JSONObject obj; + obj.put("$gt", val); + put(key, &obj); +} + +void MeAggregateObject::whereLess(const char *key, const char *val) { + JSONObject obj; + obj.put("$lt", val); + put(key, &obj); +} + +void MeAggregateObject::whereLess(const char *key, int val) { + JSONObject obj; + obj.put("$lt", val); + put(key, &obj); +} + +void MeAggregateObject::setResponseKey(const char* keyValue) { + m_keyValue = keyValue; +} + +void MeAggregateObject::setDistinctKey(const char* keyValue) { + m_distinct_keyValue = keyValue; +} + +void MeAggregateObject::setMethod(MEAGGREGATEMETHOD method) { + m_method = method; +} + +#pragma --mark MeQuery +MeQuery::MeQuery(const char* className){ + bs_strcpy(m_classname, sizeof(m_classname), className); +} + +MeQuery::MeQuery() { +} + +void MeQuery::whereEqualTo(const char* key, const char* val) { + put(key, val); +} + +void MeQuery::whereEqualTo(const char* key, int val) { + put(key, val); +} + +void MeQuery::whereNotEqualTo(const char* key, const char* val) { + JSONObject obj; + obj.put("$ne", val); + put(key, &obj); +} + +void MeQuery::whereNotEqualTo(const char* key, int val) { + JSONObject obj; + obj.put("$ne", val); + put(key, &obj); +} + +void MeQuery::whereEqualOr(const char* key, const char* value) { + if (!jsonArray) { + jsonArray = new JSONArray(); + } + JSONObject obj; + obj.setDestruct(false); + obj.put(key, value); + jsonArray->append(&obj); +} + +void MeQuery::whereEqualOr(const char* key, int value) { + if (!jsonArray) { + jsonArray = new JSONArray(); + } + JSONObject obj; + obj.setDestruct(false); + obj.put(key, value); + jsonArray->append(&obj); +} + +void MeQuery::whereGreater(const char *key, const char *val) { + JSONObject obj; + obj.put("$gt", val); + put(key, &obj); +} + +void MeQuery::whereGreater(const char *key, int val) { + JSONObject obj; + obj.put("$gt", val); + put(key, &obj); +} + +void MeQuery::whereLess(const char *key, const char *val) { + JSONObject obj; + obj.put("$lt", val); + put(key, &obj); +} + +void MeQuery::whereLess(const char *key, int val) { + JSONObject obj; + obj.put("$lt", val); + put(key, &obj); +} + +void MeQuery::selectKeys(const char* keys[], int num) { + for (int i=0; istartId = startId; +} + +void MeQuery::addAggregateObject(MeAggregateObject *aggregate) { + MeAggregateObject *newAggregate = new MeAggregateObject(aggregate); + aggregateVector.push_back(newAggregate); +} + +void MeQuery::setAggregateObject(MeAggregateObject *aggregate) { + clear(); + addAggregateObject(aggregate); +} + +void MeQuery::get(const char* objectId, MeCallback* callback) { + put("_id", objectId); + snprintf(m_url, sizeof(m_url), "%s%s/%s", MeCloud::shareInstance()->classUrl(), m_classname, objectId); + MeCloud::shareInstance()->get(m_url, callback); +} + +void MeQuery::find(MeCallback* callback) { + if (aggregateVector.size() > 0) { + requestAggregate(callback); + } else { + request(callback); + } +} + +void MeQuery::request(MeCallback* callback) { + if (jsonArray && jsonArray->size() > 0) { + put("$or", jsonArray); + } + + char *whereParam = (char *)toString(); + if (empty()) { + whereParam = "{}"; + } + + composeParam("where", (const char *)whereParam, ""); + if (!m_select_keys.empty()) { + composeParam("keys", m_select_keys.toString(), "&"); + } + + if (!m_filter_keys.empty()) { + composeParam("sort", m_filter_keys.toString(), "&"); + } + + if (limit > ME_QUERY_DEFAULT_VALUE) { + char limitParam[128] = "\0"; + snprintf(limitParam, sizeof(limitParam), "%ld", limit); + composeParam("limit", limitParam, "&"); + } + + if (startId) { + char startParam[128] = "\0"; + snprintf(startParam, sizeof(startParam), "%s", startId); + composeParam("startId", startParam, "&"); + } + + formatParam(); + snprintf(m_url, sizeof(m_url)-1, "%s%s?%s", MeCloud::shareInstance()->classUrl(), m_classname, m_param); + + MeCloud::shareInstance()->get(m_url, callback); +} + +void MeQuery::requestAggregate(MeCallback* callback) { + JSONArray *aggregateArray = new JSONArray(); + for (vector::iterator iter = aggregateVector.begin(); iter != aggregateVector.end(); iter++) { + JSONObject *aggregate = new JSONObject(); + aggregate->setDestruct(false); + aggregate->put("condition", *iter); + aggregate->put("key", (*iter)->responseKey()); + aggregate->put("method", (*iter)->aggregateMethod()); + aggregate->put("classname", (*iter)->classname()); + const char *distinctKey = (*iter)->distinctKey(); + if (distinctKey) { + aggregate->put("distinct", distinctKey); + } + aggregateArray->append(aggregate); + delete aggregate; + } + + composeParam("where", aggregateArray->toString(), ""); + + formatParam(); + snprintf(m_url, sizeof(m_url)-1, "%squery/?%s", MeCloud::shareInstance()->restUrl(), m_param); + delete aggregateArray; + + MeCloud::shareInstance()->get(m_url, callback); +} + +void MeQuery::composeParam(const char *key, const char *value, const char* connector) { + snprintf(m_param, sizeof(m_param)-1, "%s%s%s=%s", m_param, connector, key, value); +} + +void MeQuery::formatParam() { + int k = 0; + for (int i = 0; i < strlen(m_param); ++i) { + if (m_param[i] != '\n' && m_param[i] != '\t' && m_param[i] != ' ') { + m_param[k++] = m_param[i]; + } + } + m_param[k] = '\0'; +} + +void MeQuery::clear() { + for (vector::iterator iter = aggregateVector.begin(); iter != aggregateVector.end(); iter++) { + if (*iter != NULL) { + delete *iter; + *iter = NULL; + } + } + + aggregateVector.clear(); +} + +MeQuery::~MeQuery() { + clear(); + delete jsonArray; + jsonArray = NULL; +} diff --git a/src/MeQuery.h b/src/MeQuery.h new file mode 100644 index 0000000..0580c0b --- /dev/null +++ b/src/MeQuery.h @@ -0,0 +1,120 @@ +/** + * file : MeQuery.h + * author : bushaofeng + * create : 2016-08-27 01:09 + * func : + * history: + */ + +#ifndef __MEQUERY_H_ +#define __MEQUERY_H_ + +#include "MeObject.h" + +#define ME_QUERY_DEFAULT_VALUE 0 + +typedef enum { + COUNT = 1, + ID, + LIST, + JSONOBJECT +} MEAGGREGATEMETHOD; + +class MeAggregateObject: public JSONObject { +public: + MeAggregateObject(const char* className); + MeAggregateObject(MeAggregateObject *aggregateObject); + MeAggregateObject(const MeAggregateObject &aggregateObject); + ~MeAggregateObject(); + inline const char* classname() { return m_classname; } + + void whereEqualTo(const char* key, const char* val); + void whereEqualTo(const char* key, int val); + void whereNotEqualTo(const char* key, const char* val); + void whereNotEqualTo(const char* key, int val); + void whereGreater(const char *key, const char *val); + void whereGreater(const char *key, int val); + void whereLess(const char *key, const char *val); + void whereLess(const char *key, int val); + void setResponseKey(const char* keyValue); + void setDistinctKey(const char* keyValue); + void setMethod(MEAGGREGATEMETHOD method); + inline MEAGGREGATEMETHOD aggregateMethod() { return m_method; }; + inline const char* responseKey() { return m_keyValue; }; + inline const char* distinctKey() { return m_distinct_keyValue; }; + + MeAggregateObject *next = NULL; +protected: + char m_classname[ME_CLASS_SIZE]; + const char *m_keyValue = NULL; + const char *m_distinct_keyValue = NULL; + MEAGGREGATEMETHOD m_method; +}; + +class MeQuery: public JSONObject { +public: + // 单表查询需要调用该构造函数 + MeQuery(const char* className); + // 查找聚合类数据用该构造函数创建MeAuery,所谓的聚合类有count,sum,average等相关数据,难以理解参照关系型数据库 + MeQuery(); + ~MeQuery(); + + inline const char *url() { return m_url; } + + // 单表查询 + void whereEqualTo(const char* key, const char* val); + void whereEqualTo(const char* key, int value); + void whereNotEqualTo(const char* key, const char* val); + void whereNotEqualTo(const char* key, int value); + void whereGreater(const char *key, const char *val); + void whereGreater(const char *key, int val); + void whereLess(const char *key, const char *val); + void whereLess(const char *key, int val); + void whereEqualOr(const char* key, const char* value); + void whereEqualOr(const char* key, int value); + void selectKeys(const char* keys[], int num); + void addSelectKey(const char* key); + void addNotSelectKey(const char* key); + void addAscendSortKeys(const char* key); + void addDescendSortKeys(const char* key); + void addLimit(long count); + void addStartId(const char* startId); + + // 聚合类查询,如果查询中包含此查询就不会执行单表查询,此条件和单表查询条件互斥 + // 增加一个聚合查询 + void addAggregateObject(MeAggregateObject *aggregate); + // 会将已有的聚合查询全部清空,然后再新增一个聚合查询 + void setAggregateObject(MeAggregateObject *aggregate); + + void get(const char* objectId, MeCallback* callback); + void find(MeCallback* callback); + +#ifdef __IOS__ + void find(MeCallbackBlock block); + void get(const char* objectId, MeCallbackBlock block); +#endif + +protected: + char m_classname[ME_CLASS_SIZE] = "\0"; + char m_url[URL_SIZE] = "\0"; + char m_param[URL_SIZE] = "\0"; + + long limit = ME_QUERY_DEFAULT_VALUE; + const char* startId = NULL; + JSONObject m_select_keys; + JSONObject m_filter_keys; + JSONArray *jsonArray = NULL; + vector aggregateVector; +#ifdef __IOS__ + MeCallbackBlock m_callback; +#else +#endif +private: + void composeParam(const char *key, const char *value, const char* connector); + void formatParam(); + void requestAggregate(MeCallback* callback); + void request(MeCallback* callback); + void clear(); +}; + +#endif diff --git a/src/MeRole.cpp b/src/MeRole.cpp new file mode 100644 index 0000000..ec1c008 --- /dev/null +++ b/src/MeRole.cpp @@ -0,0 +1,25 @@ +/** + * file : MeRole.cpp + * author : Rex + * create : 2017-07-18 17:58 + * func : + * history: + * note: 一条角色数据只能对应一个user,如果设置了多个,最后设置的一个会覆盖之前的 + */ + +#include "MeRole.h" + +MeRole::MeRole(MeObject *object):MeObject(object) { +} + +MeRole::MeRole(const char* rolename): +MeObject("Role"){ + put(ME_ROLE_KEY, rolename); +} + +void MeRole::setUser(MeUser* user){ + setUser(user->objectId()); +} +void MeRole::setUser(const char* userId){ + put("user", userId); +} diff --git a/src/MeRole.h b/src/MeRole.h new file mode 100644 index 0000000..e9a3f4b --- /dev/null +++ b/src/MeRole.h @@ -0,0 +1,27 @@ +/** + * file : MeRole.h + * author : Rex + * create : 2017-07-18 17:57 + * func : + * history: + */ + +#ifndef __MEROLE_H_ +#define __MEROLE_H_ + +#include "MeObject.h" +#include "MeUser.h" +#include "MeQuery.h" + +#define ME_ROLE_KEY "role" + +class MeRole: public MeObject{ +public: + MeRole(MeObject *object); + MeRole(const char* rolename); + + void setUser(MeUser* user); + void setUser(const char* userId); +}; + +#endif diff --git a/src/MeSMS.cpp b/src/MeSMS.cpp new file mode 100644 index 0000000..a32a951 --- /dev/null +++ b/src/MeSMS.cpp @@ -0,0 +1,21 @@ +/** + * file : MeSMS.cpp + * author : Rex + * create : 2017-04-04 11:48 + * func : + * history: + */ + +#include "MeSMS.h" + +const char* MeSMS::getSMSUrl(const char* phone) { + char m_url[URL_SIZE]; + snprintf(m_url, sizeof(m_url), "%ssms/%s", MeCloud::shareInstance()->baseUrl(), phone); + return m_url; +} + +void MeSMS::sendSMS(const char* phone, MeCallback *callback) { + char m_url[URL_SIZE]; + snprintf(m_url, sizeof(m_url), "%ssms/%s", MeCloud::shareInstance()->baseUrl(), phone); + MeCloud::shareInstance()->get(m_url, callback); +} diff --git a/src/MeSMS.h b/src/MeSMS.h new file mode 100644 index 0000000..69b27d5 --- /dev/null +++ b/src/MeSMS.h @@ -0,0 +1,19 @@ +/** + * file : MeSMS.h + * author : Rex + * create : 2017-04-04 11:47 + * func : + * history: + */ + +#ifndef __MESMS_H_ +#define __MESMS_H_ + +#include "MeCloud.h" +class MeSMS { +public: + static void sendSMS(const char* phone, MeCallback *callback); + static const char* getSMSUrl(const char* phone); +}; + +#endif diff --git a/src/MeTimeStat.cpp b/src/MeTimeStat.cpp new file mode 100644 index 0000000..d499f7e --- /dev/null +++ b/src/MeTimeStat.cpp @@ -0,0 +1,62 @@ +/** + * file : MeTimeStat.cpp + * author : Rex + * create : 2016-10-31 23:11 + * func : + * history: + */ + +#include "McDevice.h" +#include "MeTimeStat.h" + +MeTimeStat::MeTimeStat(const char* name): +MeObject(name){ + m_start = 0; + m_prevtime = 0; + put("user", mc::device_id()); +} + +void MeTimeStat::start(){ + m_start = time(0); + m_prevtime = m_start; + m_duration = 0; + + put("start", (long)m_start); + put("duration", (long)0); +} + +void MeTimeStat::refresh(){ + time_t duration = time(0)-m_prevtime; + if (duration > 10) { + m_prevtime = time(0); + increase("duration", (long)duration); + } +} + +void MeTimeStat::stop(){ + if (m_start<=0) { + return; + } + + m_start = 0; // m_start=0用来标记stop + if (time(0)-m_prevtime>0) { + increase("duration", time(0)-m_prevtime); + save(this); + } + + clear(); +} + +void MeTimeStat::done(MeObject* obj, MeException* err, uint32_t size){ + if (err!=NULL) { + // 写入本地文件 + debug_log("errCode:%d msg:%s", err->intValue("errCode"), err->stringValue("errMsg")); + } + else{ + // debug_log("%s: duration[%ld]", className(), obj->longValue("duration")); + } + // 如果已经stop,则本次请求为最后一次,需要清空 + if (m_start<=0) { + clear(); + } +} diff --git a/src/MeTimeStat.h b/src/MeTimeStat.h new file mode 100644 index 0000000..b6130c0 --- /dev/null +++ b/src/MeTimeStat.h @@ -0,0 +1,29 @@ +/** + * file : MeTimeStat.h + * author : Rex + * create : 2016-10-31 23:11 + * func : + * history: + */ + +#ifndef __METIMESTAT_H_ +#define __METIMESTAT_H_ + +#include +#include "MeObject.h" + +class MeTimeStat: public MeObject, public MeCallback{ +public: + MeTimeStat(const char* name="StatLog"); + void start(); + void refresh(); + void stop(); + + virtual void done(MeObject* obj, MeException* err, uint32_t size=1); +protected: + time_t m_start; + time_t m_prevtime; + long m_duration; +}; + +#endif diff --git a/src/MeUploadFile.cpp b/src/MeUploadFile.cpp new file mode 100644 index 0000000..1cfc66a --- /dev/null +++ b/src/MeUploadFile.cpp @@ -0,0 +1,128 @@ +// +// MeUploadFile.cpp +// MeCloud +// +// Created by super on 2017/7/31. +// Copyright © 2017年 Rex. All rights reserved. +// + +#include "MeUploadFile.h" +#include "McHmacAuth.h" +#include "MeUser.h" + +MeUploadFile::MeUploadFile(const char* className, JSONObject* obj): MeFile(ME_HTTPFILE_UPLOAD, className, obj) { + init(); +} + +MeUploadFile::MeUploadFile(MeUploadFile* file): MeFile(file) { + init(); +} + +MeUploadFile::~MeUploadFile() { + delete m_data; +} + +void MeUploadFile::init() { + MeFile::init(); +} + +void MeUploadFile::setUploadFilePath(const char* path) { + snprintf(m_upload_path, sizeof(m_upload_path), "%s", path); +} + +void MeUploadFile::setUploadData(uint8_t *data, int size) { + if (m_data) { + delete m_data; + } + + m_data = new uint8_t[size]; + memcpy(m_data, data, size); + m_content_length = size; +} + +void MeUploadFile::upload(HttpFileCallback* callback, JSONObject* object) { + const char* access_key_secret = object->stringValue("access_key_secret"); + const char* access_key_id = object->stringValue("access_key_id"); + const char* security_token = object->stringValue("security_token"); + + time_t timep; + time(&timep); + tm* time = gmtime(&timep); + char date[80]; + strftime(date, 80, "%a, %d %b %Y %T GMT", time); + const char *content_type = "multipart/form-data"; + + char resource[1024]; + snprintf(resource, sizeof(resource), "PUT\n\n%s\n%s\nx-oss-security-token:%s\n/%s/%s", content_type, date, security_token, object->stringValue("bucket"), m_objectid); + + char key_id[1024]; + snprintf(key_id, sizeof(key_id), "%s", access_key_id); + + char key_secret[1024]; + snprintf(key_secret, sizeof(key_secret), "%s", access_key_secret); + + char output[MC_AUTH_OUPUT_SIZE]; + mc::mc_auth(resource, key_id, key_secret, output); + + // 签名计算 + vector > authHeader; + // 获取文件的大小 + + authHeader.push_back(pair("Authorization", output)); + authHeader.push_back(pair("Content-Type", content_type)); + authHeader.push_back(pair("Date", date)); + authHeader.push_back(pair("x-oss-security-token", security_token)); + + resetMeUrl(object); + char contentString[1024]; + + if (m_data) { + snprintf(contentString, sizeof(contentString), "%llu", m_content_length); + authHeader.push_back(pair("Content-Length", contentString)); + MeCloud::shareInstance()->upload(m_url, m_data, (int)m_content_length, authHeader, callback); + } else { + FILE* file = fopen(m_upload_path, "rb"); + fseek(file , 0 , SEEK_END); + m_content_length = ftell (file); + rewind (file); + snprintf(contentString, sizeof(contentString), "%llu", m_content_length); + authHeader.push_back(pair("Content-Length", contentString)); + MeCloud::shareInstance()->upload(m_url, m_upload_path, authHeader, callback); + } +} + +void MeUploadFile::resetMeUrl(JSONObject* object) { + const char *reginId = object->stringValue("region_id"); + me_bucket = object->stringValue("bucket"); + memset(m_url, 0, sizeof(m_url)); + if (has("type") && strlen(stringValue("type")) > 0) { + snprintf(m_url, sizeof(m_url), "http://%s.%s.aliyuncs.com/%s.%s", me_bucket, reginId, m_objectid, stringValue("type")); + } else{ + snprintf(m_url, sizeof(m_url), "http://%s.%s.aliyuncs.com/%s", me_bucket, reginId, m_objectid); + } +} + +void MeUploadFile::getAuthInfomation(MeCallback *callback) { + memset(m_url, 0, sizeof(m_url)); + snprintf(m_url, sizeof(m_url), "%stoken", MeCloud::shareInstance()->fileUrl()); + MeCloud::shareInstance()->get(m_url, callback); +} + +void MeUploadFile::uploadFileInfomation(MeCallback *callback) { + memset(m_url, 0, sizeof(m_url)); + snprintf(m_url, sizeof(m_url), "%supload", MeCloud::shareInstance()->fileUrl()); + JSONObject *object = new JSONObject(); + object->put("_sid", m_objectid); + object->put("name", m_objectid); + object->put("type", "jpg"); //目前写死 + object->put("platform", me_platform); + object->put("bucket", me_bucket); + object->put("size", (int)m_content_length); + MeUser *user = MeUser::currentUser(); + if (user) { + object->put("user", user->objectId()); + } + + MeCloud::shareInstance()->post(m_url, object->toString(), callback); + delete object; +} diff --git a/src/MeUploadFile.h b/src/MeUploadFile.h new file mode 100644 index 0000000..50a7e0a --- /dev/null +++ b/src/MeUploadFile.h @@ -0,0 +1,51 @@ +// +// MeUploadFile.h +// MeCloud +// +// Created by super on 2017/7/31. +// Copyright © 2017年 Rex. All rights reserved. +// + +#ifndef MeUploadFile_h +#define MeUploadFile_h + +#include "MeFile.h" + +using namespace mc; +class MeUploadFile: public MeFile { +public: + MeUploadFile(const char* className = "File", JSONObject* obj = NULL); + MeUploadFile(MeUploadFile* file); + ~MeUploadFile(); + + void init(); + + /// 上传 + void upload(HttpFileCallback* callback, JSONObject* object); + /// 获取上传授权的相关http header信息 + void getAuthInfomation(MeCallback *callback); + /// 上传文件的本地路径 + void setUploadFilePath(const char* path); + /// 上传图片二进制数据 + void setUploadData(uint8_t *data, int size); + /// 上传文件成功后给发送反馈信息给服务器 + void uploadFileInfomation(MeCallback *callback); + /// 返回处理文件类型(目前有上传和下载) + +#ifdef __IOS__ + void upload(MeHttpFileCallbackBlock block, MeHttpFileProgressBlock progressBlock); +#endif + +private: + void resetMeUrl(JSONObject* object); +#ifdef __IOS__ + void getAuthInfomation(MeCallbackBlock callbackBlock); +#endif + +protected: + char m_upload_path[256] = "\0"; + uint8_t* m_data = NULL; + uint64_t m_content_length; +}; + +#endif /* MeUploadFile_h */ diff --git a/src/MeUser.cpp b/src/MeUser.cpp new file mode 100644 index 0000000..9c606b1 --- /dev/null +++ b/src/MeUser.cpp @@ -0,0 +1,194 @@ +/** + * file : MeUser.cpp + * author : Rex + * create : 2016-09-21 15:14 + * func : + * history: + */ + +#include "MeUser.h" +#include "SharedPreferences.h" +#include "McFile.h" +#include "McZip.h" +#include "McDevice.h" + +using namespace mc; +MeUser* MeUser::m_current_user = NULL; +const char* MeUser::m_version = "2.10"; + +MeUser::MeUser(): +MeObject("User"){ + init(); +} + +MeUser::MeUser(JSONObject* obj):MeObject("User", obj) +{ + init(); +} + +void MeUser::init(){ + put("device", mc::device_id()); + + // 初始化callback + m_object = this; +#ifdef __IOS__ + m_callback = NULL; +#endif + MeCallback::m_classname = MeObject::m_classname; +} + +#pragma --mark "登出" +void MeUser::logout(){ + if (m_current_user!=NULL) { + MeCloud::shareInstance()->clearCookie(); + char path[1024]; + FileManager::remove(SharedPreferences::path("__CurrentUser", path, sizeof(path)) ); + delete m_current_user; + m_current_user = NULL; + } +} + +#pragma --mark "登录" +code_user MeUser::login(const char* username, const char* password, MeCallback* callbak){ + if (!strcmp(username, "")){ + return ME_USERNAME_ILLEGAL; + } + else if (!strcmp(password, "")){ + return ME_PASSWORD_ILLEGAL; + } + + char url[1024]; + char userpass[256]; + char sign[33]; + + snprintf(url, 1024, "%slogin", MeCloud::shareInstance()->userUrl()); + sprintf(userpass, "%s/%s", username, password); + bs_sign(userpass, sign); + + put("username", username); + put("password", sign); + + MeCloud::shareInstance()->post(url, toString(), callbak); + return ME_USER_SUCCESS; +} + +#pragma --mark "注册" +code_user MeUser::signup(const char* username, const char* password, MeCallback* callbak){ + if (!strcmp(username, "")){ + return ME_USERNAME_ILLEGAL; + } + else if (!strcmp(password, "")){ + return ME_PASSWORD_ILLEGAL; + } + + char url[1024]; + char userpass[256]; + char sign[33]; + + snprintf(url, 1024, "%ssignup", MeCloud::shareInstance()->userUrl()); + sprintf(userpass, "%s/%s", username, password); + bs_sign(userpass, sign); + + put("username", username); + put("password", sign); + + MeCloud::shareInstance()->post(url, toString(), callbak); + return ME_USER_SUCCESS; +} + +#pragma --mark "修改密码" +code_user MeUser::changePassword(const char* username, const char* oldPassword, const char* newPassword, MeCallback* callbak){ + if (strncmp(username, "", 0)){ + return ME_USERNAME_ILLEGAL; + } else if (strncmp(oldPassword, "", 0)){ + return ME_OLDPASSWORD_ILLEGAL; + } else if (strncmp(newPassword, "", 0)){ + return ME_NEWPASSWORD_ILLEGAL; + } else if (strncmp(newPassword, oldPassword, 0)){ + return ME_PASSWORD_SAME; + } + + char url[1024]; + char oldpass[256]; + char oldsign[33]; + char newpass[256]; + char newsign[33]; + + snprintf(url, 1024, "%smodifyPwd", MeCloud::shareInstance()->userUrl()); + sprintf(oldpass, "%s/%s", username, oldPassword); + bs_sign(oldpass, oldsign); + sprintf(newpass, "%s/%s", username, newPassword); + bs_sign(newpass, newsign); + put("oldPwd", oldsign); + put("newPwd", newsign); + MeCloud::shareInstance()->post(url, toString(), callbak); + return ME_USER_SUCCESS; +} + +code_user MeUser::changePassword(const char* username, const char* newPassword, MeCallback* callbak){ + if (strncmp(username, "", 0)){ + return ME_USERNAME_ILLEGAL; + } else if (strncmp(newPassword, "", 0)){ + return ME_NEWPASSWORD_ILLEGAL; + } + + char url[1024]; + char newpass[256]; + char newsign[33]; + + snprintf(url, 1024, "%smodifyPwd", MeCloud::shareInstance()->userUrl()); + sprintf(newpass, "%s/%s", username, newPassword); + bs_sign(newpass, newsign); + put("newPwd", newsign); + MeCloud::shareInstance()->post(url, toString(), callbak); + return ME_USER_SUCCESS; +} + +const char* MeUser::encodePassword(const char* username, const char* password) { + char userpass[256]; + char *sign = new char[33]; + sprintf(userpass, "%s/%s", username, password); + bs_sign(userpass, sign); + return sign; +} + +const char* MeUser::device() { + return mc::device_id(); +} + +MeUser* MeUser::currentUser() { + mc::device_id(); + if (m_current_user == NULL) { + SharedPreferences preference("__CurrentUser"); + SharedPreferences cookiePreference("__CurrentCookie"); + if (preference.exist() && cookiePreference.exist()) { + m_current_user = new MeUser(&preference); + JSONObject *cookie = new JSONObject(&cookiePreference); + MeCloud::shareInstance()->httpSession()->setCookie(cookie->stringValue("Cookie")); + delete cookie; + return m_current_user; + } + + return NULL; + } + + return m_current_user; +} + +void MeUser::saveLoginUser(MeObject *object) { + m_current_user = new MeUser(object); + m_current_user->saveLocalCache(); +} + +void MeUser::saveLocalCache() { + if (!stringValue("_id")) { + return; + } + + char path[1024]; + FileManager::remove(SharedPreferences::path("__CurrentUser", path, sizeof(path)) ); + Crypt crypt; + const char* str = toString(); + int64_t crysize = crypt.encryptByCompress((byte*)str, (uint32_t)strlen(str)); + FileManager::write(path, crypt.bytes(), crysize); +} diff --git a/src/MeUser.h b/src/MeUser.h new file mode 100644 index 0000000..22ecd59 --- /dev/null +++ b/src/MeUser.h @@ -0,0 +1,58 @@ +/** + * file : MeUser.h + * author : Rex + * create : 2016-09-21 15:14 + * func : + * history: + */ + +#ifndef __MEUSER_H_ +#define __MEUSER_H_ + +#include "MeObject.h" +#include "MeError.h" + +class MeUser: public MeObject, public MeCallback{ +public: + MeUser(); + MeUser(JSONObject* obj); + + // 验证码注册 +#ifdef __IOS__ + code_user signup(const char* username, const char* password, MeCallbackBlock callback); + code_user login(const char* username, const char* password, MeCallbackBlock callback); + code_user changePassword(const char* username, const char* oldPassword, const char* newPassword, MeCallbackBlock callback); + code_user changePassword(const char* username, const char* newPassword, MeCallbackBlock callback); +#endif + + code_user signup(const char* username, const char* password, MeCallback* callback); + code_user login(const char* username, const char* password, MeCallback* callback); + code_user changePassword(const char* username, const char* oldPassword, const char* newPassword, MeCallback* callback); + code_user changePassword(const char* username, const char* newPassword, MeCallback* callback); + + void logout(); + + static const char* encodePassword(const char* username, const char* password); + static const char* device(); + + static MeUser* currentUser(); + void saveLocalCache(); + static void saveLoginUser(MeObject* object); + +#ifdef __IOS__ + virtual void done(MeObject* obj, MeException* err, uint32_t size = 1); +#else + virtual void done(MeObject* obj, MeException* err, uint32_t size = 1){}; +#endif +protected: + void init(); + + static MeUser* m_current_user; + static const char* m_version; +#ifdef __IOS__ + MeCallbackBlock m_callback; +#else +#endif +}; + +#endif diff --git a/src/README.md b/src/README.md new file mode 100644 index 0000000..c7d5ac2 --- /dev/null +++ b/src/README.md @@ -0,0 +1 @@ +# MeCloud-Client \ No newline at end of file diff --git a/src/android/GetAuthInfomationCallback.cpp b/src/android/GetAuthInfomationCallback.cpp new file mode 100644 index 0000000..ddfe0bc --- /dev/null +++ b/src/android/GetAuthInfomationCallback.cpp @@ -0,0 +1,40 @@ +// +// Created by 陈冰 on 2017/8/1. +// + +#include "GetAuthInfomationCallback.h" +#include "UpLoadFileCallBack.h" + +GetAuthInfomationCallback::GetAuthInfomationCallback(const char *classname, + MeUploadFile *obj, + jobject thiz, + jobject jcallback) + : MeCallback(classname, obj) { + m_object = obj; + meUploadFile = obj; + this->thiz = thiz; + this->jcallback = jcallback; +} + +void GetAuthInfomationCallback::done(MeObject *obj, MeException *err, + uint32_t size) { + if (isEnd && err == NULL && obj->intValue("errCode") == 0) { // 第三步 + MeAndroidHttpFileCallBack *callback = new MeAndroidHttpFileCallBack(m_classname, meUploadFile); + callback->lock(); + callback->setPara(thiz, jcallback); + callback->done((MeFile *) obj, NULL); + } else if (err == NULL && obj->intValue("errCode") == 0) { // 第二步 + UpLoadFileCallBack *callback = new UpLoadFileCallBack(m_classname, meUploadFile, thiz, + jcallback); + callback->lock(); + callback->setPara(thiz, jcallback); + meUploadFile->upload(callback, obj); + } else { + MeAndroidHttpFileCallBack *callback = new MeAndroidHttpFileCallBack(m_classname, meUploadFile); + callback->lock(); + callback->setPara(thiz, jcallback); + callback->done(NULL, err); + } + delete this; +} + diff --git a/src/android/GetAuthInfomationCallback.h b/src/android/GetAuthInfomationCallback.h new file mode 100644 index 0000000..63dbb5f --- /dev/null +++ b/src/android/GetAuthInfomationCallback.h @@ -0,0 +1,27 @@ +// +// Created by 陈冰 on 2017/8/1. +// + +#ifndef MECLOUDTEAMP_GETAUTHINFOMATIONCALLBACK_H +#define MECLOUDTEAMP_GETAUTHINFOMATIONCALLBACK_H + +#include "jni.h" +#include +#include +#include "MeAndroidHttpFileCallBack.h" + +class GetAuthInfomationCallback : public MeCallback { + +public: + MeUploadFile *meUploadFile = NULL; + jobject thiz = NULL; + jobject jcallback = NULL; + jboolean isEnd = false; + GetAuthInfomationCallback(const char *classname, MeUploadFile *obj, jobject thiz, + jobject jcallback); + + virtual void done(MeObject *obj, MeException *err, uint32_t size); +}; + + +#endif //MECLOUDTEAMP_GETAUTHINFOMATIONCALLBACK_H diff --git a/src/android/MeAndroidCallback.cpp b/src/android/MeAndroidCallback.cpp new file mode 100644 index 0000000..4de30ba --- /dev/null +++ b/src/android/MeAndroidCallback.cpp @@ -0,0 +1,145 @@ +/** + * file : MeAndroidCallback.cpp + * author : Rex + * create : 2017-07-19 21:00 + * func : + * history: + */ +#include +#include +#include "MeAndroidCallback.h" + +#ifndef EXPORT_API +#define EXPORT_API __attribute__((visibility("default"))) +#endif +#ifdef __cplusplus +extern "C" { +#endif +extern jfieldID g_ptr; +extern jclass g_exception_class; +extern jmethodID g_exception_init; +extern jmethodID g_mecloud_callback; +extern jmethodID g_mecloud_callbackList; + +extern void globalMeObject(JNIEnv *env); + +extern void global_exception(JNIEnv *env); + +extern const char *getJclassName(JNIEnv *env, jclass clazz); +#ifdef __cplusplus +} +#endif + +MeObjectCallback::MeObjectCallback(const char *classname, MeObject *object): MeCallback(classname, object) { + +} + +MeObjectCallback::MeObjectCallback(jobject thiz, jobject callback) { + m_thiz = thiz; + m_callback = callback; +} + +void MeObjectCallback::setPara(jobject thiz, jobject callback) { + m_thiz = thiz; + m_callback = callback; +} + +void MeObjectCallback::setIsMeListCallback(bool_t isMeListCallback) { + this->isMeListCallback = isMeListCallback; +} + +void MeObjectCallback::done(MeObject *obj, MeException *err, uint32_t size) { + extern JavaVM *g_jvm; + JNIEnv *env; + int state = g_jvm->GetEnv((void **) &env, JNI_VERSION_1_6); + switch (state) { + case JNI_EDETACHED: + g_jvm->AttachCurrentThread(&env, NULL); + break; + case JNI_EVERSION: + err_log("%s", "Version not support!") + return; + case JNI_OK: + break; + default:break; + } +// err_log("MeObjectCallback::done -> callback!!!!!!!!"); + if (g_exception_class == NULL) { + global_exception(env); + } + + if (err != NULL) { + jobject errObj = env->AllocObject(g_exception_class); + jstring errMsg = env->NewStringUTF(err->errMsg()); + jstring info = env->NewStringUTF(err->info()); + env->CallVoidMethod(errObj, g_exception_init, err->errCode(), errMsg, info); + if (isMeListCallback) { + env->CallVoidMethod(m_thiz, g_mecloud_callbackList, NULL, m_callback, errObj); + } else { + env->CallVoidMethod(m_thiz, g_mecloud_callback, (jlong) 0, m_callback, errObj); + } + } else { + if (isMeListCallback) { + jlong objptrs[size]; + jlongArray jobjptrs = env->NewLongArray(size); + for (int i = 0; i < size; ++i) { + JSONObject *object = new JSONObject(&obj[i], false); + objptrs[i] = (jlong) object; + } + env->SetLongArrayRegion(jobjptrs, 0, size, objptrs); + env->CallVoidMethod(m_thiz, g_mecloud_callbackList, jobjptrs, m_callback, NULL); + } else { + JSONObject *object = new JSONObject(obj, false); + env->CallVoidMethod(m_thiz, g_mecloud_callback, (jlong)object, m_callback, NULL); + } + } + unLock(); + + env->DeleteGlobalRef(m_thiz); + env->DeleteGlobalRef(m_callback); + g_jvm->DetachCurrentThread(); + delete this; +} + +MeUserCallback::MeUserCallback(MeUser *meUser): MeObjectCallback("User", meUser) { + +} + +void MeUserCallback::done(MeObject *obj, MeException *err, uint32_t size) { + extern JavaVM *g_jvm; + JNIEnv *env; + int state = g_jvm->GetEnv((void **) &env, JNI_VERSION_1_6); + switch (state) { + case JNI_EDETACHED: + g_jvm->AttachCurrentThread(&env, NULL); + break; + case JNI_EVERSION: + return; + case JNI_OK: + break; + default:break; + } + + if (g_exception_class == NULL) { + global_exception(env); + } + + if (err != NULL) { + jobject errObj = env->AllocObject(g_exception_class); + jstring errMsg = env->NewStringUTF(err->errMsg()); + jstring info = env->NewStringUTF(err->info()); + env->CallVoidMethod(errObj, g_exception_init, err->errCode(), errMsg, info); + env->CallVoidMethod(m_thiz, g_mecloud_callback, m_callback, errObj); + } else { + MeUser *meUser = new MeUser(obj); + meUser->saveLocalCache(); + env->CallVoidMethod(m_thiz, g_mecloud_callback, (jlong)meUser, m_callback, NULL); + } + unLock(); + + env->DeleteGlobalRef(m_thiz); + env->DeleteGlobalRef(m_callback); + g_jvm->DetachCurrentThread(); + delete this; +} + diff --git a/src/android/MeAndroidCallback.h b/src/android/MeAndroidCallback.h new file mode 100644 index 0000000..744144e --- /dev/null +++ b/src/android/MeAndroidCallback.h @@ -0,0 +1,43 @@ +/** + * file : MeAndroidCallback.h + * author : Rex + * create : 2017-07-19 21:00 + * func : + * history: + */ + +#ifndef __MEANDROIDCALLBACK_H_ +#define __MEANDROIDCALLBACK_H_ + +#include +#include "bs.h" +#include "MeCallback.h" +#include "MeUser.h" + +class MeObjectCallback : public MeCallback { +public: + MeObjectCallback(const char *classname = NULL, MeObject *object = NULL); + + MeObjectCallback(jobject thiz, jobject callback); + + void setPara(jobject thiz, jobject callback); + + void setIsMeListCallback(bool_t isMeListCallback = BS_FALSE); + + virtual void done(MeObject *obj, MeException *err, uint32_t size = 1); + +protected: + jobject m_thiz; + jobject m_callback; + bool_t isMeListCallback; + +}; + +class MeUserCallback : public MeObjectCallback { +public: + MeUserCallback(MeUser *meUser); + + virtual void done(MeObject *obj, MeException *err, uint32_t size = 1); +}; + +#endif diff --git a/src/android/MeAndroidHttpFileCallBack.cpp b/src/android/MeAndroidHttpFileCallBack.cpp new file mode 100644 index 0000000..14e5abf --- /dev/null +++ b/src/android/MeAndroidHttpFileCallBack.cpp @@ -0,0 +1,210 @@ +// +// Created by 陈冰 on 2017/7/25. +// + +#include "jni.h" +#include "MeAndroidHttpFileCallBack.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif +jmethodID fileDoneId; +jmethodID fileProgressId; +jmethodID dataDoneId; +jmethodID dataProgressId; +extern jclass g_exception_class; +extern jmethodID g_exception_init; +extern void global_exception(JNIEnv *env); +#ifdef __cplusplus +}; +#endif + +MeAndroidHttpFileCallBack::MeAndroidHttpFileCallBack(const char *classname, + MeFile *file) + : MeHttpFileCallback(classname, file) { +} + +void MeAndroidHttpFileCallBack::setPara(jobject thiz, jobject callback) { + m_thiz = thiz; + m_callback = callback; +} + +void MeAndroidHttpFileCallBack::done(MeFile *file, MeException *err, + uint32_t size) { + extern JavaVM *g_jvm; + JNIEnv *env; + int state_env = g_jvm->GetEnv((void **) &env, JNI_VERSION_1_6); + switch (state_env) { + case JNI_EDETACHED: + g_jvm->AttachCurrentThread(&env, NULL); + break; + case JNI_EVERSION: + err_log("%s", "Version not support!") + return; + case JNI_OK: + break; + default: + break; + } + getCallbackMethodId(env); + if (m_callback) { + if (err != NULL) { + if (g_exception_init == NULL) { + global_exception(env); + } + jobject errObj = env->AllocObject(g_exception_class); + jstring errMsg = env->NewStringUTF(err->errMsg()); + jstring info = env->NewStringUTF(err->info()); + env->CallVoidMethod(errObj, g_exception_init, err->errCode(), errMsg, + info); + env->CallVoidMethod(m_thiz, fileDoneId,(jlong) 0, m_callback, errObj); + } else { + JSONObject *object = new JSONObject(file, false); + env->CallVoidMethod(m_thiz, fileDoneId,(jlong) object, m_callback, NULL); + } + } + unLock(); + + env->DeleteGlobalRef(m_thiz); + env->DeleteGlobalRef(m_callback); + g_jvm->DetachCurrentThread(); + delete this; +} + +void MeAndroidHttpFileCallBack::progress(uint64_t writen, uint64_t total_writen, + uint64_t total_expect_write) { + extern JavaVM *g_jvm; + JNIEnv *env; + int state_env = g_jvm->GetEnv((void **) &env, JNI_VERSION_1_6); + switch (state_env) { + case JNI_EDETACHED: + g_jvm->AttachCurrentThread(&env, NULL); + break; + case JNI_EVERSION: + err_log("%s", "Version not support!") + return; + case JNI_OK: + break; + default: + break; + } + getCallbackMethodId(env); + if (m_callback) { + env->CallVoidMethod(m_thiz, fileProgressId, m_callback, writen, total_writen, + total_expect_write); + } + g_jvm->DetachCurrentThread(); +} + +void MeAndroidHttpFileCallBack::getCallbackMethodId(JNIEnv *env) const { + jclass thizClass = env->GetObjectClass(m_thiz); + if (fileDoneId == NULL) { + fileDoneId = + env->GetMethodID( + thizClass, + "doneCallback", + "(JLcom/rex/mecloud/HttpFileCallback;Lcom/rex/mecloud/MeException;)V"); + } + if (fileProgressId == NULL) { + fileProgressId = env->GetMethodID( + thizClass, "progressCallback", + "(Lcom/rex/mecloud/HttpFileCallback;JJJ)V"); + } + env->DeleteLocalRef(thizClass); +} + +MeAndroidHttpDataCallBack::MeAndroidHttpDataCallBack(const char *classname, + MeObject *json) + : MeHttpDataCallback() { +} + +void MeAndroidHttpDataCallBack::setPara(jobject thiz, jobject callback) { + m_thiz = thiz; + m_callback = callback; +} + +void MeAndroidHttpDataCallBack::done(MeObject* obj, MeException *err, + uint32_t size) { + extern JavaVM *g_jvm; + JNIEnv *env; + int state_env = g_jvm->GetEnv((void **) &env, JNI_VERSION_1_6); + switch (state_env) { + case JNI_EDETACHED: + g_jvm->AttachCurrentThread(&env, NULL); + break; + case JNI_EVERSION: + err_log("%s", "Version not support!") + return; + case JNI_OK: + break; + default: + break; + } + getCallbackMethodId(env); + if (m_callback) { + if (err != NULL) { + if (g_exception_init == NULL) { + global_exception(env); + } + jobject errObj = env->AllocObject(g_exception_class); + jstring errMsg = env->NewStringUTF(err->errMsg()); + jstring info = env->NewStringUTF(err->info()); + env->CallVoidMethod(errObj, g_exception_init, err->errCode(), errMsg, + info); + env->CallVoidMethod(m_thiz, dataDoneId,(jlong) 0, m_callback, errObj); + } else { + JSONObject *object = new JSONObject(obj, false); + env->CallVoidMethod(m_thiz, dataDoneId,(jlong)object, m_callback, NULL); + } + } + unLock(); + + env->DeleteGlobalRef(m_thiz); + env->DeleteGlobalRef(m_callback); + g_jvm->DetachCurrentThread(); + delete this; +} + +void MeAndroidHttpDataCallBack::progress(uint64_t writen, uint64_t total_writen, + uint64_t total_expect_write) { + extern JavaVM *g_jvm; + JNIEnv *env; + int state_env = g_jvm->GetEnv((void **) &env, JNI_VERSION_1_6); + switch (state_env) { + case JNI_EDETACHED: + g_jvm->AttachCurrentThread(&env, NULL); + break; + case JNI_EVERSION: + return; + case JNI_OK: + break; + default: + break; + } + getCallbackMethodId(env); + if (m_callback) { + env->CallVoidMethod(m_thiz, dataProgressId, m_callback, (jlong)writen, (jlong) total_writen, + (jlong)total_expect_write); + } + g_jvm->DetachCurrentThread(); +} + +void MeAndroidHttpDataCallBack::getCallbackMethodId(JNIEnv *env) const { + jclass thizClass = env->GetObjectClass(m_thiz); + if (dataDoneId == NULL) { + dataDoneId = + env->GetMethodID( + thizClass, + "doneCallback", + "(JLcom/rex/mecloud/HttpDataCallback;Lcom/rex/mecloud/MeException;)V"); + } + if (dataProgressId == NULL) { + dataProgressId = env->GetMethodID( + thizClass, + "progressCallback", + "(Lcom/rex/mecloud/HttpDataCallback;JJJ)V"); + } + env->DeleteLocalRef(thizClass); +} + diff --git a/src/android/MeAndroidHttpFileCallBack.h b/src/android/MeAndroidHttpFileCallBack.h new file mode 100644 index 0000000..6756143 --- /dev/null +++ b/src/android/MeAndroidHttpFileCallBack.h @@ -0,0 +1,47 @@ +// +// MeIOSDownloadCallBack.h +// MeCloud +// +// Created by super on 2017/7/25. +// Copyright © 2017年 Rex. All rights reserved. +// + +#ifndef __MEANDROIDDOWNLOADCALLBACK_H_ +#define __MEANDROIDDOWNLOADCALLBACK_H_ + +#include "jni.h" +#include "MeHttpFileCallback.h" + +class MeAndroidHttpFileCallBack: public MeHttpFileCallback { +public: + MeAndroidHttpFileCallBack(const char *classname = NULL, MeFile *file = NULL); + + virtual void done(MeFile *file, MeException *err, uint32_t size = 1); + + virtual void progress(uint64_t writen, uint64_t total_writen, uint64_t total_expect_write); + + void setPara(jobject thiz, jobject callback); +protected: + jobject m_thiz; + jobject m_callback; + + void getCallbackMethodId(JNIEnv *env) const; +}; + +class MeAndroidHttpDataCallBack: public MeHttpDataCallback { +public: + MeAndroidHttpDataCallBack(const char *classname = NULL, MeObject* json = NULL); + + virtual void done(MeObject* json, MeException *err, uint32_t size = 1); + + virtual void progress(uint64_t writen, uint64_t total_writen, uint64_t total_expect_write); + + void setPara(jobject thiz, jobject callback); +protected: + jobject m_thiz; + jobject m_callback; + + void getCallbackMethodId(JNIEnv *env) const; +}; + +#endif diff --git a/src/android/UpLoadFileCallBack.cpp b/src/android/UpLoadFileCallBack.cpp new file mode 100644 index 0000000..20446a1 --- /dev/null +++ b/src/android/UpLoadFileCallBack.cpp @@ -0,0 +1,31 @@ +// +// Created by 陈冰 on 2017/8/1. +// + +#include "UpLoadFileCallBack.h" +#include "GetAuthInfomationCallback.h" + +UpLoadFileCallBack::UpLoadFileCallBack(const char *classname, + MeUploadFile *obj, + jobject thiz, + jobject jcallback) + : MeAndroidHttpFileCallBack(classname, obj) { + meUploadFile = obj; + this->thiz = thiz; + this->jcallback = jcallback; +} + +void UpLoadFileCallBack::done(MeFile *file, MeException *err, + uint32_t size) { + if (err == NULL) { + GetAuthInfomationCallback *callback = new GetAuthInfomationCallback(m_classname, + meUploadFile, thiz, + jcallback); + callback->isEnd = (jboolean) true; + callback->lock(); + meUploadFile->uploadFileInfomation(callback); + } else { + err_log("errMsg: %s", err->errMsg()); + } + delete this; +} diff --git a/src/android/UpLoadFileCallBack.h b/src/android/UpLoadFileCallBack.h new file mode 100644 index 0000000..2e64cfc --- /dev/null +++ b/src/android/UpLoadFileCallBack.h @@ -0,0 +1,22 @@ +// +// Created by 陈冰 on 2017/8/1. +// + + +#include "jni.h" +#include +#include +#include "MeAndroidHttpFileCallBack.h" + +class UpLoadFileCallBack : public MeAndroidHttpFileCallBack { + +public: + MeUploadFile* meUploadFile = NULL; + jobject thiz = NULL; + jobject jcallback = NULL; + UpLoadFileCallBack(const char *classname, MeUploadFile* obj, jobject thiz, jobject jcallback); + virtual void done(MeFile *file, MeException *err, + uint32_t size); +}; + + diff --git a/src/android/android_mecloud.cpp b/src/android/android_mecloud.cpp new file mode 100644 index 0000000..3c3e78b --- /dev/null +++ b/src/android/android_mecloud.cpp @@ -0,0 +1,1486 @@ +/** + * file : android_mecloud.cpp + * author : Rex + * create : 2017-07-17 18:50 + * func : + * history: + */ + +#include +#include "MeAndroidCallback.h" +#include "GetAuthInfomationCallback.h" +#include "MeAndroidHttpFileCallBack.h" +#include "MeQuery.h" +#include "MeRole.h" +#include "MeDownloadFile.h" +#include "MeUploadFile.h" +#include "MeJoinQuery.h" +#include "MeACL.h" +#include "McDevice.h" + +using namespace std; +#ifdef __cplusplus +extern "C" { +#endif +void setJSONObjectPtr(JNIEnv *env, jobject thiz); +void setObjectPtr(JNIEnv *env, jobject thiz, jstring jfieldname, jstring jsign); +jstring char2Jstring(JNIEnv *env, const char *pat); +void global_exception(JNIEnv *env); +const char *getJclassName(JNIEnv *env, jclass objectClass); +void global_mecloud_callback(JNIEnv *env); + +// JSONObject +jlong createJSONObject(JNIEnv *env, jobject thiz); +jlong createJSONObjectWithText(JNIEnv *env, jobject thiz, jstring text); +void destroy(JNIEnv *env, jobject jo); +jboolean has(JNIEnv *env, jobject thiz, jstring jname); +jbyteArray jsonByteArray(JNIEnv *env, jobject thiz); +jbyteArray byteArrayValue(JNIEnv *env, jobject jo, jstring jkey); +jdouble doubleValue(JNIEnv *env, jobject jo, jstring jkey); +jint intValue(JNIEnv *env, jobject jo, jstring jkey); +jlong longValue(JNIEnv *env, jobject jo, jstring jkey); +jfloat floatValue(JNIEnv *env, jobject jo, jstring jkey); +jboolean booleanValue(JNIEnv *env, jobject jo, jstring jkey); +jlong jsonValue(JNIEnv *env, jobject jo, jstring jkey); +jlongArray arrayValue(JNIEnv *env, jobject jo, jstring jkey); +jintArray intArrayValue(JNIEnv *env, jobject jo, jstring jkey); +jobjectArray stringByteArrayValue(JNIEnv *env, jobject jo, jstring jkey); + +void jputString(JNIEnv *env, jobject jo, jstring jkey, jbyteArray jvalue); +void jputDouble(JNIEnv *env, jobject jo, jstring jkey, jdouble jvalue); +void jputInt(JNIEnv *env, jobject jo, jstring jkey, jint jvalue); +void jpMeUploadFileutLong(JNIEnv *env, jobject jo, jstring jkey, jlong jvalue); +void jputLong(JNIEnv *env, jobject jo, jstring jkey, jlong jvalue); +void jputFloat(JNIEnv *env, jobject jo, jstring jkey, jfloat jvalue); +void jputBoolean(JNIEnv *env, jobject jo, jstring jkey, jboolean jvalue); +void jputObject(JNIEnv *env, jobject jo, jstring jkey, jlong meObjectObjectPre); + +// MeObject +jlong createMeObject(JNIEnv *env, jobject thiz); +jlong createMeObjectWithClassName(JNIEnv *env, jobject thiz, jstring className); +jlong createMeObjectWithJSONObject(JNIEnv *env, jobject thiz, jstring jname, jlong jobjectPre); +jlong createMeObjectWithObjectId(JNIEnv *env, jobject thiz, jstring jobjectid, jstring jclassName); +jstring objectId(JNIEnv *env, jobject thiz); +jstring className(JNIEnv *env, jobject thiz); +void setClassName(JNIEnv *env, jobject thiz, jstring className); +void setACL(JNIEnv *env, jobject thiz, jlong meACLObjectPre); +jlong getACL(JNIEnv *env, jobject thiz, jlong meACLObjectPre); +void putObject(JNIEnv *env, jobject jo, jstring jkey, jlong meObjectObjectPre); +jlongArray objectValue(JNIEnv *env, jobject jo, jstring jkey); +// MeQuery +jlong createMeQuery(JNIEnv *env, jobject thiz); +jlong createMeQueryWithClassName(JNIEnv *env, jobject thiz, jstring jclassName); +void whereEqualToString(JNIEnv *env, jobject thiz, jstring jkey, jbyteArray jval); +void whereNotEqualToString(JNIEnv *env, jobject thiz, jstring jkey, + jbyteArray jval); +void whereEqualToInt(JNIEnv *env, jobject thiz, jstring jkey, jint jval); +void whereNotEqualToInt(JNIEnv *env, jobject thiz, jstring jkey, jint jval); +void whereEqualOr(JNIEnv *env, jobject thiz, jstring jkey, jbyteArray jvalue); +void whereEqualOrToInt(JNIEnv *env, jobject thiz, jstring jkey, jint jvalue); +void whereGreaterToString(JNIEnv *env, jobject thiz, jstring jkey, jbyteArray jvalue); +void whereGreaterToInt(JNIEnv *env, jobject thiz, jstring jkey, jint jvalue); +void whereLessToString(JNIEnv *env, jobject thiz, jstring jkey, jbyteArray jvalue); +void whereLessToInt(JNIEnv *env, jobject thiz, jstring jkey, jint jvalue); + +void selectKeys(JNIEnv *env, jobject thiz, jobjectArray jkeys, jint num); +void addSelectKey(JNIEnv *env, jobject thiz, jstring jkey); +void addNotSelectKey(JNIEnv *env, jobject thiz, jstring jkey); +void addAscendSortKeys(JNIEnv *env, jobject thiz, jstring jkey); +void addDescendSortKeys(JNIEnv *env, jobject thiz, jstring jkey); +void addLimit(JNIEnv *env, jobject thiz, jlong jcount); +void addOffset(JNIEnv *env, jobject thiz, jstring startId); +void addAggregateObject(JNIEnv *env, jobject thiz, jobject jaggreate); +void setAggregateObject(JNIEnv *env, jobject thiz, jobject jaggreate); + +// MeRole +jlong createMeRole(JNIEnv *env, jobject thiz, jstring jrolename); +void setUserId(JNIEnv *env, jobject thiz, jstring juserid); +void setUserObjects(JNIEnv *env, jobject thiz, jlong jmeUser); + +// MeCloud +void initialize(JNIEnv *env, jobject thiz, jstring jappId, jstring jappKey); +void initialize(JNIEnv *env, jobject thiz, jstring jappId, jstring jappKey); +void config(JNIEnv *env, jobject thiz); +void setBaseUrl(JNIEnv *env, jobject thiz, jstring jurl); +void setTimeout(JNIEnv *env, jobject thiz, jint time); +void setShowLog(JNIEnv *env, jobject thiz, jboolean showLog); +void addHttpHeader(JNIEnv *env, jobject thiz, jstring jkey, jstring jvalue); +jbyteArray crypto(JNIEnv *env, jobject thiz, jbyteArray byteArray); +jbyteArray cryptoStringByte(JNIEnv *env, jobject thiz, jbyteArray byteArray); +jbyteArray decrypt(JNIEnv *env, jobject thiz, jbyteArray byteArray); +jbyteArray decryptStringByte(JNIEnv *env, jobject thiz, jbyteArray byteArray); +jstring cookie(JNIEnv *env, jobject thiz); +void login(JNIEnv *env, jobject thiz, jstring jusername, jstring jpassword, jobject callback); +void signUp(JNIEnv *env, jobject thiz, jstring jusername, jstring jpassword, jobject callback); +void changePassword(JNIEnv *env, jobject thiz, jstring jusername, jstring jpassword, jobject callback); +void save(JNIEnv *env, jobject thiz, jobject object, jobject jcallback); +void getObjectWithID(JNIEnv *env, jobject thiz, jstring jobjectId, jstring jclassName, jobject jcallback); +void getObjectsWithQuery(JNIEnv *env, jobject thiz, jobject object, jobject jcallback); +void findWithJoin(JNIEnv *env, jobject thiz, jobject object, jobject callBack); +void queryWithUrl(JNIEnv *env, jobject thiz, jstring jurl, jlong jJsonObject, jobject jcallback); +void deleteObject(JNIEnv *env, jobject thiz, jobject jJsonObject, jobject jcallback); +jstring download(JNIEnv *env, jobject thiz, jstring name, jstring jurl, jobject jcallback); +void uploadFile(JNIEnv *env, jobject thiz, jstring type, jstring jpath, jobject jcallback); +void uploadData(JNIEnv *env, jobject thiz, jstring type, jbyteArray jdata, jobject jcallback); +void postData(JNIEnv *env, jobject thiz, jstring jurl, jbyteArray jData, jobject jcallBack); +void saveWithUrl(JNIEnv *env, jobject thiz, jstring jurl, jobject jJsonObject, jobject jcallback); +void getWithUrl(JNIEnv *env, jobject thiz, jstring jurl, jobject jJsonObject, jobject jcallback); + +// MeFile +jlong createMeFile(JNIEnv *env, jobject thiz, jstring jclassName); +jlong createMeFileWithObjectId(JNIEnv *env, jobject thiz, jstring jobjId, jstring jclassName); +jstring filePath(JNIEnv *env, jobject thiz); + +jstring imageUrl(JNIEnv *env, jobject thiz, jint width, jint height); +jstring imageUrlNormal(JNIEnv *env, jobject thiz); +jstring imageCropUrl(JNIEnv *env, jobject thiz, jint x, jint y, jint width, jint height); + +// MeUser +jlong createUser(JNIEnv *env, jobject thiz); +jlong createUserWithJSONObject(JNIEnv *env, jobject thiz, jlong jsonPtr); +jlong currentUser(JNIEnv *env, jobject thiz); +void logout(JNIEnv *env, jobject thiz); +void saveLoginUser(JNIEnv *env, jobject thiz, jlong userPtr); +jstring encodePassword(JNIEnv *env, jobject thiz, jstring jusername, jstring jpassword); +jstring device(JNIEnv *env, jobject thiz); + +// MeACL +void setPublicReadAccess(JNIEnv *env, jobject thiz); +void setPublicWriteAccess(JNIEnv *env, jobject thiz); +void setRoleReadAccess(JNIEnv *env, jobject thiz, jstring jrole); +void setRoleWriteAccess(JNIEnv *env, jobject thiz, jstring jrole); +void setRoleReadAccessMeRole(JNIEnv *env, jobject thiz, jlong objectPre); +void setRoleWriteAccessMeRole(JNIEnv *env, jobject thiz, jlong objectPre); +void setUserReadAccess(JNIEnv *env, jobject thiz, jstring juserId); +void setUserWriteAccess(JNIEnv *env, jobject thiz, jstring juserId); +void setUserReadAccessMeUser(JNIEnv *env, jobject thiz, jlong objectPre); +void setUserWriteAccessMeUser(JNIEnv *env, jobject thiz, jlong objectPre); + +// MeJoinQuery +jlong createMeJoinQuery(JNIEnv *env, jobject thiz, jstring jclassName, jboolean jnestQuery); +void addSelectKeyWithJoin(JNIEnv *env, jobject thiz, jstring key); +void addNotSelectKeyWithJoin(JNIEnv *env, jobject thiz, jstring key); +void addAscendWithJoin(JNIEnv *env, jobject thiz, jstring key); +void addDescendWithJoin(JNIEnv *env, jobject thiz, jstring key); + +void matchEqualTo(JNIEnv *env, jobject thiz, jstring key, jbyteArray value); +void matchEqualToInt(JNIEnv *env, jobject thiz, jstring jkey, jint value); +void matchGreater(JNIEnv *env, jobject thiz, jstring jkey, jbyteArray value); +void matchGreaterToInt(JNIEnv *env, jobject thiz, jstring jkey, jint value); +void matchLess(JNIEnv *env, jobject thiz, jstring key, jbyteArray value); +void matchLessToInt(JNIEnv *env, jobject thiz, jstring jkey, jint value); +void addForeignTable(JNIEnv *env, jobject thiz, jstring fromTable, jstring foreignKey, jstring localKey, jstring jdocument); +void addMeJoinQueryPtr(JNIEnv *env, jobject thiz, jlong joinQuery); +void addLimitWithJoin(JNIEnv *env, jobject thiz, jint count); + +// MeAggregateObject +jlong createMeAggregateObject(JNIEnv *env, jobject thiz, jstring jclassName); +void whereEqualToWithAggregate(JNIEnv *env, jobject thiz, jstring jkey, jbyteArray jvalue); +void whereEqualToIntWithAggregate(JNIEnv *env, jobject thiz, jstring jkey, jint jvalue); +void whereNotEqualToWithAggregate(JNIEnv *env, jobject thiz, jstring jkey, jbyteArray jvalue); +void whereNotEqualToIntWithAggregate(JNIEnv *env, jobject thiz, jstring jkey, jint jvalue); +void whereGreaterWithAggregate(JNIEnv *env, jobject thiz, jstring jkey, jbyteArray jvalue); +void whereGreaterIntWithAggregate(JNIEnv *env, jobject thiz, jstring jkey, jint jvalue); +void whereLessWithAggregate(JNIEnv *env, jobject thiz, jstring jkey, jbyteArray jvalue); +void whereLessIntWithAggregate(JNIEnv *env, jobject thiz, jstring jkey, jint jvalue); +void setResponseKey(JNIEnv *env, jobject thiz, jstring jkey); +void setDistinctKey(JNIEnv *env, jobject thiz, jstring jkey); +void setMethod(JNIEnv *env, jobject thiz, jint method); + +void setDevice(JNIEnv *env, jobject thiz, jobject jcontext); +void saveJSONToCache(JNIEnv *env, jobject thiz, jlong objectPre, jstring jkey); +jlong getJSONFromCache(JNIEnv *env, jobject thiz, jstring jkey); +void removeJSONFromCache(JNIEnv *env, jobject thiz, jstring jkey); + +#ifdef __cplusplus +} +#endif + +//jclass g_class = NULL; +jfieldID g_ptr = NULL; + +jclass g_exception_class = NULL; +jmethodID g_exception_init = NULL; + +jmethodID g_mecloud_callback = NULL; +jmethodID g_mecloud_callbackList = NULL; + +const char *getJclassName(JNIEnv *env, jclass objectClass) { + if (objectClass) { + jclass classClass = env->FindClass("java/lang/Class"); + jmethodID getClassNameMethodId = env->GetMethodID(classClass, + "getSimpleName", + "()Ljava/lang/String;"); + jstring javaClassNameJString = (jstring) env->CallObjectMethod( + objectClass, getClassNameMethodId, ""); + const char *tempClassName = env->GetStringUTFChars(javaClassNameJString, + NULL); + char *className = new char[strlen(tempClassName) + 1]; + strcpy(className, tempClassName); + env->ReleaseStringUTFChars(javaClassNameJString, tempClassName); + env->DeleteLocalRef(classClass); + env->DeleteLocalRef(javaClassNameJString); + return className; + } else { + return NULL; + } +} + +void global_exception(JNIEnv *env) { + if (g_exception_class == NULL) { + g_exception_class = (jclass) env->NewGlobalRef( + env->FindClass("com/rex/mecloud/MeException")); + g_exception_init = env->GetMethodID( + g_exception_class, "", + "(ILjava/lang/String;Ljava/lang/String;)V"); + } +} + +void global_mecloud_callback(JNIEnv *env) { + if (g_mecloud_callback == NULL || g_mecloud_callbackList == NULL) { + jclass mecloud_class = env->FindClass("com/rex/mecloud/MeCloud"); + g_mecloud_callback = env->GetMethodID(mecloud_class, + "callback", + "(JLcom/rex/mecloud/MeCallback;Lcom/rex/mecloud/MeException;)V"); + g_mecloud_callbackList = env->GetMethodID(mecloud_class, + "callbackList", + "([JLcom/rex/mecloud/MeListCallback;Lcom/rex/mecloud/MeException;)V"); + env->DeleteLocalRef(mecloud_class); + } +} + +void setObjectPtr(JNIEnv *env, jobject thiz, jstring jfieldname, + jstring jsign) { + const char *fieldName = env->GetStringUTFChars(jfieldname, NULL); + const char *sign = env->GetStringUTFChars(jsign, NULL); + jclass clazz = env->FindClass("com/rex/mecloud/JSONObject"); + g_ptr = env->GetFieldID(clazz, fieldName, sign); + global_exception(env); + env->DeleteLocalRef(clazz); + env->ReleaseStringUTFChars(jfieldname, fieldName); + env->ReleaseStringUTFChars(jsign, sign); +} + +void setJSONObjectPtr(JNIEnv *env, jobject thiz) { + jstring name = env->NewStringUTF("objectPtr"); + jstring sign = env->NewStringUTF("J"); + setObjectPtr(env, thiz, name, sign); + env->DeleteLocalRef(name); + env->DeleteLocalRef(sign); +} + +//MeObject +jlong createMeObject(JNIEnv *env, jobject thiz) { + setJSONObjectPtr(env, thiz); + MeObject *meObject = new MeObject(); + return (jlong) meObject; +} + +jlong createMeObjectWithClassName(JNIEnv *env, jobject thiz, jstring jclassName) { + setJSONObjectPtr(env, thiz); + const char *className = env->GetStringUTFChars(jclassName, NULL); + MeObject *obj = new MeObject(className); + env->ReleaseStringUTFChars(jclassName, className); + return (jlong) obj; +} + +jlong createMeObjectWithJSONObject(JNIEnv *env, jobject thiz, jstring jclassName, jlong jobjectPre) { + setJSONObjectPtr(env, thiz); + const char *className = env->GetStringUTFChars(jclassName, NULL); + JSONObject *jsonObject = (JSONObject *) jobjectPre; + if (jobjectPre) { + MeObject *obj = new MeObject(className, jsonObject); + env->ReleaseStringUTFChars(jclassName, className); + return (jlong) obj; + } else { + env->ReleaseStringUTFChars(jclassName, className); + return -1; + } +} + +jlong createMeObjectWithObjectId(JNIEnv *env, jobject thiz, jstring jobjectid, jstring jclassName) { + setJSONObjectPtr(env, thiz); + const char *objectid = env->GetStringUTFChars(jobjectid, NULL); + const char *classname = env->GetStringUTFChars(jclassName, NULL); + MeObject *meObject = new MeObject(objectid, classname); + env->ReleaseStringUTFChars(jobjectid, objectid); + env->ReleaseStringUTFChars(jclassName, classname); + return (jlong) meObject; +} + + +void destroy(JNIEnv *env, jobject thiz) { + if (thiz != NULL && g_ptr != NULL) { + JSONObject *obj = (JSONObject *) env->GetLongField(thiz, g_ptr); + if (obj != NULL) { + delete obj; + obj = NULL; + } + } +} + +jstring objectId(JNIEnv *env, jobject thiz) { + MeObject *obj = (MeObject *) env->GetLongField(thiz, g_ptr); + return env->NewStringUTF(obj->objectId()); +} + +jstring className(JNIEnv *env, jobject thiz) { + MeObject *obj = (MeObject *) env->GetLongField(thiz, g_ptr); + return env->NewStringUTF(obj->className()); +} + +void setClassName(JNIEnv *env, jobject thiz, jstring className) { + MeObject *obj = (MeObject *) env->GetLongField(thiz, g_ptr); + const char *name = env->GetStringUTFChars(className, NULL); + obj->setClassName(name); + env->ReleaseStringUTFChars(className, name); +} + +void setACL(JNIEnv *env, jobject thiz, jlong meACLObjectPre) { + MeACL *meACL = (MeACL *) meACLObjectPre; + if (meACL) { + MeObject *obj = (MeObject *) env->GetLongField(thiz, g_ptr); + obj->setACL(meACL); + } +} + +jlong getACL(JNIEnv *env, jobject thiz, jlong meACLObjectPre) { + MeObject *obj = (MeObject *) env->GetLongField(thiz, g_ptr); + MeACL *meACL = new MeACL(obj->getACL()); + return (jlong) meACL; +} + +void putObject(JNIEnv *env, jobject jo, jstring jkey, jlong meObjectObjectPre) { + JSONObject *meObject = (JSONObject *) meObjectObjectPre; + if (meObject != NULL) { + const char *key = env->GetStringUTFChars(jkey, NULL); + JSONObject *obj = (JSONObject *) env->GetLongField(jo, g_ptr); + obj->put(key, meObject); + env->ReleaseStringUTFChars(jkey, key); + } +} + +jlongArray objectValue(JNIEnv *env, jobject jo, jstring jkey) { + if (jkey == NULL) { + return NULL; + } + const char *key = env->GetStringUTFChars(jkey, NULL); + MeObject *obj = (MeObject *) env->GetLongField(jo, g_ptr); + JSONArray array = obj->arrayValue(key); + //创建一个 MeObject 数组 + int size = array.size(); + jlongArray value = env->NewLongArray(size); + for (int i = 0; i < size; ++i) { + JSONObject object = array.jsonValue(i); + MeObject *childObject = new MeObject(); + childObject->copy(&object, false); + env->SetLongArrayRegion(value, i, 1, (const jlong *) &childObject); + delete childObject; + } + + env->ReleaseStringUTFChars(jkey, key); + return value;//返回数组指针 +} + +//JSONObject +jlong createJSONObject(JNIEnv *env, jobject thiz) { + setJSONObjectPtr(env, thiz); + return (jlong) new JSONObject(); +} + +jlong createJSONObjectWithText(JNIEnv *env, jobject thiz, jstring text) { + setJSONObjectPtr(env, thiz); + const char *content = env->GetStringUTFChars(text, NULL); + JSONObject *newObject = new JSONObject(content); + env->ReleaseStringUTFChars(text, content); + return (jlong) newObject; +} + +jboolean has(JNIEnv *env, jobject thiz, jstring jname) { + const char *name = env->GetStringUTFChars(jname, NULL); + JSONObject *obj = (JSONObject *) env->GetLongField(thiz, g_ptr); + env->ReleaseStringUTFChars(jname, name); + return (jboolean) (obj->has(name)); +} + +jbyteArray jsonByteArray(JNIEnv *env, jobject thiz) { + JSONObject *obj = (JSONObject *) env->GetLongField(thiz, g_ptr); + const char *string = obj->toString(); + int len = strlen(string); + jbyteArray byteArray = env->NewByteArray(len); + env->SetByteArrayRegion(byteArray, 0, len, reinterpret_cast(string)); + return byteArray; +} + +jbyteArray byteArrayValue(JNIEnv *env, jobject jo, jstring jkey) { + const char *key = env->GetStringUTFChars(jkey, NULL); + JSONObject *obj = (JSONObject *) env->GetLongField(jo, g_ptr); + const char *value = obj->stringValue(key); + int len = strlen(value); + jbyteArray byteArray = env->NewByteArray(len); + env->SetByteArrayRegion(byteArray, 0, len, reinterpret_cast(value)); + env->ReleaseStringUTFChars(jkey, key); + return byteArray; +} + +jdouble doubleValue(JNIEnv *env, jobject jo, jstring jkey) { + const char *key = env->GetStringUTFChars(jkey, NULL); + JSONObject *obj = (JSONObject *) env->GetLongField(jo, g_ptr); + const double value = obj->doubleValue(key); + env->ReleaseStringUTFChars(jkey, key); + return (jdouble) value; +} + +jint intValue(JNIEnv *env, jobject jo, jstring jkey) { + const char *key = env->GetStringUTFChars(jkey, NULL); + JSONObject *obj = (JSONObject *) env->GetLongField(jo, g_ptr); + const int value = obj->intValue(key); + env->ReleaseStringUTFChars(jkey, key); + return (jint) value; +} + +jlong longValue(JNIEnv *env, jobject jo, jstring jkey) { + const char *key = env->GetStringUTFChars(jkey, NULL); + JSONObject *obj = (JSONObject *) env->GetLongField(jo, g_ptr); + const long value = obj->longValue(key); + env->ReleaseStringUTFChars(jkey, key); + return (jlong) value; +} + +jfloat floatValue(JNIEnv *env, jobject jo, jstring jkey) { + const char *key = env->GetStringUTFChars(jkey, NULL); + JSONObject *obj = (JSONObject *) env->GetLongField(jo, g_ptr); + const float value = obj->floatValue(key); + env->ReleaseStringUTFChars(jkey, key); + return (jfloat) value; +} + +jboolean booleanValue(JNIEnv *env, jobject jo, jstring jkey) { + const char *key = env->GetStringUTFChars(jkey, NULL); + JSONObject *obj = (JSONObject *) env->GetLongField(jo, g_ptr); + const bool_t value = obj->boolValue(key); + env->ReleaseStringUTFChars(jkey, key); + return (jboolean) (value == BS_TRUE); +} + +jlong jsonValue(JNIEnv *env, jobject jo, jstring jkey) { + const char *key = env->GetStringUTFChars(jkey, NULL); + JSONObject *obj = (JSONObject *) env->GetLongField(jo, g_ptr); + JSONObject value = obj->jsonValue(key); + env->ReleaseStringUTFChars(jkey, key); + JSONObject *copyValue = new JSONObject(&value, false); + return (jlong) copyValue; +} + +jlongArray arrayValue(JNIEnv *env, jobject jo, jstring jkey) { + const char *key = env->GetStringUTFChars(jkey, NULL); + JSONObject *obj = (JSONObject *) env->GetLongField(jo, g_ptr); + JSONArray value = obj->arrayValue(key); + int size = value.size(); + jlongArray array = env->NewLongArray(size); + jlong longArray[size]; + for (int i = 0; i < size; ++i) { + JSONObject object = value.jsonValue(i); + JSONObject *objectPtr = new JSONObject(&object, false); + longArray[i] = (jlong)objectPtr; + } + env->SetLongArrayRegion(array, 0, size, longArray); + env->ReleaseStringUTFChars(jkey, key); + return array; +} + +jintArray intArrayValue(JNIEnv *env, jobject jo, jstring jkey) { + const char *key = env->GetStringUTFChars(jkey, NULL); + JSONObject *obj = (JSONObject *) env->GetLongField(jo, g_ptr); + JSONArray jsonArray = obj->arrayValue(key); + int size = jsonArray.size(); + jintArray array = env->NewIntArray(size); + jint intArray[size]; + for (int i = 0; i < size; ++i) { + int *value = jsonArray.intValue(i); + intArray[i]= (jint) *value; + } + env->SetIntArrayRegion(array, 0, size, intArray); + env->ReleaseStringUTFChars(jkey, key); + return array; +} + +jobjectArray stringByteArrayValue(JNIEnv *env, jobject jo, jstring jkey) { + const char *key = env->GetStringUTFChars(jkey, NULL); + JSONObject *obj = (JSONObject *) env->GetLongField(jo, g_ptr); + JSONArray jsonArray = obj->arrayValue(key); + int size = jsonArray.size(); + jobjectArray args = (env)->NewObjectArray(size, (env)->FindClass("java/lang/String"), 0); + for (int i = 0; i < size; ++i) { + const char *value = jsonArray.stringValue(i); + int len = strlen(value); + jbyteArray byteArray = env->NewByteArray(len); + env->SetByteArrayRegion(byteArray, 0, len, reinterpret_cast(value)); + (env)->SetObjectArrayElement(args, i, byteArray); + } + env->ReleaseStringUTFChars(jkey, key); + return args; +} + +void jputString(JNIEnv *env, jobject jo, jstring jkey, jbyteArray jvalue) { + const char *key = env->GetStringUTFChars(jkey, NULL); + jbyte *value = (jbyte *)env->GetByteArrayElements(jvalue, 0); + int len = env->GetArrayLength(jvalue); + char *string = new char[len + 1]; + memcpy(string, value, len); + string[len] = '\0'; + JSONObject *obj = (JSONObject *) env->GetLongField(jo, g_ptr); + obj->put(key, string); + env->ReleaseStringUTFChars(jkey, key); + delete string; + env->ReleaseByteArrayElements(jvalue, value, 0); +} + +void jputDouble(JNIEnv *env, jobject jo, jstring jkey, jdouble jvalue) { + const char *key = env->GetStringUTFChars(jkey, NULL); + JSONObject *obj = (JSONObject *) env->GetLongField(jo, g_ptr); + obj->put(key, jvalue); + env->ReleaseStringUTFChars(jkey, key); +} + +void jputInt(JNIEnv *env, jobject jo, jstring jkey, jint jvalue) { + const char *key = env->GetStringUTFChars(jkey, NULL); + JSONObject *obj = (JSONObject *) env->GetLongField(jo, g_ptr); + obj->put(key, jvalue); + env->ReleaseStringUTFChars(jkey, key); +} + +void jputLong(JNIEnv *env, jobject jo, jstring jkey, jlong jvalue) { + const char *key = env->GetStringUTFChars(jkey, NULL); + JSONObject *obj = (JSONObject *) env->GetLongField(jo, g_ptr); + obj->put(key, (long) jvalue); + env->ReleaseStringUTFChars(jkey, key); +} + +void jputFloat(JNIEnv *env, jobject jo, jstring jkey, jfloat jvalue) { + const char *key = env->GetStringUTFChars(jkey, NULL); + JSONObject *obj = (JSONObject *) env->GetLongField(jo, g_ptr); + obj->put(key, jvalue); + env->ReleaseStringUTFChars(jkey, key); +} + +void jputBoolean(JNIEnv *env, jobject jo, jstring jkey, jboolean jvalue) { + const char *key = env->GetStringUTFChars(jkey, NULL); + const bool value = jvalue; + JSONObject *obj = (JSONObject *) env->GetLongField(jo, g_ptr); + obj->put(key, value); + env->ReleaseStringUTFChars(jkey, key); +} + +void jputObject(JNIEnv *env, jobject jo, jstring jkey, + jlong meObjectObjectPre) { + MeObject *meObject = (MeObject *) meObjectObjectPre; + if (meObject != NULL) { + const char *key = env->GetStringUTFChars(jkey, NULL); + JSONObject *obj = (JSONObject *) env->GetLongField(jo, g_ptr); + obj->put(key, meObject); + env->ReleaseStringUTFChars(jkey, key); + } +} + +// MeQury +jlong createMeQuery(JNIEnv *env, jobject thiz) { + setJSONObjectPtr(env, thiz); + MeQuery *obj = new MeQuery(); + return (jlong) obj; +} + +jlong createMeQueryWithClassName(JNIEnv *env, jobject thiz, jstring jclassName) { + setJSONObjectPtr(env, thiz); + const char *className = env->GetStringUTFChars(jclassName, NULL); + MeQuery *obj = new MeQuery(className); + env->ReleaseStringUTFChars(jclassName, className); + return (jlong) obj; +} + +void whereEqualToString(JNIEnv *env, jobject thiz, jstring jkey, jbyteArray jvalue) { + const char *key = env->GetStringUTFChars(jkey, NULL); + jbyte *value = (jbyte *)env->GetByteArrayElements(jvalue, 0); + int len = env->GetArrayLength(jvalue); + char *string = new char[len + 1]; + memcpy(string, value, len); + string[len] = '\0'; + MeQuery *obj = (MeQuery *) env->GetLongField(thiz, g_ptr); + obj->whereEqualTo(key, string); + env->ReleaseStringUTFChars(jkey, key); + delete string; + env->ReleaseByteArrayElements(jvalue, value, 0); +} + +void whereNotEqualToString(JNIEnv *env, jobject thiz, jstring jkey, + jbyteArray jvalue) { + const char *key = env->GetStringUTFChars(jkey, NULL); + jbyte *value = (jbyte *)env->GetByteArrayElements(jvalue, 0); + int len = env->GetArrayLength(jvalue); + char *string = new char[len + 1]; + memcpy(string, value, len); + string[len] = '\0'; + MeQuery *obj = (MeQuery *) env->GetLongField(thiz, g_ptr); + obj->whereNotEqualTo(key, string); + env->ReleaseStringUTFChars(jkey, key); + delete string; + env->ReleaseByteArrayElements(jvalue, value, 0); +} + +void whereEqualToInt(JNIEnv *env, jobject thiz, jstring jkey, jint val) { + const char *key = env->GetStringUTFChars(jkey, NULL); + MeQuery *obj = (MeQuery *) env->GetLongField(thiz, g_ptr); + obj->whereEqualTo(key, val); + env->ReleaseStringUTFChars(jkey, key); +} + +void whereNotEqualToInt(JNIEnv *env, jobject thiz, jstring jkey, jint val) { + const char *key = env->GetStringUTFChars(jkey, NULL); + MeQuery *obj = (MeQuery *) env->GetLongField(thiz, g_ptr); + obj->whereNotEqualTo(key, val); + env->ReleaseStringUTFChars(jkey, key); +} + +void whereEqualOr(JNIEnv *env, jobject thiz, jstring jkey, jbyteArray jvalue) { + const char *key = env->GetStringUTFChars(jkey, NULL); + jbyte *value = (jbyte *)env->GetByteArrayElements(jvalue, 0); + int len = env->GetArrayLength(jvalue); + char *string = new char[len + 1]; + memcpy(string, value, len); + string[len] = '\0'; + MeQuery *query = (MeQuery *) env->GetLongField(thiz, g_ptr); + query->whereEqualOr(key, string); + env->ReleaseStringUTFChars(jkey, key); + delete string; + env->ReleaseByteArrayElements(jvalue, value, 0); +} + +void whereEqualOrToInt(JNIEnv *env, jobject thiz, jstring jkey, jint jvalue) { + const char *key = env->GetStringUTFChars(jkey, NULL); + MeQuery *query = (MeQuery *) env->GetLongField(thiz, g_ptr); + query->whereEqualOr(key, jvalue); + env->ReleaseStringUTFChars(jkey, key); +} + +void whereGreaterToString(JNIEnv *env, jobject thiz, jstring jkey, jbyteArray jvalue) { + const char *key = env->GetStringUTFChars(jkey, NULL); + jbyte *value = (jbyte *)env->GetByteArrayElements(jvalue, 0); + int len = env->GetArrayLength(jvalue); + char *string = new char[len + 1]; + memcpy(string, value, len); + string[len] = '\0'; + MeQuery *query = (MeQuery *) env->GetLongField(thiz, g_ptr); + query->whereGreater(key, string); + env->ReleaseStringUTFChars(jkey, key); + delete string; + env->ReleaseByteArrayElements(jvalue, value, 0); +} + +void whereGreaterToInt(JNIEnv *env, jobject thiz, jstring jkey, jint jvalue) { + const char *key = env->GetStringUTFChars(jkey, NULL); + MeQuery *query = (MeQuery *) env->GetLongField(thiz, g_ptr); + query->whereGreater(key, jvalue); + env->ReleaseStringUTFChars(jkey, key); +} + +void whereLessToString(JNIEnv *env, jobject thiz, jstring jkey, jbyteArray jvalue) { + const char *key = env->GetStringUTFChars(jkey, NULL); + jbyte *value = (jbyte *)env->GetByteArrayElements(jvalue, 0); + int len = env->GetArrayLength(jvalue); + char *string = new char[len + 1]; + memcpy(string, value, len); + string[len] = '\0'; + MeQuery *query = (MeQuery *) env->GetLongField(thiz, g_ptr); + query->whereLess(key, string); + env->ReleaseStringUTFChars(jkey, key); + delete string; + env->ReleaseByteArrayElements(jvalue, value, 0); +} + +void whereLessToInt(JNIEnv *env, jobject thiz, jstring jkey, jint jvalue) { + const char *key = env->GetStringUTFChars(jkey, NULL); + MeQuery *query = (MeQuery *) env->GetLongField(thiz, g_ptr); + query->whereLess(key, jvalue); + env->ReleaseStringUTFChars(jkey, key); +} + +void selectKeys(JNIEnv *env, jobject thiz, jobjectArray jkeys, jint num) { + const jsize size = env->GetArrayLength((jarray) jkeys); + const char **keys = (const char **) new char *[size]; + for (int i = 0; i < size; ++i) { + jstring tempString = (jstring) env->GetObjectArrayElement(jkeys, size); + const char *key = env->GetStringUTFChars(tempString, NULL); + keys[size] = key; + env->DeleteLocalRef(tempString); + env->ReleaseStringUTFChars(tempString, key); + } + MeQuery *obj = (MeQuery *) env->GetLongField(thiz, g_ptr); + obj->selectKeys(keys, num); +} + +void addSelectKey(JNIEnv *env, jobject thiz, jstring jkey) { + const char *key = env->GetStringUTFChars(jkey, NULL); + MeQuery *obj = (MeQuery *) env->GetLongField(thiz, g_ptr); + obj->addSelectKey(key); + env->ReleaseStringUTFChars(jkey, key); +} + +void addNotSelectKey(JNIEnv *env, jobject thiz, jstring jkey) { + const char *key = env->GetStringUTFChars(jkey, NULL); + MeQuery *obj = (MeQuery *) env->GetLongField(thiz, g_ptr); + obj->addNotSelectKey(key); + env->ReleaseStringUTFChars(jkey, key); +} + +void addAscendSortKeys(JNIEnv *env, jobject thiz, jstring jkey) { + const char *key = env->GetStringUTFChars(jkey, NULL); + MeQuery *obj = (MeQuery *) env->GetLongField(thiz, g_ptr); + obj->addAscendSortKeys(key); + env->ReleaseStringUTFChars(jkey, key); +} + +void addDescendSortKeys(JNIEnv *env, jobject thiz, jstring jkey) { + const char *key = env->GetStringUTFChars(jkey, NULL); + MeQuery *obj = (MeQuery *) env->GetLongField(thiz, g_ptr); + obj->addDescendSortKeys(key); + env->ReleaseStringUTFChars(jkey, key); +} + +void addLimit(JNIEnv *env, jobject thiz, jlong jcount) { + MeQuery *obj = (MeQuery *) env->GetLongField(thiz, g_ptr); + obj->addLimit(jcount); +} + +void addOffset(JNIEnv *env, jobject thiz, jstring startId) { + MeQuery *obj = (MeQuery *) env->GetLongField(thiz, g_ptr); + const char *id = env->GetStringUTFChars(startId, NULL); + obj->addStartId(id); + env->ReleaseStringUTFChars(startId, id); +} + +void addAggregateObject(JNIEnv *env, jobject thiz, jobject jaggregate) { + MeQuery *query = (MeQuery *) env->GetLongField(thiz, g_ptr); + MeAggregateObject *aggregate = (MeAggregateObject *)env->GetLongField(jaggregate, g_ptr); + query->addAggregateObject(aggregate); +} + +void setAggregateObject(JNIEnv *env, jobject thiz, jobject jaggregate) { + MeQuery *obj = (MeQuery *) env->GetLongField(thiz, g_ptr); + MeAggregateObject *aggregate = (MeAggregateObject *) env->GetLongField(jaggregate, g_ptr); + obj->setAggregateObject(aggregate); +} + + +//MeRole +jlong createMeRole(JNIEnv *env, jobject thiz, jstring jrolename) { + setJSONObjectPtr(env, thiz); + const char *roleName = env->GetStringUTFChars(jrolename, NULL); + MeRole *obj = new MeRole(roleName); + env->ReleaseStringUTFChars(jrolename, roleName); + return (jlong) obj; +} + +void setUserId(JNIEnv *env, jobject thiz, jstring juserid) { + const char *userid = env->GetStringUTFChars(juserid, NULL); + MeRole *obj = (MeRole *) env->GetLongField(thiz, g_ptr); + obj->setUser(userid); + env->ReleaseStringUTFChars(juserid, userid); +} + +void setUserObjects(JNIEnv *env, jobject thiz, jlong jmeUser) { + MeUser *meUser = (MeUser *) jmeUser; + if (meUser != NULL) { + MeRole *obj = (MeRole *) env->GetLongField(thiz, g_ptr); + obj->setUser(meUser); + } +} + +// MeFile +jlong createMeFile(JNIEnv *env, jobject thiz, jstring jclassName) { + setJSONObjectPtr(env, thiz); + const char *className = env->GetStringUTFChars(jclassName, NULL); + MeFile *obj = new MeFile(ME_HTTPFILE_Default, className); + env->ReleaseStringUTFChars(jclassName, className); + return (jlong)obj; +} + +jlong createMeFileWithObjectId(JNIEnv *env, jobject thiz, jstring jobjId, jstring jclassName) { + setJSONObjectPtr(env, thiz); + const char* objId = env->GetStringUTFChars(jobjId, NULL); + const char* classname = env->GetStringUTFChars(jclassName, NULL); + MeFile *file = new MeFile(objId, classname); + env->ReleaseStringUTFChars(jobjId, objId); + env->ReleaseStringUTFChars(jclassName, classname); + return (jlong) file; +} + +jstring filePath(JNIEnv *env, jobject thiz) { + MeFile *obj = (MeFile *) env->GetLongField(thiz, g_ptr); + return env->NewStringUTF(obj->filePath()); +} + +jstring imageUrl(JNIEnv *env, jobject thiz, jint width, jint height) { + MeFile *file = (MeFile *) env->GetLongField(thiz, g_ptr); + const char *url = file->imageUrl(width, height); + return env->NewStringUTF(url); + +} +jstring imageUrlNormal(JNIEnv *env, jobject thiz) { + MeFile *file = (MeFile *) env->GetLongField(thiz, g_ptr); + const char *url = file->imageUrl(); + return env->NewStringUTF(url); +} + +jstring imageCropUrl(JNIEnv *env, jobject thiz, jint x, jint y, jint width, jint height) { + MeFile *file = (MeFile *) env->GetLongField(thiz, g_ptr); + const char *url = file->imageCropUrl(x, y, width, height); + return env->NewStringUTF(url); +} + +// MeCloud +void initialize(JNIEnv *env, jobject thiz, jstring jappId, jstring jappKey) { + const char *appId = env->GetStringUTFChars(jappId, NULL); + const char *appKey = env->GetStringUTFChars(jappKey, NULL); + MeCloud::initialize(appId, appKey); + env->ReleaseStringUTFChars(jappId, appId); + env->ReleaseStringUTFChars(jappKey, appKey); + config(env, thiz); +} + +void config(JNIEnv *env, jobject thiz) { + global_mecloud_callback(env); +} + +jstring cookie(JNIEnv *env, jobject thiz) { + return env->NewStringUTF(MeCloud::shareInstance()->cookie()); +} + +void setBaseUrl(JNIEnv *env, jobject thiz, jstring jurl) { + MeCloud::shareInstance()->setBaseUrl(env->GetStringUTFChars(jurl, NULL)); +} + +void setTimeout(JNIEnv *env, jobject thiz, jint time) { + MeCloud::shareInstance()->setTimeout(time); +} + +void setShowLog(JNIEnv *env, jobject thiz, jboolean showLog) { + MeCloud::showLog(showLog); +} + +jbyteArray crypto(JNIEnv *env, jobject thiz, jbyteArray byteArray) { + jsize size = env->GetArrayLength(byteArray); + unsigned char *data = (unsigned char *) env->GetPrimitiveArrayCritical(byteArray, NULL); + unsigned char *cryptoData = MeCloud::shareInstance()->crypto(data, size); + env->ReleasePrimitiveArrayCritical(byteArray, data, NULL); + jbyteArray jarray = env->NewByteArray(size); + env->SetByteArrayRegion(jarray, 0, size, (jbyte *) cryptoData); + free(cryptoData); + return jarray; +} + +jbyteArray cryptoStringByte(JNIEnv *env, jobject thiz, jbyteArray byteArray) { + jsize size = env->GetArrayLength(byteArray); + char *data = (char *) env->GetPrimitiveArrayCritical(byteArray, NULL); + char *cryptoData = MeCloud::shareInstance()->crypto(data, size); + env->ReleasePrimitiveArrayCritical(byteArray, data, NULL); + jbyteArray jarray = env->NewByteArray(size); + env->SetByteArrayRegion(jarray, 0, size, (jbyte *) cryptoData); + free(cryptoData); + return jarray; +} + +jbyteArray decrypt(JNIEnv *env, jobject thiz, jbyteArray byteArray) { + jsize size = env->GetArrayLength(byteArray); + unsigned char *data = (unsigned char *) env->GetPrimitiveArrayCritical(byteArray, NULL); + unsigned char *decryptData = MeCloud::shareInstance()->decrypt(data, size); + env->ReleasePrimitiveArrayCritical(byteArray, data, NULL); + jbyteArray jarray = env->NewByteArray(size); + env->SetByteArrayRegion(jarray, 0, size, (jbyte *) decryptData); + free(decryptData); + return jarray; +} + +jbyteArray decryptStringByte(JNIEnv *env, jobject thiz, jbyteArray byteArray) { + jsize size = env->GetArrayLength(byteArray); + char *data = (char *) env->GetPrimitiveArrayCritical(byteArray, NULL); + char *decryptData = MeCloud::shareInstance()->decrypt(data, size); + env->ReleasePrimitiveArrayCritical(byteArray, data, NULL); + jbyteArray jarray = env->NewByteArray(size); + env->SetByteArrayRegion(jarray, 0, size, (jbyte *) decryptData); + free(decryptData); + return jarray; +} + +void addHttpHeader(JNIEnv *env, jobject thiz, jstring jkey, jstring jvalue) { + const char *key = env->GetStringUTFChars(jkey, NULL); + const char *value = env->GetStringUTFChars(jvalue, NULL); + MeCloud::shareInstance()->addHttpHeader(key, value); + env->ReleaseStringUTFChars(jkey, key); + env->ReleaseStringUTFChars(jvalue, value); +} + +void login(JNIEnv *env, jobject thiz, jstring jusername, jstring jpassword, jobject jcallback) { + const char *username = env->GetStringUTFChars(jusername, NULL); + const char *password = env->GetStringUTFChars(jpassword, NULL); + jobject global_thiz = env->NewGlobalRef(thiz); + jobject global_callback = env->NewGlobalRef(jcallback); + MeUser *user = new MeUser(); + MeObjectCallback *callback = new MeUserCallback(user); + callback->setPara(global_thiz, global_callback); + callback->lock(); + user->login(username, password, callback); + env->ReleaseStringUTFChars(jusername, username); + env->ReleaseStringUTFChars(jpassword, password); +} + +void signUp(JNIEnv *env, jobject thiz, jstring jusername, jstring jpassword, jobject jcallback) { + const char *username = env->GetStringUTFChars(jusername, NULL); + const char *password = env->GetStringUTFChars(jpassword, NULL); + jobject global_thiz = env->NewGlobalRef(thiz); + jobject global_callback = env->NewGlobalRef(jcallback); + MeUser *user = new MeUser(); + MeUserCallback *callback = new MeUserCallback(user); + callback->setPara(global_thiz, global_callback); + callback->lock(); + user->signup(username, password, callback); + env->ReleaseStringUTFChars(jusername, username); + env->ReleaseStringUTFChars(jpassword, password); +} + +void changePassword(JNIEnv *env, jobject thiz, jstring jusername, jstring jnewpassword, + jobject jcallback) { + const char *username = env->GetStringUTFChars(jusername, NULL); + const char *newpassword = env->GetStringUTFChars(jnewpassword, NULL); + jobject global_thiz = env->NewGlobalRef(thiz); + jobject global_callback = env->NewGlobalRef(jcallback); + MeUser *user = new MeUser(); + MeObjectCallback *callback = new MeUserCallback(user); + callback->setPara(global_thiz, global_callback); + callback->lock(); + user->changePassword(username, newpassword, callback); + env->ReleaseStringUTFChars(jusername, username); + env->ReleaseStringUTFChars(jnewpassword, newpassword); +} + +void save(JNIEnv *env, jobject thiz, jobject object, jobject jcallback) { + //传入的object组要做全局引用,否则函数返回后会被释放 + jobject global_thiz = env->NewGlobalRef(thiz); + jobject global_callback = env->NewGlobalRef(jcallback); + MeObject *obj = (MeObject *) env->GetLongField(object, g_ptr); + MeObjectCallback *callback = new MeObjectCallback(global_thiz, global_callback); + callback->setIsMeListCallback(BS_FALSE); + callback->lock(); + obj->save(callback); +} + +void getObjectWithID(JNIEnv *env, jobject thiz, jstring jobjectId, jstring jclassName, jobject jcallback) { + jobject global_thiz = env->NewGlobalRef(thiz); + jobject global_callback = env->NewGlobalRef(jcallback); + MeObjectCallback *callback = new MeObjectCallback(global_thiz, global_callback); + callback->setIsMeListCallback(BS_FALSE); + const char *objectId = env->GetStringUTFChars(jobjectId, NULL); + const char *className = env->GetStringUTFChars(jclassName, NULL); + MeQuery *query = new MeQuery(className); + query->get(objectId, callback); + env->ReleaseStringUTFChars(jobjectId, objectId); + env->ReleaseStringUTFChars(jclassName, className); +} + +void getObjectsWithQuery(JNIEnv *env, jobject thiz, jobject object, jobject jcallback) { + jobject global_thiz = env->NewGlobalRef(thiz); + jobject global_callback = env->NewGlobalRef(jcallback); + MeObjectCallback *callback = new MeObjectCallback(global_thiz, global_callback); + callback->setIsMeListCallback(BS_TRUE); + MeQuery *obj = (MeQuery *) env->GetLongField(object, g_ptr); + obj->find(callback); +} + +void findWithJoin(JNIEnv *env, jobject thiz, jobject object, jobject jcallBack) { + jobject global_thiz = env->NewGlobalRef(thiz); + jobject global_callback = env->NewGlobalRef(jcallBack); + MeObjectCallback *callback = new MeObjectCallback(global_thiz, + global_callback); + callback->setIsMeListCallback(BS_TRUE); + MeJoinQuery *obj = (MeJoinQuery *) env->GetLongField(object, g_ptr); + obj->find(callback); +} + +void deleteObject(JNIEnv *env, jobject thiz, jobject object, jobject jcallback) { + jobject global_thiz = env->NewGlobalRef(thiz); + jobject global_callback = env->NewGlobalRef(jcallback); + MeObject *obj = (MeObject *) env->GetLongField(object, g_ptr); + MeObjectCallback *callback = new MeObjectCallback(global_thiz, global_callback); + callback->lock(); + obj->deleteObject(callback); +} + +jstring download(JNIEnv *env, jobject thiz, jstring name, jstring jurl, jobject jcallback) { + MeDownloadFile *file = new MeDownloadFile(); + + const char *url = env->GetStringUTFChars(jurl, NULL); + const char *fileName = env->GetStringUTFChars(name, NULL); + file->setFilename(fileName); + file->setDownloadUrl(url); + + jobject global_thiz = env->NewGlobalRef(thiz); + jobject global_callback = env->NewGlobalRef(jcallback); + + MeAndroidHttpFileCallBack *callback = new MeAndroidHttpFileCallBack( + file->className(), file); + callback->lock(); + callback->setPara(global_thiz, global_callback); + file->download(callback); + env->ReleaseStringUTFChars(name, fileName); + env->ReleaseStringUTFChars(jurl, url); + return env->NewStringUTF(file->filePath()); +} + + +void uploadFile(JNIEnv *env, jobject thiz, jstring type, jstring jpath, jobject jcallback) { + const char *path = env->GetStringUTFChars(jpath, NULL); + const char *typeName = env->GetStringUTFChars(type, NULL); + + MeUploadFile *file = new MeUploadFile(); + file->setUploadFilePath(path); + file->put("type", typeName); + + jobject global_thiz = env->NewGlobalRef(thiz); + jobject global_callback = env->NewGlobalRef(jcallback); + GetAuthInfomationCallback *callback = new GetAuthInfomationCallback( + "File", file, global_thiz, global_callback); + callback->lock(); + file->getAuthInfomation(callback); + env->ReleaseStringUTFChars(jpath, path); + env->ReleaseStringUTFChars(type, typeName); +} + +void uploadData(JNIEnv *env, jobject thiz, jstring jtype, jbyteArray jdata, jobject jcallback) { + jobject global_thiz = env->NewGlobalRef(thiz); + jobject global_callback = env->NewGlobalRef(jcallback); + const char *type = env->GetStringUTFChars(jtype, NULL); + unsigned char *data = (unsigned char *) env->GetPrimitiveArrayCritical(jdata, NULL); + jsize size = env->GetArrayLength(jdata); + MeUploadFile *file = new MeUploadFile(); + file->setUploadData(data, size); + file->put("type", type); + GetAuthInfomationCallback *callback = new GetAuthInfomationCallback( + "File", file, global_thiz, global_callback); + callback->lock(); + file->getAuthInfomation(callback); + env->ReleasePrimitiveArrayCritical(jdata, data, NULL); + env->ReleaseStringUTFChars(jtype, type); +} + +void postData(JNIEnv *env, jobject thiz, jstring jurl, jbyteArray jData, jobject jcallBack) { + jsize size = env->GetArrayLength(jData); + const char *url = env->GetStringUTFChars(jurl, NULL); + jobject global_thiz = env->NewGlobalRef(thiz); + jobject global_callback = env->NewGlobalRef(jcallBack); + MeObject *obj = new MeObject(); + MeAndroidHttpDataCallBack *callback = new MeAndroidHttpDataCallBack( + obj->className(), obj); + callback->lock(); + callback->setPara(global_thiz, global_callback); + unsigned char *data = (unsigned char *) env->GetPrimitiveArrayCritical(jData, NULL); + MeCloud::shareInstance()->postData(url, data, size, callback); + env->ReleasePrimitiveArrayCritical(jData, data, NULL); + env->ReleaseStringUTFChars(jurl, url); +} + +void saveWithUrl(JNIEnv *env, jobject thiz, jstring jurl, jobject object, jobject jcallback) { + const char *url = env->GetStringUTFChars(jurl, NULL); + const char *param = ""; + if (object) { + JSONObject *obj = (JSONObject *) env->GetLongField(object, g_ptr); + param = obj->toString(); + } + + jobject g_callback = env->NewGlobalRef(jcallback); + jobject g_thiz = env->NewGlobalRef(thiz); + MeObjectCallback *meObjectCallback = new MeObjectCallback(g_thiz, g_callback); + meObjectCallback->setIsMeListCallback(BS_FALSE); + global_exception(env); + MeCloud::shareInstance()->post(url, param, meObjectCallback); + env->ReleaseStringUTFChars(jurl, url); +} + +void getWithUrl(JNIEnv *env, jobject thiz, jstring jurl, jobject object, jobject jcallback) { + const char *url = env->GetStringUTFChars(jurl, NULL); + map param; + if (object) { + JSONObject *obj = (JSONObject *) env->GetLongField(object, g_ptr); + param = obj->stringdict(); + } + jobject g_callback = env->NewGlobalRef(jcallback); + jobject g_thiz = env->NewGlobalRef(thiz); + MeObjectCallback *meObjectCallback = new MeObjectCallback(g_thiz, g_callback); + meObjectCallback->setIsMeListCallback(BS_FALSE); + meObjectCallback->setIsMeListCallback(BS_FALSE); + global_exception(env); + MeCloud::shareInstance()->get(url, param, meObjectCallback); + env->ReleaseStringUTFChars(jurl, url); +} + +//MeUser +jlong createUser(JNIEnv *env, jobject thiz) { + setJSONObjectPtr(env, thiz); + MeUser *user = new MeUser(); + return (jlong)user; +} + +jlong createUserWithJSONObject(JNIEnv *env, jobject thiz, jlong jsonPtr) { + setJSONObjectPtr(env, thiz); + JSONObject *object = (JSONObject *)jsonPtr; + MeUser *user = new MeUser(object); + return (jlong) user; +} + +jlong currentUser(JNIEnv *env, jobject thiz) { + return (jlong) MeUser::currentUser(); +} + +void logout(JNIEnv *env, jobject thiz) { + MeUser::currentUser()->logout(); +} + +void saveLoginUser(JNIEnv *env, jobject thiz, jlong userPtr) { + MeObject *obj = (MeObject *) userPtr; + MeUser::saveLoginUser(obj); +} + +jstring encodePassword(JNIEnv *env, jobject thiz, jstring jusername, jstring jpassword) { + const char *username = env->GetStringUTFChars(jusername, NULL); + const char *password = env->GetStringUTFChars(jpassword, NULL); + const char *newPassword = MeUser::encodePassword(username, password); + jstring newJpassword = env->NewStringUTF(newPassword); + delete newPassword; + env->ReleaseStringUTFChars(jusername, username); + env->ReleaseStringUTFChars(jpassword, password); + return newJpassword; +} + +jstring device(JNIEnv *env, jobject thiz) { + return env->NewStringUTF(MeUser::device()); +} + +// MeACL +void setPublicReadAccess(JNIEnv *env, jobject thiz) { + MeACL *obj = (MeACL *) env->GetLongField(thiz, g_ptr); + obj->setPublicReadAccess(); +} + +void setPublicWriteAccess(JNIEnv *env, jobject thiz) { + MeACL *obj = (MeACL *) env->GetLongField(thiz, g_ptr); + obj->setPublicWriteAccess(); +} + +void setRoleReadAccess(JNIEnv *env, jobject thiz, jstring jrole) { + const char *role = env->GetStringUTFChars(jrole, NULL); + MeACL *obj = (MeACL *) env->GetLongField(thiz, g_ptr); + obj->setRoleReadAccess(role); + env->ReleaseStringUTFChars(jrole, role); +} + +void setRoleWriteAccess(JNIEnv *env, jobject thiz, jstring jrole) { + const char *role = env->GetStringUTFChars(jrole, NULL); + MeACL *obj = (MeACL *) env->GetLongField(thiz, g_ptr); + obj->setRoleWriteAccess(role); + env->ReleaseStringUTFChars(jrole, role); +} + +void setRoleReadAccessMeRole(JNIEnv *env, jobject thiz, jlong objectPre) { + MeACL *obj = (MeACL *) env->GetLongField(thiz, g_ptr); + MeRole *role = (MeRole *) objectPre; + obj->setRoleReadAccess(role); +} + +void setRoleWriteAccessMeRole(JNIEnv *env, jobject thiz, jlong objectPre) { + MeACL *obj = (MeACL *) env->GetLongField(thiz, g_ptr); + MeRole *role = (MeRole *) objectPre; + obj->setRoleWriteAccess(role); +} + +void setUserReadAccess(JNIEnv *env, jobject thiz, jstring juserId) { + const char *userid = env->GetStringUTFChars(juserId, NULL); + MeACL *obj = (MeACL *) env->GetLongField(thiz, g_ptr); + obj->setUserReadAccess(userid); + env->ReleaseStringUTFChars(juserId, userid); +} + +void setUserWriteAccess(JNIEnv *env, jobject thiz, jstring juserId) { + const char *userid = env->GetStringUTFChars(juserId, NULL); + MeACL *obj = (MeACL *) env->GetLongField(thiz, g_ptr); + obj->setUserWriteAccess(userid); + env->ReleaseStringUTFChars(juserId, userid); +} + +void setUserReadAccessMeUser(JNIEnv *env, jobject thiz, jlong objectPre) { + MeACL *obj = (MeACL *) env->GetLongField(thiz, g_ptr); + MeUser *role = (MeUser *) objectPre; + obj->setUserReadAccess(role); +} + +void setUserWriteAccessMeUser(JNIEnv *env, jobject thiz, jlong objectPre) { + MeACL *obj = (MeACL *) env->GetLongField(thiz, g_ptr); + MeUser *role = (MeUser *) objectPre; + obj->setUserReadAccess(role); +} + +//MeJoinQuery +jlong createMeJoinQuery(JNIEnv *env, jobject thiz, jstring jclassName, jboolean jnestQuery) { + setJSONObjectPtr(env, thiz); + const char *className = env->GetStringUTFChars(jclassName, NULL); + MeJoinQuery *obj = new MeJoinQuery(className, jnestQuery); + env->ReleaseStringUTFChars(jclassName, className); + return (jlong) obj; +} + +void addSelectKeyWithJoin(JNIEnv *env, jobject thiz, jstring jkey) { + const char *key = env->GetStringUTFChars(jkey, NULL); + MeJoinQuery *obj = (MeJoinQuery *) env->GetLongField(thiz, g_ptr); + obj->addSelectKey(key); + env->ReleaseStringUTFChars(jkey, key); +} + + +void addNotSelectKeyWithJoin(JNIEnv *env, jobject thiz, jstring jkey) { + const char *key = env->GetStringUTFChars(jkey, NULL); + MeJoinQuery *obj = (MeJoinQuery *) env->GetLongField(thiz, g_ptr); + obj->addNotSelectKey(key); + env->ReleaseStringUTFChars(jkey, key); +} + +void addAscendWithJoin(JNIEnv *env, jobject thiz, jstring jkey) { + const char *key = env->GetStringUTFChars(jkey, NULL); + MeJoinQuery *obj = (MeJoinQuery *) env->GetLongField(thiz, g_ptr); + obj->addNotSelectKey(key); + env->ReleaseStringUTFChars(jkey, key); +} + +void addDescendWithJoin(JNIEnv *env, jobject thiz, jstring jkey) { + const char *key = env->GetStringUTFChars(jkey, NULL); + MeJoinQuery *obj = (MeJoinQuery *) env->GetLongField(thiz, g_ptr); + obj->addDescend(key); + env->ReleaseStringUTFChars(jkey, key); +} + +void matchEqualTo(JNIEnv *env, jobject thiz, jstring jkey, jbyteArray jvalue) { + const char *key = env->GetStringUTFChars(jkey, NULL); + jbyte *value = (jbyte *)env->GetByteArrayElements(jvalue, 0); + int len = env->GetArrayLength(jvalue); + char *string = new char[len + 1]; + memcpy(string, value, len); + string[len] = '\0'; + MeJoinQuery *obj = (MeJoinQuery *) env->GetLongField(thiz, g_ptr); + obj->matchEqualTo(key, string); + env->ReleaseStringUTFChars(jkey, key); + delete string; + env->ReleaseByteArrayElements(jvalue, value, 0); +} + +void matchEqualToInt(JNIEnv *env, jobject thiz, jstring jkey, jint value) { + const char *key = env->GetStringUTFChars(jkey, NULL); + MeJoinQuery *obj = (MeJoinQuery *) env->GetLongField(thiz, g_ptr); + obj->matchEqualTo(key, value); + env->ReleaseStringUTFChars(jkey, key); +} + +void matchGreater(JNIEnv *env, jobject thiz, jstring jkey, jbyteArray jvalue) { + const char *key = env->GetStringUTFChars(jkey, NULL); + jbyte *value = (jbyte *)env->GetByteArrayElements(jvalue, 0); + int len = env->GetArrayLength(jvalue); + char *string = new char[len + 1]; + memcpy(string, value, len); + string[len] = '\0'; + MeJoinQuery *obj = (MeJoinQuery *) env->GetLongField(thiz, g_ptr); + obj->matchGreater(key, string); + env->ReleaseStringUTFChars(jkey, key); + delete string; + env->ReleaseByteArrayElements(jvalue, value, 0); +} + +void matchGreaterToInt(JNIEnv *env, jobject thiz, jstring jkey, jint value) { + const char *key = env->GetStringUTFChars(jkey, NULL); + MeJoinQuery *obj = (MeJoinQuery *) env->GetLongField(thiz, g_ptr); + obj->matchGreater(key, value); + env->ReleaseStringUTFChars(jkey, key); +} + +void matchLess(JNIEnv *env, jobject thiz, jstring jkey, jbyteArray jvalue) { + const char *key = env->GetStringUTFChars(jkey, NULL); + jbyte *value = (jbyte *)env->GetByteArrayElements(jvalue, 0); + int len = env->GetArrayLength(jvalue); + char *string = new char[len + 1]; + memcpy(string, value, len); + string[len] = '\0'; + MeJoinQuery *obj = (MeJoinQuery *) env->GetLongField(thiz, g_ptr); + obj->matchLess(key, string); + env->ReleaseStringUTFChars(jkey, key); + delete string; + env->ReleaseByteArrayElements(jvalue, value, 0); +} + +void matchLessToInt(JNIEnv *env, jobject thiz, jstring jkey, jint value) { + const char *key = env->GetStringUTFChars(jkey, NULL); + MeJoinQuery *obj = (MeJoinQuery *) env->GetLongField(thiz, g_ptr); + obj->matchLess(key, value); + env->ReleaseStringUTFChars(jkey, key); +} + +void addForeignTable(JNIEnv *env, jobject thiz, jstring jfromTable, jstring jforeignKey, + jstring jlocalKey, jstring jdocument) { + const char *fromTable = env->GetStringUTFChars(jfromTable, NULL); + const char *foreignKey = env->GetStringUTFChars(jforeignKey, NULL); + const char *localKey = env->GetStringUTFChars(jlocalKey, NULL); + const char *document = env->GetStringUTFChars(jdocument, NULL); + MeJoinQuery *obj = (MeJoinQuery *) env->GetLongField(thiz, g_ptr); + obj->addForeignTable(fromTable, foreignKey, localKey, document); + env->ReleaseStringUTFChars(jfromTable, fromTable); + env->ReleaseStringUTFChars(jforeignKey, foreignKey); + env->ReleaseStringUTFChars(jlocalKey, localKey); + env->ReleaseStringUTFChars(jdocument, document); +} + +void addMeJoinQueryPtr(JNIEnv *env, jobject thiz, jlong joinQuery) { + MeJoinQuery *query = (MeJoinQuery *) joinQuery; + if (joinQuery != NULL) { + MeJoinQuery *obj = (MeJoinQuery *) env->GetLongField(thiz, g_ptr); + obj->addMeJoinQuery(query); + } +} + +void addLimitWithJoin(JNIEnv *env, jobject thiz, jint count) { + MeJoinQuery *obj = (MeJoinQuery *) env->GetLongField(thiz, g_ptr); + obj->addLimit(count); +} + +//MeAggregateObject +jlong createMeAggregateObject(JNIEnv *env, jobject thiz, jstring jclassName) { + setJSONObjectPtr(env, thiz); + const char *className = env->GetStringUTFChars(jclassName, NULL); + MeAggregateObject *obj = new MeAggregateObject(className); + env->ReleaseStringUTFChars(jclassName, className); + return (jlong) obj; +} + +void whereEqualToWithAggregate(JNIEnv *env, jobject thiz, jstring jkey, jbyteArray jvalue) { + const char *key = env->GetStringUTFChars(jkey, NULL); + jbyte *value = (jbyte *)env->GetByteArrayElements(jvalue, 0); + int len = env->GetArrayLength(jvalue); + char *string = new char[len + 1]; + memcpy(string, value, len); + string[len] = '\0'; + MeAggregateObject *obj = (MeAggregateObject *) env->GetLongField(thiz, g_ptr); + obj->whereEqualTo(key, string); + env->ReleaseStringUTFChars(jkey, key); +} + +void whereEqualToIntWithAggregate(JNIEnv *env, jobject thiz, jstring jkey, jint jvalue) { + const char *key = env->GetStringUTFChars(jkey, NULL); + MeAggregateObject *obj = (MeAggregateObject *) env->GetLongField(thiz, g_ptr); + obj->whereEqualTo(key, jvalue); + env->ReleaseStringUTFChars(jkey, key); +} + +void whereNotEqualToWithAggregate(JNIEnv *env, jobject thiz, jstring jkey, jbyteArray jvalue) { + const char *key = env->GetStringUTFChars(jkey, NULL); + jbyte *value = (jbyte *)env->GetByteArrayElements(jvalue, 0); + int len = env->GetArrayLength(jvalue); + char *string = new char[len + 1]; + memcpy(string, value, len); + string[len] = '\0'; + MeAggregateObject *obj = (MeAggregateObject *) env->GetLongField(thiz, g_ptr); + obj->whereNotEqualTo(key, string); + env->ReleaseStringUTFChars(jkey, key); + delete string; + env->ReleaseByteArrayElements(jvalue, value, 0); +} + +void whereNotEqualToIntWithAggregate(JNIEnv *env, jobject thiz, jstring jkey, jint jvalue) { + const char *key = env->GetStringUTFChars(jkey, NULL); + MeAggregateObject *obj = (MeAggregateObject *) env->GetLongField(thiz, g_ptr); + obj->whereNotEqualTo(key, jvalue); + env->ReleaseStringUTFChars(jkey, key); +} + +void whereGreaterWithAggregate(JNIEnv *env, jobject thiz, jstring jkey, jbyteArray jvalue) { + const char *key = env->GetStringUTFChars(jkey, NULL); + jbyte *value = (jbyte *)env->GetByteArrayElements(jvalue, 0); + int len = env->GetArrayLength(jvalue); + char *string = new char[len + 1]; + memcpy(string, value, len); + string[len] = '\0'; + MeAggregateObject *obj = (MeAggregateObject *) env->GetLongField(thiz, g_ptr); + obj->whereGreater(key, string); + env->ReleaseStringUTFChars(jkey, key); + delete string; + env->ReleaseByteArrayElements(jvalue, value, 0); +} + +void whereGreaterIntWithAggregate(JNIEnv *env, jobject thiz, jstring jkey, jint jvalue) { + const char *key = env->GetStringUTFChars(jkey, NULL); + MeAggregateObject *obj = (MeAggregateObject *) env->GetLongField(thiz, g_ptr); + obj->whereGreater(key, jvalue); + env->ReleaseStringUTFChars(jkey, key); +} + +void whereLessWithAggregate(JNIEnv *env, jobject thiz, jstring jkey, jbyteArray jvalue) { + const char *key = env->GetStringUTFChars(jkey, NULL); + jbyte *value = (jbyte *)env->GetByteArrayElements(jvalue, 0); + int len = env->GetArrayLength(jvalue); + char *string = new char[len + 1]; + memcpy(string, value, len); + string[len] = '\0'; + MeAggregateObject *obj = (MeAggregateObject *) env->GetLongField(thiz, g_ptr); + obj->whereLess(key, string); + env->ReleaseStringUTFChars(jkey, key); + delete string; + env->ReleaseByteArrayElements(jvalue, value, 0); +} + +void whereLessIntWithAggregate(JNIEnv *env, jobject thiz, jstring jkey, jint jvalue) { + const char *key = env->GetStringUTFChars(jkey, NULL); + MeAggregateObject *obj = (MeAggregateObject *) env->GetLongField(thiz, g_ptr); + obj->whereLess(key, jvalue); + env->ReleaseStringUTFChars(jkey, key); +} + +void setResponseKey(JNIEnv *env, jobject thiz, jstring jkey) { + const char *key = env->GetStringUTFChars(jkey, NULL); + MeAggregateObject *obj = (MeAggregateObject *) env->GetLongField(thiz, g_ptr); + obj->setResponseKey(key); +} + +void setDistinctKey(JNIEnv *env, jobject thiz, jstring jkey) { + const char *key = env->GetStringUTFChars(jkey, NULL); + MeAggregateObject *obj = (MeAggregateObject *) env->GetLongField(thiz, g_ptr); + obj->setDistinctKey(key); +} + +void setMethod(JNIEnv *env, jobject thiz, jint method) { + MeAggregateObject *obj = (MeAggregateObject *) env->GetLongField(thiz, g_ptr); + obj->setMethod((MEAGGREGATEMETHOD) method); +} + +void setDevice(JNIEnv *env, jobject thiz, jobject jcontext) { + mc::mc_set_device(env,thiz,jcontext); +} + +void saveJSONToCache(JNIEnv *env, jobject thiz, jlong objectPre, jstring jkey) { + const char *key = env->GetStringUTFChars(jkey, NULL); + JSONObject *obj = (JSONObject *) objectPre; + JSONObject *newObject = new JSONObject(obj, false); + MeCloud::shareInstance()->saveJSONToCache(newObject, key); +} + +jlong getJSONFromCache(JNIEnv *env, jobject thiz, jstring jkey) { + const char *key = env->GetStringUTFChars(jkey, NULL); + JSONObject *object = MeCloud::shareInstance()->getJSONFromCache(key); + env->ReleaseStringUTFChars(jkey, key); + return (jlong) object; +} + +void removeJSONFromCache(JNIEnv *env, jobject thiz, jstring jkey) { + const char *key = env->GetStringUTFChars(jkey, NULL); + MeCloud::shareInstance()->removeJSONFromCache(key); +} \ No newline at end of file diff --git a/src/ios/MeCrypt.h b/src/ios/MeCrypt.h new file mode 100644 index 0000000..238ea03 --- /dev/null +++ b/src/ios/MeCrypt.h @@ -0,0 +1,21 @@ +// +// MeCrypt.h +// MeCloud +// +// Created by super on 2017/9/11. +// Copyright © 2017年 Rex. All rights reserved. +// + +#import + +@interface MeCrypt : NSObject + ++ (NSData *)encodeWithData:(NSData *)data; + ++ (NSData *)decodeWithBytes:(NSData *)data; + ++ (NSString *)encodeWithString:(NSString *)string; + ++ (NSString *)decodeWithString:(NSString *)string; + +@end diff --git a/src/ios/MeCrypt.mm b/src/ios/MeCrypt.mm new file mode 100644 index 0000000..952e0fb --- /dev/null +++ b/src/ios/MeCrypt.mm @@ -0,0 +1,60 @@ +// +// MeCrypt.m +// MeCloud +// +// Created by super on 2017/9/11. +// Copyright © 2017年 Rex. All rights reserved. +// + +#import "MeCrypt.h" +#import "MeCloud.h" + +@implementation MeCrypt + ++ (NSData *)encodeWithData:(NSData *)data { + Byte *bytes = (Byte *)malloc([data length]); + [data getBytes:bytes length:[data length]]; + + Byte *cryptoBytes = MeCloud::shareInstance()->crypto(bytes, (int)[data length]); + + NSData *cryptoData = [[NSData alloc] initWithBytes:cryptoBytes length:data.length]; + free(cryptoBytes); + free(bytes); + return cryptoData; +} + ++ (NSData *)decodeWithBytes:(NSData *)data { + Byte *bytes = (Byte *)malloc([data length]); + [data getBytes:bytes length:[data length]]; + + Byte *decodeBytes = MeCloud::shareInstance()->decrypt(bytes, (int)data.length); + NSData *decodeByteData = [[NSData alloc] initWithBytes:decodeBytes length:data.length]; + + free(bytes); + free(decodeBytes); + return decodeByteData; +} + ++ (NSString *)encodeWithString:(NSString *)string { + if (!string || string.length <= 0) { + return @""; + } + + char *encode = MeCloud::shareInstance()->crypto([string UTF8String], string.length); + NSString *encodeString = [NSString stringWithUTF8String:encode]; + free(encode); + return encodeString; +} + ++ (NSString *)decodeWithString:(NSString *)string { + if (!string || string.length <= 0) { + return @""; + } + + char *decode = MeCloud::shareInstance()->decrypt([string UTF8String], string.length); + NSString *encodeString = [NSString stringWithUTF8String:decode]; + free(decode); + return encodeString; +} + +@end diff --git a/src/ios/MeDownloadFile.mm b/src/ios/MeDownloadFile.mm new file mode 100644 index 0000000..204f4b5 --- /dev/null +++ b/src/ios/MeDownloadFile.mm @@ -0,0 +1,19 @@ +// +// MeDownloadFile.m +// MeCloud +// +// Created by super on 2017/7/31. +// Copyright © 2017年 Rex. All rights reserved. +// + +#import +#import "MeDownloadFile.h" +#import "MeDownloadFile.h" + +void MeDownloadFile::download(MeHttpFileCallbackBlock block, MeHttpFileProgressBlock progressBlock) { + MeIOSHttpFileCallback *callback = new MeIOSHttpFileCallback(m_classname, this); + callback->setBlock(block); + callback->setProgressBlock(progressBlock); + + MeDownloadFile::download(callback); +} diff --git a/src/ios/MeHeader.h b/src/ios/MeHeader.h new file mode 100644 index 0000000..f3134a1 --- /dev/null +++ b/src/ios/MeHeader.h @@ -0,0 +1,24 @@ +// +// Header.h +// MeCloud +// +// Created by super on 2017/9/5. +// Copyright © 2017年 Rex. All rights reserved. +// + +#ifndef Header_h +#define Header_h + +#include "MeIOSObject.h" +#include "MeIOSException.h" +#include "MeIOSJSONObject.h" +#include "MeIOSNetManager.h" +#include "MeIOSRole.h" +#include "MeIOSACL.h" +#include "MeIOSUser.h" +#include "MeCrypt.h" +#include "MeIOSFile.h" +#include "MeIOSQuery.h" +#include "MeIOSJoinQuery.h" + +#endif /* Header_h */ diff --git a/src/ios/MeIOSACL.h b/src/ios/MeIOSACL.h new file mode 100644 index 0000000..516b84a --- /dev/null +++ b/src/ios/MeIOSACL.h @@ -0,0 +1,61 @@ +// +// MeIOSACL.h +// MeCloud +// +// Created by super on 2017/8/10. +// Copyright © 2017年 Rex. All rights reserved. +// + +#import +#import "MeIOSJSONObject.h" + +@class MeIOSUser; +@class MeIOSRole; + +@interface MeIOSACL : MeIOSJSONObject + +- (id)initWithACL:(void *)acl; + +// 设置公开读权限,所有人都可以读 +- (void)setPublicReadAccess; + +// 设置公开写权限,所有人都可以写 +- (void)setPublicWriteAccess; + +// 设置该role角色可以读,param为role name +- (void)setRoleReadAccessWithName:(NSString *)role; + +// 设置该role角色可以写,param为role name +- (void)setRoleWriteAccessWithName:(NSString *)role; + +// 设置该role数据可删除,注意(这数据得要服务器数据表支持删除功能) +- (void)setRoleDeleteAccessWithName:(NSString *)role; + +// 设置该role角色可以读,param为MeIOSRole object +- (void)setRoleReadAccessWithRole:(MeIOSRole *)role; + +// 设置该role角色可以写,param为MeIOSRole object +- (void)setRoleWriteAccessWithRole:(MeIOSRole *)role; + +// 设置该role数据可删除,注意(这数据得要服务器数据表支持删除功能) +- (void)setRoleDeleteAccessWithRole:(MeIOSRole *)role; + +// 设置该user可以读,param为userId +- (void)setUserReadAccessWithId:(NSString *)userId; + +// 设置该user可以写,param为userId +- (void)setUserWriteAccessWithId:(NSString *)userId; + +// 设置该user数据可删除,注意(这数据得要服务器数据表支持删除功能) +- (void)setUserDeleteAccessWithId:(NSString *)userId; + +// 设置该user可以写,param为MeIOSUser object +- (void)setUserReadAccessWithUser:(MeIOSUser *)user; + +// 设置该user可以写,param为MeIOSUser object +- (void)setUserWriteAccessWithUser:(MeIOSUser *)user; + +// 设置该user数据可删除,注意(这数据得要服务器数据表支持删除功能) +- (void)setUserDeleteAccessWithUser:(MeIOSUser *)user; + +@end diff --git a/src/ios/MeIOSACL.mm b/src/ios/MeIOSACL.mm new file mode 100644 index 0000000..d39c4f6 --- /dev/null +++ b/src/ios/MeIOSACL.mm @@ -0,0 +1,102 @@ +// +// MeIOSACL.m +// MeCloud +// +// Created by super on 2017/8/10. +// Copyright © 2017年 Rex. All rights reserved. +// + +#import "MeIOSACL.h" +#import "MeIOSUser.h" +#import "MeIOSRole.h" +#import "MeACL.h" + +@implementation MeIOSACL + +- (id)initWithACL:(void *)_acl { + if (self = [super init]) { + // 这一步用了赋值运算符重载,执行深拷贝 + object = _acl; + } + + return self; +} + +- (void)loadObject { + [self clearObject]; + object = new MeACL(); +} + +- (MeACL *)meACL { + return (MeACL *)object; +} + +- (void)setPublicReadAccess { + self.meACL->setPublicReadAccess(); +} + +- (void)setPublicWriteAccess { + self.meACL->setPublicWriteAccess(); +} + +- (void)setRoleReadAccessWithName:(NSString *)role { + if (!role || role.length <= 0) return; + self.meACL->setRoleReadAccess([role UTF8String]); +} + +- (void)setRoleWriteAccessWithName:(NSString *)role { + if (!role || role.length <= 0) return; + self.meACL->setRoleWriteAccess([role UTF8String]); +} + +- (void)setRoleDeleteAccessWithName:(NSString *)role { + if (!role || role.length <= 0) return; + self.meACL->setRoleDeleteAccess([role UTF8String]); +} + +- (void)setRoleReadAccessWithRole:(MeIOSRole *)role { + if (!role) return; + self.meACL->setRoleReadAccess((MeRole *)(role.getObject)); +} + +- (void)setRoleWriteAccessWithRole:(MeIOSRole *)role { + if (!role) return; + self.meACL->setRoleWriteAccess((MeRole *)(role.getObject)); +} + +- (void)setRoleDeleteAccessWithRole:(MeIOSRole *)role { + if (!role) return; + self.meACL->setRoleDeleteAccess((MeRole *)(role.getObject)); +} + +- (void)setUserReadAccessWithId:(NSString *)userId { + if (!userId || userId.length <= 0) return; + self.meACL->setUserReadAccess([userId UTF8String]); +} + +- (void)setUserWriteAccessWithId:(NSString *)userId { + if (!userId || userId.length <= 0) return; + self.meACL->setUserWriteAccess([userId UTF8String]); +} + +- (void)setUserDeleteAccessWithId:(NSString *)userId { + if (!userId || userId.length <= 0) return; + self.meACL->setUserDeleteAccess([userId UTF8String]); +} + +- (void)setUserReadAccessWithUser:(MeIOSUser *)user { + if (!user) return; + self.meACL->setUserReadAccess((MeUser *)(user.getObject)); +} + +- (void)setUserWriteAccessWithUser:(MeIOSUser *)user { + if (!user) return; + self.meACL->setUserWriteAccess((MeUser *)(user.getObject)); +} + +- (void)setUserDeleteAccessWithUser:(MeIOSUser *)user { + if (!user) return; + self.meACL->setUserDeleteAccess((MeUser *)(user.getObject)); +} + +@end diff --git a/src/ios/MeIOSCallback.h b/src/ios/MeIOSCallback.h new file mode 100644 index 0000000..3d8a816 --- /dev/null +++ b/src/ios/MeIOSCallback.h @@ -0,0 +1,29 @@ +/** + * file : MeIOSCallback.h + * author : Rex + * create : 2017-07-06 20:39 + * func : + * history: + */ + +#ifndef __MEIOSCALLBACK_H_ +#define __MEIOSCALLBACK_H_ + +#import +#import +#include "MeCallback.h" + +class MeBlockCallback: public MeCallback{ +public: + MeBlockCallback(MeCallbackBlock block, const char* classname = NULL, MeObject* obj = NULL); + MeBlockCallback(const char *classname = NULL, MeObject *obj = NULL); + ~MeBlockCallback(); + + virtual void done(MeObject* obj, MeException* err, uint32_t size = 1); + + void setBlock(MeCallbackBlock block); +protected: + MeCallbackBlock m_block; +}; + +#endif diff --git a/src/ios/MeIOSCallback.mm b/src/ios/MeIOSCallback.mm new file mode 100644 index 0000000..9a1cd04 --- /dev/null +++ b/src/ios/MeIOSCallback.mm @@ -0,0 +1,32 @@ +/** + * file : MeIOSCallback.mm + * author : Rex + * create : 2017-07-06 20:39 + * func : + * history: + */ + +#include "MeIOSCallback.h" + +MeBlockCallback::MeBlockCallback(MeCallbackBlock block, const char* classname, MeObject* obj):MeCallback(classname, obj){ + setBlock(block); +} + +MeBlockCallback::MeBlockCallback(const char* classname, MeObject* obj): +MeCallback(classname, obj){ +} + +void MeBlockCallback::done(MeObject* obj, MeException* err, uint32_t size){ + dispatch_sync(dispatch_get_main_queue(), ^(){ + m_block(obj, err, size); + delete this; + }); +} + +void MeBlockCallback::setBlock(MeCallbackBlock block){ + m_block = (__bridge MeCallbackBlock)Block_copy((__bridge void *)block); +} + +MeBlockCallback::~MeBlockCallback(){ + Block_release(m_block); +} diff --git a/src/ios/MeIOSException.h b/src/ios/MeIOSException.h new file mode 100644 index 0000000..6884d90 --- /dev/null +++ b/src/ios/MeIOSException.h @@ -0,0 +1,23 @@ +// +// MeIOSException.h +// MeCloud +// +// Created by super on 2017/8/10. +// Copyright © 2017年 Rex. All rights reserved. +// + +#import + +@interface MeIOSException : NSObject + +@property (nonatomic, assign) NSInteger errCode; + +@property (nonatomic, copy) NSString *errMessage; + +@property (nonatomic, copy) NSString *errInfo; + +- (id)initWithCode:(NSInteger)code message:(NSString *)message info:(NSString *)info; + +- (id)initWithMeException:(void *)exception; + +@end diff --git a/src/ios/MeIOSException.mm b/src/ios/MeIOSException.mm new file mode 100644 index 0000000..357e5ca --- /dev/null +++ b/src/ios/MeIOSException.mm @@ -0,0 +1,35 @@ +// +// MeIOSException.m +// MeCloud +// +// Created by super on 2017/8/10. +// Copyright © 2017年 Rex. All rights reserved. +// + +#import "MeIOSException.h" +#import "MeCloud.h" + +@implementation MeIOSException + +- (id)initWithCode:(NSInteger)code message:(NSString *)message info:(NSString *)info { + if (self = [super init]) { + _errCode = code; + _errMessage = message; + _errInfo = info; + } + + return self; +} + +- (id)initWithMeException:(void *)exception { + MeException *meException = (MeException *)exception; + NSInteger errorCode = meException->errCode(); + NSString *errorMessage = [NSString stringWithUTF8String:meException->errMsg()]; + NSString *info = nil; + if (meException->has("info")) { + info = [NSString stringWithUTF8String:meException->stringValue("info")]; + } + return [[MeIOSException alloc] initWithCode:errorCode message:errorMessage info:info]; +} + +@end diff --git a/src/ios/MeIOSFile.h b/src/ios/MeIOSFile.h new file mode 100644 index 0000000..7dcc1da --- /dev/null +++ b/src/ios/MeIOSFile.h @@ -0,0 +1,23 @@ +// +// MeIOSFile.h +// MeCloud +// +// Created by super on 2017/9/12. +// Copyright © 2017年 Rex. All rights reserved. +// + +#import "MeIOSObject.h" +#import +#import + +@interface MeIOSFile : MeIOSObject + +- (id)initWithMeObject:(MeIOSObject *)iosObject; + +- (NSString *)imageUrlWithSize:(CGSize)size; + +- (NSString *)imageUrl; + +- (NSString *)imageCropUrl:(CGRect)rect; + +@end diff --git a/src/ios/MeIOSFile.mm b/src/ios/MeIOSFile.mm new file mode 100644 index 0000000..efe81f1 --- /dev/null +++ b/src/ios/MeIOSFile.mm @@ -0,0 +1,53 @@ +// +// MeIOSFile.m +// MeCloud +// +// Created by super on 2017/9/12. +// Copyright © 2017年 Rex. All rights reserved. +// + +#import "MeIOSFile.h" +#import "MeFile.h" + +@implementation MeIOSFile + +- (id)initWithMeObject:(MeIOSObject *)iosObject { + if (self = [super init]) { + [self clearObject]; + object = new MeFile((MeObject *)iosObject.getObject, false); + } + + return self; +} + +- (id)initWithObjectID:(NSString *)objectID className:(NSString *)className { + if (self = [super init]) { + [self clearObject]; + object = new MeFile([objectID UTF8String], [className UTF8String]); + } + + return self; +} + +- (void)loadObject { + [self clearObject]; + object = new MeFile(); +} + +- (MeFile *)meFile { + return (MeFile *)object; +} + +- (NSString *)imageUrlWithSize:(CGSize)size { + return [NSString stringWithUTF8String:self.meFile->imageUrl((int)size.width, (int)size.height)]; +} + +- (NSString *)imageUrl { + return [NSString stringWithUTF8String:self.meFile->imageUrl()]; +} + +- (NSString *)imageCropUrl:(CGRect)rect { + return [NSString stringWithUTF8String:self.meFile->imageCropUrl(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height)]; +} + +@end diff --git a/src/ios/MeIOSHttpDataCallback.h b/src/ios/MeIOSHttpDataCallback.h new file mode 100644 index 0000000..7771478 --- /dev/null +++ b/src/ios/MeIOSHttpDataCallback.h @@ -0,0 +1,31 @@ +// +// MeIOSHttpDataCallback.h +// MeCloud +// +// Created by super on 2017/9/14. +// Copyright © 2017年 Rex. All rights reserved. +// + +#ifndef __MEIOSHTTPDATACALLBACK_H_ +#define __MEIOSHTTPDATACALLBACK_H_ + +#include "MeHttpFileCallback.h" +#include "MeCallback.h" + +class MeIOSHttpDataCallback: public MeHttpDataCallback{ +public: + MeIOSHttpDataCallback(); + ~MeIOSHttpDataCallback(); + + virtual void done(MeObject* object, MeException* err, uint32_t size = 1); + virtual void progress(uint64_t writen, uint64_t total_writen, uint64_t total_expect_write); + + void setBlock(MeCallbackBlock block); + void setProgressBlock(MeHttpFileProgressBlock block); + +protected: + MeCallbackBlock m_block; + MeHttpFileProgressBlock m_progress_block; +}; + +#endif diff --git a/src/ios/MeIOSHttpDataCallback.mm b/src/ios/MeIOSHttpDataCallback.mm new file mode 100644 index 0000000..3f5e8f7 --- /dev/null +++ b/src/ios/MeIOSHttpDataCallback.mm @@ -0,0 +1,40 @@ +// +// MeIOSHttpDataCallback.mm +// MeCloud +// +// Created by super on 2017/9/14. +// Copyright © 2017年 Rex. All rights reserved. +// + +#import "MeIOSHttpDataCallback.h" +#import + +MeIOSHttpDataCallback::MeIOSHttpDataCallback(): MeHttpDataCallback() { + +} + +void MeIOSHttpDataCallback::progress(uint64_t writen, uint64_t total_writen, uint64_t total_expect_write) { + dispatch_sync(dispatch_get_main_queue(), ^(){ + m_progress_block(writen, total_writen, total_expect_write); + }); +} + +void MeIOSHttpDataCallback::done(MeObject* object, MeException* err, uint32_t size) { + dispatch_sync(dispatch_get_main_queue(), ^(){ + m_block(object, err, size); + delete this; + }); +} + +void MeIOSHttpDataCallback::setBlock(MeCallbackBlock block) { + m_block = (__bridge MeCallbackBlock)Block_copy((__bridge void *)block); +} + +void MeIOSHttpDataCallback::setProgressBlock(MeHttpFileProgressBlock block) { + m_progress_block = (__bridge MeHttpFileProgressBlock)Block_copy((__bridge void *)block); +} + +MeIOSHttpDataCallback::~MeIOSHttpDataCallback() { + Block_release(m_block); + Block_release(m_progress_block); +} diff --git a/src/ios/MeIOSHttpFileCallback.h b/src/ios/MeIOSHttpFileCallback.h new file mode 100644 index 0000000..bde3f33 --- /dev/null +++ b/src/ios/MeIOSHttpFileCallback.h @@ -0,0 +1,32 @@ +// +// MeIOSHttpFileCallback.h +// MeCloud +// +// Created by super on 2017/7/25. +// Copyright © 2017年 Rex. All rights reserved. +// + +#ifndef __MEIOSHTTPFILECALLBACK_H_ +#define __MEIOSHTTPFILECALLBACK_H_ + +#include "MeHttpFileCallback.h" +#include "MeCallback.h" + +class MeIOSHttpFileCallback: public MeHttpFileCallback{ +public: + MeIOSHttpFileCallback(const char *classname=NULL, MeFile *file=NULL); + ~MeIOSHttpFileCallback(); + + virtual void done(MeFile *file, MeException *err, uint32_t size = 1); + virtual void progress(uint64_t writen, uint64_t total_writen, uint64_t total_expect_write); + + void setBlock(MeHttpFileCallbackBlock block); + void setProgressBlock(MeHttpFileProgressBlock block); + +protected: + MeHttpFileCallbackBlock m_block; + MeHttpFileProgressBlock m_progress_block; + void uploadFileInfomation(MeCallbackBlock block); +}; + +#endif diff --git a/src/ios/MeIOSHttpFileCallback.mm b/src/ios/MeIOSHttpFileCallback.mm new file mode 100644 index 0000000..4cf906b --- /dev/null +++ b/src/ios/MeIOSHttpFileCallback.mm @@ -0,0 +1,60 @@ + +// +// MeIOSHttpFileCallBack.cpp +// MeCloud +// +// Created by super on 2017/7/25. +// Copyright © 2017年 Rex. All rights reserved. +// + +#import +#include "MeIOSHttpFileCallback.h" +#include "MeIOSCallback.h" +#include "MeUploadFile.h" +#include "MeDownloadFile.h" + +MeIOSHttpFileCallback::MeIOSHttpFileCallback(const char* classname, MeFile* file):MeHttpFileCallback(classname, file) { +} + +void MeIOSHttpFileCallback::progress(uint64_t writen, uint64_t total_writen, uint64_t total_expect_write) { + dispatch_sync(dispatch_get_main_queue(), ^(){ + m_progress_block(writen, total_writen, total_expect_write); + }); +} + +void MeIOSHttpFileCallback::done(MeFile* file, MeException* err, uint32_t size) { + if (file->fileType() == ME_HTTPFILE_UPLOAD) { + MeBlockCallback *callback = new MeBlockCallback(file->className(), file); + if (err) { + dispatch_sync(dispatch_get_main_queue(), ^(){ + m_block(file, err, size); + }); + } else { + MeCallbackBlock block = ^(MeObject *obj, MeException *err, uint32_t size) { + m_block(file, err, size); + delete this; + }; + callback->setBlock(block); + MeUploadFile *uploadFile = (MeUploadFile *)file; + uploadFile->uploadFileInfomation(callback); + } + } else { + dispatch_sync(dispatch_get_main_queue(), ^(){ + m_block(file, err, size); + delete this; + }); + } +} + +void MeIOSHttpFileCallback::setBlock(MeHttpFileCallbackBlock block) { + m_block = (__bridge MeHttpFileCallbackBlock)Block_copy((__bridge void *)block); +} + +void MeIOSHttpFileCallback::setProgressBlock(MeHttpFileProgressBlock block) { + m_progress_block = (__bridge MeHttpFileProgressBlock)Block_copy((__bridge void *)block); +} + +MeIOSHttpFileCallback::~MeIOSHttpFileCallback() { + Block_release(m_block); + Block_release(m_progress_block); +} diff --git a/src/ios/MeIOSJSONObject.h b/src/ios/MeIOSJSONObject.h new file mode 100644 index 0000000..96a603b --- /dev/null +++ b/src/ios/MeIOSJSONObject.h @@ -0,0 +1,68 @@ +// +// MeIOSJSONObject.h +// MeCloud +// +// Created by super on 2017/8/10. +// Copyright © 2017年 Rex. All rights reserved. +// + +#import + +@interface MeIOSJSONObject : NSObject +{ + // C++ 多态 + void *object; +} + +@property (nonatomic, copy, readonly) NSString *jsonString; + +@property (nonatomic, assign, readonly) BOOL empty; + +- (id)initWithString:(NSString *)string; + +- (id)initWithJSONObject:(void *)_object; + +// 子类需要重载 +- (void)loadObject; + +// 禁止用这个函数 +- (void)clearObject; + +- (void *)getObject; + +- (bool)hasKey:(NSString *)name; + +- (NSString *)stringValue:(NSString *)name; + +- (void)setStringValue:(NSString *)value key:(NSString *)key; + +- (double)doubleValue:(NSString *)name; + +- (void)setDoubleValue:(double)value key:(NSString *)key; + +- (NSInteger)integerValue:(NSString *)name; + +- (void)setIntegerValue:(NSInteger)value key:(NSString *)key; + +- (long long)longValue:(NSString *)name; + +- (void)setLongValue:(long long)value key:(NSString *)key; + +- (BOOL)boolValue:(NSString *)name; + +- (void)setBoolValue:(BOOL)value key:(NSString *)key; + +- (MeIOSJSONObject *)jsonObject:(NSString *)key; + +- (void)setJSONObject:(MeIOSJSONObject *)iosObject key:(NSString *)key; + +- (NSMutableArray *)integerArrayWithKey:(NSString *)key; + +- (NSMutableArray *)stringArrayWithKey:(NSString *)key; + +- (NSMutableArray *)doubleArrayWithKey:(NSString *)key; + +- (NSMutableArray *)jsonArrayWithKey:(NSString *)key; + +@end + diff --git a/src/ios/MeIOSJSONObject.mm b/src/ios/MeIOSJSONObject.mm new file mode 100644 index 0000000..425a0d6 --- /dev/null +++ b/src/ios/MeIOSJSONObject.mm @@ -0,0 +1,204 @@ +// +// MeIOSJSONObject.m +// MeCloud +// +// Created by super on 2017/8/10. +// Copyright © 2017年 Rex. All rights reserved. +// + +#import "MeIOSJSONObject.h" +#include "JSON.h" + +using namespace mc; + +@implementation MeIOSJSONObject + +- (id)init { + if (self = [super init]) { + [self loadObject]; + } + + return self; +} + +- (id)initWithString:(NSString *)string { + if (self = [super init]) { + object = new JSONObject([string UTF8String]); + } + + return self; +} + +- (id)initWithJSONObject:(void *)_object { + if (self = [super init]) { + [self clearObject]; + object = new JSONObject((JSONObject *)_object, false); + } + + return self; +} + +- (void)loadObject { + [self clearObject]; + object = new JSONObject(); +} + +- (NSString *)jsonString { + return [NSString stringWithUTF8String:self.jsonObject->toString()]; +} + +- (BOOL)empty { + return self.jsonObject->empty(); +} + +- (void)clearObject { + if (object) { + delete (JSONObject *)object; + object = NULL; + } +} + +- (void *)getObject { + return object; +} + +- (JSONObject *)jsonObject { + return (JSONObject *)object; +} + +- (bool)hasKey:(NSString *)name { + if (!name || name.length <= 0) return nil; + return self.jsonObject->has([name UTF8String]); +} + +- (NSString *)stringValue { + return [NSString stringWithUTF8String:self.jsonObject->toString()]; +} + +- (NSString *)stringValue:(NSString *)name { + if (!name || name.length <= 0) return nil; + + if (self.jsonObject->stringValue([name UTF8String])) { + return [NSString stringWithUTF8String:self.jsonObject->stringValue([name UTF8String])]; + } + + return nil; +} + +- (void)setStringValue:(NSString *)value key:(NSString *)key { + if (!key || key.length <= 0) return; + NSString *newValue = @""; + if (value) { + newValue = value; + } + self.jsonObject->put([key UTF8String], [newValue UTF8String]); +} + +- (double)doubleValue:(NSString *)name { + if (!name || name.length <= 0) return 0; + return self.jsonObject->doubleValue([name UTF8String]); +} + +- (void)setDoubleValue:(double)value key:(NSString *)key { + if (!key || key.length <= 0) return; + self.jsonObject->put([key UTF8String], value); +} + +- (NSInteger)integerValue:(NSString *)name { + if (!name || name.length <= 0) return 0; + return self.jsonObject->longValue([name UTF8String]); +} + +- (void)setIntegerValue:(long)value key:(NSString *)key { + if (!key || key.length <= 0) return; + self.jsonObject->put([key UTF8String], value); +} + +- (long long)longValue:(NSString *)name { + if (!name || name.length <= 0) return 0; + return self.jsonObject->longValue([name UTF8String]); +} + +- (void)setLongValue:(long long)value key:(NSString *)key { + if (!key || key.length <= 0) return; + self.jsonObject->put([key UTF8String], (long)value); +} + +- (BOOL)boolValue:(NSString *)name { + if (!name || name.length <= 0) return false; + return self.jsonObject->boolValue([name UTF8String]); +} + +- (void)setBoolValue:(BOOL)value key:(NSString *)key { + self.jsonObject->putBool([key UTF8String], value); +} + +- (MeIOSJSONObject *)jsonObject:(NSString *)key { + if (!key || key.length <= 0) return nil; + JSONObject json = self.jsonObject->jsonValue([key UTF8String]); + if (!json.empty()) { + return [[MeIOSJSONObject alloc] initWithJSONObject:&json]; + } + + return nil; +} + +- (void)setJSONObject:(MeIOSJSONObject *)iosObject key:(NSString *)key { + if (!iosObject || !key || key.length <= 0) return; + self.jsonObject->put([key UTF8String], (JSONObject *)(iosObject.getObject)); +} + +- (NSMutableArray *)integerArrayWithKey:(NSString *)key { + NSMutableArray *array = [NSMutableArray array]; + JSONArray jsonArray = self.jsonObject->arrayValue([key UTF8String]); + for (int i = 0; i < jsonArray.size(); i++) { + int *value = jsonArray.intValue(i); + NSNumber *number = [NSNumber numberWithDouble:*value]; + [array addObject:number]; + } + + return array; +} + +- (NSMutableArray *)doubleArrayWithKey:(NSString *)key { + NSMutableArray *array = [NSMutableArray array]; + JSONArray jsonArray = self.jsonObject->arrayValue([key UTF8String]); + for (int i = 0; i < jsonArray.size(); i++) { + double *value = jsonArray.doubleValue(i); + NSNumber *number = [NSNumber numberWithDouble:*value]; + [array addObject:number]; + } + + return array; +} + +- (NSMutableArray *)stringArrayWithKey:(NSString *)key { + NSMutableArray *array = [NSMutableArray array]; + JSONArray jsonArray = self.jsonObject->arrayValue([key UTF8String]); + for (int i = 0; i < jsonArray.size(); i++) { + char *value = jsonArray.stringValue(i); + NSString *string = [NSString stringWithUTF8String:value]; + [array addObject:string]; + } + + return array; +} + +- (NSMutableArray *)jsonArrayWithKey:(NSString *)key { + NSMutableArray *array = [NSMutableArray array]; + JSONArray jsonArray = self.jsonObject->arrayValue([key UTF8String]); + for (int i = 0; i < jsonArray.size(); i++) { + JSONObject json = jsonArray.jsonValue(i); + MeIOSJSONObject *object = [[MeIOSJSONObject alloc] initWithJSONObject:&json]; + [array addObject:object]; + } + + return array; +} + +- (void)dealloc { + delete (JSONObject *)object; +} + +@end + diff --git a/src/ios/MeIOSJoinQuery.h b/src/ios/MeIOSJoinQuery.h new file mode 100644 index 0000000..d659658 --- /dev/null +++ b/src/ios/MeIOSJoinQuery.h @@ -0,0 +1,48 @@ +// +// MeIOSJoinQuery.h +// MeCloud +// +// Created by super on 2017/9/18. +// Copyright © 2017年 Rex. All rights reserved. +// + +#import "MeIOSJSONObject.h" +#import + +@interface MeIOSJoinQuery : MeIOSJSONObject + +- (id)initWithClassName:(NSString *)name; + +// 嵌套query +- (id)initWithNestClassName:(NSString *)ClassName; + +- (void)addSelectKey:(NSString *)key; + +- (void)addNotSelectKey:(NSString *)key; + +- (void)addLimit:(NSUInteger)count; + +// 确保加入的先后顺序,级别越高,理解关系型中的数据库select排序顺序 +- (void)addAscendSortKeys:(NSString *)key; + +- (void)addDescendSortKeys:(NSString *)key; + +- (void)matchEqualToWithKey:(NSString *)key value:(NSString *)value; + +- (void)matchEqualToWithKey:(NSString *)key intValue:(NSInteger)value; + +- (void)matchGreatThanWithKey:(NSString *)key value:(NSString *)value; + +- (void)matchGreatThanWithKey:(NSString *)key intValue:(NSInteger)value; + +- (void)matchLessThanWithKey:(NSString *)key value:(NSString *)value; + +- (void)matchLessThanWithKey:(NSString *)key intValue:(NSInteger)value; + +// 重点(关联表) +- (void)addForeignTable:(NSString *)fromTable foreignKey:(NSString *)foreignKey localKey:(NSString *)localKey document:(NSString *)document; + +// 嵌套查询,最好不要用,如果用到多表嵌套的话需要服务端优化表的结构或者走特定接口的方式,因为嵌套表越多性能越受影响 +- (void)addJoinQuery:(MeIOSJoinQuery *)joinQuery; + +@end diff --git a/src/ios/MeIOSJoinQuery.mm b/src/ios/MeIOSJoinQuery.mm new file mode 100644 index 0000000..82d13f8 --- /dev/null +++ b/src/ios/MeIOSJoinQuery.mm @@ -0,0 +1,100 @@ +// +// MeIOSJoinQuery.m +// MeCloud +// +// Created by super on 2017/9/18. +// Copyright © 2017年 Rex. All rights reserved. +// + +#import "MeIOSJoinQuery.h" +#import "MeJoinQuery.h" + +@implementation MeIOSJoinQuery + +- (id)initWithClassName:(NSString *)name { + if (self = [super init]) { + [self clearObject]; + object = new MeJoinQuery([name UTF8String]); + } + + return self; +} + +- (id)initWithNestClassName:(NSString *)ClassName { + if (self = [super init]) { + [self clearObject]; + object = new MeJoinQuery([ClassName UTF8String], true); + } + + return self; +} + +- (MeJoinQuery *)meJoinQuery { + return (MeJoinQuery *)object; +} + +- (void)addSelectKey:(NSString *)key { + if (!key || key.length <= 0) return; + self.meJoinQuery->addSelectKey([key UTF8String]); +} + +- (void)addNotSelectKey:(NSString *)key { + if (!key || key.length <= 0) return; + self.meJoinQuery->addNotSelectKey([key UTF8String]); +} + +- (void)addLimit:(NSUInteger)count { + self.meJoinQuery->addLimit((int)count); +} + +- (void)addAscendSortKeys:(NSString *)key { + if (!key || key.length <= 0) return; + self.meJoinQuery->addAscend([key UTF8String]); +} + +- (void)addDescendSortKeys:(NSString *)key { + if (!key || key.length <= 0) return; + self.meJoinQuery->addDescend([key UTF8String]); +} + +- (void)matchEqualToWithKey:(NSString *)key value:(NSString *)value { + if (!key || key.length <= 0) return; + self.meJoinQuery->matchEqualTo([key UTF8String], [value UTF8String]); +} + +- (void)matchEqualToWithKey:(NSString *)key intValue:(NSInteger)value { + if (!key || key.length <= 0) return; + self.meJoinQuery->matchEqualTo([key UTF8String], (int)value); +} + +- (void)matchGreatThanWithKey:(NSString *)key value:(NSString *)value { + if (!key || key.length <= 0) return; + self.meJoinQuery->matchGreater([key UTF8String], [value UTF8String]); +} + +- (void)matchGreatThanWithKey:(NSString *)key intValue:(NSInteger)value { + if (!key || key.length <= 0) return; + self.meJoinQuery->matchGreater([key UTF8String], (int)value); +} + +- (void)matchLessThanWithKey:(NSString *)key value:(NSString *)value { + if (!key || key.length <= 0) return; + self.meJoinQuery->matchLess([key UTF8String], [value UTF8String]); +} + +- (void)matchLessThanWithKey:(NSString *)key intValue:(NSInteger)value { + if (!key || key.length <= 0) return; + self.meJoinQuery->matchLess([key UTF8String], (int)value); +} + +- (void)addForeignTable:(NSString *)fromTable foreignKey:(NSString *)foreignKey localKey:(NSString *)localKey document:(NSString *)document { + if (!fromTable || fromTable.length <= 0 || !foreignKey || foreignKey.length <= 0 || !localKey || localKey.length <= 0 || !document || document.length <= 0) return; + self.meJoinQuery->addForeignTable([fromTable UTF8String], [foreignKey UTF8String], [localKey UTF8String], [document UTF8String]); +} + +- (void)addJoinQuery:(MeIOSJoinQuery *)joinQuery { + if (!joinQuery) return; + self.meJoinQuery->addMeJoinQuery((MeJoinQuery *)(joinQuery.getObject)); +} + +@end diff --git a/src/ios/MeIOSNetManager.h b/src/ios/MeIOSNetManager.h new file mode 100644 index 0000000..6c05f92 --- /dev/null +++ b/src/ios/MeIOSNetManager.h @@ -0,0 +1,109 @@ +// +// MeIOSNetManager.h +// MeCloud +// +// Created by super on 2017/8/10. +// Copyright © 2017年 Rex. All rights reserved. +// + +#import +#import "MeIOSObject.h" +#import "MeIOSException.h" +#import "MeIOSUser.h" +#import "MeIOSQuery.h" +#import "MeIOSJoinQuery.h" + +typedef void (^MeIOSJSONCallbackBlock)(MeIOSJSONObject *obj, MeIOSException *error, NSInteger size); + +typedef void (^MeIOSJSONListCallbackBlock)(NSMutableArray *objs, MeIOSException *error, NSInteger size); + +typedef void (^MeIOSCallbackBlock)(MeIOSObject *obj, MeIOSException *error, NSInteger size); + +typedef void (^MeIOSListCallbackBlock)(NSMutableArray *objs, MeIOSException *error, NSInteger size); + +typedef void (^MeIOSUserCallbackBlock)(MeIOSUser *obj, MeIOSException *error, NSInteger size); + +typedef void (^MeIOSDownloadCallbackBlock)(MeIOSObject *obj, NSString *localPath, MeIOSException *error, NSInteger size); + +typedef void (^MeIOSHttpFileProgressBlock)(NSUInteger totalWriten, NSUInteger totalExpectWrite); + +@interface MeIOSNetManager : NSObject + +@property (nonatomic, strong) MeIOSUser *currentUser; + +@property (nonatomic, strong, readonly) NSString *baseUrl; + +@property (nonatomic, strong, readonly) NSString *cookie; + ++ (instancetype)shared; + +// 设置MeCloud的域名 +- (void)setBaseUrl:(NSString *)url; + +// 设置http头 +- (void)addHttpHeaderWithKey:(NSString *)key value:(NSString *)value; + +// 显示log +- (void)showLog:(BOOL)showed; + +// 系统默认是20s +- (void)setHttpTimeout:(NSUInteger)timeout; + +// 目前注销只做本地注销 +- (void)logout; + +// 保存MeIOSObject,会向服务器发送请求 +- (void)saveWithIOSObject:(MeIOSObject *)iOSObject complete:(MeIOSCallbackBlock)block; + +// 删除一条数据,只支持部分表,业务层定义哪些表可以支持删除 +- (void)deleteWithIOSObject:(MeIOSObject *)iOSObject complete:(MeIOSJSONCallbackBlock)block; + +// 根据objectId做单条查询 +- (void)getIOSObjectWithID:(NSString *)objectID className:(NSString *)classname complete:(MeIOSCallbackBlock)block; + +// 批量查询 +- (void)getIOSObjects:(MeIOSQuery *)query complete:(MeIOSListCallbackBlock)block; + +// 关联查询 +- (void)getIOSObjectsWithJoinQuery:(MeIOSJoinQuery *)query complete:(MeIOSListCallbackBlock)block; + +// 登录接口 +- (void)loginWithUsername:(NSString *)name password: (NSString *)password complete:(MeIOSUserCallbackBlock)block; + +// 注册接口 +- (void)signUpWithUsername:(NSString *)name password: (NSString *)password complete:(MeIOSUserCallbackBlock)block; + +// 更改密码接口 +- (void)changePasswordWithUserName:(NSString *)name new: (NSString *)newPassword complete:(MeIOSUserCallbackBlock)block; + +// 下载文件,url可以为的http或者https的绝对链接,也可以支持自己上传到阿里服务器的相对链接,相对链接的值为objectId +- (void)downloadFile:(NSString *)url type:(NSString *)filename complete:(MeIOSDownloadCallbackBlock)complete progress:(MeIOSHttpFileProgressBlock)progress; + +// MeCloud上传二进制数据 +- (void)uploadData:(NSData *)data type:(NSString *)type complete:(MeIOSCallbackBlock)complete progress:(MeIOSHttpFileProgressBlock)progress; + +// MeCloud上传文件 +- (void)uploadFile:(NSString *)path type:(NSString *)type complete:(MeIOSCallbackBlock)complete progress:(MeIOSHttpFileProgressBlock)progress; + +// 特定接口上传二进制数据 +- (void)postDataWithUrl:(NSString *)url data:(NSData *)data complete:(MeIOSCallbackBlock)complete progress:(MeIOSHttpFileProgressBlock)progress; + +#pragma --mark 特定Api的接口 +// 单独post/put api的请求,提交表单数据 +- (void)saveWithUrl:(NSString *)url json:(MeIOSJSONObject *)json complete:(MeIOSJSONCallbackBlock)block; + +- (void)getWithUrl:(NSString *)url json:(MeIOSJSONObject *)json complete:(MeIOSJSONCallbackBlock)block; + +// 获取短信验证码 +- (void)requestSMSAuthCode:(NSString *)phone complete:(MeIOSJSONCallbackBlock)block; + +// 磁盘缓存数据 +- (void)saveJSONToCache:(MeIOSJSONObject *)document key:(NSString *)key; + +// 从磁盘缓存读取数据 +- (MeIOSJSONObject *)getJSONFromCache:(NSString *)key; + +// 从磁盘缓存删除数据 +- (void)removeJSONFromCache:(NSString *)key; + +@end diff --git a/src/ios/MeIOSNetManager.mm b/src/ios/MeIOSNetManager.mm new file mode 100644 index 0000000..4e62d72 --- /dev/null +++ b/src/ios/MeIOSNetManager.mm @@ -0,0 +1,371 @@ +// +// MeIOSNetManager.m +// MeCloud +// +// Created by super on 2017/8/10. +// Copyright © 2017年 Rex. All rights reserved. +// + +#import "MeIOSNetManager.h" +#import "MeDownloadFile.h" +#import "MeUploadFile.h" +#import "MeIOSCallback.h" +#import "MeHttpFileCallback.h" +#import "MeIOSHttpDataCallback.h" +#import "MeSMS.h" +#import +#import +#import +#import "MeUser.h" +#import "MeQuery.h" +#import "MeJoinQuery.h" + +using namespace mc; + +@implementation MeIOSNetManager + ++ (instancetype)shared { + static MeIOSNetManager *shared = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + shared = [[MeIOSNetManager alloc] init]; + }); + + return shared; +} + +- (NSString *)baseUrl { + return [NSString stringWithUTF8String:MeCloud::shareInstance()->restUrl()]; +} + +- (void)setBaseUrl:(NSString *)url { + MeCloud::setBaseUrl([url UTF8String]); +} + +- (NSString *)cookie { + const char *cookie = MeCloud::shareInstance()->cookie(); + if (!cookie) { + return nil; + } + + return [NSString stringWithUTF8String:cookie]; +} + +- (void)addHttpHeaderWithKey:(NSString *)key value:(NSString *)value { + if (!key || key.length <= 0 || !value || value.length <= 0) return; + MeCloud::shareInstance()->addHttpHeader([key UTF8String], [value UTF8String]); +} + +- (void)showLog:(BOOL)showed { + MeCloud::showLog(showed); +} + +- (void)setHttpTimeout:(NSUInteger)timeout { + MeCloud::setTimeout((uint32_t)timeout); +} + +- (MeIOSUser *)currentUser { + if (!_currentUser) { + MeUser *meUser = MeUser::currentUser(); + if (meUser) { + _currentUser = [[MeIOSUser alloc] initWithMeUser: meUser]; + } + } + + return _currentUser; +} + +- (void)logout { + _currentUser = nil; + MeUser::currentUser()->logout(); +} + +- (void)saveWithIOSObject:(MeIOSObject *)iOSObject complete:(MeIOSCallbackBlock)block { + MeObject *meObject = (MeObject *)(iOSObject.getObject); + meObject->save(^(MeObject *obj, MeException *error, uint32_t size) { + if (!error) { + block(iOSObject, nil, size); + } else { + block(nil, [[MeIOSException alloc] initWithMeException:error], size); + } + }); +} + +- (void)deleteWithIOSObject:(MeIOSObject *)iOSObject complete:(MeIOSJSONCallbackBlock)block { + MeBlockCallback* callback = new MeBlockCallback(); + MeCallbackBlock cloudBlock = ^(MeObject* obj, MeException* error, uint32_t size) { + if (!error) { + MeIOSJSONObject *json = [[MeIOSJSONObject alloc]initWithJSONObject:obj]; + block(json, nil, size); + } else { + block(nil, [[MeIOSException alloc] initWithMeException:error], size); + } + }; + callback->setBlock(cloudBlock); + MeObject *meObject = (MeObject *)(iOSObject.getObject); + meObject->deleteObject(callback); +} + +- (void)saveWithUrl:(NSString *)url json:(MeIOSJSONObject *)json complete:(MeIOSJSONCallbackBlock)block { + MeBlockCallback* callback = new MeBlockCallback(); + MeCallbackBlock cloudBlock = ^(MeObject *obj, MeException *error, uint32_t size) { + if (!error) { + MeIOSJSONObject *json = [[MeIOSJSONObject alloc]initWithJSONObject:obj]; + block(json, nil, size); + } else { + block(nil, [[MeIOSException alloc] initWithMeException:error], size); + } + }; + callback->setBlock(cloudBlock); + MeCloud::shareInstance()->post([url UTF8String], [json.jsonString UTF8String], callback); +} + +- (void)getIOSObjectWithID:(NSString *)objectID className:(NSString *)classname complete:(MeIOSCallbackBlock)block { + if (!objectID || objectID.length < BS_UNIQUE_ID_EFFECT_LENGTH || !classname || classname.length <= 0) { + return; + } + MeIOSQuery *query = [[MeIOSQuery alloc] initWithClassName:classname]; + MeQuery *meQuery = (MeQuery *)query.getObject; + meQuery->get([objectID UTF8String], ^(MeObject *obj, MeException *error, uint32_t size) { + if (!error) { + MeIOSObject *iOSObject = [[MeIOSObject alloc] initWithMeObject:obj]; + block(iOSObject, nil, size); + } else { + block(nil, [[MeIOSException alloc] initWithMeException:error], size); + } + }); +} + +- (void)getIOSObjects:(MeIOSQuery *)query complete:(MeIOSListCallbackBlock)block { + MeQuery *meQuery = (MeQuery *)query.getObject; + meQuery->find(^(MeObject *obj, MeException *error, uint32_t size) { + if (!error) { + NSMutableArray *array = [[NSMutableArray alloc] init]; + for (int i = 0; i < size; i++) { + MeIOSObject *iOSObject = [[MeIOSObject alloc] initWithMeObject:&obj[i]]; + [array addObject:iOSObject]; + } + block(array, nil, size); + } else { + block(nil, [[MeIOSException alloc] initWithMeException:error], size); + } + }); +} + +- (void)getIOSObjectsWithJoinQuery:(MeIOSJoinQuery *)query complete:(MeIOSListCallbackBlock)block { + MeJoinQuery *joinQuery = (MeJoinQuery *)query.getObject; + MeBlockCallback* callback = new MeBlockCallback(); + MeCallbackBlock cloudBlock = ^(MeObject* obj, MeException *error, uint32_t size) { + if (!error) { + NSMutableArray *array = [[NSMutableArray alloc] init]; + for (int i = 0; i < size; i++) { + MeIOSObject *iOSObject = [[MeIOSObject alloc] initWithMeObject:&obj[i]]; + [array addObject:iOSObject]; + } + block(array, nil, size); + } else { + block(nil, [[MeIOSException alloc] initWithMeException:error], size); + } + }; + + callback->setBlock(cloudBlock); + joinQuery->find(callback); +} + +- (void)getWithUrl:(NSString *)url json:(MeIOSJSONObject *)json complete:(MeIOSJSONCallbackBlock)block { + MeBlockCallback* callback = new MeBlockCallback(); + MeCallbackBlock cloudBlock = ^(MeObject* obj, MeException *error, uint32_t size) { + if (!error) { + MeIOSJSONObject *object = [[MeIOSJSONObject alloc] initWithJSONObject:obj]; + block(object, nil, size); + } else { + block(nil, [[MeIOSException alloc] initWithMeException:error], size); + } + }; + + callback->setBlock(cloudBlock); + + map param; + if (json) { + JSONObject *object = (JSONObject *)(json.getObject); + param = object->stringdict(); + } + + MeCloud::shareInstance()->get([url UTF8String], param, callback); +} + +- (void)loginWithUsername:(NSString *)name password: (NSString *)password complete:(MeIOSUserCallbackBlock)block { + MeIOSUser *user = [[MeIOSUser alloc] init]; + MeUser *meUser = (MeUser *)(user.getObject); + meUser->login([name UTF8String], [password UTF8String], ^(MeObject *obj, MeException *error, uint32_t size) { + if (!error) { + block(user, nil, size); + } else { + block(nil, [[MeIOSException alloc] initWithMeException:error], size); + } + }); +} + +- (void)signUpWithUsername:(NSString *)name password: (NSString *)password complete:(MeIOSUserCallbackBlock)block { + MeIOSUser *user = [[MeIOSUser alloc] init]; + MeUser *meUser = (MeUser *)(user.getObject); + meUser->signup([name UTF8String], [password UTF8String], ^(MeObject *obj, MeException *error, uint32_t size) { + if (!error) { + block(user, nil, size); + } else { + block(nil, [[MeIOSException alloc] initWithMeException:error], size); + } + }); +} + +- (void)changePasswordWithUserName:(NSString *)name new: (NSString *)newPassword complete:(MeIOSUserCallbackBlock)block { + MeIOSUser *user = [[MeIOSUser alloc] init]; + MeUser *meUser = (MeUser *)(user.getObject); + meUser->changePassword([name UTF8String], [newPassword UTF8String], ^(MeObject *obj, MeException *error, uint32_t size) { + if (!error) { + block(user, nil, size); + } else { + block(nil, [[MeIOSException alloc] initWithMeException:error], size); + } + }); +} + +- (void)downloadFile:(NSString *)url type:(NSString *)filename complete:(MeIOSDownloadCallbackBlock)complete progress:(MeIOSHttpFileProgressBlock)progress { + MeDownloadFile *file = new MeDownloadFile(); + file->setDownloadUrl([url UTF8String]); + file->setFilename([filename UTF8String]); + file->download(^(MeFile *obj, MeException *error, uint32_t size) { + if (!error) { + MeIOSObject * object = [[MeIOSObject alloc] initWithMeObject:obj]; + complete(object, [NSString stringWithUTF8String:file->filePath()], nil, size); + } else { + complete(nil, nil, [[MeIOSException alloc] initWithMeException:error], size); + } + + delete file; + }, ^(uint64_t writen, uint64_t total_writen, uint64_t total_expect_write) { + if (progress) { + progress((NSUInteger)total_writen, (NSUInteger)total_expect_write); + } + }); +} + +- (void)uploadFile:(NSString *)path type:(NSString *)type complete:(MeIOSCallbackBlock)complete progress:(MeIOSHttpFileProgressBlock)progress { + MeUploadFile *file = new MeUploadFile(); + file->put("type", [type UTF8String]); + file->setUploadFilePath([path UTF8String]); + file->upload(^(MeFile *obj, MeException *error, uint32_t size) { + if (!error) { + MeIOSObject * object = [[MeIOSObject alloc] initWithMeObject:obj]; + complete(object, nil, size); + } else { + complete(nil, [[MeIOSException alloc] initWithMeException:error], size); + } + delete file; + }, ^(uint64_t writen, uint64_t total_writen, uint64_t total_expect_write) { + if (progress) { + progress((NSUInteger)total_writen, (NSUInteger)total_expect_write); + } + }); +} + +- (void)uploadData:(NSData *)data type:(NSString *)type complete:(MeIOSCallbackBlock)complete progress:(MeIOSHttpFileProgressBlock)progress { + MeUploadFile *file = new MeUploadFile(); + file->put("type", [type UTF8String]); + file->setUploadData((byte *)[data bytes], (int)(data.length)); + file->upload(^(MeFile *obj, MeException *error, uint32_t size) { + if (!error) { + MeIOSObject * object = [[MeIOSObject alloc] initWithMeObject:obj]; + complete(object, nil, size); + } else { + complete(nil, [[MeIOSException alloc] initWithMeException:error], size); + } + delete file; + }, ^(uint64_t writen, uint64_t total_writen, uint64_t total_expect_write) { + if (progress) { + progress((NSUInteger)total_writen, (NSUInteger)total_expect_write); + } + }); +} + +- (void)postDataWithUrl:(NSString *)url data:(NSData *)data complete:(MeIOSCallbackBlock)complete progress:(MeIOSHttpFileProgressBlock)progress { + MeIOSHttpDataCallback *callback = new MeIOSHttpDataCallback(); + MeCallbackBlock block = ^(MeObject* obj, MeException *error, uint32_t size) { + if (!error) { + MeIOSObject *json = [[MeIOSObject alloc]initWithJSONObject:obj]; + complete(json, nil, size); + } else { + complete(nil, [[MeIOSException alloc] initWithMeException:error], size); + } + }; + callback->setBlock(block); + + if (progress) { + MeHttpFileProgressBlock progressBlock = ^(uint64_t writen, uint64_t total_writen, uint64_t total_expect_write) { + progress((NSUInteger)total_writen, (NSUInteger)total_expect_write); + }; + + callback->setProgressBlock(progressBlock); + } + + MeCloud::shareInstance()->postData([url UTF8String], (byte *)[data bytes], (int)data.length, callback); +} + +- (void)requestSMSAuthCode:(NSString *)phone complete:(MeIOSJSONCallbackBlock)complete { + MeBlockCallback* callback = new MeBlockCallback(); + MeCallbackBlock cloudBlock = ^(MeObject* obj, MeException *error, uint32_t size) { + if (!error) { + MeIOSJSONObject *json = [[MeIOSJSONObject alloc]initWithJSONObject:obj]; + complete(json, nil, size); + } else { + complete(nil, [[MeIOSException alloc] initWithMeException:error], size); + } + }; + callback->setBlock(cloudBlock); + + MeSMS::sendSMS([phone UTF8String], callback); +} + +// 发送私信 +- (void)sendMessage:(MeIOSObject *)object complete:(MeIOSCallbackBlock)block { + +} + +// 磁盘缓存数据 +- (void)saveJSONToCache:(MeIOSJSONObject *)json key:(NSString *)key { + if (!key) { + return; + } + + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + MeCloud::shareInstance()->saveJSONToCache((JSONObject *)(json.getObject), [key UTF8String]); + }); +} + +// 从磁盘缓存读取数据 +- (MeIOSJSONObject *)getJSONFromCache:(NSString *)key { + if (!key) { + return nil; + } + + JSONObject *json = MeCloud::shareInstance()->getJSONFromCache([key UTF8String]); + if (json == NULL) { + return NULL; + } + MeIOSJSONObject *object = [[MeIOSJSONObject alloc] initWithJSONObject:json]; + delete json; + + return object; +} + +- (void)removeJSONFromCache:(NSString *)key { + if (!key) { + return; + } + + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + MeCloud::shareInstance()->removeJSONFromCache([key UTF8String]); + }); +} + +@end diff --git a/src/ios/MeIOSObject.h b/src/ios/MeIOSObject.h new file mode 100644 index 0000000..5a9baf2 --- /dev/null +++ b/src/ios/MeIOSObject.h @@ -0,0 +1,43 @@ +// +// MeIOSObject.h +// MeCloud +// +// Created by super on 2017/8/10. +// Copyright © 2017年 Rex. All rights reserved. +// + +#import +#import "MeIOSJSONObject.h" +#import "MeIOSACL.h" + +@interface MeIOSObject : MeIOSJSONObject + +- (id)initWithClassName:(NSString *)className; + +- (id)initWithMeObject:(void *)_object; + +- (id)initWithObjectID:(NSString *)objectID className:(NSString *)className; + +- (NSString *)className; + +- (NSString *)objectID; + +- (void)setClassName:(NSString *)className; + +- (NSMutableArray *)meObjectArrayWithKey:(NSString *)key; + +- (MeIOSObject *)meObjectWithKey:(NSString *)key; + +// 设置权限 +- (void)setACL:(MeIOSACL *)acl; + +// 获取权限 +- (MeIOSACL *)getACL; + +- (void)setObject:(MeIOSObject *)iosObject key:(NSString *)key; + +- (void)setObjects:(NSArray *)iosObject key:(NSString *)key; + +- (void)addObject:(MeIOSObject *)iosObject key:(NSString *)key; + +@end diff --git a/src/ios/MeIOSObject.mm b/src/ios/MeIOSObject.mm new file mode 100644 index 0000000..95a4c9f --- /dev/null +++ b/src/ios/MeIOSObject.mm @@ -0,0 +1,134 @@ +// +// MeIOSObject.m +// MeCloud +// +// Created by super on 2017/8/10. +// Copyright © 2017年 Rex. All rights reserved. +// + +#import "MeIOSObject.h" +#import "MeIOSJSONObject.h" +#import "MeObject.h" + +@implementation MeIOSObject + +- (id)initWithClassName:(NSString *)className { + if (self = [super init]) { + [self clearObject]; + object = new MeObject([className UTF8String]); + } + + return self; +} + +- (id)initWithMeObject:(void *)_object { + if (self = [super init]) { + [self clearObject]; + object = new MeObject((MeObject *)_object, false); + } + + return self; +} + +- (id)initWithObjectID:(NSString *)objectID className:(NSString *)className { + if (self = [super init]) { + [self clearObject]; + object = new MeObject([objectID UTF8String], [className UTF8String]); + } + + return self; +} + +- (void)loadObject { + [self clearObject]; + object = new MeObject(); +} + +- (void *)getMeObject { + return object; +} + +- (MeObject *)meObject { + return (MeObject *)object; +} + +- (void)setMeObject:(MeObject *)_object { + if (object) { + delete (MeObject *)object; + object = NULL; + } + // 深拷贝一份 + object = new MeObject(_object, false); +} + +- (NSString *)className { + return [NSString stringWithUTF8String:self.meObject->className()]; +} + +- (void)setClassName:(NSString *)className { + if (!className || className.length <= 0) { + return; + } + + self.meObject->setClassName([className UTF8String]); +} + +- (NSString *)objectID { + return [NSString stringWithUTF8String:self.meObject->objectId()]; +} + +- (void)setACL:(MeIOSACL *)acl { + self.meObject->setACL((MeACL *)(acl.getObject)); +} + +- (MeIOSACL *)getACL { + MeACL acl = self.meObject->getACL(); + return [[MeIOSACL alloc]initWithACL:&acl]; +} + +- (MeIOSObject *)meObjectWithKey:(NSString *)key { + MeObject object = self.meObject->objectValue([key UTF8String]); + return [[MeIOSObject alloc] initWithMeObject: &object]; +} + +- (void)setObject:(MeIOSObject *)iosObject key:(NSString *)key { + if (!key || key.length <= 0 || !iosObject) return; + self.meObject->set([key UTF8String], (MeObject *)(iosObject.getObject)); +} + +- (NSMutableArray *)meObjectArrayWithKey:(NSString *)key { + if (!key || key.length <= 0) return nil; + JSONArray array = self.meObject->arrayValue([key UTF8String]); + NSMutableArray *jsonArray = [NSMutableArray array]; + for (int i = 0; i < array.size(); i++) { + JSONObject json = array.jsonValue(i); + MeObject *childObject = new MeObject(); + childObject->copy(&json, false); + [jsonArray addObject:[[MeIOSObject alloc] initWithMeObject:childObject]]; + delete childObject; + } + + return jsonArray; +} + +- (void)setObjects:(NSArray *)iosObjects key:(NSString *)key { + if (!key || key.length <= 0 || !iosObjects || iosObjects.count <= 0) return; + JSONArray *array = new JSONArray(); + __block NSString *className = @""; + [iosObjects enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + MeIOSObject *object = (MeIOSObject *)obj; + MeObject *newObject = new MeObject((MeObject *)(object.getObject), false); + array->append(newObject); + className = object.className; + }]; + + self.meObject->set([key UTF8String], array, [className UTF8String]); + delete array; +} + +- (void)addObject:(MeIOSObject *)iosObject key:(NSString *)key { + if (!key || key.length <= 0 || !iosObject) return; + self.meObject->add([key UTF8String], (MeObject *)(iosObject.getObject)); +} + +@end diff --git a/src/ios/MeIOSQuery.h b/src/ios/MeIOSQuery.h new file mode 100644 index 0000000..0d8c187 --- /dev/null +++ b/src/ios/MeIOSQuery.h @@ -0,0 +1,102 @@ +// +// MeIOSQuery.h +// MeCloud +// +// Created by super on 2017/8/11. +// Copyright © 2017年 Rex. All rights reserved. +// + +#import +#import "MeIOSJSONObject.h" + +typedef enum { + IOSCOUNT = 1, + IOSID, + IOSLIST, + IOSJSONOBJECT, + IOSDISTINCTCOUNT +} MEIOSAGGREGATEMETHOD; + +@interface MeIOSAggregate : MeIOSJSONObject + +- (id)initWithClassName:(NSString *)name; + +- (void)addWhereEqualWithKey:(NSString *)key value:(NSString *)value; + +- (void)addWhereEqualWithKey:(NSString *)key intValue:(NSInteger)value; + +- (void)addWhereNotEqualWithKey:(NSString *)key value:(NSString *)value; + +- (void)addWhereNotEqualWithKey:(NSString *)key intValue:(NSInteger)value; + +- (void)addWhereGreaterWithKey:(NSString *)key value:(NSString *)value; + +- (void)addWhereGreaterWithKey:(NSString *)key intValue:(NSInteger)value; + +- (void)addWhereLessWithKey:(NSString *)key value:(NSString *)value; + +- (void)addWhereLessWithKey:(NSString *)key intValue:(NSInteger)value; + +- (void)setMethod:(MEIOSAGGREGATEMETHOD)method; + +- (void)setResponseKey:(NSString *)key; + +- (void)setDistinctKey:(NSString *)key; + +@end + +@interface MeIOSQuery : MeIOSJSONObject + +- (id)initWithClassName:(NSString *)name; + +// where equal 条件 +- (void)addWhereEqualWithKey:(NSString *)key value:(NSString *)value; + +- (void)addWhereEqualWithKey:(NSString *)key intValue:(NSInteger)value; + +- (void)addWhereEqualOrWithKey:(NSString *)key value:(NSString *)value; + +- (void)addWhereEqualOrWithKey:(NSString *)key intValue:(NSInteger)value; + +- (void)addWhereGreaterWithKey:(NSString *)key value:(NSString *)value; + +- (void)addWhereGreaterWithKey:(NSString *)key intValue:(NSInteger)value; + +- (void)addWhereLessWithKey:(NSString *)key value:(NSString *)value; + +- (void)addWhereLessWithKey:(NSString *)key intValue:(NSInteger)value; + +// where notEqual 条件 +- (void)addWhereNotEqualWithKey:(NSString *)key value:(NSString *)value; + +- (void)addWhereNotEqualWithKey:(NSString *)key intValue:(NSInteger)value; + +// 选择那些字段 +- (void)addSelectKeys:(NSMutableArray *)array; + +// 不选择那些字段 +- (void)addNotSelectKeys:(NSMutableArray *)array; + +// 增加选择某个字段 +- (void)addSelectKey:(NSString *)key; + +// 增加放弃选择某个字段 +- (void)addNotSelectKey:(NSString *)key; + +// 升序 +- (void)addAscendSortKeys:(NSString *)key; + +// 倒序 +- (void)addDescendSortKeys:(NSString *)key; + +// 分页 +- (void)addLimit:(NSInteger)count; + +// 偏移量 +- (void)addStartId:(NSString *)startId; + +- (void)addAggregate:(MeIOSAggregate *)aggregate; + +- (void)setAggregate:(MeIOSAggregate *)aggregate; + +@end diff --git a/src/ios/MeIOSQuery.mm b/src/ios/MeIOSQuery.mm new file mode 100644 index 0000000..559f9e5 --- /dev/null +++ b/src/ios/MeIOSQuery.mm @@ -0,0 +1,203 @@ +// +// MeIOSQuery.m +// MeCloud +// +// Created by super on 2017/8/11. +// Copyright © 2017年 Rex. All rights reserved. +// + +#import "MeIOSQuery.h" +#import "MeQuery.h" + +@implementation MeIOSAggregate + +- (id)initWithClassName:(NSString *)name { + if (self = [super init]) { + [self clearObject]; + object = new MeAggregateObject([name UTF8String]); + } + + return self; +} + +- (MeAggregateObject *)aggregate { + return (MeAggregateObject *)object; +} + +- (void)addWhereEqualWithKey:(NSString *)key value:(NSString *)value { + if (!key || key.length <= 0) return; + self.aggregate->whereEqualTo([key UTF8String], [value UTF8String]); +} + +- (void)addWhereEqualWithKey:(NSString *)key intValue:(NSInteger)value { + if (!key || key.length <= 0) return; + self.aggregate->whereNotEqualTo([key UTF8String], (int)value); +} + +- (void)addWhereNotEqualWithKey:(NSString *)key value:(NSString *)value { + if (!key || key.length <= 0) return; + self.aggregate->whereNotEqualTo([key UTF8String], [value UTF8String]); + +} + +- (void)addWhereNotEqualWithKey:(NSString *)key intValue:(NSInteger)value { + if (!key || key.length <= 0) return; + self.aggregate->whereNotEqualTo([key UTF8String], (int)value); + +} + +- (void)addWhereGreaterWithKey:(NSString *)key value:(NSString *)value { + if (!key || key.length <= 0) return; + self.aggregate->whereGreater([key UTF8String], [value UTF8String]); +} + +- (void)addWhereGreaterWithKey:(NSString *)key intValue:(NSInteger)value { + if (!key || key.length <= 0) return; + self.aggregate->whereGreater([key UTF8String], (int)value); +} + +- (void)addWhereLessWithKey:(NSString *)key value:(NSString *)value { + if (!key || key.length <= 0) return; + self.aggregate->whereLess([key UTF8String], [value UTF8String]); +} + +- (void)addWhereLessWithKey:(NSString *)key intValue:(NSInteger)value { + if (!key || key.length <= 0) return; + self.aggregate->whereLess([key UTF8String], (int)value); +} + +- (void)setMethod:(MEIOSAGGREGATEMETHOD)method { + self.aggregate->setMethod((MEAGGREGATEMETHOD)method); +} + +- (void)setResponseKey:(NSString *)key { + if (!key || key.length <= 0) return; + self.aggregate->setResponseKey([key UTF8String]); +} + +- (void)setDistinctKey:(NSString *)key { + if (!key || key.length <= 0) return; + self.aggregate->setDistinctKey([key UTF8String]); +} + +@end + +@implementation MeIOSQuery + +- (id)initWithClassName:(NSString *)name { + if (self = [super init]) { + [self clearObject]; + object = new MeQuery([name UTF8String]); + } + + return self; +} + +- (void)loadObject { + [self clearObject]; + object = new MeQuery("#warning 没有查询表名称"); +} + +- (MeQuery *)meQuery { + return (MeQuery *)object; +} + +- (void)addWhereEqualWithKey:(NSString *)key value:(NSString *)value { + if (!key || key.length <= 0) return; + self.meQuery->whereEqualTo([key UTF8String], [value UTF8String]); +} + +- (void)addWhereEqualWithKey:(NSString *)key intValue:(NSInteger)value { + if (!key || key.length <= 0) return; + self.meQuery->whereEqualTo([key UTF8String], (int)value); +} + +- (void)addWhereGreaterWithKey:(NSString *)key value:(NSString *)value { + if (!key || key.length <= 0) return; + self.meQuery->whereGreater([key UTF8String], [value UTF8String]); +} + +- (void)addWhereGreaterWithKey:(NSString *)key intValue:(NSInteger)value { + self.meQuery->whereGreater([key UTF8String], value); +} + +- (void)addWhereLessWithKey:(NSString *)key value:(NSString *)value { + self.meQuery->whereLess([key UTF8String], [value UTF8String]); +} + +- (void)addWhereLessWithKey:(NSString *)key intValue:(NSInteger)value { + self.meQuery->whereLess([key UTF8String], value); +} + +- (void)addWhereEqualOrWithKey:(NSString *)key value:(NSString *)value { + if (!key || key.length <= 0) return; + self.meQuery->whereEqualOr([key UTF8String], [value UTF8String]); +} + +- (void)addWhereEqualOrWithKey:(NSString *)key intValue:(NSInteger)value { + if (!key || key.length <= 0) return; + self.meQuery->whereEqualOr([key UTF8String], (int)value); +} + +- (void)addWhereNotEqualWithKey:(NSString *)key value:(NSString *)value { + if (!key || key.length <= 0) return; + self.meQuery->whereNotEqualTo([key UTF8String], [value UTF8String]); +} + +- (void)addWhereNotEqualWithKey:(NSString *)key intValue:(NSInteger)value { + if (!key || key.length <= 0) return; + self.meQuery->whereNotEqualTo([key UTF8String], (int)value); +} + +- (void)addSelectKeys:(NSMutableArray *)array { + [array enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + [self addSelectKey:obj]; + }]; +} + +- (void)addNotSelectKeys:(NSMutableArray *)array { + [array enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + [self addNotSelectKey:obj]; + }]; +} + +- (void)addSelectKey:(NSString *)key { + if (!key || key.length <= 0) return; + self.meQuery->addSelectKey([key UTF8String]); +} + +- (void)addNotSelectKey:(NSString *)key { + if (!key || key.length <= 0) return; + self.meQuery->addNotSelectKey([key UTF8String]); +} + +- (void)addAscendSortKeys:(NSString *)key { + if (!key || key.length <= 0) return; + self.meQuery->addAscendSortKeys([key UTF8String]); +} + +- (void)addDescendSortKeys:(NSString *)key { + if (!key || key.length <= 0) return; + self.meQuery->addDescendSortKeys([key UTF8String]); +} + +- (void)addLimit:(NSInteger)count { + self.meQuery->addLimit(count); +} + +- (void)addStartId:(NSString *)startId { + if (!startId || startId.length <= 0) return; + self.meQuery->addStartId([startId UTF8String]); +} + +- (void)addAggregate:(MeIOSAggregate *)aggregate { + if (!aggregate) return; + self.meQuery->addAggregateObject((MeAggregateObject *)(aggregate.getObject)); +} + +- (void)setAggregate:(MeIOSAggregate *)aggregate { + if (!aggregate) return; + self.meQuery->setAggregateObject((MeAggregateObject *)(aggregate.getObject)); +} + +@end diff --git a/src/ios/MeIOSRole.h b/src/ios/MeIOSRole.h new file mode 100644 index 0000000..413612e --- /dev/null +++ b/src/ios/MeIOSRole.h @@ -0,0 +1,23 @@ +// +// MeIOSRole.h +// MeCloud +// +// Created by super on 2017/8/11. +// Copyright © 2017年 Rex. All rights reserved. +// + +#import +#import "MeIOSObject.h" +#import "MeIOSUser.h" + +@interface MeIOSRole : MeIOSObject + +- (id)initWithRoleName:(NSString *)roleName; + +// 为角色增加一个用户,参数为MeIOSUser object +- (void)setUser:(MeIOSUser *)user; + +// 为角色增加一个用户,参数为userId +- (void)setUserWIthId:(NSString *)userId; + +@end diff --git a/src/ios/MeIOSRole.mm b/src/ios/MeIOSRole.mm new file mode 100644 index 0000000..7d58011 --- /dev/null +++ b/src/ios/MeIOSRole.mm @@ -0,0 +1,40 @@ +// +// MeIOSRole.m +// MeCloud +// +// Created by super on 2017/8/11. +// Copyright © 2017年 Rex. All rights reserved. +// + +#import "MeIOSRole.h" +#import "MeRole.h" + +@implementation MeIOSRole + +- (id)initWithRoleName:(NSString *)roleName { + if (self = [super init]) { + [self clearObject]; + object = new MeRole([roleName UTF8String]); + } + + return self; +} + +- (MeRole *)meRole { + return (MeRole *)object; +} + +- (void) loadObject { + [self clearObject]; + object = new MeRole("#warning 没有角色名称"); +} + +- (void)setUser:(MeIOSUser *)user { + self.meRole->setUser((MeUser *)(user.getObject)); +} + +- (void)setUserWIthId:(NSString *)userId { + self.meRole->setUser([userId UTF8String]); +} + +@end diff --git a/src/ios/MeIOSUser.h b/src/ios/MeIOSUser.h new file mode 100644 index 0000000..82f7a6a --- /dev/null +++ b/src/ios/MeIOSUser.h @@ -0,0 +1,32 @@ +// +// MeIOSUser.h +// MeCloud +// +// Created by super on 2017/8/11. +// Copyright © 2017年 Rex. All rights reserved. +// + + +#import "MeIOSObject.h" + +@interface MeIOSUser : MeIOSObject + +@property (nonatomic, copy, readonly) NSString *userID; + +@property (nonatomic, copy, readonly) NSString *deviceID; + +@property (nonatomic, copy, readonly) NSString *username; + +- (id)initWithMeUser:(void *)meUser; + +- (id)initWithJSONValue:(MeIOSJSONObject *)jsonValue; + ++ (void)saveLoginUser:(MeIOSUser *)user; + ++ (NSString *)encodePassword:(NSString *)username password:(NSString *)password; + ++ (NSString *)device; + ++ (NSString *)getMeObjectID; + +@end diff --git a/src/ios/MeIOSUser.mm b/src/ios/MeIOSUser.mm new file mode 100644 index 0000000..bf04350 --- /dev/null +++ b/src/ios/MeIOSUser.mm @@ -0,0 +1,91 @@ +// +// MeIOSUser.m +// MeCloud +// +// Created by super on 2017/8/11. +// Copyright © 2017年 Rex. All rights reserved. +// + +#import "MeIOSUser.h" +#import "MeUser.h" + +@implementation MeIOSUser + ++ (void)saveLoginUser:(MeIOSUser *)user { + MeUser::saveLoginUser((MeUser *)(user.getObject)); +} + ++ (NSString *)encodePassword:(NSString *)username password:(NSString *)password { + const char *encode = MeUser::encodePassword([username UTF8String], [password UTF8String]); + NSString *iOSPassword = [NSString stringWithUTF8String:encode]; + delete encode; + return iOSPassword; +} + ++ (NSString *)device { + return [NSString stringWithUTF8String:MeUser::device()]; +} + ++ (NSString *)getMeObjectID { + MeIOSObject *object = [[MeIOSObject alloc] init]; + return object.objectID; +} + +- (id)initWithMeUser:(void *)meUser { + if (self = [super init]) { + ((MeUser *)object)->copy((MeUser *)meUser, false); + } + + return self; +} + +- (id)initWithJSONValue:(MeIOSJSONObject *)jsonValue { + if (self = [super init]) { + [self clearObject]; + object = new MeUser((JSONObject *)(jsonValue.getObject)); + } + + return self; +} + +- (void)loadObject { + [self clearObject]; + object = new MeUser(); +} + +- (MeUser *)meUser { + return (MeUser *)object; +} + +- (NSString *)username { + const char *name = self.meUser->stringValue("username"); + if (name) { + return [NSString stringWithUTF8String:name]; + } + + return nil; +} + +- (NSString *)userID { + const char *_id = self.meUser->stringValue("_id"); + if (_id) { + return [NSString stringWithUTF8String:_id]; + } + + return nil; +} + +- (NSString *)deviceID { + const char *device = self.meUser->stringValue("device"); + if (device) { + return [NSString stringWithUTF8String:device]; + } + + return nil; +} + +- (NSString *)description { + return [NSString stringWithUTF8String:self.meUser->toString()]; +} + +@end diff --git a/src/ios/MeObject.mm b/src/ios/MeObject.mm new file mode 100644 index 0000000..3b9b0de --- /dev/null +++ b/src/ios/MeObject.mm @@ -0,0 +1,17 @@ +/** + * file : MeObject.mm + * author : Rex + * create : 2017-07-06 20:22 + * func : + * history: + */ + +#include "McBasic.h" +#include "MeObject.h" +#include "MeIOSCallback.h" + +void MeObject::save(MeCallbackBlock block){ + MeBlockCallback* callback = new MeBlockCallback(m_classname, this); + callback->setBlock(block); + MeObject::save(callback); +} diff --git a/src/ios/MeQuery.mm b/src/ios/MeQuery.mm new file mode 100644 index 0000000..2a9ded6 --- /dev/null +++ b/src/ios/MeQuery.mm @@ -0,0 +1,22 @@ +// +// MeQuery.m +// MeCloud +// +// Created by super on 2017/7/20. +// Copyright © 2017年 Rex. All rights reserved. +// + +#include "MeQuery.h" +#include "MeIOSCallback.h" + +void MeQuery::find(MeCallbackBlock block){ + MeBlockCallback* callback = new MeBlockCallback(m_classname); + callback->setBlock(block); + MeQuery::find(callback); +} + +void MeQuery::get(const char* objectId, MeCallbackBlock block){ + MeBlockCallback* callback = new MeBlockCallback(m_classname); + callback->setBlock(block); + MeQuery::get(objectId, callback); +} diff --git a/src/ios/MeUploadFile.mm b/src/ios/MeUploadFile.mm new file mode 100644 index 0000000..831fbb4 --- /dev/null +++ b/src/ios/MeUploadFile.mm @@ -0,0 +1,31 @@ +// +// MeUploadFile.m +// MeCloud +// +// Created by super on 2017/7/31. +// Copyright © 2017年 Rex. All rights reserved. +// + +#import "MeUploadFile.h" +#import "MeIOSCallback.h" +#import + +void MeUploadFile::upload(MeHttpFileCallbackBlock block, MeHttpFileProgressBlock progressBlock) { + getAuthInfomation(^(MeObject *obj, MeException *err, uint32_t size) { + if (err || obj->intValue("errCode") != 0) { + block(this, err, size); + } else { + MeIOSHttpFileCallback *callback = new MeIOSHttpFileCallback(m_classname, this); + callback->setBlock(block); + callback->setProgressBlock(progressBlock); + upload(callback, obj); + } + }); +} + +// 获取上传文件的授权消息 +void MeUploadFile::getAuthInfomation(MeCallbackBlock callbackBlock){ + MeBlockCallback* callback = new MeBlockCallback(m_classname, this); + callback->setBlock(callbackBlock); + MeUploadFile::getAuthInfomation(callback); +} diff --git a/src/ios/MeUser.mm b/src/ios/MeUser.mm new file mode 100644 index 0000000..eb7162c --- /dev/null +++ b/src/ios/MeUser.mm @@ -0,0 +1,44 @@ +/** + * file : MeUser.mm + * author : Rex + * create : 2017-07-07 17:08 + * func : + * history: + */ + +#include "bs.h" +#include "MeUser.h" +#import + +code_user MeUser::signup(const char* username, const char* password, MeCallbackBlock callback) { + m_callback = (__bridge MeCallbackBlock)Block_copy((__bridge void *)callback); + return signup(username, password, this); +} + +code_user MeUser::login(const char* username, const char* password, MeCallbackBlock callback) { + m_callback = (__bridge MeCallbackBlock)Block_copy((__bridge void *)callback); + return login(username, password, this); +} + +code_user MeUser::changePassword(const char* username, const char* newPassword, MeCallbackBlock callback){ + m_callback = (__bridge MeCallbackBlock)Block_copy((__bridge void *)callback); + return changePassword(username, newPassword, this); +} + +#pragma --mark "回调" +void MeUser::done(MeObject *obj, MeException *err, uint32_t size) { + // 写currentUser + if (err == NULL) { + // 存储CurrentUser + saveLoginUser(obj); + } + + if (m_callback != nil) { + // 在主线程中回调 + dispatch_sync(dispatch_get_main_queue(), ^{ + m_callback(obj, err, size); + Block_release(m_callback); + m_callback = nil; + }); + } +} diff --git a/src/setup.sh b/src/setup.sh new file mode 100755 index 0000000..8c10bd0 --- /dev/null +++ b/src/setup.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +action=$1 +path=$2 + +modules=("mc") +remotes=("git@github.com:rexbu/MobileCross.git") +localdirs=("mc") + +echo "---- start: ${BASH_SOURCE}" + +if [ "$action" = "init" ];then + for ((i=0; i<${#modules[@]};i++)); do + git remote add ${modules[i]} ${remotes[i]} + git subtree add --prefix ${path}${localdirs[i]} ${modules[i]} master + setup=${path}${localdirs[i]}/setup.sh + if [ -f "$setup" ];then + $setup $action ${path}${localdirs[i]}/ + fi + done +elif [ "$action" = "push" ];then + for ((i=0; i<${#modules[@]};i++)); do + setup=${path}${localdirs[i]}/setup.sh + if [ -f "$setup" ];then + $setup $action ${path}${localdirs[i]}/ + fi + git subtree push --prefix ${path}${localdirs[i]} ${remotes[i]} master + done +elif [ "$action" = "pull" ];then + for ((i=0; i<${#modules[@]};i++)); do + setup=${path}${localdirs[i]}/setup.sh + if [ -f "$setup" ];then + $setup $action ${path}${localdirs[i]}/ + fi + git subtree pull --prefix ${path}${localdirs[i]} ${remotes[i]} master + done +else + echo "please use ./setup.sh {action} {path}. action:init|push|pull. when path is current dir, don't use path. eg: ./setup.sh push" +fi + +echo "#### end: ${BASH_SOURCE}"