diff --git a/.resinci.json b/.resinci.json index 56dc4038..c120aa37 100644 --- a/.resinci.json +++ b/.resinci.json @@ -17,7 +17,7 @@ "appId": "io.balena.etcher", "copyright": "Copyright 2016-2020 Balena Ltd", "productName": "balenaEtcher", - "nodeGypRebuild": true, + "nodeGypRebuild": false, "afterPack": "./afterPack.js", "asar": false, "files": [ diff --git a/Makefile b/Makefile index b543539d..fbfc70d6 100644 --- a/Makefile +++ b/Makefile @@ -124,7 +124,6 @@ TARGETS = \ lint \ lint-ts \ lint-css \ - lint-cpp \ lint-spell \ test-spectron \ test-gui \ @@ -148,9 +147,6 @@ lint-ts: lint-css: npx prettier --write lib/**/*.css -lint-cpp: - cpplint --recursive src - lint-spell: codespell \ --dictionary - \ @@ -158,7 +154,7 @@ lint-spell: --skip *.svg *.gz,*.bz2,*.xz,*.zip,*.img,*.dmg,*.iso,*.rpi-sdcard,*.wic,.DS_Store,*.dtb,*.dtbo,*.dat,*.elf,*.bin,*.foo,xz-without-extension \ lib tests docs Makefile *.md LICENSE -lint: lint-ts lint-css lint-cpp lint-spell +lint: lint-ts lint-css lint-spell MOCHA_OPTIONS=--recursive --reporter spec --require ts-node/register --require-main "tests/gui/allow-renderer-process-reuse.ts" @@ -189,7 +185,6 @@ clean: distclean: clean rm -rf node_modules - rm -rf build rm -rf dist rm -rf generated rm -rf $(BUILD_TEMPORARY_DIRECTORY) diff --git a/binding.gyp b/binding.gyp deleted file mode 100644 index 048a5746..00000000 --- a/binding.gyp +++ /dev/null @@ -1,35 +0,0 @@ -{ - "targets": [ - { - "target_name": "elevator", - "include_dirs" : [ - "src", - " { - // 'elevator' imported here as it only exists on windows - // TODO: replace this with sudo-prompt once https://github.com/jorangreef/sudo-prompt/issues/96 is fixed - // @ts-ignore this is a native module - const { elevate } = await import('../../build/Release/elevator.node'); - const elevateAsync = promisify(elevate); - + name: string, +): Promise<{ cancelled: false }> { // '&' needs to be escaped here (but not when written to a .cmd file) - const cmd = ['cmd', '/c', escapeParamCmd(path).replace(/&/g, '^&')]; - const { cancelled } = await elevateAsync(cmd); - return { cancelled }; + const cmd = ['cmd', '/c', escapeParamCmd(path).replace(/&/g, '^&')].join(' '); + await sudoExecAsync(cmd, { name }); + return { cancelled: false }; } async function elevateScriptUnix( @@ -183,7 +178,7 @@ export async function elevateCommand( async (path) => { await fs.writeFile(path, launchScript); if (isWindows) { - return elevateScriptWindows(path); + return elevateScriptWindows(path, options.applicationName); } if ( os.platform() === 'darwin' && diff --git a/package.json b/package.json index 9303cbc8..62e60249 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,6 @@ "description": "Flash OS images to SD cards and USB drives, safely and easily.", "productDescription": "Etcher is a powerful OS image flasher built with web technologies to ensure flashing an SDCard or USB drive is a pleasant and safe experience. It protects you from accidentally writing to your hard-drives, ensures every byte of data was written correctly and much more.", "homepage": "https://github.com/balena-io/etcher", - "gypfile": true, "repository": { "type": "git", "url": "git@github.com:balena-io/etcher.git" @@ -17,9 +16,6 @@ "test": "make lint test sanity-checks", "start": "./node_modules/.bin/electron .", "postshrinkwrap": "ts-node ./scripts/clean-shrinkwrap.ts", - "configure": "node-gyp configure", - "build": "node-gyp build", - "install": "node-gyp rebuild", "webpack": "webpack", "watch": "webpack --watch", "concourse-build-electron": "make webpack", @@ -85,7 +81,6 @@ "mocha": "^8.0.1", "nan": "^2.14.0", "native-addon-loader": "^2.0.1", - "node-gyp": "^7.0.0", "node-ipc": "^9.1.1", "omit-deep-lodash": "1.1.4", "outdent": "^0.7.1", diff --git a/requirements.txt b/requirements.txt index 97931b1e..408dc896 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,3 @@ codespell==1.12.0 -cpplint==1.3.0 awscli==1.11.87 shyaml==0.5.0 diff --git a/src/elevator_init.cpp b/src/elevator_init.cpp deleted file mode 100644 index 0f264e1a..00000000 --- a/src/elevator_init.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2017 balena.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include - -#include "os/elevate.h" -#include "utils/v8utils.h" - -class ElevateWorker : public Nan::AsyncWorker { - public: - ElevateWorker(Nan::Callback *callback, - const std::vector &arguments) - : Nan::AsyncWorker(callback) { - this->arguments = arguments; - } - - ~ElevateWorker() {} - - void Execute() { - etcher::ELEVATE_RESULT result = etcher::Elevate( - this->arguments.front(), - std::vector(this->arguments.begin() + 1, - this->arguments.end())); - - switch (result) { - case etcher::ELEVATE_RESULT::ELEVATE_SUCCESS: - cancelled = false; - break; - case etcher::ELEVATE_RESULT::ELEVATE_CANCELLED: - cancelled = true; - break; - default: - this->SetErrorMessage(etcher::ElevateResultToString(result).c_str()); - } - } - - void HandleOKCallback() { - v8::Local results = Nan::New(); - Nan::Set(results, Nan::New("cancelled").ToLocalChecked(), - this->cancelled ? Nan::True() : Nan::False()); - v8::Local argv[2] = { Nan::Null(), results }; - callback->Call(2, argv); - } - - private: - std::vector arguments; - v8::Local results; - bool cancelled; -}; - -NAN_METHOD(elevate) { - if (!info[0]->IsArray()) { - return Nan::ThrowError("This function expects an array"); - } - - if (!info[1]->IsFunction()) { - return Nan::ThrowError("Callback must be a function"); - } - - std::vector arguments = - etcher::v8utils::GetArguments(info[0].As()); - Nan::Callback *callback = new Nan::Callback(info[1].As()); - Nan::AsyncQueueWorker(new ElevateWorker(callback, arguments)); - info.GetReturnValue().SetUndefined(); -} - -NAN_MODULE_INIT(ElevatorInit) { NAN_EXPORT(target, elevate); } - -NODE_MODULE(elevator, ElevatorInit) diff --git a/src/os/elevate.h b/src/os/elevate.h deleted file mode 100644 index 834805f0..00000000 --- a/src/os/elevate.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef SRC_OS_ELEVATE_H_ -#define SRC_OS_ELEVATE_H_ - -/* - * Copyright 2017 balena.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifdef _WIN32 - -// Fix winsock.h redefinition errors -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif - -// Note that windows.h has to be included before any -// other Windows library to avoid declaration issues -#include -#include - -#endif - -#include -#include -#include -#include -#include - -namespace etcher { - -enum class ELEVATE_RESULT { - ELEVATE_SUCCESS, - ELEVATE_FILE_NOT_FOUND, - ELEVATE_PATH_NOT_FOUND, - ELEVATE_DDE_FAIL, - ELEVATE_NO_ASSOCIATION, - ELEVATE_ACCESS_DENIED, - ELEVATE_DLL_NOT_FOUND, - ELEVATE_CANCELLED, - ELEVATE_NOT_ENOUGH_MEMORY, - ELEVATE_SHARING_VIOLATION, - ELEVATE_UNKNOWN_ERROR -}; - -ELEVATE_RESULT Elevate(const std::wstring &command, - std::vector arguments); - -std::string ElevateResultToString(const ELEVATE_RESULT &result); - -} // namespace etcher - -#endif // SRC_OS_ELEVATE_H_ diff --git a/src/os/win32/elevate.cpp b/src/os/win32/elevate.cpp deleted file mode 100644 index 93b9e27a..00000000 --- a/src/os/win32/elevate.cpp +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2017 balena.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "os/elevate.h" - -static std::wstring JoinArguments(std::vector arguments) { - std::wostringstream result; - - std::copy(arguments.begin(), arguments.end(), - std::ostream_iterator(result, L" ")); - - return result.str(); -} - -// Make sure to delete the result after you're done -// with it by calling `delete[] result;`. -// See http://stackoverflow.com/a/1201471 -static LPCWSTR ConvertStringToLPCWSTR(const std::wstring &string) { - wchar_t *result = new wchar_t[string.size() + 1]; - std::copy(string.begin(), string.end(), result); - result[string.size()] = 0; - return result; -} - -etcher::ELEVATE_RESULT etcher::Elevate(const std::wstring &command, - std::vector arguments) { - // Initialize the SHELLEXECUTEINFO structure. We zero it out - // in order to be on the safe side, and set cbSize to the size - // of the structure as recommend by MSDN - // See: https://msdn.microsoft.com/en-us/library/windows/desktop/bb759784(v=vs.85).aspx - SHELLEXECUTEINFOW shellExecuteInfo; - ZeroMemory(&shellExecuteInfo, sizeof(shellExecuteInfo)); - shellExecuteInfo.cbSize = sizeof(SHELLEXECUTEINFOW); - - // Flags that indicate the content and validity of the other structure member. - shellExecuteInfo.fMask = - - // Used to indicate that the hProcess member receives the process handle. - // This handle is typically used to allow an application to find out - // when a process created with ShellExecuteEx terminates. - SEE_MASK_NOCLOSEPROCESS | - - // Wait for the execute operation to complete before returning. - SEE_MASK_NOASYNC | - - // Do not display an error message box if an error occurs. - SEE_MASK_FLAG_NO_UI; - - // The action to be performed. - shellExecuteInfo.lpVerb = L"runas"; - - // Run the file in the background - shellExecuteInfo.nShow = SW_HIDE; - - // Use the current directory as the working directory - shellExecuteInfo.lpDirectory = NULL; - - // Set file and parameters - // We can't just assign the result of `.c_str()`, since - // that pointer is owned by the `std::wstring` instance, - // and will not be safe after the instance is destroyed. - LPCWSTR file = ConvertStringToLPCWSTR(command); - LPCWSTR argv = ConvertStringToLPCWSTR(JoinArguments(arguments)); - shellExecuteInfo.lpFile = file; - shellExecuteInfo.lpParameters = argv; - - BOOL executeResult = ShellExecuteExW(&shellExecuteInfo); - - delete[] file; - delete[] argv; - - // Finally, let's try to elevate the command - if (!executeResult) { - DWORD executeError = GetLastError(); - - // We map Windows error codes to our own enum class - // so we can normalize all Windows error handling mechanisms. - switch (executeError) { - case ERROR_FILE_NOT_FOUND: - return etcher::ELEVATE_RESULT::ELEVATE_FILE_NOT_FOUND; - case ERROR_PATH_NOT_FOUND: - return etcher::ELEVATE_RESULT::ELEVATE_PATH_NOT_FOUND; - case ERROR_DDE_FAIL: - return etcher::ELEVATE_RESULT::ELEVATE_DDE_FAIL; - case ERROR_NO_ASSOCIATION: - return etcher::ELEVATE_RESULT::ELEVATE_NO_ASSOCIATION; - case ERROR_ACCESS_DENIED: - return etcher::ELEVATE_RESULT::ELEVATE_ACCESS_DENIED; - case ERROR_DLL_NOT_FOUND: - return etcher::ELEVATE_RESULT::ELEVATE_DLL_NOT_FOUND; - case ERROR_CANCELLED: - return etcher::ELEVATE_RESULT::ELEVATE_CANCELLED; - case ERROR_NOT_ENOUGH_MEMORY: - return etcher::ELEVATE_RESULT::ELEVATE_NOT_ENOUGH_MEMORY; - case ERROR_SHARING_VIOLATION: - return etcher::ELEVATE_RESULT::ELEVATE_SHARING_VIOLATION; - default: - return etcher::ELEVATE_RESULT::ELEVATE_UNKNOWN_ERROR; - } - } - - // Since we passed SEE_MASK_NOCLOSEPROCESS, the - // process handle is accessible from hProcess. - if (shellExecuteInfo.hProcess) { - // Wait for the process to exit before continuing. - // See: https://msdn.microsoft.com/en-us/library/windows/desktop/ms687032(v=vs.85).aspx - WaitForSingleObject(shellExecuteInfo.hProcess, INFINITE); - - if (!CloseHandle(shellExecuteInfo.hProcess)) { - return etcher::ELEVATE_RESULT::ELEVATE_UNKNOWN_ERROR; - } - } - - return etcher::ELEVATE_RESULT::ELEVATE_SUCCESS; -} - -std::string -etcher::ElevateResultToString(const etcher::ELEVATE_RESULT &result) { - switch (result) { - case etcher::ELEVATE_RESULT::ELEVATE_SUCCESS: - return "Success"; - case etcher::ELEVATE_RESULT::ELEVATE_CANCELLED: - return "The user cancelled the elevation request"; - case etcher::ELEVATE_RESULT::ELEVATE_FILE_NOT_FOUND: - return "The specified file was not found"; - case etcher::ELEVATE_RESULT::ELEVATE_PATH_NOT_FOUND: - return "The specified path was not found"; - case etcher::ELEVATE_RESULT::ELEVATE_DDE_FAIL: - return "The Dynamic Data Exchange (DDE) transaction failed"; - case etcher::ELEVATE_RESULT::ELEVATE_NO_ASSOCIATION: - return "There is no application associated with the " - "specified file name extension"; - case etcher::ELEVATE_RESULT::ELEVATE_ACCESS_DENIED: - return "Access to the specified file is denied"; - case etcher::ELEVATE_RESULT::ELEVATE_DLL_NOT_FOUND: - return "One of the library files necessary to run the " - "application can't be found"; - case etcher::ELEVATE_RESULT::ELEVATE_NOT_ENOUGH_MEMORY: - return "There is not enough memory to perform the specified action"; - case etcher::ELEVATE_RESULT::ELEVATE_SHARING_VIOLATION: - return "A sharing violation occurred"; - default: - return "Unknown error"; - } -} diff --git a/src/utils/v8utils.cpp b/src/utils/v8utils.cpp deleted file mode 100644 index f3a5f195..00000000 --- a/src/utils/v8utils.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2017 balena.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "utils/v8utils.h" - -std::vector -etcher::v8utils::GetArguments(v8::Local arguments) { - std::vector result(0); - - for (uint32_t index = 0; index < arguments->Length(); index++) { - // See https://stackoverflow.com/q/15615136/1641422 - std::string stringArgument( - *Nan::Utf8String( - arguments->Get( - Nan::GetCurrentContext(), - index).ToLocalChecked())); - std::wstring_convert> conversion; - - result.push_back(conversion.from_bytes(stringArgument)); - } - - return result; -} diff --git a/src/utils/v8utils.h b/src/utils/v8utils.h deleted file mode 100644 index cdaa1a3f..00000000 --- a/src/utils/v8utils.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef SRC_UTILS_V8UTILS_H_ -#define SRC_UTILS_V8UTILS_H_ - -/* - * Copyright 2017 balena.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include - -namespace etcher { -namespace v8utils { -std::vector GetArguments(v8::Local arguments); -} // namespace v8utils -} // namespace etcher - -#define YIELD_ERROR(CALLBACK, ERROR) \ - { \ - const wchar_t *message = (ERROR).c_str(); \ - v8::Local argv[1] = { \ - Nan::Error(v8::String::NewFromTwoByte(isolate, \ - (const uint16_t *)message)) \ - }; \ - Nan::MakeCallback(Nan::GetCurrentContext()->Global(), (CALLBACK), \ - 1, argv); \ - } \ - return; - -#define YIELD_OBJECT(CALLBACK, OBJECT) \ - { \ - v8::Local argv[2] = {Nan::Null(), (OBJECT)}; \ - Nan::MakeCallback(Nan::GetCurrentContext()->Global(), (CALLBACK), 2, \ - argv); \ - } \ - return; - -#define YIELD_NOTHING(CALLBACK) \ - Nan::MakeCallback(Nan::GetCurrentContext()->Global(), (CALLBACK), 0, 0); - -#define NAN_SET_FUNCTION(JSSYMBOL, FUNCTION) \ - Nan::Set(target, Nan::New((JSSYMBOL)).ToLocalChecked(), \ - Nan::GetFunction(Nan::New((FUNCTION))) \ - .ToLocalChecked()); - -#endif // SRC_UTILS_V8UTILS_H_