From 431444c47e8c19b7765ae2edcf2a37db02bb20b5 Mon Sep 17 00:00:00 2001 From: Pawel Wasowski Date: Thu, 22 Jun 2017 12:29:13 +0200 Subject: [PATCH 01/16] [SystemInfo] Fix for "BATTERY" property value change listener callbacks Callbacks called on "BATTERY" property value change threw an exception, if "lowThreshold" or "highThreshold" SystemInfoOptions were specified. [Verification] Tested in Chrome DevTools, registered callbacks work fine. Change-Id: Ie50dfb0710e9b203e072ff5336b77ff27c464031 Signed-off-by: Pawel Wasowski --- src/systeminfo/systeminfo_api.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/systeminfo/systeminfo_api.js b/src/systeminfo/systeminfo_api.js index 2e5dc4f..bb656c0 100644 --- a/src/systeminfo/systeminfo_api.js +++ b/src/systeminfo/systeminfo_api.js @@ -898,13 +898,13 @@ function _systeminfoBatteryListenerCallback(eventObj) { for (var watchId in callbacks) { if (callbacks.hasOwnProperty(watchId)) { var listener = callbacks[watchId]; + var propObj = !listener.isArrayType ? + _createProperty(property, eventObj.result.array[0]) : + _createPropertyArray(property, eventObj.result); var executeCall = (T_.isUndefined(listener.lowThreshold) || (propObj.level <= listener.lowThreshold)) || (T_.isUndefined(listener.highThreshold) || (propObj.level >= listener.highThreshold)); - var propObj = !listener.isArrayType ? - _createProperty(property, eventObj.result.array[0]) : - _createPropertyArray(property, eventObj.result); if (executeCall) { listener.callback(propObj); } -- 2.7.4 From 8cce89cd15716deacefede58942ea342009ad928 Mon Sep 17 00:00:00 2001 From: Lukasz Bardeli Date: Wed, 28 Jun 2017 08:24:32 +0200 Subject: [PATCH 02/16] [Application][Alarm] Free app_control_h using app_control_destroy [Verification] Code compiles without error. TCT passrate Alarm 100% AppControl 100% Application 100% Change-Id: I5c32e2307d9b7e8b36df0919c670c97b5828a572 --- src/alarm/alarm_utils.cc | 26 ++++++++++++++++++++------ src/application/application_utils.cc | 23 +++++++++++++++++------ 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/src/alarm/alarm_utils.cc b/src/alarm/alarm_utils.cc index 1c9ee9d..ba8872c 100755 --- a/src/alarm/alarm_utils.cc +++ b/src/alarm/alarm_utils.cc @@ -14,6 +14,8 @@ * limitations under the License. */ +#include + #include "alarm_utils.h" #include "common/logger.h" @@ -34,9 +36,19 @@ PlatformResult AppControlToService(const picojson::object& obj, app_control_h *a return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed."); } - app_control_create(app_control); + app_control_h app_control_tmp = nullptr; + int result = app_control_create(&app_control_tmp); + + if (APP_CONTROL_ERROR_NONE != result) { + return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Creation AppControl failed.", + ("Problem with create handle.")); + } + + std::unique_ptr::type, int(*)(app_control_h)> app_control_ptr( + app_control_tmp, &app_control_destroy); + - int ret = app_control_set_operation(*app_control, it_operation->second.get().c_str()); + int ret = app_control_set_operation(app_control_tmp, it_operation->second.get().c_str()); if (APP_CONTROL_ERROR_NONE != ret) { return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Error while setting operation.", ("Failed app_control_set_operation(): %d (%s)", ret, get_error_message(ret))); @@ -44,7 +56,7 @@ PlatformResult AppControlToService(const picojson::object& obj, app_control_h *a const auto it_uri = obj.find("uri"); if (it_end != it_uri && it_uri->second.is()) { - ret = app_control_set_uri(*app_control, it_uri->second.get().c_str()); + ret = app_control_set_uri(app_control_tmp, it_uri->second.get().c_str()); if (APP_CONTROL_ERROR_NONE != ret) { return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Error while setting uri.", ("Failed app_control_set_uri(): %d (%s)", ret, get_error_message(ret))); @@ -53,7 +65,7 @@ PlatformResult AppControlToService(const picojson::object& obj, app_control_h *a const auto it_mime = obj.find("mime"); if (it_end != it_mime && it_mime->second.is()) { - ret = app_control_set_mime(*app_control, it_mime->second.get().c_str()); + ret = app_control_set_mime(app_control_tmp, it_mime->second.get().c_str()); if (APP_CONTROL_ERROR_NONE != ret) { return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Error while setting mime.", ("Failed app_control_set_mime(): %d (%s)", ret, get_error_message(ret))); @@ -62,7 +74,7 @@ PlatformResult AppControlToService(const picojson::object& obj, app_control_h *a const auto it_category = obj.find("category"); if (it_end != it_category && it_category->second.is()) { - ret = app_control_set_category(*app_control, it_category->second.get().c_str()); + ret = app_control_set_category(app_control_tmp, it_category->second.get().c_str()); if (APP_CONTROL_ERROR_NONE != ret) { return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Error while setting category.", ("Failed app_control_set_category(): %d (%s)", ret, get_error_message(ret))); @@ -75,7 +87,7 @@ PlatformResult AppControlToService(const picojson::object& obj, app_control_h *a PlatformResult result = PlatformResult(ErrorCode::NO_ERROR); for (auto iter = data.begin(); iter != data.end(); ++iter) { - result = AppControlToServiceExtraData(iter->get(), app_control); + result = AppControlToServiceExtraData(iter->get(), &app_control_tmp); if (!result) { LoggerE("Failed AppControlToServiceExtraData()"); return result; @@ -83,6 +95,8 @@ PlatformResult AppControlToService(const picojson::object& obj, app_control_h *a } } + *app_control = app_control_ptr.release(); + return PlatformResult(ErrorCode::NO_ERROR); } diff --git a/src/application/application_utils.cc b/src/application/application_utils.cc index a7860c1..8d56999 100644 --- a/src/application/application_utils.cc +++ b/src/application/application_utils.cc @@ -207,24 +207,33 @@ PlatformResult ApplicationUtils::ApplicationControlToService( return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter was passed."); } - app_control_create(app_control); + app_control_h app_control_tmp = nullptr; + int result = app_control_create(&app_control_tmp); + + if (APP_CONTROL_ERROR_NONE != result) { + return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Creation AppControl failed.", + ("Problem with create handle.")); + } + + std::unique_ptr::type, int(*)(app_control_h)> app_control_ptr( + app_control_tmp, &app_control_destroy); // operation - app_control_set_operation(*app_control, it_operation->second.get().c_str()); + app_control_set_operation(app_control_tmp, it_operation->second.get().c_str()); // uri if (it_uri->second.is()) { - app_control_set_uri(*app_control, it_uri->second.get().c_str()); + app_control_set_uri(app_control_tmp, it_uri->second.get().c_str()); } // mime if (it_mime->second.is()) { - app_control_set_mime(*app_control, it_mime->second.get().c_str()); + app_control_set_mime(app_control_tmp, it_mime->second.get().c_str()); } // category if (it_category->second.is()) { - app_control_set_category(*app_control, it_category->second.get().c_str()); + app_control_set_category(app_control_tmp, it_category->second.get().c_str()); } // ApplicationControlData @@ -233,7 +242,7 @@ PlatformResult ApplicationUtils::ApplicationControlToService( for (auto iter = data.begin(); iter != data.end(); ++iter) { if (iter->is()) { PlatformResult ret = - ApplicationControlDataToServiceExtraData(iter->get(), *app_control); + ApplicationControlDataToServiceExtraData(iter->get(), app_control_tmp); if (ret.IsError()) { LoggerE("Failed ApplicationControlDataToServiceExtraData()"); return ret; @@ -241,6 +250,8 @@ PlatformResult ApplicationUtils::ApplicationControlToService( } } + *app_control = app_control_ptr.release(); + return PlatformResult(ErrorCode::NO_ERROR); } -- 2.7.4 From 5d1ec94bd224dbde3b64ba124f8e6f2ad0bdd486 Mon Sep 17 00:00:00 2001 From: Piotr Kosko Date: Wed, 28 Jun 2017 08:48:39 +0200 Subject: [PATCH 03/16] [version] 1.88 Change-Id: I8944a33b7b9421c481f988f09f753c668fae927c Signed-off-by: Piotr Kosko --- packaging/webapi-plugins.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/webapi-plugins.spec b/packaging/webapi-plugins.spec index 737966a..e823e27 100644 --- a/packaging/webapi-plugins.spec +++ b/packaging/webapi-plugins.spec @@ -10,7 +10,7 @@ %define crosswalk_extensions_path %{_libdir}/%{crosswalk_extensions} Name: webapi-plugins -Version: 1.87 +Version: 1.88 Release: 0 License: Apache-2.0 and BSD-3-Clause and MIT Group: Development/Libraries -- 2.7.4 From 3b71b0bac5e1bb09c50c97168dba1619b3ed40d6 Mon Sep 17 00:00:00 2001 From: Jakub Skowron Date: Fri, 30 Jun 2017 16:02:34 +0200 Subject: [PATCH 04/16] [Utils] Fix privilege bypass, StringCopy function User could redefine String and String.indexOf to bypass privilege check and to go outside of virtual-root by ../ in path Change-Id: Ia9f7210ba685d1df18c9c443706361f624a38c1e Signed-off-by: Jakub Skowron --- src/filesystem/js/common.js | 2 ++ src/utils/utils_api.js | 66 ++++++++++++++++++++++++++++++--------------- 2 files changed, 46 insertions(+), 22 deletions(-) diff --git a/src/filesystem/js/common.js b/src/filesystem/js/common.js index adf52c7..e900cb3 100644 --- a/src/filesystem/js/common.js +++ b/src/filesystem/js/common.js @@ -169,6 +169,8 @@ var commonFS_ = (function() { } function checkPathWithoutDots(aPath) { + aPath = xwalk.utils.StringCopy(aPath); + if (-1 !== aPath.indexOf('/../')) { return false; } diff --git a/src/utils/utils_api.js b/src/utils/utils_api.js index 3c4d46e..b9a4a83 100644 --- a/src/utils/utils_api.js +++ b/src/utils/utils_api.js @@ -3,20 +3,26 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -//Object xwalk.JSON - guaranteed to not being modified by the application programmer -var JSON_ = {stringify: JSON.stringify, parse: JSON.parse}; -Object.freeze(JSON_); -exports.JSON = JSON_; +//We're in a function set up by XWALK which 'use strict' mode, +//so we use below function to get out of the strict mode to get global 'this' +var _global = (new Function('return this'))(); + +var shallow_copy_own_elements = function(orig) { + var copy = {}; + //copy only own properties + var names = Object.getOwnPropertyNames(orig); + for( var i in names ) { + var key = names[i] + copy[key] = orig[key]; + } + return copy; +}; -var _enableJsLogs = false; +//xwalk.JSON: guaranteed to not being modified by the application programmer +exports.JSON = shallow_copy_own_elements(JSON); +Object.freeze(exports.JSON); -var _global = {}; -if (typeof window != 'undefined') { - _global = window; -} -else if (typeof global != 'undefiend') { - _global = global; -} +var _enableJsLogs = false; /** * @deprecated Used only by validateArguments() @@ -146,6 +152,21 @@ function Utils() { }); } +var origString = String; +var StringPrototypeCopy = shallow_copy_own_elements(String.prototype); +Object.freeze(StringPrototypeCopy); + +var StringCopy = function(str) { + return Object.setPrototypeOf( new origString(str), StringPrototypeCopy ); +}; +StringCopy.fromCharCode = String.fromCharCode; +StringCopy.fromCodePoint = String.fromCodePoint; +StringCopy.raw = String.raw; +Object.freeze(StringCopy); + +//xwalk.utils.StringCopy: returns a sanitized version of String - user cannot modify its prototype +Utils.prototype.StringCopy = StringCopy; + Utils.prototype.error = console.error.bind(console); Utils.prototype.warn = console.warn.bind(console); Utils.prototype.log = _enableJsLogs ? console.log.bind(console) : function(){}; @@ -331,8 +352,9 @@ Type.prototype.isUndefined = function(obj) { }; Type.prototype.isA = function(obj, type) { - var clas = Object.prototype.toString.call(obj).slice(8, -1); - return (obj !== undefined) && (obj !== null) && (clas === type); + return obj !== undefined && obj !== null && + obj.constructor !== null && obj.constructor !== undefined && + obj.constructor.name === type; }; Type.prototype.isEmptyObject = function(obj) { @@ -475,7 +497,7 @@ Converter.prototype.toDouble = function(val, nullable) { }; function _toString(val) { - return String(val); + return StringCopy(val).toString(); } Converter.prototype.toString = function(val, nullable) { @@ -1018,7 +1040,7 @@ var NativeManager = function(extension) { }); extension_.setMessageListener(function(json) { - var msg = JSON_.parse(json); + var msg = exports.JSON.parse(json); var id; if (msg.hasOwnProperty(this.CALLBACK_ID_KEY)) { @@ -1082,7 +1104,7 @@ NativeManager.prototype.call = function(cmd, args, callback) { }; NativeManager.prototype.callSync = function(cmd, args) { - var request = JSON_.stringify({ + var request = exports.JSON.stringify({ cmd: cmd, args: args || {} }); @@ -1092,7 +1114,7 @@ NativeManager.prototype.callSync = function(cmd, args) { /* C++ extension didn't set sync response using Instance::SendSyncReply */ throw new WebAPIException(WebAPIException.ABORT_ERR, "Internal error"); } - return JSON_.parse(response); + return exports.JSON.parse(response); }; NativeManager.prototype.sendRuntimeMessage = function(msg, body) { @@ -1346,13 +1368,13 @@ var NativeBridge = (function (extension, debug) { var Bridge = function () {}; Bridge.prototype = { sync: function (data) { - var json = JSON_.stringify({ + var json = exports.JSON.stringify({ cmd: data.cmd, args: data }); if (debug) xwalk.utilss.log('bridge.sync, json: ' + json); var result = extension.internal.sendSyncMessage(json); - var obj = JSON_.parse(result); + var obj = exports.JSON.parse(result); if (obj.error) throw new WebAPIException(obj.code, obj.name, obj.message); return obj.result; @@ -1360,7 +1382,7 @@ var NativeBridge = (function (extension, debug) { async: function (data) { var l = new Listener(); data.cid = Listeners.getInstance().add(l); - var json = JSON_.stringify({ + var json = exports.JSON.stringify({ cmd: data.cmd, args: data }); @@ -1398,7 +1420,7 @@ var NativeBridge = (function (extension, debug) { */ if (debug) xwalk.utils.log('bridge.setMessageListener, json: ' + json); - var data = JSON_.parse(json); + var data = exports.JSON.parse(json); if (data.cid && data.action) { setTimeout(function() { Listeners.getInstance().resolve(data.cid, data.action, data.args, data.keep); -- 2.7.4 From d5bd447a6a340355b9fe73fef974e71c1d1a9866 Mon Sep 17 00:00:00 2001 From: Piotr Kosko Date: Wed, 5 Jul 2017 09:10:11 +0200 Subject: [PATCH 05/16] [version] 1.89 Change-Id: Icf0dcfdfa530d3fad644cc560a00ea1933064188 Signed-off-by: Piotr Kosko --- packaging/webapi-plugins.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/webapi-plugins.spec b/packaging/webapi-plugins.spec index e823e27..ad09fb8 100644 --- a/packaging/webapi-plugins.spec +++ b/packaging/webapi-plugins.spec @@ -10,7 +10,7 @@ %define crosswalk_extensions_path %{_libdir}/%{crosswalk_extensions} Name: webapi-plugins -Version: 1.88 +Version: 1.89 Release: 0 License: Apache-2.0 and BSD-3-Clause and MIT Group: Development/Libraries -- 2.7.4 From 6c92d0b126ad6ba3e86976708879ceacbd1b0cb3 Mon Sep 17 00:00:00 2001 From: Piotr Kosko Date: Mon, 10 Jul 2017 11:46:02 +0200 Subject: [PATCH 06/16] [Filesystem] Support for 2GB+ files added [Feature] Plugins are build with '-D_FILE_OFFSET_BITS=64' flag to support files larger that 2GB. [Verification] Code compiles without errors. TCT passrate 100%. Checked in console with code: // bigfiletest contains 4GB file tizen.filesystem.resolve( 'images/bigfiletest', function(dir) { function onsuccess(files) { for (var i = 0; i < files.length; i++) { console.log(files[i].name + " size: " + files[i].fileSize ); } } dir.listFiles(onsuccess); }, function(e) { console.log("Error: " + e.message); }, "r" ); /// result // BIG.txt size: 4294967296 Change-Id: I21513b533eeee0294267888d416ec3d0a85c91bf Signed-off-by: Piotr Kosko --- src/filesystem/filesystem.gyp | 3 +++ src/filesystem/filesystem_stat.h | 7 ++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/filesystem/filesystem.gyp b/src/filesystem/filesystem.gyp index 0ab9152..9a3c737 100644 --- a/src/filesystem/filesystem.gyp +++ b/src/filesystem/filesystem.gyp @@ -30,6 +30,9 @@ 'filesystem_utils.cc', 'filesystem_utils.h', ], + 'cflags': [ + '-D_FILE_OFFSET_BITS=64', + ], 'conditions': [ [ 'tizen == 1', { 'variables': { 'packages': [ diff --git a/src/filesystem/filesystem_stat.h b/src/filesystem/filesystem_stat.h index 87e7e47..a984ab1 100755 --- a/src/filesystem/filesystem_stat.h +++ b/src/filesystem/filesystem_stat.h @@ -39,7 +39,12 @@ class FilesystemStat { bool readOnly; std::time_t ctime; std::time_t mtime; - size_t size; + +#ifndef __USE_FILE_OFFSET64 + __off_t size; +#else + __off64_t size; +#endif size_t nlink; picojson::value toJSON() const; -- 2.7.4 From 1d4ef70b38e9279d1933d8a8fc873a498e17c25c Mon Sep 17 00:00:00 2001 From: Szymon Jastrzebski Date: Mon, 10 Jul 2017 12:31:20 +0200 Subject: [PATCH 07/16] [FMRadio] Fixing memory leak There was a memory leak, which happened when user called tizen.fmradio.scanStop, after starting scanning. user_data was allocated in method FMRadioManager::ScanStart but it was lost when scanning was interrupted. FMRadio TCT passed 100%. Signed-off-by: Szymon Jastrzebski Change-Id: I2f4b8b74c8a7703dd9d31f5ca8e338caa5e90c45 --- src/radio/radio_manager.cc | 38 ++++++++++++++++++++------------------ src/radio/radio_manager.h | 19 +++++++++++++++++++ 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/src/radio/radio_manager.cc b/src/radio/radio_manager.cc index a6871a8..d94f4e9 100755 --- a/src/radio/radio_manager.cc +++ b/src/radio/radio_manager.cc @@ -111,21 +111,6 @@ double ToMHz(int frequency) { return static_cast(frequency) / 1000.0; } -struct RadioData { - explicit RadioData(FMRadioManager& manager) - : manager_(manager), - callback_id_(0.0) { - } - - FMRadioManager& manager_; - double callback_id_; -}; - -struct RadioScanData : public RadioData { - using RadioData::RadioData; - std::vector frequencies_; -}; - void RadioSeekCallback(int frequency, void* user_data) { LoggerD("Enter, freq: %d", frequency); @@ -181,6 +166,7 @@ void ScanCompleteCallback(void* user_data) { common::TaskQueue::GetInstance().Async(std::bind(&PostAsyncSuccess, &data->manager_, data->callback_id_, event)); + data->manager_.SetScanData(nullptr); delete data; } @@ -190,6 +176,8 @@ void ScanStopCallback(void *user_data) { common::TaskQueue::GetInstance().Async(std::bind( &FMRadioManager::PostResultCallbackSuccess, &data->manager_, data->callback_id_)); + delete data->manager_.GetScanData(); + data->manager_.SetScanData(nullptr); delete data; } @@ -250,6 +238,14 @@ bool FMRadioManager::IsMuted() { return muted; } +RadioScanData *FMRadioManager::GetScanData() { + return this->scan_data; +} + +void FMRadioManager::SetScanData(RadioScanData *scan_data) { + this->scan_data = scan_data; +} + void FMRadioManager::SetMute(bool mute) { LoggerD("Enter"); @@ -332,7 +328,8 @@ double FMRadioManager::GetSignalStrength() { FMRadioManager::FMRadioManager(RadioInstance& instance) : instance_(instance), - radio_instance_(nullptr) { + radio_instance_(nullptr), + scan_data(nullptr) { LoggerD("Enter"); const auto err = radio_create(&radio_instance_); @@ -352,9 +349,8 @@ FMRadioManager::~FMRadioManager() { if (RADIO_ERROR_NONE != err) { LoggerE("radio_destroy() failed: %d", err); } - - radio_instance_ = nullptr; } + delete scan_data; } PlatformResult FMRadioManager::Start(double frequency) { @@ -468,7 +464,9 @@ void FMRadioManager::ScanStart(double callback_id) { radio_unset_scan_completed_cb(radio_instance_); PostResultFailure(callback_id, GetPlatformResult("radio_scan_start", err)); delete user_data; + return; } + this->scan_data = user_data; } void FMRadioManager::ScanStop(double callback_id) { @@ -483,6 +481,8 @@ void FMRadioManager::ScanStop(double callback_id) { PostResultFailure(callback_id, GetPlatformResult("radio_unset_scan_completed_cb", err)); delete user_data; + delete this->scan_data; + this->scan_data = nullptr; return; } @@ -491,6 +491,8 @@ void FMRadioManager::ScanStop(double callback_id) { LoggerE("Failed"); PostResultFailure(callback_id, GetPlatformResult("radio_scan_stop", err)); delete user_data; + delete this->scan_data; + this->scan_data = nullptr; } } diff --git a/src/radio/radio_manager.h b/src/radio/radio_manager.h index 614f415..fd9ea34 100755 --- a/src/radio/radio_manager.h +++ b/src/radio/radio_manager.h @@ -32,6 +32,7 @@ namespace extension { namespace radio { class RadioInstance; +struct RadioScanData; class FMRadioManager { public: @@ -52,6 +53,8 @@ class FMRadioManager { common::PlatformResult UnsetAntennaChangeListener(); bool IsMuted(); + RadioScanData *GetScanData(); + void SetScanData(RadioScanData *scan_data); void SetMute(bool mute); common::PlatformResult SetFrequency(double frequency); double GetFrequency(); @@ -67,6 +70,22 @@ class FMRadioManager { private: RadioInstance& instance_; radio_h radio_instance_; + RadioScanData *scan_data; +}; + +struct RadioData { + explicit RadioData(FMRadioManager& manager) + : manager_(manager), + callback_id_(0.0) { + } + + FMRadioManager& manager_; + double callback_id_; +}; + +struct RadioScanData : public RadioData { + using RadioData::RadioData; + std::vector frequencies_; }; } // namespace radio -- 2.7.4 From 4c236233a4dbfee12a27efcc30a25a442471d97c Mon Sep 17 00:00:00 2001 From: Szymon Jastrzebski Date: Fri, 7 Jul 2017 14:41:54 +0200 Subject: [PATCH 08/16] [Messaging] Replacing call of email_attachment_data_t structure constructor to calloc Native function email_free_attachment_data uses free() to release allocated memory pointing by tmp. Thus, we should call calloc() instead of structure's constructor. Messaging-email TCT passed 100%. Change-Id: Ib81f1da2e0270cfa76aef0eab7005d968c1f102c Signed-off-by: Szymon Jastrzebski --- src/messaging/message.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/messaging/message.cc b/src/messaging/message.cc index bdd7873..57703b1 100755 --- a/src/messaging/message.cc +++ b/src/messaging/message.cc @@ -591,7 +591,7 @@ PlatformResult addSingleEmailAttachment(std::shared_ptr message, PlatformResult ret = copyFileToTemp(att->getFilePath(), &dirPath); if (ret.IsError()) return ret; - email_attachment_data_t* tmp = new email_attachment_data_t(); + email_attachment_data_t* tmp = (email_attachment_data_t*)calloc(1, sizeof(email_attachment_data_t)); tmp->attachment_name = strdup(att->getShortFileName().c_str()); tmp->attachment_path = strdup(std::string(dirPath + "/" + att->getShortFileName()).c_str()); -- 2.7.4 From c89325b9add59ed08e7b4900b58083c11b56a717 Mon Sep 17 00:00:00 2001 From: Szymon Jastrzebski Date: Mon, 10 Jul 2017 13:12:39 +0200 Subject: [PATCH 09/16] [Bluetooth] Fixing memory leak user_data was lost when native function app_control_send_launch_request returned value different from APP_CONTROL_ERROR_NONE. In case of fail, we need to delete allocated memory manually. TCT bluetooth passed 100%. Change-Id: I5aa08bfdda97a5dfab7718177be0fbb3f4c9dae0 Signed-off-by: Szymon Jastrzebski --- src/bluetooth/bluetooth_adapter.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bluetooth/bluetooth_adapter.cc b/src/bluetooth/bluetooth_adapter.cc index dd30661..126de34 100755 --- a/src/bluetooth/bluetooth_adapter.cc +++ b/src/bluetooth/bluetooth_adapter.cc @@ -602,6 +602,7 @@ void BluetoothAdapter::SetPowered(const picojson::value& data, picojson::object& ret = LogAndCreateResult( ErrorCode::UNKNOWN_ERR, "app control set launch request failed", ("app control set launch request failed: %d", err)); + delete user_data; } else { this->requested_powered_ = new_powered; this->user_request_list_[SET_POWERED] = true; -- 2.7.4 From 71285dffa6192c4e1a719941272100145bed228d Mon Sep 17 00:00:00 2001 From: Piotr Kosko Date: Wed, 12 Jul 2017 11:28:36 +0200 Subject: [PATCH 10/16] [version] 1.90 Change-Id: Iae694af4c97bdd2a918a8a2ca59d2633f1863b7b Signed-off-by: Piotr Kosko --- packaging/webapi-plugins.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/webapi-plugins.spec b/packaging/webapi-plugins.spec index ad09fb8..9d193c9 100644 --- a/packaging/webapi-plugins.spec +++ b/packaging/webapi-plugins.spec @@ -10,7 +10,7 @@ %define crosswalk_extensions_path %{_libdir}/%{crosswalk_extensions} Name: webapi-plugins -Version: 1.89 +Version: 1.90 Release: 0 License: Apache-2.0 and BSD-3-Clause and MIT Group: Development/Libraries -- 2.7.4 From e7a3c0c0f7c3c2788bea8e7294696deabf2feff6 Mon Sep 17 00:00:00 2001 From: Szymon Jastrzebski Date: Thu, 13 Jul 2017 08:19:53 +0200 Subject: [PATCH 11/16] [Contact] Fixing bug when adding Contact to AddressBook There was a bug, which caused application to crash everytime when adding more than one nickname. In every iteration of nicknames, the same nickname-handler was added to parent-handler. The crash happened during attempting to free parent-handler with all its children (double free). Contact TCT passed 100%. Change-Id: Ibaddf2ce17aacb6dcf40422fc0303ec5e1142089 Signed-off-by: Szymon Jastrzebski --- src/contact/contact_util.cc | 38 ++++++++++++++------------------------ 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/src/contact/contact_util.cc b/src/contact/contact_util.cc index bcccd3b..6251ee1 100755 --- a/src/contact/contact_util.cc +++ b/src/contact/contact_util.cc @@ -584,39 +584,29 @@ PlatformResult ExportContactNameToContactsRecord( for (auto& nickname : nicknames) { contacts_record_h nickname_record = nullptr; - err = contacts_record_get_child_record_at_p( - contacts_record, _contacts_contact.nickname, 0, &nickname_record); - if (CONTACTS_ERROR_NONE != err && nullptr == nickname_record) { - err = contacts_record_create(_contacts_nickname._uri, &nickname_record); - PlatformResult status = - ContactUtil::ErrorChecker(err, "Contacts record create error"); - if (status.IsError()) { - LoggerE("Error: %s", status.message().c_str()); - return status; - } - - update = false; + err = contacts_record_create(_contacts_nickname._uri, &nickname_record); + PlatformResult status = ContactUtil::ErrorChecker(err, "Contacts record create error"); + if (status.IsError()) { + LoggerE("Error: %s", status.message().c_str()); + return status; } ContactsRecordHPtr nickname_ptr(&nickname_record, ContactsDeleter); - PlatformResult status = - ContactUtil::SetStrInRecord(*nickname_ptr, _contacts_nickname.name, - JsonCast(nickname).c_str()); + status = ContactUtil::SetStrInRecord(*nickname_ptr, _contacts_nickname.name, + JsonCast(nickname).c_str()); if (status.IsError()) { LoggerE("Error: %s", status.message().c_str()); return status; } - if (!update) { - err = contacts_record_add_child_record( - contacts_record, _contacts_contact.nickname, *nickname_ptr); - PlatformResult status = - ContactUtil::ErrorChecker(err, "Contacts record add child error"); - if (status.IsError()) { - LoggerE("Error: %s", status.message().c_str()); - return status; - } + err = contacts_record_add_child_record(contacts_record, _contacts_contact.nickname, + *nickname_ptr); + status = ContactUtil::ErrorChecker(err, "Contacts record add child error"); + if (status.IsError()) { + LoggerE("Error: %s", status.message().c_str()); + return status; } + // Do not delete record, it is passed to the platform nickname_ptr.release(); } -- 2.7.4 From 797bf22c8636937caf9e4f48187bb22591ff742d Mon Sep 17 00:00:00 2001 From: Pawel Wasowski Date: Thu, 13 Jul 2017 21:57:37 +0200 Subject: [PATCH 12/16] [Application] Fix category array population bug Problem: application's categories were not passed from C++ to JS layer Verification: it has been proved in tests in Chrome DevTools, that application's categories may be obtained with Application API TCT Application pass rate: 100% Change-Id: I0995cd464315c9194196874fa488d52de49b1e69 Signed-off-by: Pawel Wasowski --- src/application/application_utils.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/application/application_utils.cc b/src/application/application_utils.cc index 8d56999..060dd09 100644 --- a/src/application/application_utils.cc +++ b/src/application/application_utils.cc @@ -77,7 +77,6 @@ void ApplicationUtils::CreateApplicationInformation(const pkgmgrinfo_appinfo_h h // categories picojson::value categories = picojson::value(picojson::array()); picojson::array& categories_array = categories.get(); - app_info->insert(std::make_pair("categories", categories)); ret = pkgmgrinfo_appinfo_foreach_category( handle, @@ -92,6 +91,8 @@ void ApplicationUtils::CreateApplicationInformation(const pkgmgrinfo_appinfo_h h }, &categories_array); + app_info->insert(std::make_pair("categories", categories)); + if (PMINFO_R_OK != ret) { LoggerE("Failed to get categories: %d (%s)", ret, get_error_message(ret)); } -- 2.7.4 From 53b941ffca00a9cc12d3207280f179f16452cbba Mon Sep 17 00:00:00 2001 From: Pawel Wasowski Date: Fri, 7 Jul 2017 18:02:53 +0200 Subject: [PATCH 13/16] [EXIF] Fix privilege issue Problem: implementation of getExifInfo() used Web API filesystem resolve() function to check, if file exists on the device. Use of this function required declaring http://tizen.org/privilege/filesystem.read. File existence checking has been implemented in EXIF plugin and does not require declaring any additional privileges. [Verification] TCT EXIF: 100% pass rate, manuall tests with Chrome DevTools did not show any problems Change-Id: Id9d19965eddb31902f14817eac0bd5ad897f1568 Signed-off-by: Pawel Wasowski --- src/common/tools.cc | 55 +++++++++++++++++++++++++++++++++++++++++++++++ src/common/tools.h | 6 ++++++ src/exif/exif_api.js | 21 ++---------------- src/exif/exif_instance.cc | 16 ++++++++++++++ 4 files changed, 79 insertions(+), 19 deletions(-) diff --git a/src/common/tools.cc b/src/common/tools.cc index 638352f..cd8beea 100644 --- a/src/common/tools.cc +++ b/src/common/tools.cc @@ -19,6 +19,7 @@ #include #include #include +#include #ifdef PRIVILEGE_USE_DB #include @@ -480,5 +481,59 @@ char* BinToHex(const unsigned char* bin, int size, char* hex, int hex_size) { return hex; } +bool IsPathValid(const std::string& path) { + LoggerD("Enter"); + + /* + * Directory dot-referencing is not allowed + */ + return std::string::npos == path.find("/../") && + std::string::npos == path.find("/./") && + 0 != path.find("./") && + 0 != path.find("../") && + path.length() - 2 != path.rfind("/.") && + path.length() - 3 != path.rfind("/.."); +} + +PlatformResult CheckFileStatus(const std::string& path) { + LoggerD("Enter"); + + struct stat buf; + + if (stat(path.c_str(), &buf)) { + LoggerD("Failed to stat path: %s", path.c_str()); + + if (ENOENT == errno) { + return PlatformResult(ErrorCode::NOT_FOUND_ERR, "File does not exist: " + path); + } else if (EACCES == errno) { + return PlatformResult(ErrorCode::IO_ERR, "The user cannot access the file: " + path); + } + + LoggerD("stat() error: %s", common::tools::GetErrorString(errno).c_str()); + return PlatformResult(ErrorCode::UNKNOWN_ERR, "Cannot get status of the file: " + path); + } + + if (!S_ISREG(buf.st_mode)) { + return PlatformResult(ErrorCode::NOT_FOUND_ERR, "Path does not point to a regular file: " + + path); + } + + if (!(S_IRUSR & buf.st_mode)) { + return PlatformResult(ErrorCode::IO_ERR, "The user cannot read the file: " + path); + } + + return PlatformResult(ErrorCode::NO_ERROR); +} + +PlatformResult CheckFileAvailability(const std::string& path) { + LoggerD("Enter"); + + if (!IsPathValid(path)) { + return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid path: " + path); + } + + return CheckFileStatus(path); +} + } // namespace tools } // namespace common diff --git a/src/common/tools.h b/src/common/tools.h index 5d8eec6..fc905ec 100644 --- a/src/common/tools.h +++ b/src/common/tools.h @@ -85,6 +85,12 @@ int HexToInt(char c); unsigned char* HexToBin(const char* hex, int size, unsigned char* bin, int bin_size); char* BinToHex(const unsigned char* bin, int size, char* hex, int hex_size); +bool IsPathValid(const std::string& path); + +PlatformResult CheckFileStatus(const std::string& path); + +PlatformResult CheckFileAvailability(const std::string& path); + } // namespace tools } // namespace common diff --git a/src/exif/exif_api.js b/src/exif/exif_api.js index d209d8a..3040336 100644 --- a/src/exif/exif_api.js +++ b/src/exif/exif_api.js @@ -205,7 +205,6 @@ ExifManager.prototype.getExifInfo = function() { if (native_.isFailure(result)) { native_.callIfPossible(args.errorCallback, native_.getErrorObject(result)); } else { - // call to c++ code. Fields that do not exist are undefined. var exifInfoNative = native_.getResultObject(result); @@ -218,15 +217,7 @@ ExifManager.prototype.getExifInfo = function() { } }; - tizen.filesystem.resolve(args.uri, - function() { - native_.call('ExifManager_getExifInfo', {'uri': args.uri}, callback); - }, - function() { - native_.callIfPossible(args.errorCallback, new WebAPIException( - WebAPIException.NOT_FOUND_ERR, - 'File can not be found.')); - }); + native_.call('ExifManager_getExifInfo', {'uri': args.uri}, callback); }; ExifManager.prototype.saveExifInfo = function() { @@ -316,15 +307,7 @@ ExifManager.prototype.getThumbnail = function() { } }; - tizen.filesystem.resolve(args.uri, - function() { - native_.call('ExifManager_getThumbnail', {'uri': args.uri}, _callback); - }, - function() { - native_.callIfPossible(args.errorCallback, new WebAPIException( - WebAPIException.NOT_FOUND_ERR, - 'File can not be found.')); - }); + native_.call('ExifManager_getThumbnail', {'uri': args.uri}, _callback); }; tizen.ExifInformation = function() { diff --git a/src/exif/exif_instance.cc b/src/exif/exif_instance.cc index 8be6a26..6f0101a 100755 --- a/src/exif/exif_instance.cc +++ b/src/exif/exif_instance.cc @@ -26,6 +26,7 @@ #include "common/logger.h" #include "common/platform_result.h" #include "common/task-queue.h" +#include "common/tools.h" #include "exif/exif_information.h" #include "exif/exif_util.h" @@ -62,6 +63,13 @@ void ExifInstance::ExifManagerGetExifInfo(const picojson::value& args, picojson: PlatformResult status(ErrorCode::NO_ERROR); const std::string &file_path = ExifUtil::convertUriToPath(uri); + + PlatformResult fileAvailability(common::tools::CheckFileAvailability(file_path)); + if (!fileAvailability) { + LogAndReportError(fileAvailability, &response->get()); + return; + } + LoggerD("file_path = %s", file_path.c_str()); status = GetExifInfo::LoadFromURI(uri, &result); @@ -128,6 +136,14 @@ void ExifInstance::ExifManagerGetThumbnail(const picojson::value& args, JsonValue result = JsonValue(JsonObject()); JsonObject &result_obj = result.get(); + PlatformResult fileAvailability(common::tools::CheckFileAvailability(file_path)); + if (!fileAvailability) { + LogAndReportError(fileAvailability, &response->get()); + return; + } + + LoggerD("file_path = %s", file_path.c_str()); + std::string ext = file_path.substr(file_path.find_last_of(".") + 1); std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower); -- 2.7.4 From 0c75237768f62a473b054feeb7c31c56c156f67f Mon Sep 17 00:00:00 2001 From: Szymon Jastrzebski Date: Tue, 18 Jul 2017 11:20:35 +0200 Subject: [PATCH 14/16] [Systeminfo] Fixed condition, which caused to call successCallback when not needed According to documentation, the successCallback is called in 4 different possible situations. The condition, which fills the requirements is optimized. [Verification] SystemInfo TCT passed 100%. Change-Id: Ie6b24853ed233ecb8ac9d5ee28677e84d2b22f2f Signed-off-by: Szymon Jastrzebski --- src/systeminfo/systeminfo_api.js | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/src/systeminfo/systeminfo_api.js b/src/systeminfo/systeminfo_api.js index bb656c0..63b3e5e 100644 --- a/src/systeminfo/systeminfo_api.js +++ b/src/systeminfo/systeminfo_api.js @@ -901,10 +901,20 @@ function _systeminfoBatteryListenerCallback(eventObj) { var propObj = !listener.isArrayType ? _createProperty(property, eventObj.result.array[0]) : _createPropertyArray(property, eventObj.result); - var executeCall = (T_.isUndefined(listener.lowThreshold) || - (propObj.level <= listener.lowThreshold)) || - (T_.isUndefined(listener.highThreshold) || - (propObj.level >= listener.highThreshold)); + /* + * According to documentation, the condition should look like this: + * + * (T_.isUndefined(listener.lowThreshold) && T_.isUndefined(listener.highThreshold)) || + * (!T_.isUndefined(listener.lowThreshold) && !T_.isUndefined(listener.highThreshold) && (propObj.level <= listener.lowThreshold || propObj.level >= listener.highThreshold)) || + * (!T_.isUndefined(listener.lowThreshold) && (propObj.level <= listener.lowThreshold)) || + * (!T_.isUndefined(listener.highThreshold) && (propObj.level >= listener.highThreshold)) + * + * but it can be optimized like this: + */ + var executeCall = (T_.isUndefined(listener.lowThreshold) && T_.isUndefined(listener.highThreshold)) || + (!T_.isUndefined(listener.lowThreshold) && propObj.level <= listener.lowThreshold) || + (!T_.isUndefined(listener.highThreshold) && propObj.level >= listener.highThreshold); + if (executeCall) { listener.callback(propObj); } @@ -922,10 +932,12 @@ function _systeminfoCpuListenerCallback(eventObj) { var propObj = !listener.isArrayType ? _createProperty(property, eventObj.result.array[0]) : _createPropertyArray(property, eventObj.result); - var executeCall = (T_.isUndefined(listener.lowThreshold) || - (propObj.load <= listener.lowThreshold)) || - (T_.isUndefined(listener.highThreshold) || - (propObj.load >= listener.highThreshold)); + /* + * Optimized condition: + * */ + var executeCall = (T_.isUndefined(listener.lowThreshold) && T_.isUndefined(listener.highThreshold)) || + (!T_.isUndefined(listener.lowThreshold) && propObj.load <= listener.lowThreshold) || + (!T_.isUndefined(listener.highThreshold) && propObj.load >= listener.highThreshold); if (executeCall) { listener.callback(propObj); } @@ -958,10 +970,12 @@ function _systeminfoDisplayListenerCallback(eventObj) { var propObj = !listener.isArrayType ? _createProperty(property, eventObj.result.array[0]) : _createPropertyArray(property, eventObj.result); - var executeCall = (T_.isUndefined(listener.lowThreshold) || - (propObj.brightness <= listener.lowThreshold)) || - (T_.isUndefined(listener.highThreshold) || - (propObj.brightness >= listener.highThreshold)); + /* + * Optimized condition: + * */ + var executeCall = (T_.isUndefined(listener.lowThreshold) && T_.isUndefined(listener.highThreshold)) || + (!T_.isUndefined(listener.lowThreshold) && propObj.brightness <= listener.lowThreshold) || + (!T_.isUndefined(listener.highThreshold) && propObj.brightness >= listener.highThreshold); if (executeCall) { listener.callback(propObj); } -- 2.7.4 From 557cd7f81bb475633bdaa8147bdce701880d1674 Mon Sep 17 00:00:00 2001 From: Lukasz Bardeli Date: Wed, 19 Jul 2017 09:07:36 +0200 Subject: [PATCH 15/16] [version] 1.91 Change-Id: I253cb2dfb07843f3a46694eba5a69719d6006450 --- packaging/webapi-plugins.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/webapi-plugins.spec b/packaging/webapi-plugins.spec index 9d193c9..926b460 100644 --- a/packaging/webapi-plugins.spec +++ b/packaging/webapi-plugins.spec @@ -10,7 +10,7 @@ %define crosswalk_extensions_path %{_libdir}/%{crosswalk_extensions} Name: webapi-plugins -Version: 1.90 +Version: 1.91 Release: 0 License: Apache-2.0 and BSD-3-Clause and MIT Group: Development/Libraries -- 2.7.4 From f0e83be2b496b74fa0dd5b8cc597a0b78141a360 Mon Sep 17 00:00:00 2001 From: Szymon Jastrzebski Date: Wed, 19 Jul 2017 12:35:55 +0200 Subject: [PATCH 16/16] [SystemInfo] Adding casting int to double + fix InchToMm constant SVACE detected problem with code NO_CAST.INTEGER_DIVISION. [Verification] Code compiles, TCT SystemInfo passed 100%. Change-Id: Ie6249780860cd61a8c331d77648b6d37b9241c4c Signed-off-by: Szymon Jastrzebski --- src/systeminfo/systeminfo_properties_manager.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/systeminfo/systeminfo_properties_manager.cc b/src/systeminfo/systeminfo_properties_manager.cc index 8a5c6e4..75bb33c 100644 --- a/src/systeminfo/systeminfo_properties_manager.cc +++ b/src/systeminfo/systeminfo_properties_manager.cc @@ -42,7 +42,7 @@ using common::ErrorCode; namespace { const std::string kMemoryStateNormal = "NORMAL"; const std::string kMemoryStateWarinig = "WARNING"; -const double kDisplayInchToMillimeter = 2.54; +const double kDisplayInchToMillimeter = 25.4; //Battery const double kRemainingBatteryChargeMax = 100.0; const int kVconfErrorNone = 0; @@ -306,7 +306,7 @@ PlatformResult SysteminfoPropertiesManager::ReportDisplay(picojson::object* out) //FETCH PHYSICAL WIDTH if (dotsPerInchWidth != 0 && screenWidth != 0) { - physicalWidth = (screenWidth / dotsPerInchWidth) * kDisplayInchToMillimeter; + physicalWidth = (static_cast(screenWidth) / dotsPerInchWidth) * kDisplayInchToMillimeter; } else { std::string log_msg = "Failed to get physical screen width value"; LoggerE("%s, screenWidth : %d, dotsPerInchWidth: %d", log_msg.c_str(), @@ -315,7 +315,7 @@ PlatformResult SysteminfoPropertiesManager::ReportDisplay(picojson::object* out) //FETCH PHYSICAL HEIGHT if (dotsPerInchHeight != 0 && screenHeight != 0) { - physicalHeight = (screenHeight / dotsPerInchHeight) * kDisplayInchToMillimeter; + physicalHeight = (static_cast(screenHeight) / dotsPerInchHeight) * kDisplayInchToMillimeter; } else { std::string log_msg = "Failed to get physical screen height value"; LoggerE("%s, screenHeight : %d, dotsPerInchHeight: %d", log_msg.c_str(), -- 2.7.4