├── .circleci
└── config.yml
├── .eslintrc
├── .gitattributes
├── .gitignore
├── .npmignore
├── .prettierrc
├── .releaserc
├── LICENSE
├── README.md
├── android
├── build.gradle
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── src
│ └── main
│ ├── AndroidManifest.xml
│ └── java
│ └── com
│ └── reactnativecommunity
│ └── cookies
│ ├── CookieManagerModule.java
│ └── CookieManagerPackage.java
├── index.d.ts
├── index.js
├── ios
├── RNCookieManagerIOS.xcodeproj
│ └── project.pbxproj
└── RNCookieManagerIOS
│ ├── RNCookieManagerIOS.h
│ └── RNCookieManagerIOS.m
├── package.json
├── react-native-cookies.podspec
└── yarn.lock
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | version: 2.1
2 | orbs:
3 | rn: react-native-community/react-native@3.0.0
4 |
5 | jobs:
6 | checkout_code:
7 | executor: rn/linux_js
8 | steps:
9 | - checkout
10 | - persist_to_workspace:
11 | root: .
12 | paths: .
13 |
14 | analyse_js:
15 | executor: rn/linux_js
16 | steps:
17 | - attach_workspace:
18 | at: .
19 | - rn/yarn_install
20 | - run:
21 | name: Run ESLint
22 | command: yarn lint
23 |
24 | release:
25 | executor: rn/linux_js
26 | steps:
27 | - attach_workspace:
28 | at: .
29 | - rn/yarn_install
30 | - run:
31 | name: Publish to NPM
32 | command: yarn semantic-release || true
33 |
34 | workflows:
35 | ci:
36 | jobs:
37 | - checkout_code
38 | - analyse_js:
39 | requires:
40 | - checkout_code
41 | - release:
42 | requires:
43 | - analyse_js
44 | filters:
45 | branches:
46 | only: master
47 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@react-native-community"
3 | }
4 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.pbxproj -text
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | #
3 | .DS_Store
4 |
5 | # node.js
6 | #
7 | node_modules/
8 | npm-debug.log
9 | yarn-error.log
10 |
11 | # Xcode
12 | #
13 | build/
14 | *.pbxuser
15 | !default.pbxuser
16 | *.mode1v3
17 | !default.mode1v3
18 | *.mode2v3
19 | !default.mode2v3
20 | *.perspectivev3
21 | !default.perspectivev3
22 | xcuserdata
23 | *.xccheckout
24 | *.moved-aside
25 | DerivedData
26 | *.hmap
27 | *.ipa
28 | *.xcuserstate
29 | project.xcworkspace
30 |
31 | # Android/IntelliJ
32 | #
33 | build/
34 | .idea
35 | .gradle
36 | local.properties
37 | *.iml
38 | .classpath
39 | .project
40 | .settings
41 |
42 | # BUCK
43 | buck-out/
44 | \.buckd/
45 | *.keystore
46 |
47 | # VS Code
48 | .vscode
49 |
50 | # Yarn
51 | .yarnrc
52 | .yarn/
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .eslintrc
2 | .prettierrc
3 | .releaserc
4 | .circleci/*
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "semi": true,
3 | "singleQuote": true,
4 | "trailingComma": "all"
5 | }
6 |
--------------------------------------------------------------------------------
/.releaserc:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": [
3 | "@semantic-release/commit-analyzer",
4 | "@semantic-release/release-notes-generator",
5 | "@semantic-release/npm",
6 | "@semantic-release/github",
7 | [
8 | "@semantic-release/git",
9 | {
10 | "assets": "package.json",
11 | "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
12 | }
13 | ]
14 | ]
15 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 React Native Community
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # React Native Cookies - A Cookie Manager for React Native
2 |
3 | Cookie Manager for React Native
4 |
5 |
6 |
8 |
9 | This module was ported from [joeferraro/react-native-cookies](https://github.com/joeferraro/react-native-cookies). This would not exist without the work of the original author, [Joe Ferraro](https://github.com/joeferraro).
10 |
11 | ## Important notices & Breaking Changes
12 | - **v6.0.0**: Package name updated to `@react-native-cookies/cookies`.
13 | - **v5.0.0**: Peer Dependency of >= React Native 0.60.2
14 | - **v4.0.0**: Android SDK version bumpted to 21
15 | - **v3.0.0**: Remove React Native Core dependencies, CookieManager.set() support for Android
16 | - **v2.0.0**: Package name updated to `@react-native-community/cookies`.
17 |
18 | ## Maintainers
19 |
20 | - [Jason Safaiyeh](https://github.com/safaiyeh) ([Twitter @safaiyeh](https://twitter.com/safaiyeh)) from [🪄 Magic Eden](https://magiceden.io)
21 |
22 | ## Platforms Supported
23 |
24 | - ✅ iOS
25 | - ✅ Android
26 | - ❌ Currently lacking support for Windows, macOS, and web. Support for these platforms will be created when there is a need for them. Starts with a posted issue.
27 |
28 | ## Expo
29 |
30 | - ✅ You can use this library with [Development Builds](https://docs.expo.dev/development/introduction/). No config plugin is required.
31 | - ❌ This library can't be used in the "Expo Go" app because it [requires custom native code](https://docs.expo.dev/workflow/customizing/).
32 |
33 | ## Installation
34 |
35 | ```
36 | yarn add @react-native-cookies/cookies
37 | ```
38 |
39 | Then link the native iOS package
40 |
41 | ```
42 | npx pod-install
43 | ```
44 |
45 | ## Usage
46 |
47 | A cookie object can have one of the following fields:
48 |
49 | ```typescript
50 | export interface Cookie {
51 | name: string;
52 | value: string;
53 | path?: string;
54 | domain?: string;
55 | version?: string;
56 | expires?: string;
57 | secure?: boolean;
58 | httpOnly?: boolean;
59 | }
60 |
61 | export interface Cookies {
62 | [key: string]: Cookie;
63 | }
64 | ```
65 |
66 | ```javascript
67 | import CookieManager from '@react-native-cookies/cookies';
68 |
69 | // set a cookie
70 | CookieManager.set('http://example.com', {
71 | name: 'myCookie',
72 | value: 'myValue',
73 | domain: 'some domain',
74 | path: '/',
75 | version: '1',
76 | expires: '2015-05-30T12:30:00.00-05:00'
77 | }).then((done) => {
78 | console.log('CookieManager.set =>', done);
79 | });
80 |
81 | *NB:* When no `domain` is specified, url host will be used instead.
82 | *NB:* When no `path` is specified, an empty path `/` will be assumed.
83 |
84 | // Set cookies from a response header
85 | // This allows you to put the full string provided by a server's Set-Cookie
86 | // response header directly into the cookie store.
87 | CookieManager.setFromResponse(
88 | 'http://example.com',
89 | 'user_session=abcdefg; path=/; expires=Thu, 1 Jan 2030 00:00:00 -0000; secure; HttpOnly')
90 | .then((success) => {
91 | console.log('CookieManager.setFromResponse =>', success);
92 | });
93 |
94 | // Get cookies for a url
95 | CookieManager.get('http://example.com')
96 | .then((cookies) => {
97 | console.log('CookieManager.get =>', cookies);
98 | });
99 |
100 | // list cookies (IOS ONLY)
101 | CookieManager.getAll()
102 | .then((cookies) => {
103 | console.log('CookieManager.getAll =>', cookies);
104 | });
105 |
106 | // clear cookies
107 | CookieManager.clearAll()
108 | .then((success) => {
109 | console.log('CookieManager.clearAll =>', success);
110 | });
111 |
112 | // clear a specific cookie by its name (IOS ONLY)
113 | CookieManager.clearByName('http://example.com', 'cookie_name')
114 | .then((success) => {
115 | console.log('CookieManager.clearByName =>', success);
116 | });
117 |
118 | // flush cookies (ANDROID ONLY)
119 | CookieManager.flush()
120 | .then((success) => {
121 | console.log('CookieManager.flush =>', success);
122 | });
123 |
124 | // Remove session cookies (ANDROID ONLY)
125 | // Session cookies are cookies with no expires set. Android typically does not
126 | // remove these, it is up to the developer to decide when to remove them.
127 | // The return value is true if any session cookies were removed.
128 | // iOS handles removal of session cookies automatically on app open.
129 | CookieManager.removeSessionCookies()
130 | .then((sessionCookiesRemoved) => {
131 | console.log('CookieManager.removeSessionCookies =>', sessionCookiesRemoved);
132 | });
133 | ```
134 |
135 | ### WebKit-Support (iOS only)
136 |
137 | React Native comes with a WebView component, which uses UIWebView on iOS. Introduced in iOS 8 Apple implemented the WebKit-Support with all the performance boost.
138 |
139 | Prior to WebKit-Support, cookies would have been stored in `NSHTTPCookieStorage` and sharedCookiesEnabled must be set on webviews to ensure access to them.
140 |
141 | With WebKit-Support, cookies are stored in a separate webview store `WKHTTPCookieStore` and not necessarily shared with other http requests. Caveat is that this store is available upon mounting the component but not necessarily prior so any attempts to set a cookie too early may result in a false positive.
142 |
143 | To use WebKit-Support, you should be able to simply make advantage of the react-native-webview as is OR alternatively use the webview component like [react-native-wkwebview](https://github.com/CRAlpha/react-native-wkwebview).
144 |
145 | To use this _CookieManager_ with WebKit-Support we extended the interface with the attribute `useWebKit` (a boolean value, default: `FALSE`) for the following methods:
146 |
147 | | Method | WebKit-Support | Method-Signature |
148 | | ----------- | -------------- | ------------------------------------------------------------------------ |
149 | | getAll | Yes | `CookieManager.getAll(useWebKit:boolean)` |
150 | | clearAll | Yes | `CookieManager.clearAll(useWebKit:boolean)` |
151 | | clearByName | Yes | `CookieManager.clearByName(url:string, name: string, useWebKit:boolean)` |
152 | | get | Yes | `CookieManager.get(url:string, useWebKit:boolean)` |
153 | | set | Yes | `CookieManager.set(url:string, cookie:object, useWebKit:boolean)` |
154 |
155 | ##### Usage
156 |
157 | ```javascript
158 | import CookieManager from '@react-native-cookies/cookies';
159 |
160 | const useWebKit = true;
161 |
162 | // list cookies (IOS ONLY)
163 | CookieManager.getAll(useWebKit)
164 | .then((cookies) => {
165 | console.log('CookieManager.getAll from webkit-view =>', cookies);
166 | });
167 |
168 | // clear cookies
169 | CookieManager.clearAll(useWebKit)
170 | .then((succcess) => {
171 | console.log('CookieManager.clearAll from webkit-view =>', succcess);
172 | });
173 |
174 | // clear cookies with name (IOS ONLY)
175 | CookieManager.clearByName('http://example.com', 'cookie name', useWebKit)
176 | .then((succcess) => {
177 | console.log('CookieManager.clearByName from webkit-view =>', succcess);
178 | });
179 |
180 | // Get cookies as a request header string
181 | CookieManager.get('http://example.com', useWebKit)
182 | .then((cookies) => {
183 | console.log('CookieManager.get from webkit-view =>', cookies);
184 | });
185 |
186 | // set a cookie
187 | const newCookie: = {
188 | name: 'myCookie',
189 | value: 'myValue',
190 | domain: 'some domain',
191 | path: '/',
192 | version: '1',
193 | expires: '2015-05-30T12:30:00.00-05:00'
194 | };
195 |
196 | CookieManager.set('http://example.com', newCookie, useWebKit)
197 | .then((res) => {
198 | console.log('CookieManager.set from webkit-view =>', res);
199 | });
200 | ```
201 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 |
2 |
3 | // android/build.gradle
4 |
5 | // based on:
6 | //
7 | // * https://github.com/facebook/react-native/blob/0.60-stable/template/android/build.gradle
8 | // original location:
9 | // - https://github.com/facebook/react-native/blob/0.58-stable/local-cli/templates/HelloWorld/android/build.gradle
10 | //
11 | // * https://github.com/facebook/react-native/blob/0.60-stable/template/android/app/build.gradle
12 | // original location:
13 | // - https://github.com/facebook/react-native/blob/0.58-stable/local-cli/templates/HelloWorld/android/app/build.gradle
14 |
15 | def DEFAULT_COMPILE_SDK_VERSION = 29
16 | def DEFAULT_BUILD_TOOLS_VERSION = '29.0.3'
17 | def DEFAULT_MIN_SDK_VERSION = 21
18 | def DEFAULT_TARGET_SDK_VERSION = 29
19 |
20 | def safeExtGet(prop, fallback) {
21 | rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
22 | }
23 |
24 | apply plugin: 'com.android.library'
25 |
26 | buildscript {
27 | // The Android Gradle plugin is only required when opening the android folder stand-alone.
28 | // This avoids unnecessary downloads and potential conflicts when the library is included as a
29 | // module dependency in an application project.
30 | // ref: https://docs.gradle.org/current/userguide/tutorial_using_tasks.html#sec:build_script_external_dependencies
31 | if (project == rootProject) {
32 | repositories {
33 | google()
34 | jcenter()
35 | }
36 | dependencies {
37 | classpath 'com.android.tools.build:gradle:3.5.3'
38 | }
39 | }
40 | }
41 |
42 | apply plugin: 'com.android.library'
43 |
44 | android {
45 | compileSdkVersion safeExtGet('compileSdkVersion', DEFAULT_COMPILE_SDK_VERSION)
46 | buildToolsVersion safeExtGet('buildToolsVersion', DEFAULT_BUILD_TOOLS_VERSION)
47 | defaultConfig {
48 | minSdkVersion safeExtGet('minSdkVersion', DEFAULT_MIN_SDK_VERSION)
49 | targetSdkVersion safeExtGet('targetSdkVersion', DEFAULT_TARGET_SDK_VERSION)
50 | versionCode 1
51 | versionName "1.0"
52 | }
53 | lintOptions {
54 | abortOnError false
55 | }
56 | }
57 |
58 | repositories {
59 | // ref: https://www.baeldung.com/maven-local-repository
60 | mavenLocal()
61 | maven {
62 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
63 | url "$rootDir/../node_modules/react-native/android"
64 | }
65 | maven {
66 | // Android JSC is installed from npm
67 | url "$rootDir/../node_modules/jsc-android/dist"
68 | }
69 | google()
70 | jcenter()
71 | }
72 |
73 | dependencies {
74 | //noinspection GradleDynamicVersion
75 | implementation 'com.facebook.react:react-native:+' // From node_modules
76 | }
77 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/react-native-cookies/cookies/69fe6557b0f2c286e6df6fa9100391ad2d163860/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sun Dec 29 13:32:23 PST 2019
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
7 |
--------------------------------------------------------------------------------
/android/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
--------------------------------------------------------------------------------
/android/src/main/java/com/reactnativecommunity/cookies/CookieManagerModule.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Joseph P. Ferraro
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file here: https://github.com/joeferraro/react-native-cookies/blob/master/LICENSE.md.
6 | */
7 |
8 | package com.reactnativecommunity.cookies;
9 |
10 | import android.os.Build;
11 | import android.util.Log;
12 | import android.webkit.CookieManager;
13 | import android.webkit.CookieSyncManager;
14 | import android.webkit.ValueCallback;
15 |
16 | import com.facebook.react.bridge.Arguments;
17 | import com.facebook.react.bridge.Promise;
18 | import com.facebook.react.bridge.ReactApplicationContext;
19 | import com.facebook.react.bridge.ReactContextBaseJavaModule;
20 | import com.facebook.react.bridge.ReactMethod;
21 | import com.facebook.react.bridge.ReadableMap;
22 | import com.facebook.react.bridge.WritableMap;
23 |
24 | import java.io.IOException;
25 | import java.net.HttpCookie;
26 | import java.net.URISyntaxException;
27 | import java.net.URL;
28 | import java.text.DateFormat;
29 | import java.text.SimpleDateFormat;
30 | import java.util.Date;
31 | import java.util.List;
32 | import java.util.Locale;
33 | import java.util.TimeZone;
34 |
35 | public class CookieManagerModule extends ReactContextBaseJavaModule {
36 |
37 | private static final boolean USES_LEGACY_STORE = Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP;
38 | private static final boolean HTTP_ONLY_SUPPORTED = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N;
39 |
40 | private static final String INVALID_URL_MISSING_HTTP = "Invalid URL: It may be missing a protocol (ex. http:// or https://).";
41 | private static final String INVALID_COOKIE_VALUES = "Unable to add cookie - invalid values";
42 | private static final String GET_ALL_NOT_SUPPORTED = "Get all cookies not supported for Android (iOS only)";
43 | private static final String CLEAR_BY_NAME_NOT_SUPPORTED = "Cannot remove a single cookie by name on Android";
44 | private static final String INVALID_DOMAINS = "Cookie URL host %s and domain %s mismatched. The cookie won't set correctly.";
45 |
46 | private CookieSyncManager mCookieSyncManager;
47 |
48 | CookieManagerModule(ReactApplicationContext context) {
49 | super(context);
50 | this.mCookieSyncManager = CookieSyncManager.createInstance(context);
51 | }
52 |
53 | private CookieManager getCookieManager() throws Exception {
54 | try {
55 | CookieManager cookieManager = CookieManager.getInstance();
56 | cookieManager.setAcceptCookie(true);
57 | return cookieManager;
58 | } catch (Exception e) {
59 | throw new Exception(e);
60 | }
61 | }
62 |
63 | public String getName() {
64 | return "RNCookieManagerAndroid";
65 | }
66 |
67 | @ReactMethod
68 | public void set(String url, ReadableMap cookie, Boolean useWebKit, final Promise promise) {
69 | String cookieString = null;
70 | try {
71 | cookieString = toRFC6265string(makeHTTPCookieObject(url, cookie));
72 | } catch (Exception e) {
73 | promise.reject(e);
74 | return;
75 | }
76 |
77 | if (cookieString == null) {
78 | promise.reject(new Exception(INVALID_COOKIE_VALUES));
79 | return;
80 | }
81 |
82 | addCookies(url, cookieString, promise);
83 | }
84 |
85 | @ReactMethod
86 | public void setFromResponse(String url, String cookie, final Promise promise) {
87 | if (cookie == null) {
88 | promise.reject(new Exception(INVALID_COOKIE_VALUES));
89 | return;
90 | }
91 |
92 | addCookies(url, cookie, promise);
93 | }
94 |
95 | @ReactMethod
96 | public void flush(Promise promise) {
97 | try {
98 | getCookieManager().flush();
99 | promise.resolve(true);
100 | } catch (Exception e) {
101 | promise.reject(e);
102 | }
103 | }
104 |
105 | @ReactMethod
106 | public void removeSessionCookies(final Promise promise) {
107 | try {
108 | getCookieManager().removeSessionCookies(new ValueCallback() {
109 | @Override
110 | public void onReceiveValue(Boolean data) {
111 | promise.resolve(data);
112 | }
113 | });
114 | } catch (Exception e) {
115 | promise.reject(e);
116 | }
117 | }
118 |
119 | @ReactMethod
120 | public void getFromResponse(String url, Promise promise) throws URISyntaxException, IOException {
121 | promise.resolve(url);
122 | }
123 |
124 | @ReactMethod
125 | public void getAll(Boolean useWebKit, Promise promise) {
126 | promise.reject(new Exception(GET_ALL_NOT_SUPPORTED));
127 | }
128 |
129 | @ReactMethod
130 | public void get(String url, Boolean useWebKit, Promise promise) {
131 | if (isEmpty(url)) {
132 | promise.reject(new Exception(INVALID_URL_MISSING_HTTP));
133 | return;
134 | }
135 | try {
136 | String cookiesString = getCookieManager().getCookie(url);
137 |
138 | WritableMap cookieMap = createCookieList(cookiesString);
139 | promise.resolve(cookieMap);
140 | } catch (Exception e) {
141 | promise.reject(e);
142 | }
143 | }
144 |
145 | @ReactMethod
146 | public void clearByName(String url, String name, Boolean useWebKit, final Promise promise) {
147 | promise.reject(new Exception(CLEAR_BY_NAME_NOT_SUPPORTED));
148 | }
149 |
150 | @ReactMethod
151 | public void clearAll(Boolean useWebKit, final Promise promise) {
152 | try {
153 | CookieManager cookieManager = getCookieManager();
154 | if (USES_LEGACY_STORE) {
155 | cookieManager.removeAllCookie();
156 | cookieManager.removeSessionCookie();
157 | mCookieSyncManager.sync();
158 | promise.resolve(true);
159 | } else {
160 | cookieManager.removeAllCookies(new ValueCallback() {
161 | @Override
162 | public void onReceiveValue(Boolean value) {
163 | promise.resolve(value);
164 | }
165 | });
166 | cookieManager.flush();
167 | }
168 | } catch (Exception e) {
169 | promise.reject(e);
170 | }
171 | }
172 |
173 | private void addCookies(String url, String cookieString, final Promise promise) {
174 | try {
175 | CookieManager cookieManager = getCookieManager();
176 | if (USES_LEGACY_STORE) {
177 | cookieManager.setCookie(url, cookieString);
178 | mCookieSyncManager.sync();
179 | promise.resolve(true);
180 | } else {
181 | cookieManager.setCookie(url, cookieString, new ValueCallback() {
182 | @Override
183 | public void onReceiveValue(Boolean value) {
184 | promise.resolve(value);
185 | }
186 | });
187 | cookieManager.flush();
188 | }
189 | } catch (Exception e) {
190 | promise.reject(e);
191 | }
192 | }
193 |
194 | private WritableMap createCookieList(String allCookies) throws Exception {
195 | WritableMap allCookiesMap = Arguments.createMap();
196 |
197 | if (!isEmpty(allCookies)) {
198 | String[] cookieHeaders = allCookies.split(";");
199 | for (String singleCookie : cookieHeaders) {
200 | List cookies = HttpCookie.parse(singleCookie);
201 | for (HttpCookie cookie : cookies) {
202 | if (cookie != null) {
203 | String name = cookie.getName();
204 | String value = cookie.getValue();
205 | if (!isEmpty(name) && !isEmpty(value)) {
206 | WritableMap cookieMap = createCookieData(cookie);
207 | allCookiesMap.putMap(name, cookieMap);
208 | }
209 | }
210 | }
211 | }
212 | }
213 |
214 | return allCookiesMap;
215 | }
216 |
217 | private HttpCookie makeHTTPCookieObject(String url, ReadableMap cookie) throws Exception {
218 | URL parsedUrl = null;
219 | try {
220 | parsedUrl = new URL(url);
221 | } catch (Exception e) {
222 | throw new Exception(INVALID_URL_MISSING_HTTP);
223 | }
224 |
225 | String topLevelDomain = parsedUrl.getHost();
226 |
227 | if (isEmpty(topLevelDomain)) {
228 | // assume something went terribly wrong here and no cookie can be created
229 | throw new Exception(INVALID_URL_MISSING_HTTP);
230 | }
231 |
232 | HttpCookie cookieBuilder = new HttpCookie(cookie.getString("name"), cookie.getString("value"));
233 |
234 | if (cookie.hasKey("domain") && !isEmpty(cookie.getString("domain"))) {
235 | String domain = cookie.getString("domain");
236 | // strip the leading . as Android doesn't take it
237 | // but will include subdomains by default
238 | if (domain.startsWith(".")) {
239 | domain = domain.substring(1);
240 | }
241 |
242 | if (!topLevelDomain.contains(domain) && !topLevelDomain.equals(domain)) {
243 | throw new Exception(String.format(INVALID_DOMAINS, topLevelDomain, domain));
244 | }
245 |
246 | cookieBuilder.setDomain(domain);
247 | } else {
248 | cookieBuilder.setDomain(topLevelDomain);
249 | }
250 |
251 | // unlike iOS, Android will handle no path gracefully and assume "/""
252 | if (cookie.hasKey("path") && !isEmpty(cookie.getString("path"))) {
253 | cookieBuilder.setPath(cookie.getString("path"));
254 | }
255 |
256 | if (cookie.hasKey("expires") && !isEmpty(cookie.getString("expires"))) {
257 | Date date = parseDate(cookie.getString("expires"));
258 | if (date != null) {
259 | cookieBuilder.setMaxAge(date.getTime());
260 | }
261 | }
262 |
263 | if (cookie.hasKey("secure") && cookie.getBoolean("secure")) {
264 | cookieBuilder.setSecure(true);
265 | }
266 |
267 | if (HTTP_ONLY_SUPPORTED) {
268 | if (cookie.hasKey("httpOnly") && cookie.getBoolean("httpOnly")) {
269 | cookieBuilder.setHttpOnly(true);
270 | }
271 | }
272 |
273 | return cookieBuilder;
274 | }
275 |
276 | private WritableMap createCookieData(HttpCookie cookie) {
277 | WritableMap cookieMap = Arguments.createMap();
278 | cookieMap.putString("name", cookie.getName());
279 | cookieMap.putString("value", cookie.getValue());
280 | cookieMap.putString("domain", cookie.getDomain());
281 | cookieMap.putString("path", cookie.getPath());
282 | cookieMap.putBoolean("secure", cookie.getSecure());
283 | if (HTTP_ONLY_SUPPORTED) {
284 | cookieMap.putBoolean("httpOnly", cookie.isHttpOnly());
285 | }
286 |
287 | // if persistent the max Age will be -1
288 | long expires = cookie.getMaxAge();
289 | if (expires > 0) {
290 | String expiry = formatDate(new Date(expires));
291 | if (!isEmpty(expiry)) {
292 | cookieMap.putString("expires", expiry);
293 | }
294 | }
295 | return cookieMap;
296 | }
297 |
298 | /**
299 | * As HttpCookie is designed specifically for headers, it only gives us 2 formats on toString
300 | * dependent on the cookie version: 0 = Netscape; 1 = RFC 2965/2109, both without leading "Cookie:" token.
301 | * For our purposes RFC 6265 is the right way to go.
302 | * This is a convenience method to give us the right formatting.
303 | */
304 | private String toRFC6265string(HttpCookie cookie) {
305 | StringBuilder builder = new StringBuilder();
306 |
307 | builder.append(cookie.getName())
308 | .append('=')
309 | .append(cookie.getValue());
310 |
311 | if (!cookie.hasExpired()) {
312 | long expiresAt = cookie.getMaxAge();
313 | if (expiresAt > 0) {
314 | String dateString = formatDate(new Date(expiresAt), true);
315 | if (!isEmpty(dateString)) {
316 | builder.append("; expires=").append(dateString);
317 | }
318 | }
319 | }
320 |
321 | if (!isEmpty(cookie.getDomain())) {
322 | builder.append("; domain=")
323 | .append(cookie.getDomain());
324 | }
325 |
326 | if (!isEmpty(cookie.getPath())) {
327 | builder.append("; path=")
328 | .append(cookie.getPath());
329 | }
330 |
331 | if (cookie.getSecure()) {
332 | builder.append("; secure");
333 | }
334 |
335 | if (HTTP_ONLY_SUPPORTED && cookie.isHttpOnly()) {
336 | builder.append("; httponly");
337 | }
338 |
339 | return builder.toString();
340 | }
341 |
342 | private boolean isEmpty(String value) {
343 | return value == null || value.isEmpty();
344 | }
345 |
346 | /**
347 | * Used for pushing cookies expiry time in and out of the library.
348 | *
349 | * @return simple date formatter
350 | */
351 | private DateFormat dateFormatter() {
352 | // suggested formatting -> return DateTimeFormatter.RFC_1123_DATE_TIME;
353 | // matching ios format as yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ
354 | DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ", Locale.US);
355 | df.setTimeZone(TimeZone.getTimeZone("GMT"));
356 | return df;
357 | }
358 |
359 | /**
360 | * Used building the correctly formatted date for a cookie string in RFC_1123_DATE_TIME format
361 | *
362 | * @return simple date formatter
363 | */
364 | private DateFormat RFC1123dateFormatter() {
365 | DateFormat df = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US);
366 | df.setTimeZone(TimeZone.getTimeZone("GMT"));
367 | return df;
368 | }
369 |
370 | private Date parseDate(String dateString) {
371 | return parseDate(dateString, false);
372 | }
373 |
374 | private Date parseDate(String dateString, boolean rfc1123) {
375 | Date date = null;
376 | try {
377 | date = (rfc1123 ? RFC1123dateFormatter() : dateFormatter()).parse(dateString);
378 | } catch (Exception e) {
379 | String message = e.getMessage();
380 | Log.i("Cookies", message != null ? message : "Unable to parse date");
381 | }
382 | return date;
383 | }
384 |
385 | private String formatDate(Date date) {
386 | return formatDate(date, false);
387 | }
388 |
389 | private String formatDate(Date date, boolean rfc1123) {
390 | String dateString = null;
391 | try {
392 | dateString = (rfc1123 ? RFC1123dateFormatter() : dateFormatter()).format(date);
393 | } catch (Exception e) {
394 | String message = e.getMessage();
395 | Log.i("Cookies", message != null ? message : "Unable to format date");
396 | }
397 | return dateString;
398 | }
399 | }
400 |
--------------------------------------------------------------------------------
/android/src/main/java/com/reactnativecommunity/cookies/CookieManagerPackage.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Joseph P. Ferraro
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file here: https://github.com/joeferraro/react-native-cookies/blob/master/LICENSE.md.
6 | */
7 |
8 | package com.reactnativecommunity.cookies;
9 |
10 | import com.facebook.react.ReactPackage;
11 | import com.facebook.react.bridge.NativeModule;
12 | import com.facebook.react.bridge.JavaScriptModule;
13 | import com.facebook.react.bridge.ReactApplicationContext;
14 | import com.facebook.react.uimanager.ViewManager;
15 |
16 | import java.util.ArrayList;
17 | import java.util.Arrays;
18 | import java.util.Collections;
19 | import java.util.List;
20 |
21 | public class CookieManagerPackage implements ReactPackage {
22 |
23 | public CookieManagerPackage() {}
24 |
25 | @Override
26 | public List createNativeModules(
27 | ReactApplicationContext reactContext) {
28 | List modules = new ArrayList<>();
29 |
30 | modules.add(new CookieManagerModule(reactContext));
31 | return modules;
32 | }
33 |
34 | // Deprecated
35 | public List> createJSModules() {
36 | return Collections.emptyList();
37 | }
38 |
39 | @Override
40 | public List createViewManagers(ReactApplicationContext reactContext) {
41 | return Arrays.asList();
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/index.d.ts:
--------------------------------------------------------------------------------
1 | declare module '@react-native-cookies/cookies' {
2 | export interface Cookie {
3 | name: string;
4 | value: string;
5 | path?: string;
6 | domain?: string;
7 | version?: string;
8 | expires?: string;
9 | secure?: boolean;
10 | httpOnly?: boolean;
11 | }
12 |
13 | export interface Cookies {
14 | [key: string]: Cookie;
15 | }
16 |
17 | export interface CookieManagerStatic {
18 | set(url: string, cookie: Cookie, useWebKit?: boolean): Promise;
19 | setFromResponse(url: string, cookie: string): Promise;
20 |
21 | get(url: string, useWebKit?: boolean): Promise;
22 | getFromResponse(url: string): Promise;
23 |
24 | clearAll(useWebKit?: boolean): Promise;
25 |
26 | // Android only
27 | flush(): Promise;
28 | removeSessionCookies(): Promise;
29 |
30 | // iOS only
31 | getAll(useWebKit?: boolean): Promise;
32 | clearByName(
33 | url: string,
34 | name: string,
35 | useWebKit?: boolean,
36 | ): Promise;
37 | }
38 |
39 | const CookieManager: CookieManagerStatic;
40 |
41 | export default CookieManager;
42 | }
43 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Joseph P. Ferraro
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file here: https://github.com/joeferraro/react-native-cookies/blob/master/LICENSE.md.
6 | */
7 |
8 | import { NativeModules, Platform } from 'react-native';
9 | const invariant = require('invariant');
10 | const RNCookieManagerIOS = NativeModules.RNCookieManagerIOS;
11 | const RNCookieManagerAndroid = NativeModules.RNCookieManagerAndroid;
12 |
13 | let CookieManager;
14 |
15 | if (Platform.OS === 'ios') {
16 | invariant(
17 | RNCookieManagerIOS,
18 | '@react-native-community/cookies: Add RNCookieManagerIOS.h and RNCookieManagerIOS.m to your Xcode project',
19 | );
20 | CookieManager = RNCookieManagerIOS;
21 | } else if (Platform.OS === 'android') {
22 | invariant(
23 | RNCookieManagerAndroid,
24 | '@react-native-community/cookies: Import libraries to android "react-native link @react-native-community/cookies"',
25 | );
26 | CookieManager = RNCookieManagerAndroid;
27 | } else {
28 | invariant(
29 | CookieManager,
30 | '@react-native-community/cookies: Invalid platform. This library only supports Android and iOS.',
31 | );
32 | }
33 |
34 | const functions = ['setFromResponse', 'getFromResponse'];
35 |
36 | module.exports = {
37 | getAll: (useWebKit = false) => CookieManager.getAll(useWebKit),
38 | clearAll: (useWebKit = false) => CookieManager.clearAll(useWebKit),
39 | get: (url, useWebKit = false) => CookieManager.get(url, useWebKit),
40 | set: (url, cookie, useWebKit = false) =>
41 | CookieManager.set(url, cookie, useWebKit),
42 | clearByName: (url, name, useWebKit = false) =>
43 | CookieManager.clearByName(url, name, useWebKit),
44 | flush: async () => {
45 | if (Platform.OS === 'android') {
46 | await CookieManager.flush();
47 | }
48 | },
49 | removeSessionCookies: async () => {
50 | if (Platform.OS === 'android') {
51 | return await CookieManager.removeSessionCookies();
52 | }
53 | },
54 | };
55 |
56 | for (var i = 0; i < functions.length; i++) {
57 | module.exports[functions[i]] = CookieManager[functions[i]];
58 | }
59 |
--------------------------------------------------------------------------------
/ios/RNCookieManagerIOS.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 1BD726021CF77DD1005DBD79 /* RNCookieManagerIOS.m in Sources */ = {isa = PBXBuildFile; fileRef = 1BD726011CF77DD1005DBD79 /* RNCookieManagerIOS.m */; };
11 | A2387BE556B46F28BB9C62FD /* Pods_RNCookieManagerIOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A3E91C9DB889DAEAB299FB5 /* Pods_RNCookieManagerIOS.framework */; };
12 | /* End PBXBuildFile section */
13 |
14 | /* Begin PBXCopyFilesBuildPhase section */
15 | 1BD725D81CF77A8B005DBD79 /* CopyFiles */ = {
16 | isa = PBXCopyFilesBuildPhase;
17 | buildActionMask = 2147483647;
18 | dstPath = "include/$(PRODUCT_NAME)";
19 | dstSubfolderSpec = 16;
20 | files = (
21 | );
22 | runOnlyForDeploymentPostprocessing = 0;
23 | };
24 | /* End PBXCopyFilesBuildPhase section */
25 |
26 | /* Begin PBXFileReference section */
27 | 1BD725DA1CF77A8B005DBD79 /* libRNCookieManagerIOS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNCookieManagerIOS.a; sourceTree = BUILT_PRODUCTS_DIR; };
28 | 1BD726001CF77DD1005DBD79 /* RNCookieManagerIOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNCookieManagerIOS.h; sourceTree = ""; };
29 | 1BD726011CF77DD1005DBD79 /* RNCookieManagerIOS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNCookieManagerIOS.m; sourceTree = ""; };
30 | 6CDA467A38779CEFE54AF652 /* Pods-RNCookieManagerIOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNCookieManagerIOS.debug.xcconfig"; path = "Target Support Files/Pods-RNCookieManagerIOS/Pods-RNCookieManagerIOS.debug.xcconfig"; sourceTree = ""; };
31 | 7A3E91C9DB889DAEAB299FB5 /* Pods_RNCookieManagerIOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RNCookieManagerIOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
32 | AC0CCEFD0D5DDBC08A3F9FDB /* Pods-RNCookieManagerIOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNCookieManagerIOS.release.xcconfig"; path = "Target Support Files/Pods-RNCookieManagerIOS/Pods-RNCookieManagerIOS.release.xcconfig"; sourceTree = ""; };
33 | /* End PBXFileReference section */
34 |
35 | /* Begin PBXFrameworksBuildPhase section */
36 | 1BD725D71CF77A8B005DBD79 /* Frameworks */ = {
37 | isa = PBXFrameworksBuildPhase;
38 | buildActionMask = 2147483647;
39 | files = (
40 | A2387BE556B46F28BB9C62FD /* Pods_RNCookieManagerIOS.framework in Frameworks */,
41 | );
42 | runOnlyForDeploymentPostprocessing = 0;
43 | };
44 | /* End PBXFrameworksBuildPhase section */
45 |
46 | /* Begin PBXGroup section */
47 | 1ABCC227200901826854EA3A /* Frameworks */ = {
48 | isa = PBXGroup;
49 | children = (
50 | 7A3E91C9DB889DAEAB299FB5 /* Pods_RNCookieManagerIOS.framework */,
51 | );
52 | name = Frameworks;
53 | sourceTree = "";
54 | };
55 | 1BD725CD1CF7795C005DBD79 = {
56 | isa = PBXGroup;
57 | children = (
58 | 1BD725FF1CF77DD1005DBD79 /* RNCookieManagerIOS */,
59 | 1BD725DB1CF77A8B005DBD79 /* Products */,
60 | 71405C5FF90D2ACAB4F0366B /* Pods */,
61 | 1ABCC227200901826854EA3A /* Frameworks */,
62 | );
63 | sourceTree = "";
64 | };
65 | 1BD725DB1CF77A8B005DBD79 /* Products */ = {
66 | isa = PBXGroup;
67 | children = (
68 | 1BD725DA1CF77A8B005DBD79 /* libRNCookieManagerIOS.a */,
69 | );
70 | name = Products;
71 | sourceTree = "";
72 | };
73 | 1BD725FF1CF77DD1005DBD79 /* RNCookieManagerIOS */ = {
74 | isa = PBXGroup;
75 | children = (
76 | 1BD726001CF77DD1005DBD79 /* RNCookieManagerIOS.h */,
77 | 1BD726011CF77DD1005DBD79 /* RNCookieManagerIOS.m */,
78 | );
79 | path = RNCookieManagerIOS;
80 | sourceTree = "";
81 | };
82 | 71405C5FF90D2ACAB4F0366B /* Pods */ = {
83 | isa = PBXGroup;
84 | children = (
85 | 6CDA467A38779CEFE54AF652 /* Pods-RNCookieManagerIOS.debug.xcconfig */,
86 | AC0CCEFD0D5DDBC08A3F9FDB /* Pods-RNCookieManagerIOS.release.xcconfig */,
87 | );
88 | path = Pods;
89 | sourceTree = "";
90 | };
91 | /* End PBXGroup section */
92 |
93 | /* Begin PBXNativeTarget section */
94 | 1BD725D91CF77A8B005DBD79 /* RNCookieManagerIOS */ = {
95 | isa = PBXNativeTarget;
96 | buildConfigurationList = 1BD725E31CF77A8B005DBD79 /* Build configuration list for PBXNativeTarget "RNCookieManagerIOS" */;
97 | buildPhases = (
98 | 749140BD317DEE62C1AE6F51 /* [CP] Check Pods Manifest.lock */,
99 | 1BD725D61CF77A8B005DBD79 /* Sources */,
100 | 1BD725D71CF77A8B005DBD79 /* Frameworks */,
101 | 1BD725D81CF77A8B005DBD79 /* CopyFiles */,
102 | );
103 | buildRules = (
104 | );
105 | dependencies = (
106 | );
107 | name = RNCookieManagerIOS;
108 | productName = RNCookieManagerIOS;
109 | productReference = 1BD725DA1CF77A8B005DBD79 /* libRNCookieManagerIOS.a */;
110 | productType = "com.apple.product-type.library.static";
111 | };
112 | /* End PBXNativeTarget section */
113 |
114 | /* Begin PBXProject section */
115 | 1BD725CE1CF7795C005DBD79 /* Project object */ = {
116 | isa = PBXProject;
117 | attributes = {
118 | LastUpgradeCheck = 1130;
119 | TargetAttributes = {
120 | 1BD725D91CF77A8B005DBD79 = {
121 | CreatedOnToolsVersion = 7.3.1;
122 | };
123 | };
124 | };
125 | buildConfigurationList = 1BD725D11CF7795C005DBD79 /* Build configuration list for PBXProject "RNCookieManagerIOS" */;
126 | compatibilityVersion = "Xcode 3.2";
127 | developmentRegion = English;
128 | hasScannedForEncodings = 0;
129 | knownRegions = (
130 | English,
131 | en,
132 | );
133 | mainGroup = 1BD725CD1CF7795C005DBD79;
134 | productRefGroup = 1BD725DB1CF77A8B005DBD79 /* Products */;
135 | projectDirPath = "";
136 | projectRoot = "";
137 | targets = (
138 | 1BD725D91CF77A8B005DBD79 /* RNCookieManagerIOS */,
139 | );
140 | };
141 | /* End PBXProject section */
142 |
143 | /* Begin PBXShellScriptBuildPhase section */
144 | 749140BD317DEE62C1AE6F51 /* [CP] Check Pods Manifest.lock */ = {
145 | isa = PBXShellScriptBuildPhase;
146 | buildActionMask = 2147483647;
147 | files = (
148 | );
149 | inputFileListPaths = (
150 | );
151 | inputPaths = (
152 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
153 | "${PODS_ROOT}/Manifest.lock",
154 | );
155 | name = "[CP] Check Pods Manifest.lock";
156 | outputFileListPaths = (
157 | );
158 | outputPaths = (
159 | "$(DERIVED_FILE_DIR)/Pods-RNCookieManagerIOS-checkManifestLockResult.txt",
160 | );
161 | runOnlyForDeploymentPostprocessing = 0;
162 | shellPath = /bin/sh;
163 | 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";
164 | showEnvVarsInLog = 0;
165 | };
166 | /* End PBXShellScriptBuildPhase section */
167 |
168 | /* Begin PBXSourcesBuildPhase section */
169 | 1BD725D61CF77A8B005DBD79 /* Sources */ = {
170 | isa = PBXSourcesBuildPhase;
171 | buildActionMask = 2147483647;
172 | files = (
173 | 1BD726021CF77DD1005DBD79 /* RNCookieManagerIOS.m in Sources */,
174 | );
175 | runOnlyForDeploymentPostprocessing = 0;
176 | };
177 | /* End PBXSourcesBuildPhase section */
178 |
179 | /* Begin XCBuildConfiguration section */
180 | 1BD725D21CF7795C005DBD79 /* Debug */ = {
181 | isa = XCBuildConfiguration;
182 | buildSettings = {
183 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
184 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
185 | CLANG_WARN_BOOL_CONVERSION = YES;
186 | CLANG_WARN_COMMA = YES;
187 | CLANG_WARN_CONSTANT_CONVERSION = YES;
188 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
189 | CLANG_WARN_EMPTY_BODY = YES;
190 | CLANG_WARN_ENUM_CONVERSION = YES;
191 | CLANG_WARN_INFINITE_RECURSION = YES;
192 | CLANG_WARN_INT_CONVERSION = YES;
193 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
194 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
195 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
196 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
197 | CLANG_WARN_STRICT_PROTOTYPES = YES;
198 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
199 | CLANG_WARN_UNREACHABLE_CODE = YES;
200 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
201 | ENABLE_STRICT_OBJC_MSGSEND = YES;
202 | ENABLE_TESTABILITY = YES;
203 | GCC_NO_COMMON_BLOCKS = YES;
204 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
205 | GCC_WARN_ABOUT_RETURN_TYPE = YES;
206 | GCC_WARN_UNDECLARED_SELECTOR = YES;
207 | GCC_WARN_UNINITIALIZED_AUTOS = YES;
208 | GCC_WARN_UNUSED_FUNCTION = YES;
209 | GCC_WARN_UNUSED_VARIABLE = YES;
210 | ONLY_ACTIVE_ARCH = YES;
211 | };
212 | name = Debug;
213 | };
214 | 1BD725D31CF7795C005DBD79 /* Release */ = {
215 | isa = XCBuildConfiguration;
216 | buildSettings = {
217 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
218 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
219 | CLANG_WARN_BOOL_CONVERSION = YES;
220 | CLANG_WARN_COMMA = YES;
221 | CLANG_WARN_CONSTANT_CONVERSION = YES;
222 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
223 | CLANG_WARN_EMPTY_BODY = YES;
224 | CLANG_WARN_ENUM_CONVERSION = YES;
225 | CLANG_WARN_INFINITE_RECURSION = YES;
226 | CLANG_WARN_INT_CONVERSION = YES;
227 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
228 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
229 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
230 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
231 | CLANG_WARN_STRICT_PROTOTYPES = YES;
232 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
233 | CLANG_WARN_UNREACHABLE_CODE = YES;
234 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
235 | ENABLE_STRICT_OBJC_MSGSEND = YES;
236 | GCC_NO_COMMON_BLOCKS = YES;
237 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
238 | GCC_WARN_ABOUT_RETURN_TYPE = YES;
239 | GCC_WARN_UNDECLARED_SELECTOR = YES;
240 | GCC_WARN_UNINITIALIZED_AUTOS = YES;
241 | GCC_WARN_UNUSED_FUNCTION = YES;
242 | GCC_WARN_UNUSED_VARIABLE = YES;
243 | };
244 | name = Release;
245 | };
246 | 1BD725E11CF77A8B005DBD79 /* Debug */ = {
247 | isa = XCBuildConfiguration;
248 | baseConfigurationReference = 6CDA467A38779CEFE54AF652 /* Pods-RNCookieManagerIOS.debug.xcconfig */;
249 | buildSettings = {
250 | ALWAYS_SEARCH_USER_PATHS = NO;
251 | CLANG_ANALYZER_NONNULL = YES;
252 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
253 | CLANG_CXX_LIBRARY = "libc++";
254 | CLANG_ENABLE_MODULES = YES;
255 | CLANG_ENABLE_OBJC_ARC = YES;
256 | CLANG_WARN_BOOL_CONVERSION = YES;
257 | CLANG_WARN_CONSTANT_CONVERSION = YES;
258 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
259 | CLANG_WARN_EMPTY_BODY = YES;
260 | CLANG_WARN_ENUM_CONVERSION = YES;
261 | CLANG_WARN_INT_CONVERSION = YES;
262 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
263 | CLANG_WARN_UNREACHABLE_CODE = YES;
264 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
265 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
266 | COPY_PHASE_STRIP = NO;
267 | DEBUG_INFORMATION_FORMAT = dwarf;
268 | ENABLE_STRICT_OBJC_MSGSEND = YES;
269 | ENABLE_TESTABILITY = YES;
270 | FRAMEWORK_SEARCH_PATHS = (
271 | "$(SRCROOT)/../../React/**",
272 | "$(inherited)",
273 | "$(SRCROOT)/node_modules/react-native/React/**",
274 | "$(SRCROOT)/../react-native/React/**",
275 | "$(SRCROOT)/../../../node_modules/react-native/React/**",
276 | );
277 | GCC_C_LANGUAGE_STANDARD = gnu99;
278 | GCC_DYNAMIC_NO_PIC = NO;
279 | GCC_NO_COMMON_BLOCKS = YES;
280 | GCC_OPTIMIZATION_LEVEL = 0;
281 | GCC_PREPROCESSOR_DEFINITIONS = (
282 | "DEBUG=1",
283 | "$(inherited)",
284 | );
285 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
286 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
287 | GCC_WARN_UNDECLARED_SELECTOR = YES;
288 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
289 | GCC_WARN_UNUSED_FUNCTION = YES;
290 | GCC_WARN_UNUSED_VARIABLE = YES;
291 | HEADER_SEARCH_PATHS = (
292 | "$(SRCROOT)/../../React/**",
293 | "$(inherited)",
294 | "$(SRCROOT)/node_modules/react-native/React/**",
295 | "$(SRCROOT)/../react-native/React/**",
296 | "$(SRCROOT)/../../../node_modules/react-native/React/**",
297 | );
298 | IPHONEOS_DEPLOYMENT_TARGET = 9.3;
299 | MTL_ENABLE_DEBUG_INFO = YES;
300 | ONLY_ACTIVE_ARCH = YES;
301 | OTHER_LDFLAGS = "-ObjC";
302 | PRODUCT_NAME = "$(TARGET_NAME)";
303 | SDKROOT = iphoneos;
304 | SKIP_INSTALL = YES;
305 | };
306 | name = Debug;
307 | };
308 | 1BD725E21CF77A8B005DBD79 /* Release */ = {
309 | isa = XCBuildConfiguration;
310 | baseConfigurationReference = AC0CCEFD0D5DDBC08A3F9FDB /* Pods-RNCookieManagerIOS.release.xcconfig */;
311 | buildSettings = {
312 | ALWAYS_SEARCH_USER_PATHS = NO;
313 | CLANG_ANALYZER_NONNULL = YES;
314 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
315 | CLANG_CXX_LIBRARY = "libc++";
316 | CLANG_ENABLE_MODULES = YES;
317 | CLANG_ENABLE_OBJC_ARC = YES;
318 | CLANG_WARN_BOOL_CONVERSION = YES;
319 | CLANG_WARN_CONSTANT_CONVERSION = YES;
320 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
321 | CLANG_WARN_EMPTY_BODY = YES;
322 | CLANG_WARN_ENUM_CONVERSION = YES;
323 | CLANG_WARN_INT_CONVERSION = YES;
324 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
325 | CLANG_WARN_UNREACHABLE_CODE = YES;
326 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
327 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
328 | COPY_PHASE_STRIP = NO;
329 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
330 | ENABLE_NS_ASSERTIONS = NO;
331 | ENABLE_STRICT_OBJC_MSGSEND = YES;
332 | FRAMEWORK_SEARCH_PATHS = (
333 | "$(SRCROOT)/../../React/**",
334 | "$(inherited)",
335 | "$(SRCROOT)/node_modules/react-native/React/**",
336 | "$(SRCROOT)/../react-native/React/**",
337 | "$(SRCROOT)/../../../node_modules/react-native/React/**",
338 | );
339 | GCC_C_LANGUAGE_STANDARD = gnu99;
340 | GCC_NO_COMMON_BLOCKS = YES;
341 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
342 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
343 | GCC_WARN_UNDECLARED_SELECTOR = YES;
344 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
345 | GCC_WARN_UNUSED_FUNCTION = YES;
346 | GCC_WARN_UNUSED_VARIABLE = YES;
347 | HEADER_SEARCH_PATHS = (
348 | "$(SRCROOT)/../../React/**",
349 | "$(inherited)",
350 | "$(SRCROOT)/node_modules/react-native/React/**",
351 | "$(SRCROOT)/../react-native/React/**",
352 | "$(SRCROOT)/../../../node_modules/react-native/React/**",
353 | );
354 | IPHONEOS_DEPLOYMENT_TARGET = 9.3;
355 | MTL_ENABLE_DEBUG_INFO = NO;
356 | OTHER_LDFLAGS = "-ObjC";
357 | PRODUCT_NAME = "$(TARGET_NAME)";
358 | SDKROOT = iphoneos;
359 | SKIP_INSTALL = YES;
360 | VALIDATE_PRODUCT = YES;
361 | };
362 | name = Release;
363 | };
364 | /* End XCBuildConfiguration section */
365 |
366 | /* Begin XCConfigurationList section */
367 | 1BD725D11CF7795C005DBD79 /* Build configuration list for PBXProject "RNCookieManagerIOS" */ = {
368 | isa = XCConfigurationList;
369 | buildConfigurations = (
370 | 1BD725D21CF7795C005DBD79 /* Debug */,
371 | 1BD725D31CF7795C005DBD79 /* Release */,
372 | );
373 | defaultConfigurationIsVisible = 0;
374 | defaultConfigurationName = Release;
375 | };
376 | 1BD725E31CF77A8B005DBD79 /* Build configuration list for PBXNativeTarget "RNCookieManagerIOS" */ = {
377 | isa = XCConfigurationList;
378 | buildConfigurations = (
379 | 1BD725E11CF77A8B005DBD79 /* Debug */,
380 | 1BD725E21CF77A8B005DBD79 /* Release */,
381 | );
382 | defaultConfigurationIsVisible = 0;
383 | defaultConfigurationName = Release;
384 | };
385 | /* End XCConfigurationList section */
386 | };
387 | rootObject = 1BD725CE1CF7795C005DBD79 /* Project object */;
388 | }
389 |
--------------------------------------------------------------------------------
/ios/RNCookieManagerIOS/RNCookieManagerIOS.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Joseph P. Ferraro
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file here: https://github.com/joeferraro/react-native-cookies/blob/master/LICENSE.md.
6 | */
7 |
8 | #import
9 |
10 | #import
11 |
12 | @interface RNCookieManagerIOS : NSObject
13 |
14 | @property (nonatomic, strong) NSDateFormatter *formatter;
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/ios/RNCookieManagerIOS/RNCookieManagerIOS.m:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Joseph P. Ferraro
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file here: https://github.com/joeferraro/react-native-cookies/blob/master/LICENSE.md.
6 | */
7 |
8 | #import "RNCookieManagerIOS.h"
9 | #import
10 |
11 | static NSString * const NOT_AVAILABLE_ERROR_MESSAGE = @"WebKit/WebKit-Components are only available with iOS11 and higher!";
12 | static NSString * const INVALID_URL_MISSING_HTTP = @"Invalid URL: It may be missing a protocol (ex. http:// or https://).";
13 | static NSString * const INVALID_DOMAINS = @"Cookie URL host %@ and domain %@ mismatched. The cookie won't set correctly.";
14 |
15 | static inline BOOL isEmpty(id value)
16 | {
17 | return value == nil
18 | || ([value respondsToSelector:@selector(length)] && [(NSData *)value length] == 0)
19 | || ([value respondsToSelector:@selector(count)] && [(NSArray *)value count] == 0);
20 | }
21 |
22 | @implementation RNCookieManagerIOS
23 |
24 | - (instancetype)init
25 | {
26 | self = [super init];
27 | if (self) {
28 | self.formatter = [NSDateFormatter new];
29 | [self.formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"];
30 | }
31 | return self;
32 | }
33 |
34 | + (BOOL)requiresMainQueueSetup
35 | {
36 | return NO;
37 | }
38 |
39 | RCT_EXPORT_MODULE()
40 |
41 | RCT_EXPORT_METHOD(
42 | set:(NSURL *)url
43 | cookie:(NSDictionary *)props
44 | useWebKit:(BOOL)useWebKit
45 | resolver:(RCTPromiseResolveBlock)resolve
46 | rejecter:(RCTPromiseRejectBlock)reject)
47 | {
48 | NSHTTPCookie *cookie;
49 | @try {
50 | cookie = [self makeHTTPCookieObject:url props:props];
51 | }
52 | @catch ( NSException *e ) {
53 | reject(@"", [e reason], nil);
54 | return;
55 | }
56 |
57 | if (useWebKit) {
58 | if (@available(iOS 11.0, *)) {
59 | dispatch_async(dispatch_get_main_queue(), ^(){
60 | WKHTTPCookieStore *cookieStore = [[WKWebsiteDataStore defaultDataStore] httpCookieStore];
61 | [cookieStore setCookie:cookie completionHandler:^() {
62 | resolve(@(YES));
63 | }];
64 | });
65 | } else {
66 | reject(@"", NOT_AVAILABLE_ERROR_MESSAGE, nil);
67 | }
68 | } else {
69 | [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
70 | resolve(@(YES));
71 | }
72 | }
73 |
74 | RCT_EXPORT_METHOD(
75 | setFromResponse:(NSURL *)url
76 | cookie:(NSString *)cookie
77 | resolver:(RCTPromiseResolveBlock)resolve
78 | rejecter:(RCTPromiseRejectBlock)reject) {
79 |
80 | NSArray *cookies = [NSHTTPCookie cookiesWithResponseHeaderFields:@{@"Set-Cookie": cookie} forURL:url];
81 | [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookies:cookies forURL:url mainDocumentURL:nil];
82 | resolve(@(YES));
83 | }
84 |
85 | RCT_EXPORT_METHOD(
86 | getFromResponse:(NSURL *)url
87 | resolver:(RCTPromiseResolveBlock)resolve
88 | rejecter:(RCTPromiseRejectBlock)reject) {
89 | NSURLRequest *request = [NSURLRequest requestWithURL:url];
90 | [NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init]
91 | completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
92 |
93 | NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
94 | NSArray *cookies = [NSHTTPCookie cookiesWithResponseHeaderFields:httpResponse.allHeaderFields forURL:response.URL];
95 | NSMutableDictionary *dics = [NSMutableDictionary dictionary];
96 |
97 | for (int i = 0; i < cookies.count; i++) {
98 | NSHTTPCookie *cookie = [cookies objectAtIndex:i];
99 | [dics setObject:cookie.value forKey:cookie.name];
100 | [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
101 | }
102 | resolve(dics);
103 | }];
104 | }
105 |
106 | RCT_EXPORT_METHOD(
107 | get:(NSURL *)url
108 | useWebKit:(BOOL)useWebKit
109 | resolver:(RCTPromiseResolveBlock)resolve
110 | rejecter:(RCTPromiseRejectBlock)reject)
111 | {
112 | if (useWebKit) {
113 | if (@available(iOS 11.0, *)) {
114 | dispatch_async(dispatch_get_main_queue(), ^(){
115 | NSString *topLevelDomain = url.host;
116 |
117 | if (isEmpty(topLevelDomain)) {
118 | reject(@"", INVALID_URL_MISSING_HTTP, nil);
119 | return;
120 | }
121 |
122 | WKHTTPCookieStore *cookieStore = [[WKWebsiteDataStore defaultDataStore] httpCookieStore];
123 | [cookieStore getAllCookies:^(NSArray *allCookies) {
124 | NSMutableDictionary *cookies = [NSMutableDictionary dictionary];
125 | for (NSHTTPCookie *cookie in allCookies) {
126 | if ([topLevelDomain containsString:cookie.domain] ||
127 | [cookie.domain isEqualToString: topLevelDomain]) {
128 | [cookies setObject:[self createCookieData:cookie] forKey:cookie.name];
129 | }
130 | }
131 | resolve(cookies);
132 | }];
133 | });
134 | } else {
135 | reject(@"", NOT_AVAILABLE_ERROR_MESSAGE, nil);
136 | }
137 | } else {
138 | NSMutableDictionary *cookies = [NSMutableDictionary dictionary];
139 | for (NSHTTPCookie *cookie in [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:url]) {
140 | [cookies setObject:[self createCookieData:cookie] forKey:cookie.name];
141 | }
142 | resolve(cookies);
143 | }
144 | }
145 |
146 | RCT_EXPORT_METHOD(
147 | clearAll:(BOOL)useWebKit
148 | resolver:(RCTPromiseResolveBlock)resolve
149 | rejecter:(RCTPromiseRejectBlock)reject)
150 | {
151 | if (useWebKit) {
152 | if (@available(iOS 11.0, *)) {
153 | dispatch_async(dispatch_get_main_queue(), ^(){
154 | // https://stackoverflow.com/questions/46465070/how-to-delete-cookies-from-wkhttpcookiestore#answer-47928399
155 | NSSet *websiteDataTypes = [NSSet setWithArray:@[WKWebsiteDataTypeCookies]];
156 | NSDate *dateFrom = [NSDate dateWithTimeIntervalSince1970:0];
157 | [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:websiteDataTypes
158 | modifiedSince:dateFrom
159 | completionHandler:^() {
160 | resolve(@(YES));
161 | }];
162 | });
163 | } else {
164 | reject(@"", NOT_AVAILABLE_ERROR_MESSAGE, nil);
165 | }
166 | } else {
167 | NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
168 | for (NSHTTPCookie *c in cookieStorage.cookies) {
169 | [cookieStorage deleteCookie:c];
170 | }
171 | [[NSUserDefaults standardUserDefaults] synchronize];
172 | resolve(@(YES));
173 | }
174 | }
175 |
176 | RCT_EXPORT_METHOD(
177 | clearByName:(NSURL *)url
178 | name:(NSString *)name
179 | useWebKit:(BOOL)useWebKit
180 | resolver:(RCTPromiseResolveBlock)resolve
181 | rejecter:(RCTPromiseRejectBlock)reject) {
182 | __block NSNumber * foundCookies = @NO;
183 | NSMutableArray * foundCookiesList = [NSMutableArray new];
184 |
185 | if (useWebKit) {
186 | if (@available(iOS 11.0, *)) {
187 | dispatch_async(dispatch_get_main_queue(), ^(){
188 | NSString *topLevelDomain = url.host;
189 |
190 | if (isEmpty(topLevelDomain)) {
191 | reject(@"", INVALID_URL_MISSING_HTTP, nil);
192 | return;
193 | }
194 |
195 | WKHTTPCookieStore *cookieStore = [[WKWebsiteDataStore defaultDataStore] httpCookieStore];
196 | [cookieStore getAllCookies:^(NSArray *allCookies) {
197 | for (NSHTTPCookie *cookie in allCookies) {
198 | if ([name isEqualToString:cookie.name] && [self isMatchingDomain:topLevelDomain cookieDomain:cookie.domain]) {
199 | [foundCookiesList addObject:cookie];
200 | foundCookies = @YES;
201 | }
202 | }
203 | for (NSHTTPCookie *fCookie in foundCookiesList) {
204 | [cookieStore deleteCookie:fCookie completionHandler:nil];
205 | }
206 | resolve(foundCookies);
207 | }];
208 | });
209 | } else {
210 | reject(@"", NOT_AVAILABLE_ERROR_MESSAGE, nil);
211 | }
212 | } else {
213 | NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
214 | for (NSHTTPCookie *c in cookieStorage.cookies) {
215 | if ([[c name] isEqualToString:name] && [self isMatchingDomain:url.host cookieDomain:c.domain]) {
216 | [cookieStorage deleteCookie:c];
217 | foundCookies = @YES;
218 | }
219 | }
220 | resolve(foundCookies);
221 | }
222 | }
223 |
224 | RCT_EXPORT_METHOD(
225 | getAll:(BOOL)useWebKit
226 | resolver:(RCTPromiseResolveBlock)resolve
227 | rejecter:(RCTPromiseRejectBlock)reject)
228 | {
229 | if (useWebKit) {
230 | if (@available(iOS 11.0, *)) {
231 | dispatch_async(dispatch_get_main_queue(), ^(){
232 | WKHTTPCookieStore *cookieStore = [[WKWebsiteDataStore defaultDataStore] httpCookieStore];
233 | [cookieStore getAllCookies:^(NSArray *allCookies) {
234 | resolve([self createCookieList: allCookies]);
235 | }];
236 | });
237 | } else {
238 | reject(@"", NOT_AVAILABLE_ERROR_MESSAGE, nil);
239 | }
240 | } else {
241 | NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
242 | resolve([self createCookieList:cookieStorage.cookies]);
243 | }
244 | }
245 |
246 | -(NSDictionary *)createCookieList:(NSArray*)cookies
247 | {
248 | NSMutableDictionary *cookieList = [NSMutableDictionary dictionary];
249 | for (NSHTTPCookie *cookie in cookies) {
250 | [cookieList setObject:[self createCookieData:cookie] forKey:cookie.name];
251 | }
252 | return cookieList;
253 | }
254 |
255 | -(NSHTTPCookie *)makeHTTPCookieObject:(NSURL *)url
256 | props:(NSDictionary *)props
257 | {
258 | NSString *topLevelDomain = url.host;
259 |
260 | if (isEmpty(topLevelDomain)){
261 | NSException* myException = [NSException
262 | exceptionWithName:@"Exception"
263 | reason:INVALID_URL_MISSING_HTTP
264 | userInfo:nil];
265 | @throw myException;
266 | }
267 |
268 | NSString *name = [RCTConvert NSString:props[@"name"]];
269 | NSString *value = [RCTConvert NSString:props[@"value"]];
270 | NSString *path = [RCTConvert NSString:props[@"path"]];
271 | NSString *domain = [RCTConvert NSString:props[@"domain"]];
272 | NSString *version = [RCTConvert NSString:props[@"version"]];
273 | NSDate *expires = [RCTConvert NSDate:props[@"expires"]];
274 | NSNumber *secure = [RCTConvert NSNumber:props[@"secure"]];
275 | NSNumber *httpOnly = [RCTConvert NSNumber:props[@"httpOnly"]];
276 |
277 | NSMutableDictionary *cookieProperties = [NSMutableDictionary dictionary];
278 | [cookieProperties setObject:name forKey:NSHTTPCookieName];
279 | [cookieProperties setObject:value forKey:NSHTTPCookieValue];
280 |
281 | if (!isEmpty(path)) {
282 | [cookieProperties setObject:path forKey:NSHTTPCookiePath];
283 | } else {
284 | [cookieProperties setObject:@"/" forKey:NSHTTPCookiePath];
285 | }
286 | if (!isEmpty(domain)) {
287 | // Stripping the leading . to ensure the following check is accurate
288 | NSString *strippedDomain = domain;
289 | if ([strippedDomain hasPrefix:@"."]) {
290 | strippedDomain = [strippedDomain substringFromIndex:1];
291 | }
292 |
293 | if (![topLevelDomain containsString:strippedDomain] &&
294 | ![topLevelDomain isEqualToString: strippedDomain]) {
295 | NSException* myException = [NSException
296 | exceptionWithName:@"Exception"
297 | reason: [NSString stringWithFormat:INVALID_DOMAINS, topLevelDomain, domain]
298 | userInfo:nil];
299 | @throw myException;
300 | }
301 |
302 | [cookieProperties setObject:domain forKey:NSHTTPCookieDomain];
303 | } else {
304 | [cookieProperties setObject:topLevelDomain forKey:NSHTTPCookieDomain];
305 | }
306 | if (!isEmpty(version)) {
307 | [cookieProperties setObject:version forKey:NSHTTPCookieVersion];
308 | }
309 | if (!isEmpty(expires)) {
310 | [cookieProperties setObject:expires forKey:NSHTTPCookieExpires];
311 | }
312 | if ([secure boolValue]) {
313 | [cookieProperties setObject:secure forKey:NSHTTPCookieSecure];
314 | }
315 | if ([httpOnly boolValue]) {
316 | [cookieProperties setObject:httpOnly forKey:@"HttpOnly"];
317 | }
318 |
319 | NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:cookieProperties];
320 |
321 | return cookie;
322 | }
323 |
324 | -(NSDictionary *)createCookieData:(NSHTTPCookie *)cookie
325 | {
326 | NSMutableDictionary *cookieData = [NSMutableDictionary dictionary];
327 | [cookieData setObject:cookie.name forKey:@"name"];
328 | [cookieData setObject:cookie.value forKey:@"value"];
329 | [cookieData setObject:cookie.path forKey:@"path"];
330 | [cookieData setObject:cookie.domain forKey:@"domain"];
331 | [cookieData setObject:[NSString stringWithFormat:@"%@", @(cookie.version)] forKey:@"version"];
332 | if (!isEmpty(cookie.expiresDate)) {
333 | [cookieData setObject:[self.formatter stringFromDate:cookie.expiresDate] forKey:@"expires"];
334 | }
335 | [cookieData setObject:[NSNumber numberWithBool:(BOOL)cookie.secure] forKey:@"secure"];
336 | [cookieData setObject:[NSNumber numberWithBool:(BOOL)cookie.HTTPOnly] forKey:@"httpOnly"];
337 | return cookieData;
338 | }
339 |
340 | -(BOOL)isMatchingDomain:(NSString *)originDomain
341 | cookieDomain:(NSString *)cookieDomain
342 | {
343 | if ([originDomain isEqualToString: cookieDomain]) {
344 | return @YES;
345 | }
346 | NSString *parentDomain = [cookieDomain hasPrefix:@"."] ? cookieDomain : [@"." stringByAppendingString: cookieDomain];
347 | return [originDomain hasSuffix:parentDomain];
348 | }
349 |
350 | @end
351 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@react-native-cookies/cookies",
3 | "version": "6.2.1",
4 | "description": "Cookie Manager for React Native",
5 | "repository": {
6 | "type": "git",
7 | "url": "git+https://github.com/react-native-cookies/cookies.git",
8 | "baseUrl": "https://github.com/react-native-cookies/cookies"
9 | },
10 | "keywords": [
11 | "react native",
12 | "react-native-component",
13 | "android",
14 | "ios",
15 | "cookies",
16 | "webview"
17 | ],
18 | "files": [
19 | "android",
20 | "ios",
21 | "index.d.ts",
22 | "react-native-cookies.podspec"
23 | ],
24 | "author": {
25 | "name": "Jason Safaiyeh",
26 | "email": "safaiyeh@protonmail.com"
27 | },
28 | "license": "MIT",
29 | "licenseFilename": "LICENSE",
30 | "readmeFilename": "README.md",
31 | "bugs": {
32 | "url": "https://github.com/react-native-cookies/cookies/issues"
33 | },
34 | "homepage": "https://github.com/react-native-cookies/cookies#readme",
35 | "main": "index.js",
36 | "types": "index.d.ts",
37 | "scripts": {
38 | "lint": "eslint index.js",
39 | "semantic-release": "semantic-release"
40 | },
41 | "dependencies": {
42 | "invariant": "^2.2.4"
43 | },
44 | "peerDependencies": {
45 | "react-native": ">= 0.60.2"
46 | },
47 | "devDependencies": {
48 | "@react-native-community/eslint-config": "^0.0.6",
49 | "@react-native-community/eslint-plugin": "^1.0.0",
50 | "@semantic-release/git": "^8.0.0",
51 | "eslint": "^6.8.0",
52 | "semantic-release": "^17.2.3"
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/react-native-cookies.podspec:
--------------------------------------------------------------------------------
1 | require "json"
2 |
3 | package = JSON.parse(File.read(File.join(__dir__, "package.json")))
4 |
5 | Pod::Spec.new do |s|
6 | s.name = "react-native-cookies"
7 | s.version = package["version"]
8 | s.summary = package["description"]
9 | s.homepage = package["homepage"]
10 | s.license = package["license"]
11 | s.author = { package["author"]["name"] => package["author"]["email"] }
12 | s.source = { :git => "git@github.com:react-native-community/cookies.git", :tag => "v#{s.version}" }
13 | s.requires_arc = true
14 | s.platform = :ios, "7.0"
15 | s.preserve_paths = "*.framework"
16 | s.source_files = "ios/**/*.{h,m}"
17 | s.dependency "React-Core"
18 | end
19 |
--------------------------------------------------------------------------------