[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[tor-commits] [Git][tpo/applications/tor-browser][tor-browser-115.10.0esr-13.5-1] 4 commits: fixup! Bug 40701: Add security warning when downloading a file



Title: GitLab

richard pushed to branch tor-browser-115.10.0esr-13.5-1 at The Tor Project / Applications / Tor Browser

Commits:

  • 49db61d8
    by Henry Wilkes at 2024-04-15T18:16:31+00:00
    fixup! Bug 40701: Add security warning when downloading a file
    
    Bug 42221: Migrate downloads warning strings to Fluent.
    
  • 93684ca3
    by Henry Wilkes at 2024-04-15T18:16:31+00:00
    fixup! Tor Browser strings
    
    Bug 42221: Migrate downloads warning strings to Fluent.
    
  • 4e772ce6
    by Henry Wilkes at 2024-04-15T18:16:31+00:00
    fixup! Add TorStrings module for localization
    
    Bug 42221: Migrate downloads warning strings to Fluent.
    
  • e7445294
    by Henry Wilkes at 2024-04-15T18:16:31+00:00
    fixup! Tor Browser localization migration scripts.
    
    Bug 42221: Migrate downloads warning strings to Fluent.
    

9 changed files:

Changes:

  • browser/components/downloads/content/contentAreaDownloadsView.js
    ... ... @@ -62,53 +62,6 @@ var ContentAreaDownloadsView = {
    62 62
         if (!PrivateBrowsingUtils.isContentWindowPrivate(window)) {
    
    63 63
           view.place = "place:transition=7&sort=4";
    
    64 64
         }
    
    65
    -
    
    66
    -    torWarningMessage.querySelector(
    
    67
    -      ".downloads-tor-warning-title"
    
    68
    -    ).textContent = this._getTorString("torbutton.download.warning.title");
    
    69
    -
    
    70
    -    const tailsLink = document.createElement("a");
    
    71
    -    tailsLink.href = "https://tails.net/";
    
    72
    -    tailsLink.target = "_blank";
    
    73
    -    tailsLink.textContent = this._getTorString(
    
    74
    -      "torbutton.download.warning.tails_brand_name"
    
    75
    -    );
    
    76
    -
    
    77
    -    const [beforeLink, afterLink] = this._getTorString(
    
    78
    -      "torbutton.download.warning.description"
    
    79
    -    ).split("%S");
    
    80
    -
    
    81
    -    torWarningMessage
    
    82
    -      .querySelector(".downloads-tor-warning-description")
    
    83
    -      .append(beforeLink, tailsLink, afterLink);
    
    84
    -
    
    85
    -    torWarningMessage.querySelector(
    
    86
    -      ".downloads-tor-warning-dismiss-button"
    
    87
    -    ).textContent = this._getTorString("torbutton.download.warning.dismiss");
    
    88
    -  },
    
    89
    -
    
    90
    -  /**
    
    91
    -   * Get a string from the properties bundle.
    
    92
    -   *
    
    93
    -   * @param {string} name - The string name.
    
    94
    -   *
    
    95
    -   * @return {string} The string.
    
    96
    -   */
    
    97
    -  _getTorString(name) {
    
    98
    -    if (!this._stringBundle) {
    
    99
    -      this._stringBundle = Services.strings.createBundle(
    
    100
    -        "chrome://torbutton/locale/torbutton.properties"
    
    101
    -      );
    
    102
    -    }
    
    103
    -    try {
    
    104
    -      return this._stringBundle.GetStringFromName(name);
    
    105
    -    } catch {}
    
    106
    -    if (!this._fallbackStringBundle) {
    
    107
    -      this._fallbackStringBundle = Services.strings.createBundle(
    
    108
    -        "resource://torbutton/locale/en-US/torbutton.properties"
    
    109
    -      );
    
    110
    -    }
    
    111
    -    return this._fallbackStringBundle.GetStringFromName(name);
    
    112 65
       },
    
    113 66
     };
    
    114 67
     
    

  • browser/components/downloads/content/contentAreaDownloadsView.xhtml
    ... ... @@ -21,6 +21,7 @@
    21 21
       <linkset>
    
    22 22
         <html:link rel="localization" href="">"toolkit/global/textActions.ftl"/>
    
    23 23
         <html:link rel="localization" href="">"browser/downloads.ftl" />
    
    24
    +    <html:link rel="localization" href="">"browser/tor-browser.ftl" />
    
    24 25
       </linkset>
    
    25 26
     
    
    26 27
       <script src="">"chrome://global/content/globalOverlay.js"/>
    
    ... ... @@ -36,20 +37,34 @@
    36 37
       </keyset>
    
    37 38
     #endif
    
    38 39
     
    
    39
    -  <html:message-bar id="aboutDownloadsTorWarning"
    
    40
    -                    class="downloads-tor-warning-message-bar"
    
    41
    -                    role="alert"
    
    42
    -                    aria-labelledby="aboutDownloadsTorWarningTitle"
    
    43
    -                    aria-describedby="aboutDownloadsTorWarningDescription">
    
    40
    +  <html:message-bar
    
    41
    +    id="aboutDownloadsTorWarning"
    
    42
    +    class="downloads-tor-warning-message-bar"
    
    43
    +    role="alert"
    
    44
    +    aria-labelledby="aboutDownloadsTorWarningTitle"
    
    45
    +    aria-describedby="aboutDownloadsTorWarningDescription"
    
    46
    +  >
    
    44 47
         <html:div class="downloads-tor-warning-grid">
    
    45
    -      <html:p id="aboutDownloadsTorWarningTitle"
    
    46
    -              class="downloads-tor-warning-title">
    
    48
    +      <html:p
    
    49
    +        id="aboutDownloadsTorWarningTitle"
    
    50
    +        class="downloads-tor-warning-title"
    
    51
    +        data-l10n-id="downloads-tor-warning-title"
    
    52
    +      ></html:p>
    
    53
    +      <html:p
    
    54
    +        id="aboutDownloadsTorWarningDescription"
    
    55
    +        class="downloads-tor-warning-description"
    
    56
    +        data-l10n-id="downloads-tor-warning-description"
    
    57
    +      >
    
    58
    +        <html:a
    
    59
    +          href="https://tails.net/"
    
    60
    +          target="_blank"
    
    61
    +          data-l10n-name="tails-link"
    
    62
    +        ></html:a>
    
    47 63
           </html:p>
    
    48
    -      <html:p id="aboutDownloadsTorWarningDescription"
    
    49
    -              class="downloads-tor-warning-description">
    
    50
    -      </html:p>
    
    51
    -      <html:button class="downloads-tor-warning-dismiss-button">
    
    52
    -      </html:button>
    
    64
    +      <html:button
    
    65
    +        class="downloads-tor-warning-dismiss-button"
    
    66
    +        data-l10n-id="downloads-tor-warning-dismiss-button"
    
    67
    +      ></html:button>
    
    53 68
         </html:div>
    
    54 69
       </html:message-bar>
    
    55 70
     
    

  • browser/components/downloads/content/downloads.js
    ... ... @@ -167,38 +167,29 @@ var DownloadsPanel = {
    167 167
         );
    
    168 168
     
    
    169 169
         if (!this._torWarningInitialized) {
    
    170
    -      torWarningMessage.querySelector(
    
    171
    -        ".downloads-tor-warning-title"
    
    172
    -      ).textContent = this._getTorString("torbutton.download.warning.title");
    
    173
    -
    
    174
    -      const tailsLink = document.createElement("a");
    
    175
    -      tailsLink.href = "https://tails.net";
    
    176
    -      tailsLink.textContent = this._getTorString(
    
    177
    -        "torbutton.download.warning.tails_brand_name"
    
    178
    -      );
    
    179
    -      tailsLink.addEventListener("click", event => {
    
    180
    -        event.preventDefault();
    
    181
    -        this.hidePanel();
    
    182
    -        openWebLinkIn(tailsLink.href, "tab");
    
    183
    -      });
    
    184
    -
    
    185
    -      const [beforeLink, afterLink] = this._getTorString(
    
    186
    -        "torbutton.download.warning.description"
    
    187
    -      ).split("%S");
    
    188
    -
    
    170
    +      // Intercept clicks on the tails link.
    
    171
    +      // NOTE: We listen for clicks on the parent instead of the
    
    172
    +      // <a data-l10n-name="tails-link"> element because the latter may be
    
    173
    +      // swapped for a new instance by Fluent when refreshing the parent.
    
    189 174
           torWarningMessage
    
    190 175
             .querySelector(".downloads-tor-warning-description")
    
    191
    -        .append(beforeLink, tailsLink, afterLink);
    
    176
    +        .addEventListener("click", event => {
    
    177
    +          const tailsLink = event.target.closest(
    
    178
    +            ".downloads-tor-warning-tails-link"
    
    179
    +          );
    
    180
    +          if (!tailsLink) {
    
    181
    +            return;
    
    182
    +          }
    
    183
    +          event.preventDefault();
    
    184
    +          this.hidePanel();
    
    185
    +          openWebLinkIn(tailsLink.href, "tab");
    
    186
    +        });
    
    192 187
     
    
    193
    -      let dismissButton = torWarningMessage.querySelector(
    
    194
    -        ".downloads-tor-warning-dismiss-button"
    
    195
    -      );
    
    196
    -      dismissButton.textContent = this._getTorString(
    
    197
    -        "torbutton.download.warning.dismiss"
    
    198
    -      );
    
    199
    -      dismissButton.addEventListener("click", event => {
    
    200
    -        Services.prefs.setBoolPref(PREF_SHOW_DOWNLOAD_WARNING, false);
    
    201
    -      });
    
    188
    +      torWarningMessage
    
    189
    +        .querySelector(".downloads-tor-warning-dismiss-button")
    
    190
    +        .addEventListener("click", event => {
    
    191
    +          Services.prefs.setBoolPref(PREF_SHOW_DOWNLOAD_WARNING, false);
    
    192
    +        });
    
    202 193
           this._torWarningInitialized = true;
    
    203 194
         }
    
    204 195
     
    
    ... ... @@ -725,30 +716,6 @@ var DownloadsPanel = {
    725 716
           }
    
    726 717
         }, 0);
    
    727 718
       },
    
    728
    -
    
    729
    -  /**
    
    730
    -   * Get a string from the properties bundle.
    
    731
    -   *
    
    732
    -   * @param {string} name - The string name.
    
    733
    -   *
    
    734
    -   * @return {string} The string.
    
    735
    -   */
    
    736
    -  _getTorString(name) {
    
    737
    -    if (!this._stringBundle) {
    
    738
    -      this._stringBundle = Services.strings.createBundle(
    
    739
    -        "chrome://torbutton/locale/torbutton.properties"
    
    740
    -      );
    
    741
    -    }
    
    742
    -    try {
    
    743
    -      return this._stringBundle.GetStringFromName(name);
    
    744
    -    } catch {}
    
    745
    -    if (!this._fallbackStringBundle) {
    
    746
    -      this._fallbackStringBundle = Services.strings.createBundle(
    
    747
    -        "resource://torbutton/locale/en-US/torbutton.properties"
    
    748
    -      );
    
    749
    -    }
    
    750
    -    return this._fallbackStringBundle.GetStringFromName(name);
    
    751
    -  },
    
    752 719
     };
    
    753 720
     
    
    754 721
     XPCOMUtils.defineConstant(this, "DownloadsPanel", DownloadsPanel);
    

  • browser/components/downloads/content/downloadsPanel.inc.xhtml
    ... ... @@ -125,19 +125,32 @@
    125 125
     
    
    126 126
         <panelview id="downloadsPanel-mainView">
    
    127 127
           <vbox id="downloadsPanelTorWarning">
    
    128
    -        <vbox role="alert"
    
    129
    -              aria-labelledby="downloadsPanelTorWarningTitle"
    
    130
    -              aria-describedby="downloadsPanelTorWarningDescription">
    
    131
    -          <html:p id="downloadsPanelTorWarningTitle"
    
    132
    -                  class="downloads-tor-warning-title">
    
    128
    +        <vbox
    
    129
    +          role="alert"
    
    130
    +          aria-labelledby="downloadsPanelTorWarningTitle"
    
    131
    +          aria-describedby="downloadsPanelTorWarningDescription"
    
    132
    +        >
    
    133
    +          <html:p
    
    134
    +            id="downloadsPanelTorWarningTitle"
    
    135
    +            class="downloads-tor-warning-title"
    
    136
    +            data-l10n-id="downloads-tor-warning-title"
    
    137
    +          ></html:p>
    
    138
    +          <html:p
    
    139
    +            id="downloadsPanelTorWarningDescription"
    
    140
    +            class="downloads-tor-warning-description"
    
    141
    +            data-l10n-id="downloads-tor-warning-description"
    
    142
    +          >
    
    143
    +            <html:a
    
    144
    +              href="">"https://tails.net/"
    
    145
    +              data-l10n-name="tails-link"
    
    146
    +              class="downloads-tor-warning-tails-link"
    
    147
    +            ></html:a>
    
    133 148
               </html:p>
    
    134
    -          <html:p id="downloadsPanelTorWarningDescription"
    
    135
    -                  class="downloads-tor-warning-description">
    
    136
    -          </html:p>
    
    137
    -
    
    138 149
               <html:div class="panel-footer">
    
    139
    -            <html:button class="downloads-tor-warning-dismiss-button">
    
    140
    -            </html:button>
    
    150
    +            <html:button
    
    151
    +              class="downloads-tor-warning-dismiss-button"
    
    152
    +              data-l10n-id="downloads-tor-warning-dismiss-button"
    
    153
    +            ></html:button>
    
    141 154
               </html:div>
    
    142 155
             </vbox>
    
    143 156
             <toolbarseparator />
    

  • browser/components/places/content/places.js
    ... ... @@ -176,32 +176,22 @@ var PlacesOrganizer = {
    176 176
           }
    
    177 177
         );
    
    178 178
     
    
    179
    -    // Initialize tor warning text content.
    
    180
    -    torWarningMessage.querySelector(
    
    181
    -      ".downloads-tor-warning-title"
    
    182
    -    ).textContent = this._getTorString("torbutton.download.warning.title");
    
    183
    -
    
    184
    -    const tailsLink = document.createElement("a");
    
    185
    -    tailsLink.href = "https://tails.net/";
    
    186
    -    tailsLink.textContent = this._getTorString(
    
    187
    -      "torbutton.download.warning.tails_brand_name"
    
    188
    -    );
    
    189
    -    tailsLink.addEventListener("click", event => {
    
    190
    -      event.preventDefault();
    
    191
    -      openWebLinkIn(tailsLink.href, "tab");
    
    192
    -    });
    
    193
    -
    
    194
    -    const [beforeLink, afterLink] = this._getTorString(
    
    195
    -      "torbutton.download.warning.description"
    
    196
    -    ).split("%S");
    
    197
    -
    
    198
    -    torWarningMessage
    
    179
    +    // Intercept clicks on the tor warning tails link.
    
    180
    +    // NOTE: We listen for clicks on the parent instead of the
    
    181
    +    // <a data-l10n-name="tails-link"> element because the latter may be
    
    182
    +    // swapped for a new instance by Fluent when refreshing the parent.
    
    183
    +    document
    
    199 184
           .querySelector(".downloads-tor-warning-description")
    
    200
    -      .append(beforeLink, tailsLink, afterLink);
    
    201
    -
    
    202
    -    torWarningMessage.querySelector(
    
    203
    -      ".downloads-tor-warning-dismiss-button"
    
    204
    -    ).textContent = this._getTorString("torbutton.download.warning.dismiss");
    
    185
    +      .addEventListener("click", event => {
    
    186
    +        const tailsLink = event.target.closest(
    
    187
    +          ".downloads-tor-warning-tails-link"
    
    188
    +        );
    
    189
    +        if (!tailsLink) {
    
    190
    +          return;
    
    191
    +        }
    
    192
    +        event.preventDefault();
    
    193
    +        openWebLinkIn(tailsLink.href, "tab");
    
    194
    +      });
    
    205 195
     
    
    206 196
         ContentArea.init();
    
    207 197
     
    
    ... ... @@ -274,30 +264,6 @@ var PlacesOrganizer = {
    274 264
         ContentArea.focus();
    
    275 265
       },
    
    276 266
     
    
    277
    -  /**
    
    278
    -   * Get a string from the properties bundle.
    
    279
    -   *
    
    280
    -   * @param {string} name - The string name.
    
    281
    -   *
    
    282
    -   * @returns {string} The string.
    
    283
    -   */
    
    284
    -  _getTorString(name) {
    
    285
    -    if (!this._stringBundle) {
    
    286
    -      this._stringBundle = Services.strings.createBundle(
    
    287
    -        "chrome://torbutton/locale/torbutton.properties"
    
    288
    -      );
    
    289
    -    }
    
    290
    -    try {
    
    291
    -      return this._stringBundle.GetStringFromName(name);
    
    292
    -    } catch {}
    
    293
    -    if (!this._fallbackStringBundle) {
    
    294
    -      this._fallbackStringBundle = Services.strings.createBundle(
    
    295
    -        "resource://torbutton/locale/en-US/torbutton.properties"
    
    296
    -      );
    
    297
    -    }
    
    298
    -    return this._fallbackStringBundle.GetStringFromName(name);
    
    299
    -  },
    
    300
    -
    
    301 267
       QueryInterface: ChromeUtils.generateQI([]),
    
    302 268
     
    
    303 269
       handleEvent: function PO_handleEvent(aEvent) {
    

  • browser/components/places/content/places.xhtml
    ... ... @@ -40,6 +40,7 @@
    40 40
         <html:link rel="localization" href="">"browser/places.ftl"/>
    
    41 41
         <html:link rel="localization" href="">"browser/downloads.ftl"/>
    
    42 42
         <html:link rel="localization" href="">"browser/editBookmarkOverlay.ftl"/>
    
    43
    +    <html:link rel="localization" href="">"browser/tor-browser.ftl"/>
    
    43 44
       </linkset>
    
    44 45
     
    
    45 46
       <script src="">"chrome://browser/content/places/places.js"/>
    
    ... ... @@ -338,19 +339,33 @@
    338 339
         </tree>
    
    339 340
         <splitter collapse="none" persist="state"></splitter>
    
    340 341
         <vbox id="contentView">
    
    341
    -      <html:message-bar id="placesDownloadsTorWarning"
    
    342
    -                        role="alert"
    
    343
    -                        aria-labelledby="placesDownloadsTorWarningTitle"
    
    344
    -                        aria-describedby="placesDownloadsTorWarningDescription">
    
    342
    +      <html:message-bar
    
    343
    +        id="placesDownloadsTorWarning"
    
    344
    +        role="alert"
    
    345
    +        aria-labelledby="placesDownloadsTorWarningTitle"
    
    346
    +        aria-describedby="placesDownloadsTorWarningDescription"
    
    347
    +      >
    
    345 348
             <html:div class="downloads-tor-warning-grid">
    
    346
    -          <html:p id="placesDownloadsTorWarningTitle"
    
    347
    -                  class="downloads-tor-warning-title">
    
    349
    +          <html:p
    
    350
    +            id="placesDownloadsTorWarningTitle"
    
    351
    +            class="downloads-tor-warning-title"
    
    352
    +            data-l10n-id="downloads-tor-warning-title"
    
    353
    +          ></html:p>
    
    354
    +          <html:p
    
    355
    +            id="placesDownloadsTorWarningDescription"
    
    356
    +            class="downloads-tor-warning-description"
    
    357
    +            data-l10n-id="downloads-tor-warning-description"
    
    358
    +          >
    
    359
    +            <html:a
    
    360
    +              href="https://tails.net/"
    
    361
    +              class="downloads-tor-warning-tails-link"
    
    362
    +              data-l10n-name="tails-link"
    
    363
    +            ></html:a>
    
    348 364
               </html:p>
    
    349
    -          <html:p id="placesDownloadsTorWarningDescription"
    
    350
    -                  class="downloads-tor-warning-description">
    
    351
    -          </html:p>
    
    352
    -          <html:button class="downloads-tor-warning-dismiss-button">
    
    353
    -          </html:button>
    
    365
    +          <html:button
    
    366
    +            class="downloads-tor-warning-dismiss-button"
    
    367
    +            data-l10n-id="downloads-tor-warning-dismiss-button"
    
    368
    +          ></html:button>
    
    354 369
             </html:div>
    
    355 370
           </html:message-bar>
    
    356 371
           <vbox id="placesViewsBox" flex="1">
    

  • browser/locales/en-US/browser/tor-browser.ftl
    ... ... @@ -548,3 +548,12 @@ crypto-safety-prompt-title = Cryptocurrency address copied from an insecure webs
    548 548
     crypto-safety-prompt-body = The copied text ({ $address }) appears to be a cryptocurrency address. Since the connection to { $host } is not secure, the address may have been modified and should not be trusted. You can try establishing a secure connection by reconnecting with a new circuit.
    
    549 549
     crypto-safety-prompt-reload-button = Reload Tab with a New Circuit
    
    550 550
     crypto-safety-prompt-dismiss-button = Dismiss Warning
    
    551
    +
    
    552
    +## Downloads warning.
    
    553
    +## Shown in downloads panel, about:downloads and Library window.
    
    554
    +
    
    555
    +downloads-tor-warning-title = Be careful opening downloads
    
    556
    +# "Tails" is the brand name for the Tails operating system and should be localized appropriately, and will be a link to its website. The name should be wrapped in '<a data-l10n-name="tails-link">' and '</a>'.
    
    557
    +downloads-tor-warning-description = Some files may connect to the internet when opened without using Tor. To be safe, open the files while offline or use a portable operating system like <a data-l10n-name="tails-link">Tails</a>.
    
    558
    +# Button to dismiss the warning forever.
    
    559
    +downloads-tor-warning-dismiss-button = Got it

  • toolkit/torbutton/chrome/locale/en-US/torbutton.properties
    ... ... @@ -3,14 +3,6 @@
    3 3
     # License, v. 2.0. If a copy of the MPL was not distributed with this
    
    4 4
     # file, You can obtain one at http://mozilla.org/MPL/2.0/.
    
    5 5
     
    
    6
    -# Download pane warning
    
    7
    -torbutton.download.warning.title = Be careful opening downloads
    
    8
    -# %S will be a link to the Tails operating system website. With the content given by torbutton.download.warning.tails_brand_name
    
    9
    -torbutton.download.warning.description = Some files may connect to the internet when opened without using Tor. To be safe, open the files while offline or use a portable operating system like %S.
    
    10
    -# Locale name for Tails operating system.
    
    11
    -torbutton.download.warning.tails_brand_name = Tails
    
    12
    -torbutton.download.warning.dismiss = Got it
    
    13
    -
    
    14 6
     # .Onion Page Info prompt.
    
    15 7
     pageInfo_OnionEncryptionWithBitsAndProtocol=Connection Encrypted (Onion Service, %1$S, %2$S bit keys, %3$S)
    
    16 8
     pageInfo_OnionEncryption=Connection Encrypted (Onion Service)
    

  • tools/torbrowser/l10n/migrations/bug-42210-download-warning.py
    1
    +import fluent.syntax.ast as FTL
    
    2
    +from fluent.migrate.helpers import transforms_from
    
    3
    +from fluent.migrate.transforms import CONCAT, COPY, REPLACE
    
    4
    +
    
    5
    +
    
    6
    +def migrate(ctx):
    
    7
    +    legacy_path = "torbutton.properties"
    
    8
    +
    
    9
    +    ctx.add_transforms(
    
    10
    +        "tor-browser.ftl",
    
    11
    +        "tor-browser.ftl",
    
    12
    +        transforms_from(
    
    13
    +            """
    
    14
    +downloads-tor-warning-title = { COPY(path, "torbutton.download.warning.title") }
    
    15
    +downloads-tor-warning-dismiss-button = { COPY(path, "torbutton.download.warning.dismiss") }
    
    16
    +""",
    
    17
    +            path=legacy_path,
    
    18
    +        )
    
    19
    +        + [
    
    20
    +            # Replace "%S" with link to Tails website.
    
    21
    +            FTL.Message(
    
    22
    +                id=FTL.Identifier("downloads-tor-warning-description"),
    
    23
    +                value=REPLACE(
    
    24
    +                    legacy_path,
    
    25
    +                    "torbutton.download.warning.description",
    
    26
    +                    {
    
    27
    +                        "%1$S": CONCAT(
    
    28
    +                            FTL.TextElement('<a data-l10n-name="tails-link">'),
    
    29
    +                            COPY(
    
    30
    +                                legacy_path,
    
    31
    +                                "torbutton.download.warning.tails_brand_name",
    
    32
    +                            ),
    
    33
    +                            FTL.TextElement("</a>"),
    
    34
    +                        )
    
    35
    +                    },
    
    36
    +                ),
    
    37
    +            ),
    
    38
    +        ],
    
    39
    +    )

  • _______________________________________________
    tor-commits mailing list
    tor-commits@xxxxxxxxxxxxxxxxxxxx
    https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits