parent
a15c9788fe
commit
6a169bd0bd
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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,7 +247,7 @@
|
|||
(not= (.indexOf ^js url (second v)) -1))
|
||||
(:resolved-ens options)))
|
||||
resolved-url (if resolved-ens
|
||||
(http/normalize-url (string/replace url
|
||||
(url/normalize-url (string/replace url
|
||||
(second resolved-ens)
|
||||
(first resolved-ens)))
|
||||
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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))))
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)}))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}]
|
||||
|
|
|
@ -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))))
|
|
@ -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})
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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,7 +55,7 @@
|
|||
:index index}])}
|
||||
[fast-image/fast-image
|
||||
{:style (style/image dimensions index portrait? images-count)
|
||||
:source {:uri (http/replace-port (:image (:content item))
|
||||
: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))
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -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}])
|
||||
|
||||
|
|
|
@ -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))))
|
|
@ -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'><script>\\\\x3Bjavascript:alert(1)</script>")))))
|
||||
|
||||
(testing
|
||||
|
@ -55,19 +55,19 @@
|
|||
(testing "it returns false"
|
||||
(is
|
||||
(not
|
||||
(http/url-sanitized?
|
||||
(url/url-sanitized?
|
||||
"https://www.etheremon.com/assets/images/mons'><script>\\\\x3Bjavascript:alert(1)</script>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"))))))
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue