diff --git a/.gitignore b/.gitignore
index 97104ee..dfc65ae 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,7 @@
/.idea
*.lock
*.iml
+
+.DS_Store
+.packages
+.metadata
\ No newline at end of file
diff --git a/.idea/libraries/Dart_SDK.xml b/.idea/libraries/Dart_SDK.xml
deleted file mode 100644
index 824a5c2..0000000
--- a/.idea/libraries/Dart_SDK.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Flutter_Plugins.xml b/.idea/libraries/Flutter_Plugins.xml
deleted file mode 100644
index 53449da..0000000
--- a/.idea/libraries/Flutter_Plugins.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
deleted file mode 100644
index 8b2d6a3..0000000
--- a/.idea/modules.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/stringcare.iml b/.idea/stringcare.iml
deleted file mode 100644
index 0dd1aec..0000000
--- a/.idea/stringcare.iml
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
deleted file mode 100644
index 35eb1dd..0000000
--- a/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
deleted file mode 100644
index 994b7bd..0000000
--- a/.idea/workspace.xml
+++ /dev/null
@@ -1,162 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 1613351449213
-
-
- 1613351449213
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
deleted file mode 100644
index 5f34dd8..0000000
--- a/.vscode/settings.json
+++ /dev/null
@@ -1,67 +0,0 @@
-{
- "files.associations": {
- "__bit_reference": "cpp",
- "__config": "cpp",
- "__debug": "cpp",
- "__errc": "cpp",
- "__functional_base": "cpp",
- "__hash_table": "cpp",
- "__locale": "cpp",
- "__mutex_base": "cpp",
- "__node_handle": "cpp",
- "__nullptr": "cpp",
- "__split_buffer": "cpp",
- "__string": "cpp",
- "__threading_support": "cpp",
- "__tree": "cpp",
- "__tuple": "cpp",
- "algorithm": "cpp",
- "array": "cpp",
- "atomic": "cpp",
- "bit": "cpp",
- "bitset": "cpp",
- "cctype": "cpp",
- "chrono": "cpp",
- "cmath": "cpp",
- "complex": "cpp",
- "cstdarg": "cpp",
- "cstddef": "cpp",
- "cstdint": "cpp",
- "cstdio": "cpp",
- "cstdlib": "cpp",
- "cstring": "cpp",
- "ctime": "cpp",
- "cwchar": "cpp",
- "cwctype": "cpp",
- "exception": "cpp",
- "functional": "cpp",
- "initializer_list": "cpp",
- "ios": "cpp",
- "iosfwd": "cpp",
- "iostream": "cpp",
- "istream": "cpp",
- "iterator": "cpp",
- "limits": "cpp",
- "locale": "cpp",
- "map": "cpp",
- "memory": "cpp",
- "mutex": "cpp",
- "new": "cpp",
- "optional": "cpp",
- "ostream": "cpp",
- "ratio": "cpp",
- "set": "cpp",
- "sstream": "cpp",
- "stdexcept": "cpp",
- "streambuf": "cpp",
- "string": "cpp",
- "string_view": "cpp",
- "system_error": "cpp",
- "tuple": "cpp",
- "type_traits": "cpp",
- "typeinfo": "cpp",
- "unordered_map": "cpp",
- "utility": "cpp",
- "vector": "cpp"
- }
-}
\ No newline at end of file
diff --git a/README.md b/README.md
index 6f5309e..7a889df 100644
--- a/README.md
+++ b/README.md
@@ -1,153 +1,37 @@
-Stringcare for Flutter
+Stringcare Flutter
Land-a dependency
-
+#### [Home](https://github.com/StringCare/stringcare/wiki)
-- Platforms supported: Android, iOS, MacOS, Windows
+#### [Setup](https://github.com/StringCare/stringcare/wiki/Setup)
-This is a Flutter plugin for encrypt/decrypt `String` and `Uint8List` objects easily with C++ code.
+#### [String Usage](https://github.com/StringCare/stringcare/wiki/String-Usage)
-Only `ffi` and `crypto` dependencies are used.
-
-### Installation
-
-It is not possible to use the plugin directly by adding the dependency to the `pubspec.yaml` file.
-Due to some limitations when adding the C++ file to the iOS and macOS runner targets and some other (recommended) modifications, you need to fork/clone the repository.
-
-> In order to increase the security, it is recommended to modify the code (how the keys are generated) in your repository before use it.
-
-> Make your repository private.
-
-#### Prepare your private repository
-
-Prepare your empty private repository. For example:
-
-```
-https://github.com/YOUR-USERNAME/stringcare
-```
-
-In your machine, duplicate this repo to yours:
-
-```bash
-// clone original
-git clone --bare https://github.com/StringCare/stringcare.git
-cd stringcare.git/
-git push --mirror https://github.com/YOUR-USERNAME/stringcare.git
-
-// remove old repository
-cd ..
-rm -rf stringcare
-
-// clone yours
-git clone https://github.com/YOUR-USERNAME/stringcare.git
-```
-
-Then include the dependency to the `pubspec.yaml` file.
-
-```yaml
-dependencies:
- stringcare:
- git:
- url: https://github.com/YOUR-USERNAME/stringcare.git
-```
-
-> Since Flutter 2, I noticed dangerous problems when indexing the project after adding the local dependency by `path: ../whatever`. That's why I recommend to implement the plugin by `git: url: https://..`.
-
-#### iOS and macOS setup
-
-Add the C++ file to the `Runner` targets.
-
-You can locate the `stringcare.cpp` file in your cloned private repository:
-
-```
-stringcare/ios/Classes/stringcare.cpp
-```
+#### [Uint8List Usage](https://github.com/StringCare/stringcare/wiki/Uint8List-Usage)
-If XCode ask for include the `Runner-Bridging-Header.h` file to the project, do it.
+-----
-
+Flutter plugin for encrypt/decrypt `String` and `Uint8List` objects easily with C++ code.
-#### Key setup
+| | Android | iOS | [Web](https://flutter.dev/web) | [macOS](https://flutter.dev/desktop) | [Windows](https://flutter.dev/desktop) | [Linux](https://flutter.dev/desktop) | [Fuchsia](https://fuchsia.dev/) |
+| :-------------: | :-------------:| :-----: | :-----: | :-----: | :-----: | :-----: | :-----: |
+| Status | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :gear: [WIP] | β |
+| Language | C++ | C++ | Dart | C++ | C++ | C++ | |
-This is the default key used when no extra keys are provided.
-Implement your own key by changing the `pd` value:
-> stringcare/ios/Classes/stringcare.cpp
-
-```cpp
-std::string pd = "your_pasword";
-```
-
-> Feel free to change anything you want in this C++ file. I recommend you to change the numeric values of the `sign` method in this file.
-
-### Finish the setup
-
-Once you modify the C++ file as you want, you need to push those changes to your private repository. For updating the plugin from a git repository you can:
-
-```bash
-// remove stringcare from your pubspec.yaml
-
-flutter pub get
-
-// add stringcare again to your pubspec.yaml
-
-flutter pub get
-```
-
-### String usage
-
-#### Simple
-
-```dart
-String obfuscated = Stringcare.obfuscate("hello there π");
-String revealed = Stringcare.reveal(obfuscated);
-
-print(revealed); // prints "hello there π"
-```
-
-#### With extra keys
-```dart
-String p1 = "dsgfjkbndsgfbldsgbdjns";
-String p2 = "sfvsfdgvsdfvsfdvsfvsrf";
-String p3 = "dtlbkjdnsfvsftrglbjknd";
-
-String obfuscated = Stringcare.obfuscateWith([p2, p1, p3], "hello there π");
-String revealed = Stringcare.revealWith([p1, p3, p2], obfuscated);
-
-print(revealed); // prints "hello there π"
-```
-
-### Uint8List usage
-
-#### Simple
-
-```dart
-var file = File("file/path");
-Uint8List original = file.readAsBytesSync();
+Only `ffi` and `crypto` dependencies are used.
-Uint8List obfuscated = Stringcare.obfuscateData(original);
-file.writeAsBytesSync(obfuscated);
+-----
-Uint8List revealed = Stringcare.revealData(obfuscated);
-file.writeAsBytesSync(revealed);
-```
+
-#### With extra keys
-```dart
-String p1 = "dsgfjkbndsgfbldsgbdjns";
-String p2 = "sfvsfdgvsdfvsfdvsfvsrf";
-String p3 = "dtlbkjdnsfvsftrglbjknd";
+
-var file = File("file/path");
-Uint8List original = file.readAsBytesSync();
+
-Uint8List obfuscated = Stringcare.obfuscateDataWith([p2, p1, p3], original);
-file.writeAsBytesSync(obfuscated);
+
-Uint8List revealed = Stringcare.revealDataWith([p1, p3, p2], obfuscated);
-file.writeAsBytesSync(revealed);
-```
diff --git a/example/.metadata b/example/.metadata
deleted file mode 100644
index cd984dd..0000000
--- a/example/.metadata
+++ /dev/null
@@ -1,10 +0,0 @@
-# This file tracks properties of this Flutter project.
-# Used by Flutter tool to assess capabilities and perform upgrades etc.
-#
-# This file should be version controlled and should not be manually edited.
-
-version:
- revision: 9b2d32b605630f28625709ebd9d78ab3016b2bf6
- channel: stable
-
-project_type: app
diff --git a/example/CHANGELOG.md b/example/CHANGELOG.md
new file mode 100644
index 0000000..41cc7d8
--- /dev/null
+++ b/example/CHANGELOG.md
@@ -0,0 +1,3 @@
+## 0.0.1
+
+* TODO: Describe initial release.
diff --git a/example/LICENSE b/example/LICENSE
new file mode 100644
index 0000000..ba75c69
--- /dev/null
+++ b/example/LICENSE
@@ -0,0 +1 @@
+TODO: Add your license here.
diff --git a/example/README.md b/example/README.md
index 84978bb..f5e0c1f 100644
--- a/example/README.md
+++ b/example/README.md
@@ -1,4 +1,19 @@
-# Stringcare for Flutter Sample
+# Stringcare Flutter Sample
+
+| | Android | iOS | [Web](https://flutter.dev/web) | [macOS](https://flutter.dev/desktop) | [Windows](https://flutter.dev/desktop) | [Linux](https://flutter.dev/desktop) | [Fuchsia](https://fuchsia.dev/) |
+| :-------------: | :-------------:| :-----: | :-----: | :-----: | :-----: | :-----: | :-----: |
+| Status | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :gear: [WIP] | β |
+| Language | C++ | C++ | Dart | C++ | C++ | C++ | |
+
+-----
+
+
+
+
+
+
+
+
+
-Works in iOS, Android, macOS and Windows.
diff --git a/example/android/app/src/main/res/drawable-v21/launch_background.xml b/example/android/app/src/main/res/drawable-v21/launch_background.xml
new file mode 100644
index 0000000..f74085f
--- /dev/null
+++ b/example/android/app/src/main/res/drawable-v21/launch_background.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
diff --git a/example/android/app/src/main/res/values-night/styles.xml b/example/android/app/src/main/res/values-night/styles.xml
new file mode 100644
index 0000000..449a9f9
--- /dev/null
+++ b/example/android/app/src/main/res/values-night/styles.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock
deleted file mode 100644
index 351c520..0000000
--- a/example/ios/Podfile.lock
+++ /dev/null
@@ -1,22 +0,0 @@
-PODS:
- - Flutter (1.0.0)
- - stringcare (0.0.1):
- - Flutter
-
-DEPENDENCIES:
- - Flutter (from `Flutter`)
- - stringcare (from `.symlinks/plugins/stringcare/ios`)
-
-EXTERNAL SOURCES:
- Flutter:
- :path: Flutter
- stringcare:
- :path: ".symlinks/plugins/stringcare/ios"
-
-SPEC CHECKSUMS:
- Flutter: 434fef37c0980e73bb6479ef766c45957d4b510c
- stringcare: 843b229f81e53627e09cb2e999f21d52a554a030
-
-PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c
-
-COCOAPODS: 1.10.1
diff --git a/example/lib/main.dart b/example/lib/main.dart
index d352605..d4d9185 100644
--- a/example/lib/main.dart
+++ b/example/lib/main.dart
@@ -24,7 +24,7 @@ class _MyAppState extends State {
void initState() {
super.initState();
initPlatformState();
- widget.presenter.prepareImages();
+ // widget.presenter.prepareImages();
}
// Platform messages are asynchronous, so we initialize in an async method.
@@ -49,6 +49,7 @@ class _MyAppState extends State {
@override
Widget build(BuildContext context) {
+ var obEmoji = widget.presenter.obfuscatedEmoji.split(",");
return MaterialApp(
home: Scaffold(
appBar: AppBar(
@@ -70,6 +71,18 @@ class _MyAppState extends State {
padding: EdgeInsets.all(15),
child: Column(
children: [
+ ListTile(
+ title: Text("Test hash"),
+ ),
+ Text(Stringcare.testHash([
+ "xfgbxsfgbdxfgnbxfgnbxfgnbsfgbxfgbxfgbxfgcvb xcvb"
+ ])),
+ ListTile(
+ title: Text("Test sign"),
+ ),
+ Text(Stringcare.testSign([
+ "xfgbxsfgbdxfgnbxfgnbxfgnbsfgbxfgbxfgbxfgcvb xcvb"
+ ])),
ListTile(
title: Text("Obfuscation blank"),
),
@@ -78,7 +91,7 @@ class _MyAppState extends State {
ListTile(
title: Text("Reveal blank"),
),
- Text(widget.presenter.revealedBlank),
+ Text("'${widget.presenter.revealedBlank}'"),
],
),
),
@@ -117,9 +130,9 @@ class _MyAppState extends State {
ListTile(
title: Text("Obfuscation emojis"),
),
- Text(widget.presenter.obfuscatedEmoji
- .split(",")
- .getRange(0, 30)
+ Text(obEmoji
+ .getRange(
+ 0, obEmoji.length > 30 ? 30 : obEmoji.length)
.toString()),
Padding(padding: EdgeInsets.all(8)),
ListTile(
diff --git a/example/lib/presenter.dart b/example/lib/presenter.dart
index 7630a86..1198cd7 100644
--- a/example/lib/presenter.dart
+++ b/example/lib/presenter.dart
@@ -34,6 +34,7 @@ class Presenter {
revealedBlank = Stringcare.reveal(obfuscatedBlank);
obfuscatedHello = Stringcare.obfuscate(Vars.hello);
revealedHello = Stringcare.reveal(obfuscatedHello);
+
obfuscatedEmoji = Stringcare.obfuscateWith([p2, p1, p3], Vars.emojis);
revealedEmoji = Stringcare.revealWith([p1, p3, p2], obfuscatedEmoji);
signatureEmoji = Stringcare.getSignature([p1, p2, p3]);
diff --git a/example/lib/vars.dart b/example/lib/vars.dart
index f01e6d1..b1bbaf7 100644
--- a/example/lib/vars.dart
+++ b/example/lib/vars.dart
@@ -1,6 +1,5 @@
class Vars {
- static String blank =
- " ";
+ static String blank = " ";
static String hello = "Hello";
static String emojis = [
"πΆ",
diff --git a/example/linux/.gitignore b/example/linux/.gitignore
new file mode 100644
index 0000000..d3896c9
--- /dev/null
+++ b/example/linux/.gitignore
@@ -0,0 +1 @@
+flutter/ephemeral
diff --git a/example/linux/CMakeLists.txt b/example/linux/CMakeLists.txt
new file mode 100644
index 0000000..290c3e8
--- /dev/null
+++ b/example/linux/CMakeLists.txt
@@ -0,0 +1,106 @@
+cmake_minimum_required(VERSION 3.10)
+project(runner LANGUAGES CXX)
+
+set(BINARY_NAME "example")
+set(APPLICATION_ID "com.example.example")
+
+cmake_policy(SET CMP0063 NEW)
+
+set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")
+
+# Configure build options.
+if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
+ set(CMAKE_BUILD_TYPE "Debug" CACHE
+ STRING "Flutter build mode" FORCE)
+ set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
+ "Debug" "Profile" "Release")
+endif()
+
+# Compilation settings that should be applied to most targets.
+function(APPLY_STANDARD_SETTINGS TARGET)
+ target_compile_features(${TARGET} PUBLIC cxx_std_14)
+ target_compile_options(${TARGET} PRIVATE -Wall -Werror)
+ target_compile_options(${TARGET} PRIVATE "$<$>:-O3>")
+ target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>")
+endfunction()
+
+set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
+
+# Flutter library and tool build rules.
+add_subdirectory(${FLUTTER_MANAGED_DIR})
+
+# System-level dependencies.
+find_package(PkgConfig REQUIRED)
+pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
+
+add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}")
+
+# Application build
+add_executable(${BINARY_NAME}
+ "main.cc"
+ "my_application.cc"
+ "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
+)
+apply_standard_settings(${BINARY_NAME})
+target_link_libraries(${BINARY_NAME} PRIVATE flutter)
+target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
+add_dependencies(${BINARY_NAME} flutter_assemble)
+# Only the install-generated bundle's copy of the executable will launch
+# correctly, since the resources must in the right relative locations. To avoid
+# people trying to run the unbundled copy, put it in a subdirectory instead of
+# the default top-level location.
+set_target_properties(${BINARY_NAME}
+ PROPERTIES
+ RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run"
+)
+
+# Generated plugin build rules, which manage building the plugins and adding
+# them to the application.
+include(flutter/generated_plugins.cmake)
+
+
+# === Installation ===
+# By default, "installing" just makes a relocatable bundle in the build
+# directory.
+set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle")
+if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
+ set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
+endif()
+
+# Start with a clean build bundle directory every time.
+install(CODE "
+ file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\")
+ " COMPONENT Runtime)
+
+set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
+set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")
+
+install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
+ COMPONENT Runtime)
+
+install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
+ COMPONENT Runtime)
+
+install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
+ COMPONENT Runtime)
+
+if(PLUGIN_BUNDLED_LIBRARIES)
+ install(FILES "${PLUGIN_BUNDLED_LIBRARIES}"
+ DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
+ COMPONENT Runtime)
+endif()
+
+# Fully re-copy the assets directory on each build to avoid having stale files
+# from a previous install.
+set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
+install(CODE "
+ file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
+ " COMPONENT Runtime)
+install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
+ DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
+
+# Install the AOT library on non-Debug builds only.
+if(NOT CMAKE_BUILD_TYPE MATCHES "Debug")
+ install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
+ COMPONENT Runtime)
+endif()
diff --git a/example/linux/flutter/CMakeLists.txt b/example/linux/flutter/CMakeLists.txt
new file mode 100644
index 0000000..a1da1b9
--- /dev/null
+++ b/example/linux/flutter/CMakeLists.txt
@@ -0,0 +1,91 @@
+cmake_minimum_required(VERSION 3.10)
+
+set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
+
+# Configuration provided via flutter tool.
+include(${EPHEMERAL_DIR}/generated_config.cmake)
+
+# TODO: Move the rest of this into files in ephemeral. See
+# https://github.com/flutter/flutter/issues/57146.
+
+# Serves the same purpose as list(TRANSFORM ... PREPEND ...),
+# which isn't available in 3.10.
+function(list_prepend LIST_NAME PREFIX)
+ set(NEW_LIST "")
+ foreach(element ${${LIST_NAME}})
+ list(APPEND NEW_LIST "${PREFIX}${element}")
+ endforeach(element)
+ set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE)
+endfunction()
+
+# === Flutter Library ===
+# System-level dependencies.
+find_package(PkgConfig REQUIRED)
+pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
+pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
+pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)
+pkg_check_modules(BLKID REQUIRED IMPORTED_TARGET blkid)
+pkg_check_modules(LZMA REQUIRED IMPORTED_TARGET liblzma)
+
+set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so")
+
+# Published to parent scope for install step.
+set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
+set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
+set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
+set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE)
+
+list(APPEND FLUTTER_LIBRARY_HEADERS
+ "fl_basic_message_channel.h"
+ "fl_binary_codec.h"
+ "fl_binary_messenger.h"
+ "fl_dart_project.h"
+ "fl_engine.h"
+ "fl_json_message_codec.h"
+ "fl_json_method_codec.h"
+ "fl_message_codec.h"
+ "fl_method_call.h"
+ "fl_method_channel.h"
+ "fl_method_codec.h"
+ "fl_method_response.h"
+ "fl_plugin_registrar.h"
+ "fl_plugin_registry.h"
+ "fl_standard_message_codec.h"
+ "fl_standard_method_codec.h"
+ "fl_string_codec.h"
+ "fl_value.h"
+ "fl_view.h"
+ "flutter_linux.h"
+)
+list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/")
+add_library(flutter INTERFACE)
+target_include_directories(flutter INTERFACE
+ "${EPHEMERAL_DIR}"
+)
+target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}")
+target_link_libraries(flutter INTERFACE
+ PkgConfig::GTK
+ PkgConfig::GLIB
+ PkgConfig::GIO
+ PkgConfig::BLKID
+ PkgConfig::LZMA
+)
+add_dependencies(flutter flutter_assemble)
+
+# === Flutter tool backend ===
+# _phony_ is a non-existent file to force this command to run every time,
+# since currently there's no way to get a full input/output list from the
+# flutter tool.
+add_custom_command(
+ OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
+ ${CMAKE_CURRENT_BINARY_DIR}/_phony_
+ COMMAND ${CMAKE_COMMAND} -E env
+ ${FLUTTER_TOOL_ENVIRONMENT}
+ "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh"
+ linux-x64 ${CMAKE_BUILD_TYPE}
+ VERBATIM
+)
+add_custom_target(flutter_assemble DEPENDS
+ "${FLUTTER_LIBRARY}"
+ ${FLUTTER_LIBRARY_HEADERS}
+)
diff --git a/example/linux/flutter/generated_plugin_registrant.cc b/example/linux/flutter/generated_plugin_registrant.cc
new file mode 100644
index 0000000..d38195a
--- /dev/null
+++ b/example/linux/flutter/generated_plugin_registrant.cc
@@ -0,0 +1,9 @@
+//
+// Generated file. Do not edit.
+//
+
+#include "generated_plugin_registrant.h"
+
+
+void fl_register_plugins(FlPluginRegistry* registry) {
+}
diff --git a/example/linux/flutter/generated_plugin_registrant.h b/example/linux/flutter/generated_plugin_registrant.h
new file mode 100644
index 0000000..9bf7478
--- /dev/null
+++ b/example/linux/flutter/generated_plugin_registrant.h
@@ -0,0 +1,13 @@
+//
+// Generated file. Do not edit.
+//
+
+#ifndef GENERATED_PLUGIN_REGISTRANT_
+#define GENERATED_PLUGIN_REGISTRANT_
+
+#include
+
+// Registers Flutter plugins.
+void fl_register_plugins(FlPluginRegistry* registry);
+
+#endif // GENERATED_PLUGIN_REGISTRANT_
diff --git a/example/linux/flutter/generated_plugins.cmake b/example/linux/flutter/generated_plugins.cmake
new file mode 100644
index 0000000..51436ae
--- /dev/null
+++ b/example/linux/flutter/generated_plugins.cmake
@@ -0,0 +1,15 @@
+#
+# Generated file, do not edit.
+#
+
+list(APPEND FLUTTER_PLUGIN_LIST
+)
+
+set(PLUGIN_BUNDLED_LIBRARIES)
+
+foreach(plugin ${FLUTTER_PLUGIN_LIST})
+ add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
+ target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
+ list(APPEND PLUGIN_BUNDLED_LIBRARIES $)
+ list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
+endforeach(plugin)
diff --git a/example/linux/main.cc b/example/linux/main.cc
new file mode 100644
index 0000000..e7c5c54
--- /dev/null
+++ b/example/linux/main.cc
@@ -0,0 +1,6 @@
+#include "my_application.h"
+
+int main(int argc, char** argv) {
+ g_autoptr(MyApplication) app = my_application_new();
+ return g_application_run(G_APPLICATION(app), argc, argv);
+}
diff --git a/example/linux/my_application.cc b/example/linux/my_application.cc
new file mode 100644
index 0000000..543eaca
--- /dev/null
+++ b/example/linux/my_application.cc
@@ -0,0 +1,104 @@
+#include "my_application.h"
+
+#include
+#ifdef GDK_WINDOWING_X11
+#include
+#endif
+
+#include "flutter/generated_plugin_registrant.h"
+
+struct _MyApplication {
+ GtkApplication parent_instance;
+ char** dart_entrypoint_arguments;
+};
+
+G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION)
+
+// Implements GApplication::activate.
+static void my_application_activate(GApplication* application) {
+ MyApplication* self = MY_APPLICATION(application);
+ GtkWindow* window =
+ GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));
+
+ // Use a header bar when running in GNOME as this is the common style used
+ // by applications and is the setup most users will be using (e.g. Ubuntu
+ // desktop).
+ // If running on X and not using GNOME then just use a traditional title bar
+ // in case the window manager does more exotic layout, e.g. tiling.
+ // If running on Wayland assume the header bar will work (may need changing
+ // if future cases occur).
+ gboolean use_header_bar = TRUE;
+#ifdef GDK_WINDOWING_X11
+ GdkScreen *screen = gtk_window_get_screen(window);
+ if (GDK_IS_X11_SCREEN(screen)) {
+ const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen);
+ if (g_strcmp0(wm_name, "GNOME Shell") != 0) {
+ use_header_bar = FALSE;
+ }
+ }
+#endif
+ if (use_header_bar) {
+ GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
+ gtk_widget_show(GTK_WIDGET(header_bar));
+ gtk_header_bar_set_title(header_bar, "example");
+ gtk_header_bar_set_show_close_button(header_bar, TRUE);
+ gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
+ }
+ else {
+ gtk_window_set_title(window, "example");
+ }
+
+ gtk_window_set_default_size(window, 1280, 720);
+ gtk_widget_show(GTK_WIDGET(window));
+
+ g_autoptr(FlDartProject) project = fl_dart_project_new();
+ fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments);
+
+ FlView* view = fl_view_new(project);
+ gtk_widget_show(GTK_WIDGET(view));
+ gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
+
+ fl_register_plugins(FL_PLUGIN_REGISTRY(view));
+
+ gtk_widget_grab_focus(GTK_WIDGET(view));
+}
+
+// Implements GApplication::local_command_line.
+static gboolean my_application_local_command_line(GApplication* application, gchar ***arguments, int *exit_status) {
+ MyApplication* self = MY_APPLICATION(application);
+ // Strip out the first argument as it is the binary name.
+ self->dart_entrypoint_arguments = g_strdupv(*arguments + 1);
+
+ g_autoptr(GError) error = nullptr;
+ if (!g_application_register(application, nullptr, &error)) {
+ g_warning("Failed to register: %s", error->message);
+ *exit_status = 1;
+ return TRUE;
+ }
+
+ g_application_activate(application);
+ *exit_status = 0;
+
+ return TRUE;
+}
+
+// Implements GObject::dispose.
+static void my_application_dispose(GObject *object) {
+ MyApplication* self = MY_APPLICATION(object);
+ g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev);
+ G_OBJECT_CLASS(my_application_parent_class)->dispose(object);
+}
+
+static void my_application_class_init(MyApplicationClass* klass) {
+ G_APPLICATION_CLASS(klass)->activate = my_application_activate;
+ G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line;
+ G_OBJECT_CLASS(klass)->dispose = my_application_dispose;
+}
+
+static void my_application_init(MyApplication* self) {}
+
+MyApplication* my_application_new() {
+ return MY_APPLICATION(g_object_new(my_application_get_type(),
+ "application-id", APPLICATION_ID,
+ nullptr));
+}
diff --git a/example/linux/my_application.h b/example/linux/my_application.h
new file mode 100644
index 0000000..72271d5
--- /dev/null
+++ b/example/linux/my_application.h
@@ -0,0 +1,18 @@
+#ifndef FLUTTER_MY_APPLICATION_H_
+#define FLUTTER_MY_APPLICATION_H_
+
+#include
+
+G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION,
+ GtkApplication)
+
+/**
+ * my_application_new:
+ *
+ * Creates a new Flutter-based application.
+ *
+ * Returns: a new #MyApplication.
+ */
+MyApplication* my_application_new();
+
+#endif // FLUTTER_MY_APPLICATION_H_
diff --git a/example/macos/Podfile.lock b/example/macos/Podfile.lock
deleted file mode 100644
index 133a8ee..0000000
--- a/example/macos/Podfile.lock
+++ /dev/null
@@ -1,22 +0,0 @@
-PODS:
- - FlutterMacOS (1.0.0)
- - stringcare (0.0.1):
- - FlutterMacOS
-
-DEPENDENCIES:
- - FlutterMacOS (from `Flutter/ephemeral`)
- - stringcare (from `Flutter/ephemeral/.symlinks/plugins/stringcare/macos`)
-
-EXTERNAL SOURCES:
- FlutterMacOS:
- :path: Flutter/ephemeral
- stringcare:
- :path: Flutter/ephemeral/.symlinks/plugins/stringcare/macos
-
-SPEC CHECKSUMS:
- FlutterMacOS: 57701585bf7de1b3fc2bb61f6378d73bbdea8424
- stringcare: 12ca62e6fdff5f7a90576ec0bcc4f4f7aab05ed1
-
-PODFILE CHECKSUM: 6eac6b3292e5142cfc23bdeb71848a40ec51c14c
-
-COCOAPODS: 1.10.1
diff --git a/example/macos/Runner.xcodeproj/project.pbxproj b/example/macos/Runner.xcodeproj/project.pbxproj
index 161c820..a965b77 100644
--- a/example/macos/Runner.xcodeproj/project.pbxproj
+++ b/example/macos/Runner.xcodeproj/project.pbxproj
@@ -189,7 +189,7 @@
33CC10EB2044A3C60003C045 /* Resources */,
33CC110E2044A8840003C045 /* Bundle Framework */,
3399D490228B24CF009A79C7 /* ShellScript */,
- 95403333E81DDA7C9FD93C2E /* [CP] Embed Pods Frameworks */,
+ C82EA4853E0329FE8D016FA7 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
@@ -296,43 +296,43 @@
shellPath = /bin/sh;
shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire";
};
- 95403333E81DDA7C9FD93C2E /* [CP] Embed Pods Frameworks */ = {
+ A3AA704E031909ADBF1E16D6 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
- "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
- name = "[CP] Embed Pods Frameworks";
+ inputPaths = (
+ "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+ "${PODS_ROOT}/Manifest.lock",
+ );
+ name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
- "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
+ );
+ outputPaths = (
+ "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
+ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
- A3AA704E031909ADBF1E16D6 /* [CP] Check Pods Manifest.lock */ = {
+ C82EA4853E0329FE8D016FA7 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
- inputPaths = (
- "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
- "${PODS_ROOT}/Manifest.lock",
- );
- name = "[CP] Check Pods Manifest.lock";
+ name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
- );
- outputPaths = (
- "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
+ "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
diff --git a/example/pubspec.lock b/example/pubspec.lock
deleted file mode 100644
index efdf935..0000000
--- a/example/pubspec.lock
+++ /dev/null
@@ -1,175 +0,0 @@
-# Generated by pub
-# See https://dart.dev/tools/pub/glossary#lockfile
-packages:
- async:
- dependency: transitive
- description:
- name: async
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.5.0"
- boolean_selector:
- dependency: transitive
- description:
- name: boolean_selector
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.1.0"
- characters:
- dependency: transitive
- description:
- name: characters
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.1.0"
- charcode:
- dependency: transitive
- description:
- name: charcode
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.2.0"
- clock:
- dependency: transitive
- description:
- name: clock
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.1.0"
- collection:
- dependency: transitive
- description:
- name: collection
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.15.0"
- crypto:
- dependency: transitive
- description:
- name: crypto
- url: "https://pub.dartlang.org"
- source: hosted
- version: "3.0.0"
- cupertino_icons:
- dependency: "direct main"
- description:
- name: cupertino_icons
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.0.0"
- fake_async:
- dependency: transitive
- description:
- name: fake_async
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.2.0"
- ffi:
- dependency: transitive
- description:
- name: ffi
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.0.0"
- flutter:
- dependency: "direct main"
- description: flutter
- source: sdk
- version: "0.0.0"
- flutter_test:
- dependency: "direct dev"
- description: flutter
- source: sdk
- version: "0.0.0"
- matcher:
- dependency: transitive
- description:
- name: matcher
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.12.10"
- meta:
- dependency: transitive
- description:
- name: meta
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.3.0"
- path:
- dependency: transitive
- description:
- name: path
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.8.0"
- sky_engine:
- dependency: transitive
- description: flutter
- source: sdk
- version: "0.0.99"
- source_span:
- dependency: transitive
- description:
- name: source_span
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.8.0"
- stack_trace:
- dependency: transitive
- description:
- name: stack_trace
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.10.0"
- stream_channel:
- dependency: transitive
- description:
- name: stream_channel
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.1.0"
- string_scanner:
- dependency: transitive
- description:
- name: string_scanner
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.1.0"
- stringcare:
- dependency: "direct main"
- description:
- path: ".."
- relative: true
- source: path
- version: "0.0.1"
- term_glyph:
- dependency: transitive
- description:
- name: term_glyph
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.2.0"
- test_api:
- dependency: transitive
- description:
- name: test_api
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.2.19"
- typed_data:
- dependency: transitive
- description:
- name: typed_data
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.3.0"
- vector_math:
- dependency: transitive
- description:
- name: vector_math
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.1.0"
-sdks:
- dart: ">=2.12.0-259.9.beta <3.0.0"
- flutter: ">=1.20.0"
diff --git a/example/pubspec.yaml b/example/pubspec.yaml
index 5fae7a7..2e56805 100644
--- a/example/pubspec.yaml
+++ b/example/pubspec.yaml
@@ -1,9 +1,7 @@
name: stringcare_example
description: Demonstrates how to use the stringcare plugin.
-# The following line prevents the package from being accidentally published to
-# pub.dev using `pub publish`. This is preferred for private packages.
-publish_to: 'none' # Remove this line if you wish to publish to pub.dev
+publish_to: 'none'
environment:
sdk: ">=2.7.0 <3.0.0"
@@ -11,62 +9,21 @@ environment:
dependencies:
flutter:
sdk: flutter
+ flutter_web_plugins:
+ sdk: flutter
stringcare:
- # When depending on this package from a real application you should use:
- # stringcare: ^x.y.z
- # See https://dart.dev/tools/pub/dependencies#version-constraints
- # The example app is bundled with the plugin so we use a path dependency on
- # the parent directory to use the current plugin's version.
path: ../
- # The following adds the Cupertino Icons font to your application.
- # Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.0
dev_dependencies:
flutter_test:
sdk: flutter
-# For information on the generic Dart part of this file, see the
-# following page: https://dart.dev/tools/pub/pubspec
-
-# The following section is specific to Flutter.
flutter:
- # The following line ensures that the Material Icons font is
- # included with your application, so that you can use the icons in
- # the material Icons class.
uses-material-design: true
- # To add assets to your application, add an assets section, like this:
assets:
- assets/voyager.jpeg
- # - images/a_dot_burr.jpeg
- # - images/a_dot_ham.jpeg
-
- # An image asset can refer to one or more resolution-specific "variants", see
- # https://flutter.dev/assets-and-images/#resolution-aware.
-
- # For details regarding adding assets from package dependencies, see
- # https://flutter.dev/assets-and-images/#from-packages
-
- # To add custom fonts to your application, add a fonts section here,
- # in this "flutter" section. Each entry in this list should have a
- # "family" key with the font family name, and a "fonts" key with a
- # list giving the asset and other descriptors for the font. For
- # example:
- # fonts:
- # - family: Schyler
- # fonts:
- # - asset: fonts/Schyler-Regular.ttf
- # - asset: fonts/Schyler-Italic.ttf
- # style: italic
- # - family: Trajan Pro
- # fonts:
- # - asset: fonts/TrajanPro.ttf
- # - asset: fonts/TrajanPro_Bold.ttf
- # weight: 700
- #
- # For details regarding fonts from package dependencies,
- # see https://flutter.dev/custom-fonts/#from-packages
diff --git a/example/web/favicon.png b/example/web/favicon.png
new file mode 100644
index 0000000..8aaa46a
Binary files /dev/null and b/example/web/favicon.png differ
diff --git a/example/web/icons/Icon-192.png b/example/web/icons/Icon-192.png
new file mode 100644
index 0000000..b749bfe
Binary files /dev/null and b/example/web/icons/Icon-192.png differ
diff --git a/example/web/icons/Icon-512.png b/example/web/icons/Icon-512.png
new file mode 100644
index 0000000..88cfd48
Binary files /dev/null and b/example/web/icons/Icon-512.png differ
diff --git a/example/web/index.html b/example/web/index.html
new file mode 100644
index 0000000..053c11c
--- /dev/null
+++ b/example/web/index.html
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ stringcare_example
+
+
+
+
+
+
+
+
diff --git a/example/web/manifest.json b/example/web/manifest.json
new file mode 100644
index 0000000..09cc320
--- /dev/null
+++ b/example/web/manifest.json
@@ -0,0 +1,23 @@
+{
+ "name": "stringcare_example",
+ "short_name": "stringcare_example",
+ "start_url": ".",
+ "display": "standalone",
+ "background_color": "#0175C2",
+ "theme_color": "#0175C2",
+ "description": "Demonstrates how to use the stringcare plugin.",
+ "orientation": "portrait-primary",
+ "prefer_related_applications": false,
+ "icons": [
+ {
+ "src": "icons/Icon-192.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ },
+ {
+ "src": "icons/Icon-512.png",
+ "sizes": "512x512",
+ "type": "image/png"
+ }
+ ]
+}
diff --git a/images/android_sample.png b/images/android_sample.png
new file mode 100644
index 0000000..8d2eb87
Binary files /dev/null and b/images/android_sample.png differ
diff --git a/images/ios_sample.png b/images/ios_sample.png
new file mode 100644
index 0000000..f4d3021
Binary files /dev/null and b/images/ios_sample.png differ
diff --git a/images/macos_sample.png b/images/macos_sample.png
new file mode 100644
index 0000000..dba1fc6
Binary files /dev/null and b/images/macos_sample.png differ
diff --git a/images/web_sample.png b/images/web_sample.png
new file mode 100644
index 0000000..61d1943
Binary files /dev/null and b/images/web_sample.png differ
diff --git a/images/windows_sample.png b/images/windows_sample.png
new file mode 100644
index 0000000..b832e15
Binary files /dev/null and b/images/windows_sample.png differ
diff --git a/ios/Classes/stringcare.cpp b/ios/Classes/stringcare.cpp
index 4ae4dfa..c1af676 100644
--- a/ios/Classes/stringcare.cpp
+++ b/ios/Classes/stringcare.cpp
@@ -63,11 +63,11 @@ std::string sign(std::string key) {
u++;
i++;
if (i % 2 == 0) {
- i = (i + (int) c + (3 * u) + 5 * i / 2) + 4 * u;
+ i = (i + (int) c + (3 * u));
} else if (u % 2 == 0) {
- i = (i * 3 - (int) c + (2 * u) + 3 * i / 4) + 2 * u;
+ i = (i * 3 - (int) c + (2 * u));
} else {
- i = (i / 2 + (int) c + (6 * u) + 2 * i / 3) + 8 * u;
+ i = (i / 2 + (int) c + (6 * u));
}
val += std::to_string(i);
val = reverse(val);
@@ -76,6 +76,29 @@ std::string sign(std::string key) {
return reverse(val);
}
+#if defined _WIN32 || defined __CYGWIN__
+ extern "C" __declspec(dllexport)
+#else
+ extern "C" __attribute__((visibility("default"))) __attribute__((used))
+#endif
+char* hashTest(char const *key) {
+ std::string strKey = char2String(key);
+ std::string hash = join(strKey, pd);
+ return string2Char(hash);
+}
+
+#if defined _WIN32 || defined __CYGWIN__
+ extern "C" __declspec(dllexport)
+#else
+ extern "C" __attribute__((visibility("default"))) __attribute__((used))
+#endif
+char* signTest(char const *key) {
+ std::string strKey = char2String(key);
+ std::string hash = join(strKey, pd);
+ std::string na = sign(hash);
+ return string2Char(na);
+}
+
#if defined _WIN32 || defined __CYGWIN__
extern "C" __declspec(dllexport)
#else
diff --git a/lib/src/commons/stringcare_commons.dart b/lib/src/commons/stringcare_commons.dart
new file mode 100644
index 0000000..01b206b
--- /dev/null
+++ b/lib/src/commons/stringcare_commons.dart
@@ -0,0 +1,87 @@
+import 'dart:convert';
+import 'dart:typed_data';
+import 'package:crypto/crypto.dart';
+import 'package:flutter/services.dart';
+
+import 'stringcare_platform.dart';
+
+abstract class StringcareCommons implements StringcarePlatform {
+ static const MethodChannel _channel = const MethodChannel('stringcare');
+
+ Future get platformVersion async {
+ final String version = await _channel.invokeMethod('getPlatformVersion');
+ return version;
+ }
+
+ String obfuscate(String value) {
+ return obfuscateWith([], value);
+ }
+
+ Uint8List obfuscateData(Uint8List value) {
+ return obfuscateDataWith([], value);
+ }
+
+ String reveal(String value) {
+ return revealWith([], value);
+ }
+
+ Uint8List revealData(Uint8List value) {
+ return revealDataWith([], value);
+ }
+
+ int originalStringInt32Size(String string) {
+ final units = utf8.encode(string);
+ return units.length;
+ }
+
+ int obfuscatedInt32Lent(String string) {
+ return string.split(",").length;
+ }
+
+ String prepareKey(List keys) {
+ keys.sort((a, b) => a.compareTo(b));
+ int max = 0;
+
+ keys.forEach((key) {
+ if (max < key.length) {
+ max = key.length;
+ }
+ });
+
+ String key = "";
+ for (int x = 0; x < max; x++) {
+ for (int y = 0; y < keys.length; y++) {
+ var list = keys[y];
+ if (x < list.length) {
+ key += list[x];
+ }
+ }
+ }
+
+ return key;
+ }
+
+ String getSignature(List keys) {
+ return sha256.convert(utf8.encode(prepareKey(keys))).toString();
+ }
+
+ String getSignatureOfValue(String value) {
+ return sha256.convert(utf8.encode(value)).toString();
+ }
+
+ String getSignatureOfBytes(List data) {
+ return sha256.convert(data).toString();
+ }
+
+ bool validSignature(String signature, List keys) {
+ if (keys != null && keys.isNotEmpty && keys.join("").isNotEmpty) {
+ return signature == getSignature(keys);
+ }
+ return false;
+ }
+
+ String readableObfuscate(String value) {
+ return utf8.decode(value.split(",").map((e) => int.parse(e)).toList(),
+ allowMalformed: true);
+ }
+}
diff --git a/lib/src/commons/stringcare_platform.dart b/lib/src/commons/stringcare_platform.dart
new file mode 100644
index 0000000..865ce98
--- /dev/null
+++ b/lib/src/commons/stringcare_platform.dart
@@ -0,0 +1,68 @@
+import 'dart:typed_data';
+
+/// The interface that implementations of stringcare must implement.
+///
+/// Platform implementations should extend this class rather than implement it as `stringcare`
+/// does not consider newly added methods to be breaking changes. Extending this class
+/// (using `extends`) ensures that the subclass will get the default implementation, while
+/// platform implementations that `implements` this interface will be broken by newly added
+/// [StringcarePlatform] methods.
+abstract class StringcarePlatform {
+ /// Constructs a StringcarePlatform.
+ StringcarePlatform();
+
+ Future get platformVersion async {
+ throw UnimplementedError(
+ 'Future get platformVersion has not been implemented.');
+ }
+
+ String testHash(List keys) {
+ throw UnimplementedError(
+ 'String obfuscate(String value) has not been implemented.');
+ }
+
+ String testSign(List keys) {
+ throw UnimplementedError(
+ 'String obfuscate(String value) has not been implemented.');
+ }
+
+ String obfuscate(String value) {
+ throw UnimplementedError(
+ 'String obfuscate(String value) has not been implemented.');
+ }
+
+ String obfuscateWith(List keys, String value) {
+ throw UnimplementedError(
+ 'String obfuscateWith(List keys, String value) has not been implemented.');
+ }
+
+ Uint8List obfuscateData(Uint8List value) {
+ throw UnimplementedError(
+ 'Uint8List obfuscateData(Uint8List value) has not been implemented.');
+ }
+
+ Uint8List obfuscateDataWith(List keys, Uint8List value) {
+ throw UnimplementedError(
+ 'Uint8List obfuscateDataWith(List keys, Uint8List value) has not been implemented.');
+ }
+
+ String reveal(String value) {
+ throw UnimplementedError(
+ 'String reveal(String value) has not been implemented.');
+ }
+
+ String revealWith(List keys, String value) {
+ throw UnimplementedError(
+ 'String revealWith(List keys, String value) has not been implemented.');
+ }
+
+ Uint8List revealData(Uint8List value) {
+ throw UnimplementedError(
+ 'Uint8List revealData(Uint8List value) has not been implemented.');
+ }
+
+ Uint8List revealDataWith(List keys, Uint8List value) {
+ throw UnimplementedError(
+ 'Uint8List revealDataWith(List keys, Uint8List value) has not been implemented.');
+ }
+}
diff --git a/lib/src/native/c_helper.dart b/lib/src/native/c_helper.dart
new file mode 100644
index 0000000..fae048f
--- /dev/null
+++ b/lib/src/native/c_helper.dart
@@ -0,0 +1,59 @@
+import 'dart:convert';
+import 'dart:ffi';
+import 'dart:typed_data';
+
+import 'package:ffi/ffi.dart';
+
+Pointer dataToInt32(
+ Uint8List value,
+) {
+ var list = value.toList();
+ final Pointer result = malloc(list.length);
+ final Int32List nativeArray = result.asTypedList(list.length);
+ nativeArray.setAll(0, list);
+ return result;
+}
+
+Pointer stringToInt32(
+ String string,
+) {
+ final units = utf8.encode(string);
+ final Pointer result = malloc(units.length);
+ final Int32List nativeArray = result.asTypedList(units.length);
+ nativeArray.setAll(0, units);
+ return result;
+}
+
+Pointer stringByteToInt32(
+ String string,
+) {
+ final array = string.split(",").map((e) => int.parse(e));
+ final Pointer result = malloc(array.length);
+ final Int32List nativeArray = result.asTypedList(array.length);
+ nativeArray.setAll(0, array);
+ return result;
+}
+
+Uint8List getBytesFromIntList(Pointer listOfBytes, int size) {
+ return Uint8List.fromList(listOfBytes.asTypedList(size).toList());
+}
+
+String getStringFromUtf8List(Pointer listOfBytes) {
+ return listOfBytes.toDartString();
+}
+
+String getStringFromRevealed(Pointer listOfBytes, int size) {
+ var list = listOfBytes.asTypedList(size).toList();
+ return utf8.decode(list.sublist(0, size), allowMalformed: true);
+}
+
+String getStringBytesFromIntList(Pointer listOfBytes, int size) {
+ return listOfBytes
+ .asTypedList(size)
+ .toList()
+ .map((e) {
+ return e.toString();
+ })
+ .toList()
+ .join(",");
+}
diff --git a/lib/src/native/stringcare_impl.dart b/lib/src/native/stringcare_impl.dart
new file mode 100644
index 0000000..324a100
--- /dev/null
+++ b/lib/src/native/stringcare_impl.dart
@@ -0,0 +1,216 @@
+import 'dart:typed_data';
+import 'dart:io';
+
+import 'dart:ffi';
+import 'package:ffi/ffi.dart';
+import 'package:stringcare/src/commons/stringcare_commons.dart';
+
+import 'c_helper.dart';
+
+class StringcareImpl extends StringcareCommons {
+ DynamicLibrary stringcareLib;
+
+ StringcareImpl() {
+ if (Platform.isAndroid) {
+ stringcareLib = DynamicLibrary.open("libstringcare.so");
+ } else if (Platform.isIOS) {
+ stringcareLib = DynamicLibrary.process();
+ } else if (Platform.isMacOS) {
+ stringcareLib = DynamicLibrary.process();
+ } else if (Platform.isWindows) {
+ stringcareLib = DynamicLibrary.open('stringcare.dll');
+ }
+ }
+
+ @override
+ String obfuscateWith(List keys, String value) {
+ try {
+ var key = "";
+ if (value == null || value.isEmpty) {
+ return "";
+ }
+
+ if (keys != null && keys.isNotEmpty && keys.join("").isNotEmpty) {
+ key = prepareKey(keys);
+ }
+
+ final Pointer Function(
+ Pointer key, Pointer val, int keySize, int valueSize)
+ obfuscate = stringcareLib
+ .lookup<
+ NativeFunction<
+ Pointer Function(Pointer, Pointer,
+ Int32, Int32)>>("obfuscate")
+ .asFunction();
+
+ var intSize = originalStringInt32Size(value);
+
+ var data = stringToInt32(value);
+
+ var res = getStringBytesFromIntList(
+ obfuscate(key.toNativeUtf8(), data, key.length, intSize), intSize);
+
+ malloc.free(data);
+
+ return res;
+ } catch (e) {
+ print(e);
+ return "";
+ }
+ }
+
+ @override
+ Uint8List obfuscateDataWith(List keys, Uint8List value) {
+ try {
+ var key = "";
+ if (value == null || value.isEmpty) {
+ return null;
+ }
+
+ if (keys != null && keys.isNotEmpty && keys.join("").isNotEmpty) {
+ key = prepareKey(keys);
+ }
+
+ final Pointer Function(
+ Pointer key, Pointer val, int keySize, int valueSize)
+ obfuscate = stringcareLib
+ .lookup<
+ NativeFunction<
+ Pointer Function(Pointer, Pointer,
+ Int32, Int32)>>("obfuscate")
+ .asFunction();
+
+ var data = dataToInt32(value);
+
+ var res = getBytesFromIntList(
+ obfuscate(key.toNativeUtf8(), data, key.length, value.length),
+ value.length);
+
+ malloc.free(data);
+
+ return res;
+ } catch (e) {
+ print(e);
+ return null;
+ }
+ }
+
+ @override
+ String revealWith(List keys, String value) {
+ try {
+ var key = "";
+ if (value == null || value.isEmpty) {
+ return "";
+ }
+
+ if (keys != null && keys.isNotEmpty && keys.join("").isNotEmpty) {
+ key = prepareKey(keys);
+ }
+
+ final Pointer Function(
+ Pointer key, Pointer val, int keySize, int valueSize)
+ reveal = stringcareLib
+ .lookup<
+ NativeFunction<
+ Pointer Function(Pointer, Pointer,
+ Int32, Int32)>>("reveal")
+ .asFunction();
+
+ var intSize = obfuscatedInt32Lent(value);
+
+ var data = stringByteToInt32(value);
+
+ var res = getStringFromRevealed(
+ reveal(key.toNativeUtf8(), data, key.length, intSize), intSize);
+
+ malloc.free(data);
+
+ return res;
+ } catch (e) {
+ print(e);
+ return "";
+ }
+ }
+
+ @override
+ Uint8List revealDataWith(List keys, Uint8List value) {
+ try {
+ var key = "";
+ if (value == null || value.isEmpty) {
+ return null;
+ }
+
+ if (keys != null && keys.isNotEmpty && keys.join("").isNotEmpty) {
+ key = prepareKey(keys);
+ }
+
+ final Pointer Function(
+ Pointer key, Pointer val, int keySize, int valueSize)
+ reveal = stringcareLib
+ .lookup<
+ NativeFunction<
+ Pointer Function(Pointer, Pointer,
+ Int32, Int32)>>("reveal")
+ .asFunction();
+
+ var data = dataToInt32(value);
+
+ var res = getBytesFromIntList(
+ reveal(key.toNativeUtf8(), data, key.length, value.length),
+ value.length);
+
+ malloc.free(data);
+
+ return res;
+ } catch (e) {
+ print(e);
+ return null;
+ }
+ }
+
+ @override
+ String testSign(List keys) {
+ try {
+ var key = "";
+ if (keys != null && keys.isNotEmpty && keys.join("").isNotEmpty) {
+ key = prepareKey(keys);
+ }
+
+ final Pointer Function(Pointer key) signTest = stringcareLib
+ .lookup Function(Pointer)>>(
+ "signTest")
+ .asFunction();
+
+ var res = getStringFromUtf8List(signTest(key.toNativeUtf8()));
+
+ return res;
+ } catch (e) {
+ print(e);
+ return "";
+ }
+ }
+
+ @override
+ String testHash(List keys) {
+ try {
+ var key = "";
+ if (keys != null && keys.isNotEmpty && keys.join("").isNotEmpty) {
+ key = prepareKey(keys);
+ }
+
+ final Pointer Function(Pointer key) hashTest = stringcareLib
+ .lookup Function(Pointer)>>(
+ "hashTest")
+ .asFunction();
+
+ print("keys: $key");
+
+ var res = getStringFromUtf8List(hashTest(key.toNativeUtf8()));
+
+ return res;
+ } catch (e) {
+ print(e);
+ return "";
+ }
+ }
+}
diff --git a/lib/src/web/c_aproximation.dart b/lib/src/web/c_aproximation.dart
new file mode 100644
index 0000000..05899a1
--- /dev/null
+++ b/lib/src/web/c_aproximation.dart
@@ -0,0 +1,486 @@
+import 'dart:typed_data';
+import 'dart:convert';
+import 'package:characters/characters.dart';
+
+String pd = "a6ExQWqgF67n4OTMWgztgPExNjsGx2bsfmvjjtbJOoMiQlkWfwYNLfyPq88GowmvzJ1kdiPGbB5QC1wNc6lPSP0RQxAItqVIRzJTeaPsrCaXByvUesQK1hh5JXjNZraWcW4s4TR5TTOhEJ9UsCJqa3J9erM1s5JjjJMur88ksRJFHaUHUWq0kG76UHwJkMNu6FFrEGJ63kdBeh1qzywvXbIfNYZKDKUIRs1VfCxSMzwszgH2JPMZfrCLDlrZTMCIo0QUWwlnyLAW9ty1OT5jZkcPYoJJ7nFgGJh1OAG7q0CRxTBehOQ6sSBsF2m0rlzoW4d0BskTs2JH6mtldJiI";
+
+String ba2String(Uint8List data) {
+ return utf8.decode(data);
+}
+
+String reverse(String str) {
+ String r = "";
+ for (int i = str.length - 1; i >= 0; i--) r += str[i];
+ return r;
+}
+
+// Joins the key with the auxiliar
+String join(String aux, String key) {
+ if (aux.length == 0) {
+ return key;
+ } else {
+ int size = aux.length + key.length;
+ String val = "";
+
+ int a = 0;
+ int b = 0;
+ for (int i = 0; i < size; i++) {
+ if (a == b && a < aux.length) {
+ val += aux[a];
+ a++;
+ } else if (a > b && b < key.length) {
+ val += key[b];
+ b++;
+ } else if (a < aux.length) {
+ val += aux[a];
+ a++;
+ } else if (b < key.length) {
+ val += key[b];
+ b++;
+ }
+ }
+ return val;
+ }
+}
+
+String replaceCharAt(String oldString, int index, String newChar) {
+ try {
+ if (oldString.length <= index) {
+ int diff = index - oldString.length;
+ for (int c = 0; c < diff + 1; c++) {
+ oldString += " ";
+ }
+ }
+
+ var value = "";
+
+ if (index == 0) {
+ if (oldString.length <= 1) {
+ value = newChar;
+ } else {
+ value = newChar + oldString.substring(1);
+ }
+ }
+
+ if (index == oldString.length - 1) {
+ value = oldString.substring(0, index) + newChar;
+ }
+ value = oldString.substring(0, index) +
+ newChar +
+ oldString.substring(index + 1);
+ return value;
+ } catch (e) {
+ print("replace error: $e");
+ return "";
+ }
+}
+
+String toExact(double value) {
+ var sign = "";
+ if (value < 0) {
+ value = -value;
+ sign = "-";
+ }
+ var string = value.toString();
+ var e = string.lastIndexOf('e');
+ if (e < 0) return "$sign$string";
+ assert(string.indexOf('.') == 1);
+ var offset =
+ int.parse(string.substring(e + (string.startsWith('-', e + 1) ? 1 : 2)));
+ var digits = string.substring(0, 1) + string.substring(2, e);
+ if (offset < 0) {
+ return "${sign}0.${"0" * ~offset}$digits";
+ }
+ if (offset > 0) {
+ if (offset >= digits.length) return sign + digits.padRight(offset + 1, "0");
+ return "$sign${digits.substring(0, offset + 1)}"
+ ".${digits.substring(offset + 1)}";
+ }
+ return digits;
+}
+
+String sign(String key) {
+ try {
+ String val = "";
+
+ int i = 0;
+ int u = 0;
+ for (String c in key.characters) {
+ val = replaceCharAt(val, u, c);
+ u++;
+ i++;
+ if (i % 2 == 0) {
+ i = (i + c.codeUnits.first + (3 * u));
+ } else if (u % 2 == 0) {
+ i = (i * 3 - c.codeUnits.first + (2 * u));
+ } else {
+ i = (i ~/ 2 + c.codeUnits.first + (6 * u));
+ }
+ val += toExact(i.toDouble());
+ val = reverse(val);
+ u = u + (toExact(i.toDouble()).length - 1);
+ }
+ return reverse(val);
+ } catch (e) {
+ print("sign error: $e");
+ return "";
+ }
+}
+
+String testHash(String key) {
+ String hash = join(key, pd);
+ return hash;
+}
+
+String testSign(String key) {
+ String hash = join(key, pd);
+ return sign(hash);
+}
+
+Uint8List obfuscate(String key, Uint8List value, int keySize, int valueSize) {
+ String hash = join(key, pd);
+ String na = sign(hash);
+ int keyS = keySize + pd.length;
+
+ for (int a = 19; a < valueSize + 20; a = a + 20) {
+ if (a >= keyS) {
+ if (a - 19 < valueSize) {
+ int reminder = (a - 19) % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a - 19] = value[a - 19] + mark;
+ }
+ if (a - 18 < valueSize) {
+ int reminder = (a - 18) % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a - 18] = value[a - 18] + mark;
+ }
+ if (a - 17 < valueSize) {
+ int reminder = (a - 17) % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a - 17] = value[a - 17] + mark;
+ }
+ if (a - 16 < valueSize) {
+ int reminder = (a - 16) % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a - 16] = value[a - 16] + mark;
+ }
+ if (a - 15 < valueSize) {
+ int reminder = (a - 15) % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a - 15] = value[a - 15] + mark;
+ }
+ if (a - 14 < valueSize) {
+ int reminder = (a - 14) % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a - 14] = value[a - 14] + mark;
+ }
+ if (a - 13 < valueSize) {
+ int reminder = (a - 13) % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a - 13] = value[a - 13] + mark;
+ }
+ if (a - 12 < valueSize) {
+ int reminder = (a - 12) % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a - 12] = value[a - 12] + mark;
+ }
+ if (a - 11 < valueSize) {
+ int reminder = (a - 11) % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a - 11] = value[a - 11] + mark;
+ }
+ if (a - 10 < valueSize) {
+ int reminder = (a - 10) % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a - 10] = value[a - 10] + mark;
+ }
+ if (a - 9 < valueSize) {
+ int reminder = (a - 9) % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a - 9] = value[a - 9] + mark;
+ }
+ if (a - 8 < valueSize) {
+ int reminder = (a - 8) % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a - 8] = value[a - 8] + mark;
+ }
+ if (a - 7 < valueSize) {
+ int reminder = (a - 7) % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a - 7] = value[a - 7] + mark;
+ }
+ if (a - 6 < valueSize) {
+ int reminder = (a - 6) % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a - 6] = value[a - 6] + mark;
+ }
+ if (a - 5 < valueSize) {
+ int reminder = (a - 5) % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a - 5] = value[a - 5] + mark;
+ }
+ if (a - 4 < valueSize) {
+ int reminder = (a - 4) % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a - 4] = value[a - 4] + mark;
+ }
+ if (a - 3 < valueSize) {
+ int reminder = (a - 3) % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a - 3] = value[a - 3] + mark;
+ }
+ if (a - 2 < valueSize) {
+ int reminder = (a - 2) % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a - 2] = value[a - 2] + mark;
+ }
+ if (a - 1 < valueSize) {
+ int reminder = (a - 1) % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a - 1] = value[a - 1] + mark;
+ }
+ if (a < valueSize) {
+ int reminder = a % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a] = value[a] + mark;
+ }
+ } else {
+ if (a - 19 < valueSize) {
+ value[a - 19] = value[a - 19] + na[a - 19].codeUnits.first;
+ }
+ if (a - 18 < valueSize) {
+ value[a - 18] = value[a - 18] + na[a - 18].codeUnits.first;
+ }
+ if (a - 17 < valueSize) {
+ value[a - 17] = value[a - 17] + na[a - 17].codeUnits.first;
+ }
+ if (a - 16 < valueSize) {
+ value[a - 16] = value[a - 16] + na[a - 16].codeUnits.first;
+ }
+ if (a - 15 < valueSize) {
+ value[a - 15] = value[a - 15] + na[a - 15].codeUnits.first;
+ }
+ if (a - 14 < valueSize) {
+ value[a - 14] = value[a - 14] + na[a - 14].codeUnits.first;
+ }
+ if (a - 13 < valueSize) {
+ value[a - 13] = value[a - 13] + na[a - 13].codeUnits.first;
+ }
+ if (a - 12 < valueSize) {
+ value[a - 12] = value[a - 12] + na[a - 12].codeUnits.first;
+ }
+ if (a - 11 < valueSize) {
+ value[a - 11] = value[a - 11] + na[a - 11].codeUnits.first;
+ }
+ if (a - 10 < valueSize) {
+ value[a - 10] = value[a - 10] + na[a - 10].codeUnits.first;
+ }
+ if (a - 9 < valueSize) {
+ value[a - 9] = value[a - 9] + na[a - 9].codeUnits.first;
+ }
+ if (a - 8 < valueSize) {
+ value[a - 8] = value[a - 8] + na[a - 8].codeUnits.first;
+ }
+ if (a - 7 < valueSize) {
+ value[a - 7] = value[a - 7] + na[a - 7].codeUnits.first;
+ }
+ if (a - 6 < valueSize) {
+ value[a - 6] = value[a - 6] + na[a - 6].codeUnits.first;
+ }
+ if (a - 5 < valueSize) {
+ value[a - 5] = value[a - 5] + na[a - 5].codeUnits.first;
+ }
+ if (a - 4 < valueSize) {
+ value[a - 4] = value[a - 4] + na[a - 4].codeUnits.first;
+ }
+ if (a - 3 < valueSize) {
+ value[a - 3] = value[a - 3] + na[a - 3].codeUnits.first;
+ }
+ if (a - 2 < valueSize) {
+ value[a - 2] = value[a - 2] + na[a - 2].codeUnits.first;
+ }
+ if (a - 1 < valueSize) {
+ value[a - 1] = value[a - 1] + na[a - 1].codeUnits.first;
+ }
+ if (a < valueSize) {
+ value[a] = value[a] + na[a].codeUnits.first;
+ }
+ }
+ }
+
+ return value;
+}
+
+Uint8List reveal(String key, Uint8List value, int keySize, int valueSize) {
+ String hash = join(key, pd);
+ String na = sign(hash);
+ int keyS = keySize + pd.length;
+
+ for (int a = 19; a < valueSize + 20; a = a + 20) {
+ if (a >= keyS) {
+ if (a - 19 < valueSize) {
+ int reminder = (a - 19) % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a - 19] = value[a - 19] - mark;
+ }
+ if (a - 18 < valueSize) {
+ int reminder = (a - 18) % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a - 18] = value[a - 18] - mark;
+ }
+ if (a - 17 < valueSize) {
+ int reminder = (a - 17) % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a - 17] = value[a - 17] - mark;
+ }
+ if (a - 16 < valueSize) {
+ int reminder = (a - 16) % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a - 16] = value[a - 16] - mark;
+ }
+ if (a - 15 < valueSize) {
+ int reminder = (a - 15) % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a - 15] = value[a - 15] - mark;
+ }
+ if (a - 14 < valueSize) {
+ int reminder = (a - 14) % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a - 14] = value[a - 14] - mark;
+ }
+ if (a - 13 < valueSize) {
+ int reminder = (a - 13) % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a - 13] = value[a - 13] - mark;
+ }
+ if (a - 12 < valueSize) {
+ int reminder = (a - 12) % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a - 12] = value[a - 12] - mark;
+ }
+ if (a - 11 < valueSize) {
+ int reminder = (a - 11) % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a - 11] = value[a - 11] - mark;
+ }
+ if (a - 10 < valueSize) {
+ int reminder = (a - 10) % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a - 10] = value[a - 10] - mark;
+ }
+ if (a - 9 < valueSize) {
+ int reminder = (a - 9) % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a - 9] = value[a - 9] - mark;
+ }
+ if (a - 8 < valueSize) {
+ int reminder = (a - 8) % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a - 8] = value[a - 8] - mark;
+ }
+ if (a - 7 < valueSize) {
+ int reminder = (a - 7) % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a - 7] = value[a - 7] - mark;
+ }
+ if (a - 6 < valueSize) {
+ int reminder = (a - 6) % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a - 6] = value[a - 6] - mark;
+ }
+ if (a - 5 < valueSize) {
+ int reminder = (a - 5) % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a - 5] = value[a - 5] - mark;
+ }
+ if (a - 4 < valueSize) {
+ int reminder = (a - 4) % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a - 4] = value[a - 4] - mark;
+ }
+ if (a - 3 < valueSize) {
+ int reminder = (a - 3) % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a - 3] = value[a - 3] - mark;
+ }
+ if (a - 2 < valueSize) {
+ int reminder = (a - 2) % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a - 2] = value[a - 2] - mark;
+ }
+ if (a - 1 < valueSize) {
+ int reminder = (a - 1) % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a - 1] = value[a - 1] - mark;
+ }
+ if (a < valueSize) {
+ int reminder = a % keyS;
+ int mark = na[reminder].codeUnits.first;
+ value[a] = value[a] - mark;
+ }
+ } else {
+ if (a - 19 < valueSize) {
+ value[a - 19] = value[a - 19] - na[a - 19].codeUnits.first;
+ }
+ if (a - 18 < valueSize) {
+ value[a - 18] = value[a - 18] - na[a - 18].codeUnits.first;
+ }
+ if (a - 17 < valueSize) {
+ value[a - 17] = value[a - 17] - na[a - 17].codeUnits.first;
+ }
+ if (a - 16 < valueSize) {
+ value[a - 16] = value[a - 16] - na[a - 16].codeUnits.first;
+ }
+ if (a - 15 < valueSize) {
+ value[a - 15] = value[a - 15] - na[a - 15].codeUnits.first;
+ }
+ if (a - 14 < valueSize) {
+ value[a - 14] = value[a - 14] - na[a - 14].codeUnits.first;
+ }
+ if (a - 13 < valueSize) {
+ value[a - 13] = value[a - 13] - na[a - 13].codeUnits.first;
+ }
+ if (a - 12 < valueSize) {
+ value[a - 12] = value[a - 12] - na[a - 12].codeUnits.first;
+ }
+ if (a - 11 < valueSize) {
+ value[a - 11] = value[a - 11] - na[a - 11].codeUnits.first;
+ }
+ if (a - 10 < valueSize) {
+ value[a - 10] = value[a - 10] - na[a - 10].codeUnits.first;
+ }
+ if (a - 9 < valueSize) {
+ value[a - 9] = value[a - 9] - na[a - 9].codeUnits.first;
+ }
+ if (a - 8 < valueSize) {
+ value[a - 8] = value[a - 8] - na[a - 8].codeUnits.first;
+ }
+ if (a - 7 < valueSize) {
+ value[a - 7] = value[a - 7] - na[a - 7].codeUnits.first;
+ }
+ if (a - 6 < valueSize) {
+ value[a - 6] = value[a - 6] - na[a - 6].codeUnits.first;
+ }
+ if (a - 5 < valueSize) {
+ value[a - 5] = value[a - 5] - na[a - 5].codeUnits.first;
+ }
+ if (a - 4 < valueSize) {
+ value[a - 4] = value[a - 4] - na[a - 4].codeUnits.first;
+ }
+ if (a - 3 < valueSize) {
+ value[a - 3] = value[a - 3] - na[a - 3].codeUnits.first;
+ }
+ if (a - 2 < valueSize) {
+ value[a - 2] = value[a - 2] - na[a - 2].codeUnits.first;
+ }
+ if (a - 1 < valueSize) {
+ value[a - 1] = value[a - 1] - na[a - 1].codeUnits.first;
+ }
+ if (a < valueSize) {
+ value[a] = value[a] - na[a].codeUnits.first;
+ }
+ }
+ }
+
+ return value;
+}
diff --git a/lib/src/web/c_helper.dart b/lib/src/web/c_helper.dart
new file mode 100644
index 0000000..54fdaba
--- /dev/null
+++ b/lib/src/web/c_helper.dart
@@ -0,0 +1,29 @@
+import 'dart:typed_data';
+import 'dart:convert';
+
+String getStringFromRevealed(Uint8List listOfBytes) {
+ return utf8.decode(listOfBytes, allowMalformed: true);
+}
+
+Uint8List stringToUint8List(
+ String string,
+) {
+ return utf8.encode(string);
+}
+
+Uint8List stringByteToInt32(
+ String string,
+) {
+ final array = string.split(",").map((e) => int.parse(e));
+ return Uint8List.fromList(array.toList());
+}
+
+String getStringBytesFromIntList(Uint8List listOfBytes) {
+ return listOfBytes
+ .toList()
+ .map((e) {
+ return e.toString();
+ })
+ .toList()
+ .join(",");
+}
diff --git a/lib/src/web/stringcare_impl.dart b/lib/src/web/stringcare_impl.dart
new file mode 100644
index 0000000..e4c1c97
--- /dev/null
+++ b/lib/src/web/stringcare_impl.dart
@@ -0,0 +1,114 @@
+import 'dart:typed_data';
+
+import 'package:stringcare/src/commons/stringcare_commons.dart';
+import 'package:stringcare/src/web/c_helper.dart';
+
+import 'c_aproximation.dart' as c;
+
+class StringcareImpl extends StringcareCommons {
+ StringcareImpl();
+
+ String obfuscateWith(List keys, String value) {
+ try {
+ var key = "";
+ if (value == null || value.isEmpty) {
+ return "";
+ }
+
+ if (keys != null && keys.isNotEmpty && keys.join("").isNotEmpty) {
+ key = prepareKey(keys);
+ }
+
+ var data = stringToUint8List(value);
+
+ var res = getStringBytesFromIntList(
+ c.obfuscate(key, data, key.length, data.length));
+
+ return res;
+ } catch (e) {
+ print(e);
+ return "";
+ }
+ }
+
+ Uint8List obfuscateDataWith(List keys, Uint8List value) {
+ try {
+ var key = "";
+ if (value == null || value.isEmpty) {
+ return null;
+ }
+
+ if (keys != null && keys.isNotEmpty && keys.join("").isNotEmpty) {
+ key = prepareKey(keys);
+ }
+
+ var res = c.obfuscate(key, value, key.length, value.length);
+
+ return res;
+ } catch (e) {
+ print(e);
+ return null;
+ }
+ }
+
+ String revealWith(List keys, String value) {
+ try {
+ var key = "";
+ if (value == null || value.isEmpty) {
+ return "";
+ }
+
+ if (keys != null && keys.isNotEmpty && keys.join("").isNotEmpty) {
+ key = prepareKey(keys);
+ }
+
+ var data = stringByteToInt32(value);
+
+ var res =
+ getStringFromRevealed(c.reveal(key, data, key.length, data.length));
+
+ return res;
+ } catch (e) {
+ print(e);
+ return "";
+ }
+ }
+
+ Uint8List revealDataWith(List keys, Uint8List value) {
+ try {
+ var key = "";
+ if (value == null || value.isEmpty) {
+ return null;
+ }
+
+ if (keys != null && keys.isNotEmpty && keys.join("").isNotEmpty) {
+ key = prepareKey(keys);
+ }
+
+ var res = c.reveal(key, value, key.length, value.length);
+
+ return res;
+ } catch (e) {
+ print(e);
+ return null;
+ }
+ }
+
+ @override
+ String testSign(List keys) {
+ var key = "";
+ if (keys != null && keys.isNotEmpty && keys.join("").isNotEmpty) {
+ key = prepareKey(keys);
+ }
+ return c.testSign(key);
+ }
+
+ @override
+ String testHash(List keys) {
+ var key = "";
+ if (keys != null && keys.isNotEmpty && keys.join("").isNotEmpty) {
+ key = prepareKey(keys);
+ }
+ return c.testHash(key);
+ }
+}
diff --git a/lib/stringcare.dart b/lib/stringcare.dart
index 2299496..0b05414 100644
--- a/lib/stringcare.dart
+++ b/lib/stringcare.dart
@@ -1,299 +1,72 @@
-import 'dart:async';
-import 'dart:convert';
-import 'dart:ffi';
-import 'dart:io';
import 'dart:typed_data';
-
-import 'package:crypto/crypto.dart';
-import 'package:ffi/ffi.dart';
-import 'package:flutter/services.dart';
+import 'package:stringcare/src/web/stringcare_impl.dart'
+ if (dart.library.io) 'package:stringcare/src/native/stringcare_impl.dart';
+import 'src/commons/stringcare_commons.dart';
class Stringcare {
- static const MethodChannel _channel = const MethodChannel('stringcare');
+ static StringcareCommons api = StringcareImpl();
static Future get platformVersion async {
- final String version = await _channel.invokeMethod('getPlatformVersion');
- return version;
- }
-
- static DynamicLibrary getLibrary() {
- DynamicLibrary stringcareLib;
- if (Platform.isAndroid) {
- stringcareLib = DynamicLibrary.open("libstringcare.so");
- } else if (Platform.isIOS) {
- stringcareLib = DynamicLibrary.process();
- } else if (Platform.isMacOS) {
- stringcareLib = DynamicLibrary.process();
- } else if (Platform.isWindows) {
- stringcareLib = DynamicLibrary.open('stringcare.dll');
- }
- return stringcareLib;
- }
-
- static String getSignature(List keys) {
- return sha256.convert(utf8.encode(_prepareKey(keys))).toString();
+ return api.platformVersion;
}
- static String getSignatureOfValue(String value) {
- return sha256.convert(utf8.encode(value)).toString();
+ static String testHash(List keys) {
+ return api.testHash(keys);
}
- static String getSignatureOfBytes(List data) {
- return sha256.convert(data).toString();
- }
-
- static bool validSignature(String signature, List keys) {
- if (keys != null && keys.isNotEmpty && keys.join("").isNotEmpty) {
- return signature == getSignature(keys);
- }
- return false;
- }
-
- static String readableObfuscate(String value) {
- return utf8.decode(value.split(",").map((e) => int.parse(e)).toList(),
- allowMalformed: true);
+ static String testSign(List keys) {
+ return api.testSign(keys);
}
static String obfuscate(String value) {
- return obfuscateWith([], value);
+ return api.obfuscate(value);
}
static String obfuscateWith(List keys, String value) {
- try {
- var key = "";
- if (value == null || value.isEmpty) {
- return "";
- }
-
- if (keys != null && keys.isNotEmpty && keys.join("").isNotEmpty) {
- key = _prepareKey(keys);
- }
-
- final DynamicLibrary stringcareLib = getLibrary();
-
- final Pointer Function(
- Pointer key, Pointer val, int keySize, int valueSize)
- obfuscate = stringcareLib
- .lookup<
- NativeFunction<
- Pointer Function(Pointer, Pointer,
- Int32, Int32)>>("obfuscate")
- .asFunction();
-
- var intSize = _originalStringInt32Size(value);
-
- var data = _stringToInt32(value);
-
- var res = _getStringBytesFromIntList(
- obfuscate(key.toNativeUtf8(), data, key.length, intSize), intSize);
-
- malloc.free(data);
-
- return res;
- } catch (e) {
- print(e);
- return "";
- }
+ return api.obfuscateWith(keys, value);
}
static Uint8List obfuscateData(Uint8List value) {
- return obfuscateDataWith([], value);
+ return api.obfuscateData(value);
}
static Uint8List obfuscateDataWith(List keys, Uint8List value) {
- try {
- var key = "";
- if (value == null || value.isEmpty) {
- return null;
- }
-
- if (keys != null && keys.isNotEmpty && keys.join("").isNotEmpty) {
- key = _prepareKey(keys);
- }
-
- final DynamicLibrary stringcareLib = getLibrary();
-
- final Pointer Function(
- Pointer key, Pointer val, int keySize, int valueSize)
- obfuscate = stringcareLib
- .lookup<
- NativeFunction<
- Pointer Function(Pointer, Pointer,
- Int32, Int32)>>("obfuscate")
- .asFunction();
-
- var data = _dataToInt32(value);
-
- var res = _getBytesFromIntList(
- obfuscate(key.toNativeUtf8(), data, key.length, value.length),
- value.length);
-
- malloc.free(data);
-
- return res;
- } catch (e) {
- print(e);
- return null;
- }
+ return api.obfuscateDataWith(keys, value);
}
static String reveal(String value) {
- return revealWith([], value);
+ return api.reveal(value);
}
static String revealWith(List keys, String value) {
- try {
- var key = "";
- if (value == null || value.isEmpty) {
- return "";
- }
-
- if (keys != null && keys.isNotEmpty && keys.join("").isNotEmpty) {
- key = _prepareKey(keys);
- }
-
- final DynamicLibrary stringcareLib = getLibrary();
-
- final Pointer Function(
- Pointer key, Pointer val, int keySize, int valueSize)
- reveal = stringcareLib
- .lookup<
- NativeFunction<
- Pointer Function(Pointer, Pointer,
- Int32, Int32)>>("reveal")
- .asFunction();
-
- var intSize = _obfuscatedInt32Lent(value);
-
- var data = _stringByteToInt32(value);
-
- var res = _getBytesFromObfuscated(
- reveal(key.toNativeUtf8(), data, key.length, intSize), intSize);
-
- malloc.free(data);
-
- return res;
- } catch (e) {
- print(e);
- return "";
- }
+ return api.revealWith(keys, value);
}
static Uint8List revealData(Uint8List value) {
- return revealDataWith([], value);
+ return api.revealData(value);
}
static Uint8List revealDataWith(List keys, Uint8List value) {
- try {
- var key = "";
- if (value == null || value.isEmpty) {
- return null;
- }
-
- if (keys != null && keys.isNotEmpty && keys.join("").isNotEmpty) {
- key = _prepareKey(keys);
- }
-
- final DynamicLibrary stringcareLib = getLibrary();
-
- final Pointer Function(
- Pointer key, Pointer val, int keySize, int valueSize)
- reveal = stringcareLib
- .lookup<
- NativeFunction<
- Pointer Function(Pointer, Pointer,
- Int32, Int32)>>("reveal")
- .asFunction();
-
- var data = _dataToInt32(value);
-
- var res = _getBytesFromIntList(
- reveal(key.toNativeUtf8(), data, key.length, value.length),
- value.length);
-
- malloc.free(data);
-
- return res;
- } catch (e) {
- print(e);
- return null;
- }
- }
-
- static String _getStringBytesFromIntList(
- Pointer listOfBytes, int size) {
- return listOfBytes
- .asTypedList(size)
- .toList()
- .map((e) {
- return e.toString();
- })
- .toList()
- .join(",");
- }
-
- static Uint8List _getBytesFromIntList(Pointer listOfBytes, int size) {
- return Uint8List.fromList(listOfBytes.asTypedList(size).toList());
- }
-
- static String _getBytesFromObfuscated(Pointer listOfBytes, int size) {
- var list = listOfBytes.asTypedList(size).toList();
- return utf8.decode(list.sublist(0, size), allowMalformed: true);
- }
-
- static int _originalStringInt32Size(String string) {
- final units = utf8.encode(string);
- return units.length;
+ return api.revealDataWith(keys, value);
}
- static int _obfuscatedInt32Lent(String string) {
- return string.split(",").length;
+ static String getSignature(List keys) {
+ return api.getSignature(keys);
}
- static String _prepareKey(List keys) {
- keys.sort((a, b) => a.compareTo(b));
- int max = 0;
-
- keys.forEach((key) {
- if (max < key.length) {
- max = key.length;
- }
- });
-
- String key = "";
- for (int x = 0; x < max; x++) {
- for (int y = 0; y < keys.length; y++) {
- var list = keys[y];
- if (x < list.length) {
- key += list[x];
- }
- }
- }
-
- return key;
+ static String getSignatureOfValue(String value) {
+ return api.getSignatureOfValue(value);
}
- static Pointer _dataToInt32(Uint8List value) {
- var list = value.toList();
- final Pointer result = malloc(list.length);
- final Int32List nativeArray = result.asTypedList(list.length);
- nativeArray.setAll(0, list);
- return result;
+ static String getSignatureOfBytes(List data) {
+ return api.getSignatureOfBytes(data);
}
- static Pointer _stringToInt32(String string) {
- final units = utf8.encode(string);
- final Pointer result = malloc(units.length);
- final Int32List nativeArray = result.asTypedList(units.length);
- nativeArray.setAll(0, units);
- return result;
+ static bool validSignature(String signature, List keys) {
+ return api.validSignature(signature, keys);
}
- static Pointer _stringByteToInt32(String string) {
- final array = string.split(",").map((e) => int.parse(e));
- final Pointer result = malloc(array.length);
- final Int32List nativeArray = result.asTypedList(array.length);
- nativeArray.setAll(0, array);
- return result;
+ static String readableObfuscate(String value) {
+ return api.readableObfuscate(value);
}
}
diff --git a/lib/stringcare_web.dart b/lib/stringcare_web.dart
new file mode 100644
index 0000000..98d40cd
--- /dev/null
+++ b/lib/stringcare_web.dart
@@ -0,0 +1,45 @@
+import 'dart:async';
+// In order to *not* need this ignore, consider extracting the "web" version
+// of your plugin as a separate package, instead of inlining it in the same
+// package as the core of your plugin.
+// ignore: avoid_web_libraries_in_flutter
+import 'dart:html' as html show window;
+
+import 'package:flutter/services.dart';
+import 'package:flutter_web_plugins/flutter_web_plugins.dart';
+
+/// A web implementation of the Stringcare plugin.
+class StringcareWeb {
+ static void registerWith(Registrar registrar) {
+ final MethodChannel channel = MethodChannel(
+ 'stringcare',
+ const StandardMethodCodec(),
+ registrar,
+ );
+
+ final pluginInstance = StringcareWeb();
+ channel.setMethodCallHandler(pluginInstance.handleMethodCall);
+ }
+
+ /// Handles method calls over the MethodChannel of this plugin.
+ /// Note: Check the "federated" architecture for a new way of doing this:
+ /// https://flutter.dev/go/federated-plugins
+ Future handleMethodCall(MethodCall call) async {
+ switch (call.method) {
+ case 'getPlatformVersion':
+ return getPlatformVersion();
+ break;
+ default:
+ throw PlatformException(
+ code: 'Unimplemented',
+ details: 'stringcare for web doesn\'t implement \'${call.method}\'',
+ );
+ }
+ }
+
+ /// Returns a [String] containing the version of the platform.
+ Future getPlatformVersion() {
+ final version = html.window.navigator.userAgent;
+ return Future.value(version);
+ }
+}
diff --git a/pubspec.yaml b/pubspec.yaml
index 7ec9283..dc8bf14 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -3,6 +3,7 @@ description: A new flutter plugin project.
version: 0.0.1
author: EfraΓn Espada Fraile
homepage: https://github.com/StringCare/stringcare
+publish_to: none
environment:
sdk: ">=2.7.0 <3.0.0"
@@ -11,22 +12,21 @@ environment:
dependencies:
flutter:
sdk: flutter
+ flutter_web_plugins:
+ sdk: flutter
ffi: ^1.0.0
- crypto: ^3.0.0
+ crypto: ^3.0.1
+ characters: ^1.1.0
dev_dependencies:
flutter_test:
sdk: flutter
+ # test: ^1.16.7
+ mockito: ^5.0.4
+ plugin_platform_interface: ^2.0.0
+ pedantic: ^1.11.0
-# For information on the generic Dart part of this file, see the
-# following page: https://dart.dev/tools/pub/pubspec
-
-# The following section is specific to Flutter.
flutter:
- # This section identifies this Flutter project as a plugin project.
- # The 'pluginClass' and Android 'package' identifiers should not ordinarily
- # be modified. They are used by the tooling to maintain consistency when
- # adding or updating assets for this project.
plugin:
platforms:
android:
@@ -38,34 +38,6 @@ flutter:
pluginClass: StringcarePlugin
windows:
pluginClass: StringcarePlugin
-
- # To add assets to your plugin package, add an assets section, like this:
- # assets:
- # - images/a_dot_burr.jpeg
- # - images/a_dot_ham.jpeg
- #
- # For details regarding assets in packages, see
- # https://flutter.dev/assets-and-images/#from-packages
- #
- # An image asset can refer to one or more resolution-specific "variants", see
- # https://flutter.dev/assets-and-images/#resolution-aware.
-
- # To add custom fonts to your plugin package, add a fonts section here,
- # in this "flutter" section. Each entry in this list should have a
- # "family" key with the font family name, and a "fonts" key with a
- # list giving the asset and other descriptors for the font. For
- # example:
- # fonts:
- # - family: Schyler
- # fonts:
- # - asset: fonts/Schyler-Regular.ttf
- # - asset: fonts/Schyler-Italic.ttf
- # style: italic
- # - family: Trajan Pro
- # fonts:
- # - asset: fonts/TrajanPro.ttf
- # - asset: fonts/TrajanPro_Bold.ttf
- # weight: 700
- #
- # For details regarding fonts in packages, see
- # https://flutter.dev/custom-fonts/#from-packages
+ web:
+ pluginClass: StringcareWeb
+ fileName: stringcare_web.dart
diff --git a/test/stringcare_test.dart b/test/stringcare_test.dart
index dd08af0..d3a13bc 100644
--- a/test/stringcare_test.dart
+++ b/test/stringcare_test.dart
@@ -1,5 +1,7 @@
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
+import 'package:stringcare/src/native/stringcare_impl.dart' as native;
+import 'package:stringcare/src/web/stringcare_impl.dart' as web;
import 'package:stringcare/stringcare.dart';
void main() {
@@ -18,6 +20,30 @@ void main() {
});
test('getPlatformVersion', () async {
+ var nativeImpl = native.StringcareImpl();
+ var webImpl = web.StringcareImpl();
+ print("nativeImpl sign: " + nativeImpl.testSign([]));
+ print("webImpl sign: " + webImpl.testSign([]));
expect(await Stringcare.platformVersion, '42');
});
+
+ test('init hash match', () async {
+ var nativeImpl = native.StringcareImpl();
+ var webImpl = web.StringcareImpl();
+ var nHash = nativeImpl.testHash([]);
+ var wHash = webImpl.testHash([]);
+ print("native hash: $nHash");
+ print("web hash: $wHash");
+ expect(nHash, wHash);
+ });
+
+ test('sign match', () async {
+ var nativeImpl = native.StringcareImpl();
+ var webImpl = web.StringcareImpl();
+ var nSign = nativeImpl.testSign([]);
+ var wSign = webImpl.testSign([]);
+ print("native sign: $nSign");
+ print("web sign: $wSign");
+ expect(nSign, wSign);
+ });
}