From 6a169bd0bdd4d10d828554303d917578a372d6eb Mon Sep 17 00:00:00 2001 From: flexsurfer Date: Wed, 20 Sep 2023 14:16:07 +0200 Subject: [PATCH] [#17347] move [status-im.utils.http :as http] to status-im2 (#17350) --- ios/Podfile.lock | 6 +- package.json | 1 - src/status_im/browser/core.cljs | 22 +- src/status_im/browser/core_test.cljs | 4 +- src/status_im/events.cljs | 1 - src/status_im/http/core.cljs | 11 - src/status_im/network/core.cljs | 29 +-- src/status_im/router/core.cljs | 6 +- .../ui/components/list_selection.cljs | 6 +- .../ui/screens/browser/empty_tab/views.cljs | 4 +- .../ui/screens/browser/options/views.cljs | 6 +- .../ui/screens/browser/tabs/views.cljs | 4 +- src/status_im/ui/screens/browser/views.cljs | 6 +- src/status_im/utils/http.cljs | 196 ------------------ .../wallet/choose_recipient/core.cljs | 4 +- .../contexts/chat/lightbox/top_view.cljs | 8 +- .../chat/lightbox/zoomable_image/view.cljs | 4 +- .../chat/messages/content/album/view.cljs | 6 +- .../chat/messages/content/image/view.cljs | 4 +- .../notification/reply/view.cljs | 4 +- src/utils/url.cljs | 59 ++++++ .../http_test.cljs => utils/url_test.cljs} | 32 +-- yarn.lock | 5 - 23 files changed, 123 insertions(+), 305 deletions(-) delete mode 100644 src/status_im/http/core.cljs delete mode 100644 src/status_im/utils/http.cljs create mode 100644 src/utils/url.cljs rename src/{status_im/utils/http_test.cljs => utils/url_test.cljs} (70%) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 9a047e492d..74d395bf13 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -707,7 +707,7 @@ SPEC CHECKSUMS: FBLazyVector: a8af91c2b5a0029d12ff6b32e428863d63c48991 FBReactNativeSpec: 1b2309b096448a1dc9d0c43999216f8fda809ae8 fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9 - glog: 166d178815c300e8126de9a7900101814eb16253 + glog: d93527a855523adb8c113837db4be68fb00e230d HMSegmentedControl: 34c1f54d822d8308e7b24f5d901ec674dfa31352 Keycard: ac6df4d91525c3c82635ac24d4ddd9a80aca5fc8 libwebp: f62cb61d0a484ba548448a4bd52aabf150ff6eef @@ -772,7 +772,7 @@ SPEC CHECKSUMS: RNLanguages: 962e562af0d34ab1958d89bcfdb64fafc37c513e RNPermissions: ad71dd4f767ec254f2cd57592fbee02afee75467 RNReactNativeHapticFeedback: 2566b468cc8d0e7bb2f84b23adc0f4614594d071 - RNReanimated: b3b67ebe099c0b0e7b5c7386b18d2468e29c9d41 + RNReanimated: 43adb0307a62c1ce9694f36f124ca3b51a15272a RNShare: d82e10f6b7677f4b0048c23709bd04098d5aee6c RNStaticSafeAreaInsets: 055ddbf5e476321720457cdaeec0ff2ba40ec1b8 RNSVG: 80584470ff1ffc7994923ea135a3e5ad825546b9 @@ -785,6 +785,6 @@ SPEC CHECKSUMS: TouchID: ba4c656d849cceabc2e4eef722dea5e55959ecf4 Yoga: d24d6184b6b85f742536bd93bd07d69d7b9bb4c1 -PODFILE CHECKSUM: 8df67467da1e4e60ec164479744536c6f8fc98ed +PODFILE CHECKSUM: ac30a0172ff0126b6f307c20f34c47ce0ebf278f COCOAPODS: 1.12.0 diff --git a/package.json b/package.json index 8bd09bc6c4..6bbda2221a 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,6 @@ "react-native-dialogs": "^1.0.4", "react-native-draggable-flatlist": "^4.0.1", "react-native-fast-image": "^8.5.11", - "react-native-fetch-polyfill": "^1.1.2", "react-native-fs": "^2.14.1", "react-native-gesture-handler": "2.6.1", "react-native-gifted-charts": "git+https://github.com/status-im/react-native-gifted-charts.git#refs/tags/1.3.2-status.1", diff --git a/src/status_im/browser/core.cljs b/src/status_im/browser/core.cljs index a6191c21d5..7089d1fd12 100644 --- a/src/status_im/browser/core.cljs +++ b/src/status_im/browser/core.cljs @@ -17,7 +17,7 @@ [status-im.signing.core :as signing] [status-im.ui.components.list-selection :as list-selection] [utils.re-frame :as rf] - [status-im.utils.http :as http] + [utils.url :as url] [status-im.utils.platform :as platform] [status-im.utils.random :as random] [status-im.utils.types :as types] @@ -75,7 +75,7 @@ (defn check-if-phishing-url [{:keys [history history-index] :as browser}] - (let [history-host (http/url-host (try (nth history history-index) (catch js/Error _)))] + (let [history-host (url/url-host (try (nth history history-index) (catch js/Error _)))] (cond-> browser history-host (assoc :unsafe? (eth-phishing-detect history-host))))) (defn resolve-ens-contenthash-callback @@ -88,7 +88,7 @@ [{:keys [db]} {:keys [error? resolved-url]}] (when (not error?) (let [current-url (get-current-url (get-current-browser db)) - host (http/url-host current-url)] + host (url/url-host current-url)] (if (and (not resolved-url) (ens/is-valid-eth-name? host)) {:db (update db :browser/options assoc :resolving? true) :browser/resolve-ens-contenthash {:chain-id (ethereum/chain-id db) @@ -162,7 +162,7 @@ {:events [:browser/ignore-unsafe]} [cofx] (let [browser (get-current-browser (:db cofx)) - host (http/url-host (get-current-url browser))] + host (url/url-host (get-current-url browser))] (update-browser cofx (assoc browser :ignore-unsafe host)))) (defn can-go-forward? @@ -194,7 +194,7 @@ {:events [:browser.callback/resolve-ens-multihash-success]} [{:keys [db] :as cofx} url] (let [current-url (get-current-url (get-current-browser db)) - host (http/url-host current-url) + host (url/url-host current-url) path (subs current-url (+ (.indexOf ^js current-url host) (count host))) gateway url] (rf/merge cofx @@ -247,9 +247,9 @@ (not= (.indexOf ^js url (second v)) -1)) (:resolved-ens options))) resolved-url (if resolved-ens - (http/normalize-url (string/replace url - (second resolved-ens) - (first resolved-ens))) + (url/normalize-url (string/replace url + (second resolved-ens) + (first resolved-ens))) url)] (rf/merge cofx (update-browser-history browser resolved-url) @@ -282,7 +282,7 @@ {:events [:browser.ui/url-submitted]} [cofx url] (let [browser (get-current-browser (:db cofx)) - normalized-url (http/normalize-and-decode-url url)] + normalized-url (url/normalize-and-decode-url url)] (if (links/universal-link? normalized-url) {:dispatch [:universal-links/handle-url normalized-url]} (rf/merge cofx @@ -296,7 +296,7 @@ If the browser is reused, the history is flushed" {:events [:browser.ui/open-url]} [{:keys [db] :as cofx} url] - (let [normalized-url (http/normalize-and-decode-url url) + (let [normalized-url (url/normalize-and-decode-url url) browser {:browser-id (random/id) :history-index 0 :history [normalized-url]}] @@ -503,7 +503,7 @@ {:keys [dapp? name]} browser dapp-name (if dapp? name - (http/url-host + (url/url-host url-original))] (cond (and (= type constants/history-state-changed) diff --git a/src/status_im/browser/core_test.cljs b/src/status_im/browser/core_test.cljs index bc5bf31f88..bdc9d826bb 100644 --- a/src/status_im/browser/core_test.cljs +++ b/src/status_im/browser/core_test.cljs @@ -1,7 +1,7 @@ (ns status-im.browser.core-test (:require [cljs.test :refer-macros [deftest is testing]] [status-im.browser.core :as browser] - [status-im.utils.http :as http])) + [utils.url :as url])) (defn has-wrong-properties? [result dapp-url expected-browser] @@ -16,7 +16,7 @@ (defn get-dapp-id [result dapp-url] - (some #(when (= (http/normalize-and-decode-url dapp-url) (first (:history %))) (:browser-id %)) + (some #(when (= (url/normalize-and-decode-url dapp-url) (first (:history %))) (:browser-id %)) (vals (get-in result [:db :browser/browsers])))) (deftest browser-test diff --git a/src/status_im/events.cljs b/src/status_im/events.cljs index 6ae282ef00..1a8aa38601 100644 --- a/src/status_im/events.cljs +++ b/src/status_im/events.cljs @@ -17,7 +17,6 @@ status-im.currency.core status-im.ethereum.subscriptions status-im.fleet.core - status-im.http.core [utils.i18n :as i18n] [status-im.keycard.core :as keycard] status-im.log-level.core diff --git a/src/status_im/http/core.cljs b/src/status_im/http/core.cljs deleted file mode 100644 index 92c532ce9a..0000000000 --- a/src/status_im/http/core.cljs +++ /dev/null @@ -1,11 +0,0 @@ -(ns status-im.http.core - (:require [re-frame.core :as re-frame] - [status-im.utils.http :as http])) - -(re-frame/reg-fx - :http-post - (fn [{:keys [url data response-validator on-success on-error timeout-ms opts]}] - (let [all-opts (assoc opts - :valid-response? response-validator - :timeout-ms timeout-ms)] - (http/post url data on-success on-error all-opts)))) diff --git a/src/status_im/network/core.cljs b/src/status_im/network/core.cljs index 2ad05b2a1c..40bc7765bd 100644 --- a/src/status_im/network/core.cljs +++ b/src/status_im/network/core.cljs @@ -5,8 +5,6 @@ [utils.i18n :as i18n] [status-im.node.core :as node] [utils.re-frame :as rf] - [status-im.utils.http :as http] - [status-im.utils.types :as types] [status-im2.navigation.events :as navigation])) (def url-regex @@ -97,31 +95,8 @@ (rf/defn connect {:events [::connect-network-pressed]} [{:keys [db] :as cofx} network-id] - (if-let [config (get-in db [:networks/networks network-id :config])] - (if-let [upstream-url (get-in config [:UpstreamConfig :URL])] - {:http-post {:url upstream-url - :data (types/clj->json {:jsonrpc "2.0" - :method "net_version" - :id 2}) - :opts {:headers {"Content-Type" "application/json"}} - :on-success (fn [{:keys [response-body]}] - (let [response (http/parse-payload response-body) - expected-network-id (:NetworkId config) - rpc-network-id (when-let [res (:result response)] - (js/parseInt res))] - (if (and network-id (= expected-network-id rpc-network-id)) - (re-frame/dispatch [::connect-success network-id]) - (re-frame/dispatch [::connect-failure - (if (not= expected-network-id rpc-network-id) - (i18n/label :t/network-invalid-network-id) - (i18n/label :t/network-invalid-url))])))) - :on-error (fn [{:keys [response-body status-code]}] - (let [reason (if status-code - (i18n/label :t/network-invalid-status-code - {:code status-code}) - (str response-body))] - (re-frame/dispatch [::connect-failure reason])))}} - (connect-success cofx network-id)) + (if (get-in db [:networks/networks network-id :config]) + (connect-success cofx network-id) (connect-failure cofx "A network with the specified id doesn't exist"))) (rf/defn delete diff --git a/src/status_im/router/core.cljs b/src/status_im/router/core.cljs index a54894f8a5..ceadb510b4 100644 --- a/src/status_im/router/core.cljs +++ b/src/status_im/router/core.cljs @@ -11,7 +11,7 @@ [native-module.core :as native-module] [status-im.ethereum.stateofus :as stateofus] [utils.validators :as validators] - [status-im.utils.http :as http] + [utils.url :as url] [status-im.utils.wallet-connect :as wallet-connect] [taoensso.timbre :as log] [utils.security.core :as security])) @@ -60,7 +60,7 @@ (defn parse-query-params [url] (let [url (goog.Uri. url)] - (http/query->map (.getQuery url)))) + (url/query->map (.getQuery url)))) (defn match-uri [uri] @@ -247,7 +247,7 @@ (ethereum/address? uri) (cb (address->eip681 uri)) - (http/url? uri) + (url/url? uri) (cb (match-browser-string uri)) (wallet-connect/url? uri) diff --git a/src/status_im/ui/components/list_selection.cljs b/src/status_im/ui/components/list_selection.cljs index 50292670db..ffd1092a46 100644 --- a/src/status_im/ui/components/list_selection.cljs +++ b/src/status_im/ui/components/list_selection.cljs @@ -4,7 +4,7 @@ [status-im.ui.components.action-sheet :as action-sheet] [status-im.ui.components.dialog :as dialog] [status-im.ui.components.react :as react] - [status-im.utils.http :as http] + [utils.url :as url] [status-im.utils.platform :as platform])) (defn open-share @@ -29,12 +29,12 @@ :options [{:label (i18n/label :t/browsing-open-in-status) :action #(re-frame/dispatch [:browser.ui/open-url link])} {:label (i18n/label (platform-web-browser)) - :action #(.openURL ^js react/linking (http/normalize-url link))}] + :action #(.openURL ^js react/linking (url/normalize-url link))}] :cancel-text (i18n/label :t/browsing-cancel)})) (defn browse-in-web-browser [link] (show {:title (i18n/label :t/browsing-title) :options [{:label (i18n/label (platform-web-browser)) - :action #(.openURL ^js react/linking (http/normalize-url link))}] + :action #(.openURL ^js react/linking (url/normalize-url link))}] :cancel-text (i18n/label :t/browsing-cancel)})) diff --git a/src/status_im/ui/screens/browser/empty_tab/views.cljs b/src/status_im/ui/screens/browser/empty_tab/views.cljs index d6c2c343b9..803e9bf7aa 100644 --- a/src/status_im/ui/screens/browser/empty_tab/views.cljs +++ b/src/status_im/ui/screens/browser/empty_tab/views.cljs @@ -13,7 +13,7 @@ [status-im.ui.screens.browser.empty-tab.styles :as styles] [status-im.ui.screens.browser.views :as browser] [status-im.ui.screens.wallet.components.views :as components] - [status-im.utils.http :as http]) + [utils.url :as url]) (:require-macros [status-im.utils.views :as views])) (defn hide-sheet-and-dispatch @@ -67,7 +67,7 @@ [react/image {:onLoad #(reset! loaded true) :style {:width 32 :height 32 :position :absolute :top 4 :left 4} - :source {:uri (str "https://" (http/url-host url) "/favicon.ico")}}]) + :source {:uri (str "https://" (url/url-host url) "/favicon.ico")}}]) (when-not @loaded [react/view {:width 40 diff --git a/src/status_im/ui/screens/browser/options/views.cljs b/src/status_im/ui/screens/browser/options/views.cljs index 96c447d514..78da3a2dff 100644 --- a/src/status_im/ui/screens/browser/options/views.cljs +++ b/src/status_im/ui/screens/browser/options/views.cljs @@ -10,7 +10,7 @@ [status-im.ui.components.icons.icons :as icons] [status-im.ui.components.react :as react] [status-im.ui.screens.wallet.components.views :as components] - [status-im.utils.http :as http] + [utils.url :as url] [status-im.utils.utils :as utils])) (defn hide-sheet-and-dispatch @@ -45,7 +45,7 @@ permissions @(re-frame/subscribe [:dapps/permissions]) fav? (get bookmarks url) connected? (some #{constants/dapp-permission-web3} - (get-in permissions [(http/url-host url) :permissions]))] + (get-in permissions [(url/url-host url) :permissions]))] [react/view {:flex 1} [quo/button {:style {:align-self :flex-end @@ -94,7 +94,7 @@ :chevron true :on-press #(hide-sheet-and-dispatch [:bottom-sheet/show-sheet-old - {:content (wallet-connection (http/url-host url) account)}])}] + {:content (wallet-connection (url/url-host url) account)}])}] [quo/list-item {:theme :accent :title (i18n/label :t/connect-wallet) diff --git a/src/status_im/ui/screens/browser/tabs/views.cljs b/src/status_im/ui/screens/browser/tabs/views.cljs index 939621e72f..b3f260987b 100644 --- a/src/status_im/ui/screens/browser/tabs/views.cljs +++ b/src/status_im/ui/screens/browser/tabs/views.cljs @@ -11,7 +11,7 @@ [status-im.ui.components.react :as react] [status-im.ui.components.topbar :as topbar] [status-im.ui.screens.wallet.components.views :as components] - [status-im.utils.http :as http])) + [utils.url :as url])) (defn list-item [_] @@ -35,7 +35,7 @@ [react/image {:onLoad #(reset! loaded true) :style {:width 32 :height 32 :position :absolute :top 4 :left 4} - :source {:uri (str "https://" (http/url-host url) "/favicon.ico")}}]) + :source {:uri (str "https://" (url/url-host url) "/favicon.ico")}}]) (when-not @loaded [react/view {:width 40 diff --git a/src/status_im/ui/screens/browser/views.cljs b/src/status_im/ui/screens/browser/views.cljs index 7e8fb58e92..ca073dd944 100644 --- a/src/status_im/ui/screens/browser/views.cljs +++ b/src/status_im/ui/screens/browser/views.cljs @@ -21,7 +21,7 @@ [status-im.ui.screens.browser.site-blocked.views :as site-blocked.views] [status-im.ui.screens.browser.styles :as styles] [status-im.ui.screens.wallet.components.views :as components] - [status-im.utils.http :as http] + [utils.url :as url] [status-im.utils.js-resources :as js-res] [utils.debounce :as debounce]) (:require-macros [status-im.utils.views :as views])) @@ -52,7 +52,7 @@ [react/touchable-highlight {:style styles/url-text-container :on-press #(re-frame/dispatch [:browser.ui/url-input-pressed])} - [react/text {:number-of-lines 1} (http/url-host url-original)]]) + [react/text {:number-of-lines 1} (url/url-host url-original)]]) (when-not unsafe? [react/touchable-highlight {:on-press #(.reload ^js @webview-ref/webview-ref) @@ -192,7 +192,7 @@ {:flex 1 :elevation -10} [react/view {:flex 1} - (if (and unsafe? (not= (http/url-host url) ignore-unsafe)) + (if (and unsafe? (not= (url/url-host url) ignore-unsafe)) [site-blocked.views/view {:can-go-back? can-go-back? :site browser-id}] diff --git a/src/status_im/utils/http.cljs b/src/status_im/utils/http.cljs deleted file mode 100644 index 8ceda7637e..0000000000 --- a/src/status_im/utils/http.cljs +++ /dev/null @@ -1,196 +0,0 @@ -(ns status-im.utils.http - (:require ["react-native-fetch-polyfill" :default fetch] - [clojure.string :as string] - [status-im.utils.utils :as utils] - [taoensso.timbre :as log]) - (:refer-clojure :exclude [get])) - -;; Default HTTP request timeout ms -(def http-request-default-timeout-ms 3000) - -(defn- response-headers - [^js response] - (let [entries (es6-iterator-seq (.entries ^js (.-headers response)))] - (reduce #(assoc %1 (string/trim (string/lower-case (first %2))) (string/trim (second %2))) - {} - entries))) - -(defn raw-post - "Performs an HTTP POST request and returns raw results :status :headers :body." - ([url body on-success] (raw-post url body on-success nil)) - ([url body on-success on-error] - (raw-post url body on-success on-error nil)) - ([url body on-success on-error {:keys [timeout-ms headers]}] - (-> (fetch - url - (clj->js {:method "POST" - :headers (merge {"Cache-Control" "no-cache"} headers) - :body body - :timeout (or timeout-ms http-request-default-timeout-ms)})) - (.then (fn [^js response] - (-> - (.text response) - (.then (fn [body] - (on-success {:status (.-status response) - :headers (response-headers response) - :body body})))))) - (.catch (or on-error - (fn [error] - (utils/show-popup "Error" url (str error)))))))) - -;; FIXME: Should be more extensible and accept multiple methods -(defn post - "Performs an HTTP POST request" - ([url data on-success] - (post url data on-success nil)) - ([url data on-success on-error] - (post url data on-success on-error nil)) - ([url data on-success on-error - {:keys [valid-response? method timeout-ms headers] - :or {method "POST"}}] - (-> (fetch - url - (clj->js (merge {:method method - :body data - :timeout (or timeout-ms http-request-default-timeout-ms)} - (when headers - {:headers headers})))) - (.then (fn [^js response] - (-> (.text response) - (.then (fn [response-body] - (let [ok? (.-ok response) - ok?' (if valid-response? - (and ok? (valid-response? response)) - ok?)] - {:response-body response-body - :ok? ok?' - :status-text (.-statusText response) - :status-code (.-status response)})))))) - (.then (fn [{:keys [ok?] :as data}] - (cond - (and on-success ok?) - (on-success data) - - (and on-error (not ok?)) - (on-error data) - - :else false))) - (.catch (fn [error] - (if on-error - (on-error {:response-body error}) - (utils/show-popup "Error" url (str error)))))))) - -(defn get - "Performs an HTTP GET request" - ([url] (get url nil)) - ([url on-success] (get url on-success nil)) - ([url on-success on-error] - (get url on-success on-error nil)) - ([url on-success on-error params] - (get url on-success on-error params nil)) - ([url on-success on-error {:keys [valid-response? timeout-ms]} headers] - (-> (fetch - url - (clj->js {:method "GET" - :headers (merge {"Cache-Control" "no-cache"} headers) - :timeout (or timeout-ms http-request-default-timeout-ms)})) - (.then (fn [^js response] - (-> - (.text response) - (.then (fn [response-body] - (let [ok? (.-ok response) - ok?' (if valid-response? - (and ok? (valid-response? response)) - ok?)] - [response-body ok?'])))))) - (.then (fn [[response ok?]] - (cond - (and on-success ok?) - (on-success response) - - (and on-error (not ok?)) - (on-error response) - - :else false))) - (.catch (or on-error #()))))) - -(defn normalize-url - [url] - (str (when (and (string? url) - (not (re-find #"^[a-zA-Z-_]+:/" url))) - "https://") - ((fnil string/trim "") url))) - -(def normalize-and-decode-url (comp js/decodeURI normalize-url)) - -(defn url-host - [url] - (try - (when-let [host (.getDomain ^js (goog.Uri. url))] - (when-not (string/blank? host) - (string/replace host #"www." ""))) - (catch :default _ nil))) - -(defn url? - [s] - (try - (when-let [host (.getDomain ^js (goog.Uri. s))] - (not (string/blank? host))) - (catch :default _ nil))) - -(defn parse-payload - [o] - (when o - (try - (js->clj (js/JSON.parse o) - :keywordize-keys - true) - (catch :default _ - (log/debug (str "Failed to parse " o)))))) - -(defn url-sanitized? - [uri] - (not (nil? (re-find #"^(https:)([/|.|\w|\s|-])*\.(?:jpg|svg|png)$" uri)))) - -(defn- split-param - [param] - (-> - (string/split param #"=") - (concat (repeat "")) - (->> - (take 2)))) - -(defn- url-decode - [string] - (some-> string - str - (string/replace #"\+" "%20") - (js/decodeURIComponent))) - -(defn query->map - [qstr] - (when-not (string/blank? qstr) - (some->> (string/split qstr #"&") - seq - (mapcat split-param) - (map url-decode) - (apply hash-map)))) - -(defn filter-letters-numbers-and-replace-dot-on-dash - [^js value] - (let [cc (.charCodeAt value 0)] - (cond (or (and (> cc 96) (< cc 123)) - (and (> cc 64) (< cc 91)) - (and (> cc 47) (< cc 58))) - value - (= cc 46) - "-"))) - -(defn topic-from-url - [url] - (string/lower-case (apply str (map filter-letters-numbers-and-replace-dot-on-dash (url-host url))))) - -(defn replace-port - [url new-port] - (when url - (string/replace url #"(:\d+)" (str ":" new-port)))) diff --git a/src/status_im/wallet/choose_recipient/core.cljs b/src/status_im/wallet/choose_recipient/core.cljs index 593cb464c3..e7e1abf35e 100644 --- a/src/status_im/wallet/choose_recipient/core.cljs +++ b/src/status_im/wallet/choose_recipient/core.cljs @@ -9,7 +9,7 @@ [status-im.qr-scanner.core :as qr-scaner] [status-im.router.core :as router] [utils.re-frame :as rf] - [status-im.utils.http :as http] + [utils.url :as url] [utils.money :as money] [status-im.utils.universal-links.utils :as links] [status-im.utils.wallet-connect :as wallet-connect] @@ -140,7 +140,7 @@ (assoc-in message path address)) message (map vector paths addresses)) uri]))}}) - (if (and (http/url? uri) (not ignore-url)) + (if (and (url/url? uri) (not ignore-url)) (if (links/universal-link? uri) {:dispatch [:universal-links/handle-url uri]} {:browser/show-browser-selection uri}) diff --git a/src/status_im2/contexts/chat/lightbox/top_view.cljs b/src/status_im2/contexts/chat/lightbox/top_view.cljs index 4561f0b82d..6aff855056 100644 --- a/src/status_im2/contexts/chat/lightbox/top_view.cljs +++ b/src/status_im2/contexts/chat/lightbox/top_view.cljs @@ -6,7 +6,7 @@ [react-native.orientation :as orientation] [react-native.platform :as platform] [react-native.reanimated :as reanimated] - [status-im.utils.http :as http] + [utils.url :as url] [status-im2.contexts.chat.lightbox.animations :as anim] [status-im2.contexts.chat.lightbox.style :as style] [utils.datetime :as datetime] @@ -45,8 +45,7 @@ (defn drawer [messages index] (let [{:keys [content]} (nth messages index) - uri (http/replace-port (:image content) - (rf/sub [:mediaserver/port]))] + uri (url/replace-port (:image content) (rf/sub [:mediaserver/port]))] [quo/action-drawer [[{:icon :i/save :accessibility-label :save-image @@ -65,8 +64,7 @@ (defn share-image [messages index] (let [{:keys [content]} (nth messages index) - uri (http/replace-port (:image content) - (rf/sub [:mediaserver/port]))] + uri (url/replace-port (:image content) (rf/sub [:mediaserver/port]))] (images/share-image uri))) (defn top-view diff --git a/src/status_im2/contexts/chat/lightbox/zoomable_image/view.cljs b/src/status_im2/contexts/chat/lightbox/zoomable_image/view.cljs index cc3aaa76d5..025ddd1ace 100644 --- a/src/status_im2/contexts/chat/lightbox/zoomable_image/view.cljs +++ b/src/status_im2/contexts/chat/lightbox/zoomable_image/view.cljs @@ -11,7 +11,7 @@ [status-im2.contexts.chat.lightbox.zoomable-image.constants :as c] [status-im2.contexts.chat.lightbox.zoomable-image.style :as style] [status-im2.contexts.chat.lightbox.zoomable-image.utils :as utils] - [status-im.utils.http :as http])) + [utils.url :as url])) (defn tap-gesture [on-tap] @@ -227,7 +227,7 @@ (= curr-orientation orientation/portrait))} [reanimated/fast-image (merge - {:source {:uri (http/replace-port (:image content) (rf/sub [:mediaserver/port]))} + {:source {:uri (url/replace-port (:image content) (rf/sub [:mediaserver/port]))} :native-ID (when focused? :shared-element) :style (style/image dimensions animations render-data index)} (when image-dimensions-nil? diff --git a/src/status_im2/contexts/chat/messages/content/album/view.cljs b/src/status_im2/contexts/chat/messages/content/album/view.cljs index 00e11efab3..673c3ca176 100644 --- a/src/status_im2/contexts/chat/messages/content/album/view.cljs +++ b/src/status_im2/contexts/chat/messages/content/album/view.cljs @@ -8,7 +8,7 @@ [status-im2.contexts.chat.messages.content.image.view :as image] [status-im2.contexts.chat.messages.content.text.view :as text] [utils.re-frame :as rf] - [status-im.utils.http :as http])) + [utils.url :as url])) (def rectangular-style-count 3) @@ -55,8 +55,8 @@ :index index}])} [fast-image/fast-image {:style (style/image dimensions index portrait? images-count) - :source {:uri (http/replace-port (:image (:content item)) - (rf/sub [:mediaserver/port]))} + :source {:uri (url/replace-port (:image (:content item)) + (rf/sub [:mediaserver/port]))} :native-ID (when (and (= shared-element-id (:message-id item)) (< index constants/max-album-photos)) :shared-element)}] diff --git a/src/status_im2/contexts/chat/messages/content/image/view.cljs b/src/status_im2/contexts/chat/messages/content/image/view.cljs index b9c11430ae..7a2580754a 100644 --- a/src/status_im2/contexts/chat/messages/content/image/view.cljs +++ b/src/status_im2/contexts/chat/messages/content/image/view.cljs @@ -6,7 +6,7 @@ [status-im2.constants :as constants] [utils.re-frame :as rf] [status-im2.contexts.chat.messages.content.text.view :as text] - [status-im.utils.http :as http])) + [utils.url :as url])) (defn calculate-dimensions [width height] @@ -19,7 +19,7 @@ (let [insets (safe-area/get-insets) dimensions (calculate-dimensions (or image-width 1000) (or image-height 1000)) shared-element-id (rf/sub [:shared-element-id]) - image-local-url (http/replace-port (:image content) (rf/sub [:mediaserver/port]))] + image-local-url (url/replace-port (:image content) (rf/sub [:mediaserver/port]))] [:<> (when (= index 0) [text/text-content message]) diff --git a/src/status_im2/contexts/shell/activity_center/notification/reply/view.cljs b/src/status_im2/contexts/shell/activity_center/notification/reply/view.cljs index 738f9b19b2..4c6eadad0f 100644 --- a/src/status_im2/contexts/shell/activity_center/notification/reply/view.cljs +++ b/src/status_im2/contexts/shell/activity_center/notification/reply/view.cljs @@ -10,7 +10,7 @@ [utils.datetime :as datetime] [utils.i18n :as i18n] [utils.re-frame :as rf] - [status-im.utils.http :as http])) + [utils.url :as url])) ;; NOTE: Replies support text, image and stickers only. (defn- get-message-content @@ -21,7 +21,7 @@ constants/content-type-image (let [image (get-in message [:content :image]) - image-local-url (http/replace-port image (rf/sub [:mediaserver/port])) + image-local-url (url/replace-port image (rf/sub [:mediaserver/port])) photos (when image-local-url [{:uri image-local-url}])] [quo/activity-logs-photos {:photos photos}]) diff --git a/src/utils/url.cljs b/src/utils/url.cljs new file mode 100644 index 0000000000..f4cf111e38 --- /dev/null +++ b/src/utils/url.cljs @@ -0,0 +1,59 @@ +(ns utils.url + (:require [clojure.string :as string])) + +(defn normalize-url + [url] + (str (when (and (string? url) + (not (re-find #"^[a-zA-Z-_]+:/" url))) + "https://") + ((fnil string/trim "") url))) + +(def normalize-and-decode-url (comp js/decodeURI normalize-url)) + +(defn url-host + [url] + (try + (when-let [host (.getDomain ^js (goog.Uri. url))] + (when-not (string/blank? host) + (string/replace host #"www." ""))) + (catch :default _ nil))) + +(defn url? + [s] + (try + (when-let [host (.getDomain ^js (goog.Uri. s))] + (not (string/blank? host))) + (catch :default _ nil))) + +(defn url-sanitized? + [uri] + (not (nil? (re-find #"^(https:)([/|.|\w|\s|-])*\.(?:jpg|svg|png)$" uri)))) + +(defn- split-param + [param] + (-> + (string/split param #"=") + (concat (repeat "")) + (->> + (take 2)))) + +(defn- url-decode + [string] + (some-> string + str + (string/replace #"\+" "%20") + (js/decodeURIComponent))) + +(defn query->map + [qstr] + (when-not (string/blank? qstr) + (some->> (string/split qstr #"&") + seq + (mapcat split-param) + (map url-decode) + (apply hash-map)))) + +(defn replace-port + [url new-port] + (when url + (string/replace url #"(:\d+)" (str ":" new-port)))) diff --git a/src/status_im/utils/http_test.cljs b/src/utils/url_test.cljs similarity index 70% rename from src/status_im/utils/http_test.cljs rename to src/utils/url_test.cljs index db6307fa04..1823cf7b51 100644 --- a/src/status_im/utils/http_test.cljs +++ b/src/utils/url_test.cljs @@ -1,37 +1,37 @@ -(ns status-im.utils.http-test +(ns utils.url-test (:require [cljs.test :refer-macros [deftest is testing]] - [status-im.utils.http :as http])) + [utils.url :as url])) (deftest url-sanitize-check (testing "https://storage.googleapis.com/ck-kitty-image/0x06012c8cf97bead5deae237070f9587f8e7a266d/818934.svg" (testing "it returns true" (is - (http/url-sanitized? + (url/url-sanitized? "https://storage.googleapis.com/ck-kitty-image/0x06012c8cf97bead5deae237070f9587f8e7a266d/818934.svg")))) (testing "https://www.cryptostrikers.com/assets/images/cards/017.svg" (testing "it returns true" - (is (http/url-sanitized? "https://www.cryptostrikers.com/assets/images/cards/017.svg")))) + (is (url/url-sanitized? "https://www.cryptostrikers.com/assets/images/cards/017.svg")))) (testing "https://www.etheremon.com/assets/images/mons_origin/025.png" (testing "it returns true" - (is (http/url-sanitized? "https://www.etheremon.com/assets/images/mons_origin/025.png")))) + (is (url/url-sanitized? "https://www.etheremon.com/assets/images/mons_origin/025.png")))) (testing "http://www.etheremon.com/assets/images/mons_origin/025.png" (testing "it returns false" - (is (not (http/url-sanitized? "http://www.etheremon.com/assets/images/mons_origin/025.png"))))) + (is (not (url/url-sanitized? "http://www.etheremon.com/assets/images/mons_origin/025.png"))))) (testing "xxx:x \\\\x0Aonerror=javascript:alert(1)" (testing "it returns false" - (is (not (http/url-sanitized? "xxx:x \\\\x0Aonerror=javascript:alert(1)"))))) + (is (not (url/url-sanitized? "xxx:x \\\\x0Aonerror=javascript:alert(1)"))))) (testing "https://www.etheremon.com/assets/images/mons_origin/025.png'<script>alert('123');</script>" (testing "it returns false" (is (not - (http/url-sanitized? + (url/url-sanitized? "https://www.etheremon.com/assets/images/mons_origin/025.png'<script>alert('123');</script>"))))) (testing @@ -39,7 +39,7 @@ (testing "it returns false" (is (not - (http/url-sanitized? + (url/url-sanitized? "https://www.etheremon.com/assets/images/mons'<script>alert('123');</script>origin/025.png"))))) (testing @@ -47,7 +47,7 @@ (testing "it returns false" (is (not - (http/url-sanitized? + (url/url-sanitized? "https://www.etheremon.com/assets/images/mons_origin/025.png'>"))))) (testing @@ -55,19 +55,19 @@ (testing "it returns false" (is (not - (http/url-sanitized? + (url/url-sanitized? "https://www.etheremon.com/assets/images/mons'>origin/025.png")))))) (deftest url-host-check (testing "Extract host/domain from URL" (testing "Valid URL with endpoint" - (is (= "status.im" (http/url-host "https://status.im/testing")))) + (is (= "status.im" (url/url-host "https://status.im/testing")))) (testing "Valid URL" - (is (= "status.im" (http/url-host "http://status.im")))) + (is (= "status.im" (url/url-host "http://status.im")))) (testing "Blank domainlocalhost" - (is (nil? (http/url-host "localhost:3000/testing"))))) + (is (nil? (url/url-host "localhost:3000/testing"))))) (testing "Return nil for Invalid URL" (testing "Bad scheme" - (is (nil? (http/url-host "invalid//status.im/testing")))) + (is (nil? (url/url-host "invalid//status.im/testing")))) (testing "No scheme" - (is (nil? (http/url-host "status.im/testing")))))) + (is (nil? (url/url-host "status.im/testing")))))) diff --git a/yarn.lock b/yarn.lock index 3f52262630..16842e1988 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8878,11 +8878,6 @@ react-native-fast-image@^8.5.11: resolved "https://registry.yarnpkg.com/react-native-fast-image/-/react-native-fast-image-8.5.11.tgz#e3dc969d0e4e8df026646bf18194465aa55cbc2b" integrity sha512-cNW4bIJg3nvKaheG8vGMfqCt5LMWX9MS5+wMudgKIHbGO51spRr4sgnlhVgwHLcZ5aeNOVJ8CPRxDIWKRq/0QA== -react-native-fetch-polyfill@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/react-native-fetch-polyfill/-/react-native-fetch-polyfill-1.1.3.tgz#a02d9069a2f7108ca0b70b8469085c67cc02949c" - integrity sha512-zr5yXQftuGq+ABGa3n4ZE+vkL1lBsMSePkRINm3/6vlpbwnLXYoijwazTO/W8GjsV4LAgGmzuieZxKO/NxW19A== - react-native-fs@^2.14.1: version "2.16.6" resolved "https://registry.yarnpkg.com/react-native-fs/-/react-native-fs-2.16.6.tgz#2901789a43210a35a0ef0a098019bbef3af395fd"