diff --git a/.gitignore b/.gitignore index 9cadbfe..7fb013d 100644 --- a/.gitignore +++ b/.gitignore @@ -38,6 +38,7 @@ build/ .gradle local.properties *.iml +.cxx # BUCK buck-out/ diff --git a/android/CMakeLists.txt b/android/CMakeLists.txt new file mode 100644 index 0000000..cbb47f3 --- /dev/null +++ b/android/CMakeLists.txt @@ -0,0 +1,29 @@ +cmake_minimum_required(VERSION 3.9.0) + +add_library( + reactnativegetrandomvalues + SHARED + ../../react-native/ReactCommon/jsi/jsi/jsi.cpp + ../cpp/react-native-get-random-values.cpp + ../cpp/base64.cpp + ./cpp-adapter.cpp +) + +include_directories( + ../../react-native/React + ../../react-native/React/Base + ../../react-native/ReactCommon/jsi + ../cpp +) + +set_target_properties( + reactnativegetrandomvalues PROPERTIES + CXX_STANDARD 17 + CXX_EXTENSIONS OFF + POSITION_INDEPENDENT_CODE ON +) + +target_link_libraries( + reactnativegetrandomvalues + android +) diff --git a/android/build.gradle b/android/build.gradle index 9f8e491..bda2206 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -6,6 +6,7 @@ buildscript { repositories { mavenCentral() google() + jcenter() } def buildGradleVersion = ext.has('buildGradlePluginVersion') ? ext.get('buildGradlePluginVersion') : '4.2.2' @@ -30,19 +31,47 @@ android { targetSdkVersion safeExtGet('targetSdkVersion', 30) versionCode 1 versionName "1.0" + + externalNativeBuild { + cmake { + cppFlags "-O2 -frtti -fexceptions -Wall -fstack-protector-all" + abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a' + } + } } + + externalNativeBuild { + cmake { + path "CMakeLists.txt" + } + } + + buildTypes { + release { + minifyEnabled false + } + } + lintOptions { abortOnError false + disable 'GradleCompatible' + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 } } repositories { + mavenLocal() mavenCentral() google() maven { // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm url "$rootDir/../node_modules/react-native/android" } + jcenter() } dependencies { diff --git a/android/cpp-adapter.cpp b/android/cpp-adapter.cpp new file mode 100644 index 0000000..287f673 --- /dev/null +++ b/android/cpp-adapter.cpp @@ -0,0 +1,13 @@ +#include +#include "react-native-get-random-values.h" + +extern "C" JNIEXPORT void JNICALL +Java_org_linusu_RNGetRandomValuesModule_nativeInstall(JNIEnv *env, jobject thiz, jlong jsi) +{ + auto runtime = reinterpret_cast(jsi); + + if (runtime) + { + reactnativegetrandomvalues::install(*runtime); + } +} diff --git a/android/src/main/java/org/linusu/RNGetRandomValuesModule.java b/android/src/main/java/org/linusu/RNGetRandomValuesModule.java index 37c728d..5b81e7b 100644 --- a/android/src/main/java/org/linusu/RNGetRandomValuesModule.java +++ b/android/src/main/java/org/linusu/RNGetRandomValuesModule.java @@ -1,22 +1,14 @@ package org.linusu; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; - -import android.util.Base64; - import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.Callback; public class RNGetRandomValuesModule extends ReactContextBaseJavaModule { - - private final ReactApplicationContext reactContext; + private native void nativeInstall(long jsiPtr, String docDir); public RNGetRandomValuesModule(ReactApplicationContext reactContext) { super(reactContext); - this.reactContext = reactContext; } @Override @@ -25,12 +17,18 @@ public String getName() { } @ReactMethod(isBlockingSynchronousMethod = true) - public String getRandomBase64(int byteLength) throws NoSuchAlgorithmException { - byte[] data = new byte[byteLength]; - SecureRandom random = new SecureRandom(); - - random.nextBytes(data); - - return Base64.encodeToString(data, Base64.NO_WRAP); + public boolean install() { + try { + System.loadLibrary("reactnativegetrandomvalues"); + + ReactApplicationContext context = getReactApplicationContext(); + nativeInstall( + context.getJavaScriptContextHolder().get(), + context.getFilesDir().getAbsolutePath() + ); + return true; + } catch (Exception exception) { + return false; + } } } diff --git a/cpp/base64.cpp b/cpp/base64.cpp new file mode 100644 index 0000000..7666ef8 --- /dev/null +++ b/cpp/base64.cpp @@ -0,0 +1,282 @@ +/* + base64.cpp and base64.h + + base64 encoding and decoding with C++. + More information at + https://renenyffenegger.ch/notes/development/Base64/Encoding-and-decoding-base-64-with-cpp + + Version: 2.rc.08 (release candidate) + + Copyright (C) 2004-2017, 2020, 2021 René Nyffenegger + + This source code is provided 'as-is', without any express or implied + warranty. In no event will the author be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this source code must not be misrepresented; you must not + claim that you wrote the original source code. If you use this source code + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original source code. + + 3. This notice may not be removed or altered from any source distribution. + + René Nyffenegger rene.nyffenegger@adp-gmbh.ch + +*/ + +#include "base64.h" + +#include +#include + + // + // Depending on the url parameter in base64_chars, one of + // two sets of base64 characters needs to be chosen. + // They differ in their last two characters. + // +static const char* base64_chars[2] = { + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789" + "+/", + + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789" + "-_"}; + +static unsigned int pos_of_char(const unsigned char chr) { + // + // Return the position of chr within base64_encode() + // + + if (chr >= 'A' && chr <= 'Z') return chr - 'A'; + else if (chr >= 'a' && chr <= 'z') return chr - 'a' + ('Z' - 'A') + 1; + else if (chr >= '0' && chr <= '9') return chr - '0' + ('Z' - 'A') + ('z' - 'a') + 2; + else if (chr == '+' || chr == '-') return 62; // Be liberal with input and accept both url ('-') and non-url ('+') base 64 characters ( + else if (chr == '/' || chr == '_') return 63; // Ditto for '/' and '_' + else + // + // 2020-10-23: Throw std::exception rather than const char* + //(Pablo Martin-Gomez, https://github.com/Bouska) + // + throw std::runtime_error("Input is not valid base64-encoded data."); +} + +static std::string insert_linebreaks(std::string str, size_t distance) { + // + // Provided by https://github.com/JomaCorpFX, adapted by me. + // + if (!str.length()) { + return ""; + } + + size_t pos = distance; + + while (pos < str.size()) { + str.insert(pos, "\n"); + pos += distance + 1; + } + + return str; +} + +template +static std::string encode_with_line_breaks(String s) { + return insert_linebreaks(base64_encode(s, false), line_length); +} + +template +static std::string encode_pem(String s) { + return encode_with_line_breaks(s); +} + +template +static std::string encode_mime(String s) { + return encode_with_line_breaks(s); +} + +template +static std::string encode(String s, bool url) { + return base64_encode(reinterpret_cast(s.data()), s.length(), url); +} + +std::string base64_encode(unsigned char const* bytes_to_encode, size_t in_len, bool url) { + + size_t len_encoded = (in_len +2) / 3 * 4; + + unsigned char trailing_char = url ? '.' : '='; + + // + // Choose set of base64 characters. They differ + // for the last two positions, depending on the url + // parameter. + // A bool (as is the parameter url) is guaranteed + // to evaluate to either 0 or 1 in C++ therefore, + // the correct character set is chosen by subscripting + // base64_chars with url. + // + const char* base64_chars_ = base64_chars[url]; + + std::string ret; + ret.reserve(len_encoded); + + unsigned int pos = 0; + + while (pos < in_len) { + ret.push_back(base64_chars_[(bytes_to_encode[pos + 0] & 0xfc) >> 2]); + + if (pos+1 < in_len) { + ret.push_back(base64_chars_[((bytes_to_encode[pos + 0] & 0x03) << 4) + ((bytes_to_encode[pos + 1] & 0xf0) >> 4)]); + + if (pos+2 < in_len) { + ret.push_back(base64_chars_[((bytes_to_encode[pos + 1] & 0x0f) << 2) + ((bytes_to_encode[pos + 2] & 0xc0) >> 6)]); + ret.push_back(base64_chars_[ bytes_to_encode[pos + 2] & 0x3f]); + } + else { + ret.push_back(base64_chars_[(bytes_to_encode[pos + 1] & 0x0f) << 2]); + ret.push_back(trailing_char); + } + } + else { + + ret.push_back(base64_chars_[(bytes_to_encode[pos + 0] & 0x03) << 4]); + ret.push_back(trailing_char); + ret.push_back(trailing_char); + } + + pos += 3; + } + + + return ret; +} + +template +static std::string decode(String encoded_string, bool remove_linebreaks) { + // + // decode(…) is templated so that it can be used with String = const std::string& + // or std::string_view (requires at least C++17) + // + + if (encoded_string.empty()) return std::string(); + + if (remove_linebreaks) { + + std::string copy(encoded_string); + + copy.erase(std::remove(copy.begin(), copy.end(), '\n'), copy.end()); + + return base64_decode(copy, false); + } + + size_t length_of_string = encoded_string.length(); + size_t pos = 0; + + // + // The approximate length (bytes) of the decoded string might be one or + // two bytes smaller, depending on the amount of trailing equal signs + // in the encoded string. This approximation is needed to reserve + // enough space in the string to be returned. + // + size_t approx_length_of_decoded_string = length_of_string / 4 * 3; + std::string ret; + ret.reserve(approx_length_of_decoded_string); + + while (pos < length_of_string) { + // + // Iterate over encoded input string in chunks. The size of all + // chunks except the last one is 4 bytes. + // + // The last chunk might be padded with equal signs or dots + // in order to make it 4 bytes in size as well, but this + // is not required as per RFC 2045. + // + // All chunks except the last one produce three output bytes. + // + // The last chunk produces at least one and up to three bytes. + // + + size_t pos_of_char_1 = pos_of_char(encoded_string[pos+1] ); + + // + // Emit the first output byte that is produced in each chunk: + // + ret.push_back(static_cast( ( (pos_of_char(encoded_string[pos+0]) ) << 2 ) + ( (pos_of_char_1 & 0x30 ) >> 4))); + + if ( ( pos + 2 < length_of_string ) && // Check for data that is not padded with equal signs (which is allowed by RFC 2045) + encoded_string[pos+2] != '=' && + encoded_string[pos+2] != '.' // accept URL-safe base 64 strings, too, so check for '.' also. + ) + { + // + // Emit a chunk's second byte (which might not be produced in the last chunk). + // + unsigned int pos_of_char_2 = pos_of_char(encoded_string[pos+2] ); + ret.push_back(static_cast( (( pos_of_char_1 & 0x0f) << 4) + (( pos_of_char_2 & 0x3c) >> 2))); + + if ( ( pos + 3 < length_of_string ) && + encoded_string[pos+3] != '=' && + encoded_string[pos+3] != '.' + ) + { + // + // Emit a chunk's third byte (which might not be produced in the last chunk). + // + ret.push_back(static_cast( ( (pos_of_char_2 & 0x03 ) << 6 ) + pos_of_char(encoded_string[pos+3]) )); + } + } + + pos += 4; + } + + return ret; +} + +std::string base64_decode(std::string const& s, bool remove_linebreaks) { + return decode(s, remove_linebreaks); +} + +std::string base64_encode(std::string const& s, bool url) { + return encode(s, url); +} + +std::string base64_encode_pem (std::string const& s) { + return encode_pem(s); +} + +std::string base64_encode_mime(std::string const& s) { + return encode_mime(s); +} + +#if __cplusplus >= 201703L +// +// Interface with std::string_view rather than const std::string& +// Requires C++17 +// Provided by Yannic Bonenberger (https://github.com/Yannic) +// + +std::string base64_encode(std::string_view s, bool url) { + return encode(s, url); +} + +std::string base64_encode_pem(std::string_view s) { + return encode_pem(s); +} + +std::string base64_encode_mime(std::string_view s) { + return encode_mime(s); +} + +std::string base64_decode(std::string_view s, bool remove_linebreaks) { + return decode(s, remove_linebreaks); +} + +#endif // __cplusplus >= 201703L diff --git a/cpp/base64.h b/cpp/base64.h new file mode 100644 index 0000000..866505e --- /dev/null +++ b/cpp/base64.h @@ -0,0 +1,35 @@ +// +// base64 encoding and decoding with C++. +// Version: 2.rc.08 (release candidate) +// + +#ifndef BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A +#define BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A + +#include + +#if __cplusplus >= 201703L +#include +#endif // __cplusplus >= 201703L + +std::string base64_encode (std::string const& s, bool url = false); +std::string base64_encode_pem (std::string const& s); +std::string base64_encode_mime(std::string const& s); + +std::string base64_decode(std::string const& s, bool remove_linebreaks = false); +std::string base64_encode(unsigned char const*, size_t len, bool url = false); + +#if __cplusplus >= 201703L +// +// Interface with std::string_view rather than const std::string& +// Requires C++17 +// Provided by Yannic Bonenberger (https://github.com/Yannic) +// +std::string base64_encode (std::string_view s, bool url = false); +std::string base64_encode_pem (std::string_view s); +std::string base64_encode_mime(std::string_view s); + +std::string base64_decode(std::string_view s, bool remove_linebreaks = false); +#endif // __cplusplus >= 201703L + +#endif /* BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A */ diff --git a/cpp/react-native-get-random-values.cpp b/cpp/react-native-get-random-values.cpp new file mode 100644 index 0000000..5c75c67 --- /dev/null +++ b/cpp/react-native-get-random-values.cpp @@ -0,0 +1,40 @@ +#include "react-native-get-random-values.h" +#include "base64.h" +#include +#include +#include + +using namespace facebook::jsi; +using namespace std; + +namespace reactnativegetrandomvalues +{ + void install(Runtime &jsiRuntime) + { + auto getRandomBase64 = Function::createFromHostFunction(jsiRuntime, + PropNameID::forAscii(jsiRuntime, + "getRandomBase64"), + 0, + [](Runtime &runtime, + const Value &thisValue, + const Value *arguments, + size_t count) -> Value + { + int byteLength = arguments[0].getNumber(); + vector buffer(byteLength, 0); + arc4random_buf(&buffer[0], + buffer.size()); + + string encodedData = base64_encode(&buffer[0], + buffer.size()); + + return Value(runtime, + String::createFromUtf8(runtime, + encodedData)); + }); + + Object RNGetRandomValues = Object(jsiRuntime); + RNGetRandomValues.setProperty(jsiRuntime, "getRandomBase64", move(getRandomBase64)); + jsiRuntime.global().setProperty(jsiRuntime, "RNGetRandomValues", move(RNGetRandomValues)); + } +} diff --git a/cpp/react-native-get-random-values.h b/cpp/react-native-get-random-values.h new file mode 100644 index 0000000..7cf8a1b --- /dev/null +++ b/cpp/react-native-get-random-values.h @@ -0,0 +1,7 @@ +#include +#include + +namespace reactnativegetrandomvalues +{ + void install(facebook::jsi::Runtime &jsiRuntime); +} diff --git a/index.js b/index.js index 7b5e313..b8129fb 100644 --- a/index.js +++ b/index.js @@ -1,11 +1,17 @@ const base64Decode = require('fast-base64-decode') const { NativeModules } = require('react-native') -class TypeMismatchError extends Error {} -class QuotaExceededError extends Error {} +const { RNGetRandomValues } = NativeModules + +if (RNGetRandomValues && typeof RNGetRandomValues.install === 'function') { + RNGetRandomValues.install() +} + +class TypeMismatchError extends Error { } +class QuotaExceededError extends Error { } let warned = false -function insecureRandomValues (array) { +function insecureRandomValues(array) { if (!warned) { console.warn('Using an insecure random number generator, this should only happen when running in a debugger without support for crypto.getRandomValues') warned = true @@ -23,9 +29,9 @@ function insecureRandomValues (array) { * @param {number} byteLength * @returns {string} */ -function getRandomBase64 (byteLength) { - if (NativeModules.RNGetRandomValues) { - return NativeModules.RNGetRandomValues.getRandomBase64(byteLength) +function getRandomBase64(byteLength) { + if (global.RNGetRandomValues) { + return global.RNGetRandomValues.getRandomBase64(byteLength) } else if (NativeModules.ExpoRandom) { // Expo SDK 41-44 return NativeModules.ExpoRandom.getRandomBase64String(byteLength) @@ -40,7 +46,7 @@ function getRandomBase64 (byteLength) { /** * @param {Int8Array|Uint8Array|Int16Array|Uint16Array|Int32Array|Uint32Array|Uint8ClampedArray} array */ -function getRandomValues (array) { +function getRandomValues(array) { if (!(array instanceof Int8Array || array instanceof Uint8Array || array instanceof Int16Array || array instanceof Uint16Array || array instanceof Int32Array || array instanceof Uint32Array || array instanceof Uint8ClampedArray)) { throw new TypeMismatchError('Expected an integer array') } diff --git a/ios/RNGetRandomValues.h b/ios/RNGetRandomValues.h index b88e04a..00a68d7 100644 --- a/ios/RNGetRandomValues.h +++ b/ios/RNGetRandomValues.h @@ -1,5 +1,5 @@ #import @interface RNGetRandomValues : NSObject --(NSString*)getRandomBase64:(NSUInteger)byteLength; + @end diff --git a/ios/RNGetRandomValues.m b/ios/RNGetRandomValues.m deleted file mode 100644 index 4eaa540..0000000 --- a/ios/RNGetRandomValues.m +++ /dev/null @@ -1,20 +0,0 @@ -#import "RNGetRandomValues.h" - -@implementation RNGetRandomValues - -- (dispatch_queue_t)methodQueue -{ - return dispatch_get_main_queue(); -} -RCT_EXPORT_MODULE() - -RCT_EXPORT_SYNCHRONOUS_TYPED_METHOD(NSString*, getRandomBase64:(NSUInteger)byteLength) { - NSMutableData *data = [NSMutableData dataWithLength:byteLength]; - int result = SecRandomCopyBytes(kSecRandomDefault, byteLength, data.mutableBytes); - if (result != errSecSuccess) { - @throw([NSException exceptionWithName:@"NO_RANDOM_BYTES" reason:@"Failed to aquire secure random bytes" userInfo:nil]); - } - return [data base64EncodedStringWithOptions:0]; -} - -@end diff --git a/ios/RNGetRandomValues.mm b/ios/RNGetRandomValues.mm new file mode 100644 index 0000000..5617f97 --- /dev/null +++ b/ios/RNGetRandomValues.mm @@ -0,0 +1,23 @@ +#import "RNGetRandomValues.h" +#import +#import +#import +#import "react-native-get-random-values.h" + +@implementation RNGetRandomValues + +RCT_EXPORT_MODULE(); + +RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(install) { + RCTBridge* bridge = [RCTBridge currentBridge]; + RCTCxxBridge* cxxBridge = (RCTCxxBridge*)bridge; + + if (cxxBridge.runtime) { + reactnativegetrandomvalues::install(*(facebook::jsi::Runtime *)cxxBridge.runtime); + return @true; + } + + return @false; +} + +@end diff --git a/ios/RNGetRandomValues.xcodeproj/project.pbxproj b/ios/RNGetRandomValues.xcodeproj/project.pbxproj index 02ff1e3..05cf5bb 100644 --- a/ios/RNGetRandomValues.xcodeproj/project.pbxproj +++ b/ios/RNGetRandomValues.xcodeproj/project.pbxproj @@ -6,10 +6,6 @@ objectVersion = 46; objects = { -/* Begin PBXBuildFile section */ - B3E7B58A1CC2AC0600A0062D /* RNGetRandomValues.m in Sources */ = {isa = PBXBuildFile; fileRef = B3E7B5891CC2AC0600A0062D /* RNGetRandomValues.m */; }; -/* End PBXBuildFile section */ - /* Begin PBXCopyFilesBuildPhase section */ 58B511D91A9E6C8500147676 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; @@ -24,8 +20,12 @@ /* Begin PBXFileReference section */ 134814201AA4EA6300B7C361 /* libRNGetRandomValues.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNGetRandomValues.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 5DBE5CF32896460300C3D3E7 /* RNGetRandomValues.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = RNGetRandomValues.mm; sourceTree = ""; }; + 5DBE5CF42896461000C3D3E7 /* react-native-get-random-values.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "react-native-get-random-values.cpp"; path = "../cpp/react-native-get-random-values.cpp"; sourceTree = ""; }; + 5DBE5CF52896461000C3D3E7 /* base64.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = base64.cpp; path = ../cpp/base64.cpp; sourceTree = ""; }; + 5DBE5CF62896461000C3D3E7 /* base64.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = base64.h; path = ../cpp/base64.h; sourceTree = ""; }; + 5DBE5CF72896461000C3D3E7 /* react-native-get-random-values.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "react-native-get-random-values.h"; path = "../cpp/react-native-get-random-values.h"; sourceTree = ""; }; B3E7B5881CC2AC0600A0062D /* RNGetRandomValues.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNGetRandomValues.h; sourceTree = ""; }; - B3E7B5891CC2AC0600A0062D /* RNGetRandomValues.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNGetRandomValues.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -51,7 +51,11 @@ isa = PBXGroup; children = ( B3E7B5881CC2AC0600A0062D /* RNGetRandomValues.h */, - B3E7B5891CC2AC0600A0062D /* RNGetRandomValues.m */, + 5DBE5CF32896460300C3D3E7 /* RNGetRandomValues.mm */, + 5DBE5CF52896461000C3D3E7 /* base64.cpp */, + 5DBE5CF62896461000C3D3E7 /* base64.h */, + 5DBE5CF42896461000C3D3E7 /* react-native-get-random-values.cpp */, + 5DBE5CF72896461000C3D3E7 /* react-native-get-random-values.h */, 134814211AA4EA7D00B7C361 /* Products */, ); sourceTree = ""; @@ -95,6 +99,7 @@ developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( + English, en, ); mainGroup = 58B511D21A9E6C8500147676; @@ -112,7 +117,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - B3E7B58A1CC2AC0600A0062D /* RNGetRandomValues.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -204,7 +208,7 @@ isa = XCBuildConfiguration; buildSettings = { HEADER_SEARCH_PATHS = ( - "$(inherited)", + "$(inherited)", /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, "$(SRCROOT)/../../../React/**", "$(SRCROOT)/../../react-native/React/**", diff --git a/ios/RNGetRandomValues.xcworkspace/contents.xcworkspacedata b/ios/RNGetRandomValues.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index fab555a..0000000 --- a/ios/RNGetRandomValues.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,9 +0,0 @@ -// !$*UTF8*$! - - - - - - \ No newline at end of file diff --git a/react-native-get-random-values.podspec b/react-native-get-random-values.podspec index f7075eb..00aa773 100644 --- a/react-native-get-random-values.podspec +++ b/react-native-get-random-values.podspec @@ -13,7 +13,7 @@ Pod::Spec.new do |s| s.platforms = { :ios => "9.0", :tvos => "9.0", :osx => "10.14" } s.source = { :git => "https://github.com/LinusU/react-native-get-random-values.git", :tag => "v#{s.version}" } - s.source_files = "ios/**/*.{h,m,swift}" + s.source_files = 'ios/**/*.{h,m,mm}', 'cpp/**/*.{h,c,cpp}' s.requires_arc = true s.dependency "React-Core"