Repository: mozilla/pdf.js
File: src/display/display_utils.js (JavaScript)

Code before:
/**
 * Gets the filename from a given URL.
 * @param {string} url
 * @returns {string}
 */
function getFilenameFromUrl(url) {
  [url] = url.split(/[#?]/, 1);
  return url.substring(url.lastIndexOf("/") + 1);
}

/**
 * Returns the filename or guessed filename from the url (see issue 3455).
 * @param {string} url - The original PDF location.
 * @param {string} defaultFilename - The value returned if the filename is
 *   unknown, or the protocol is unsupported.
 * @returns {string} Guessed PDF filename.
 */
function getPdfFilenameFromUrl(url, defaultFilename = "document.pdf") {
  if (typeof url !== "string") {
    return defaultFilename;
  }
  if (isDataScheme(url)) {
    warn('getPdfFilenameFromUrl: ignore "data:"-URL for performance reasons.');
    return defaultFilename;
  }
  const reURI = /^(([^:]+:)?\/\/[^/]+)?([^?#]*)(\?[^#]*)?(#.*)?$/;
  //              SCHEME       HOST        1.PATH  2.QUERY   3.REF
  // Pattern to get last matching NAME.pdf
  const reFilename = /[^/?#=]+\.pdf\b(?!.*\.pdf\b)/i;
  let splitURI = reURI.exec(url);
  let suggestedFilename =
    reFilename.exec(splitURI[3]) ||
    reFilename.exec(splitURI[4]) ||
    reFilename.exec(splitURI[5]);
  if (suggestedFilename) {
    suggestedFilename = suggestedFilename[0];
    if (suggestedFilename.includes("%")) {
      // URL-encoded %2Fpath%2Fto%2Ffile.pdf should be file.pdf
      try {
        const decodedFilename = decodeURIComponent(suggestedFilename);
        splitURI = reURI.exec(decodedFilename);
        if (splitURI[1]) {
          // The decoded filename has a scheme.
          return getPdfFilenameFromUrl(decodedFilename, defaultFilename);
        }
        const fixedPath = suggestedFilename.replaceAll("%2F", "/");
        if (reFilename.test(fixedPath)) {
          suggestedFilename = decodeURIComponent(reFilename.exec(fixedPath));
        }
      } catch {
        // URIError "Malformed URI", e.g. for "%AA.pdf"

Review comment (bug):
Would it be possible to use `new URL(...)` to parse the URL, rather than a regexp? URL parsing is incredibly complex and has a lot of edge cases.

Code after:
/**
 * Gets the filename from a given URL.
 * @param {string} url
 * @returns {string}
 */
function getFilenameFromUrl(url) {
  [url] = url.split(/[#?]/, 1);
  return url.substring(url.lastIndexOf("/") + 1);
}

/**
 * Returns the filename or guessed filename from the url (see issue 3455).
 * @param {string} url - The original PDF location.
 * @param {string} defaultFilename - The value returned if the filename is
 *   unknown, or the protocol is unsupported.
 * @returns {string} Guessed PDF filename.
 */
function getPdfFilenameFromUrl(url, defaultFilename = "document.pdf") {
  if (typeof url !== "string") {
    return defaultFilename;
  }
  if (isDataScheme(url)) {
    warn('getPdfFilenameFromUrl: ignore "data:"-URL for performance reasons.');
    return defaultFilename;
  }

  const getURL = urlString => {
    try {
      return new URL(urlString);
    } catch {
      try {
        return new URL(decodeURIComponent(urlString));
      } catch {
        try {
          // Attempt to parse the URL using the document's base URI.
          return new URL(urlString, "https://foo.bar");
        } catch {
          try {
            return new URL(decodeURIComponent(urlString), "https://foo.bar");
          } catch {
            return null;
          }
        }
      }
    }
  };

  const newURL = getURL(url);
  if (!newURL) {
    // If the URL is invalid, return the default filename.
    return defaultFilename;