tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

SafeAnchor.jsx (2229B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 import { actionCreators as ac, actionTypes as at } from "common/Actions.mjs";
      6 import React from "react";
      7 
      8 export class SafeAnchor extends React.PureComponent {
      9  constructor(props) {
     10    super(props);
     11    this.onClick = this.onClick.bind(this);
     12  }
     13 
     14  onClick(event) {
     15    // Use dispatch instead of normal link click behavior to include referrer
     16    if (this.props.dispatch) {
     17      event.preventDefault();
     18      const { altKey, button, ctrlKey, metaKey, shiftKey } = event;
     19      this.props.dispatch(
     20        ac.OnlyToMain({
     21          type: at.OPEN_LINK,
     22          data: {
     23            event: { altKey, button, ctrlKey, metaKey, shiftKey },
     24            referrer:
     25              this.props.referrer || "https://getpocket.com/recommendations",
     26            // Use the anchor's url, which could have been cleaned up
     27            url: event.currentTarget.href,
     28            is_sponsored: this.props.isSponsored,
     29          },
     30        })
     31      );
     32    }
     33 
     34    // Propagate event if there's a handler
     35    if (this.props.onLinkClick) {
     36      this.props.onLinkClick(event);
     37    }
     38  }
     39 
     40  safeURI(url) {
     41    let protocol = null;
     42    try {
     43      protocol = new URL(url).protocol;
     44    } catch (e) {
     45      return "";
     46    }
     47 
     48    const isAllowed = ["http:", "https:"].includes(protocol);
     49    if (!isAllowed) {
     50      console.warn(`${url} is not allowed for anchor targets.`); // eslint-disable-line no-console
     51      return "";
     52    }
     53    return url;
     54  }
     55 
     56  render() {
     57    const { url, className, title, isSponsored, onFocus } = this.props;
     58 
     59    let anchor = (
     60      <a
     61        href={this.safeURI(url)}
     62        title={title}
     63        className={className}
     64        onClick={this.onClick}
     65        data-is-sponsored-link={!!isSponsored}
     66        {...(this.props.tabIndex === 0 || this.props.tabIndex
     67          ? {
     68              ref: this.props.setRef,
     69              tabIndex: this.props.tabIndex,
     70            }
     71          : {})}
     72        {...(onFocus ? { onFocus } : {})}
     73      >
     74        {this.props.children}
     75      </a>
     76    );
     77 
     78    return anchor;
     79  }
     80 }