Files
Jihad-Browser/app/source/CertificateDetail.js
T
NotAlexNoyleandClaude Fable 5.1 62df604c54 Licensing audit: notices for everything bundled, no borrowed marks
The owner: "ensure that all software patent and trademark licenses in
the repo are being respected". A read-only audit of what the packages
carry found no blocker and these gaps, all closed here (the record is
impl-review-findings-6.md, "Licensing audit"):

- NOTICE names the runtime the engine ships with: glibc 2.23 as
  crosstool-NG modifies it (LGPL-2.1), the GCC 9.4.0 runtime (GPL-3.0
  with the Runtime Library Exception), and the eight Debian jessie
  libraries, with the FreeType disclaimer, Lato, the hyphenation
  patterns, and where the corresponding source is. licenses/ gains
  LGPL-2.1, GPL-3.0 and the GCC exception from the pinned tarballs and
  Debian's copyright files from the sysroot; every package ships all of
  licenses/ and CREDITS.md, checked in the payload preflight.
- NOTICE names the modified engine's source (the fork, branch, pinned
  commit, base release, the patches), as MPL-2.0 3.2 asks.
- README and LICENSE no longer call the packages Apache-2.0 and MPL-2.0
  only; the dead licensing.shtml reference is replaced by the UXP
  LICENSE and TRADEMARK files and Moonchild's legal and redist pages.
- Apache-2.0 4(b) change notices on the 29 HP-derived files changed
  since import.
- A drawn magnifier is the DuckDuckGo engines' icon; Google's logo is
  Google's only; the unused Bing logo is gone.
- The engine's services-sync.js defaults pointed at Moonchild's Sync,
  key server and add-on host: blanked at bundle time, checked.
- The "Blazer" keyword, the Goanna-mark tagline, a stray screenshot and
  a .bak dropped; the HP SDK's terms stated where it is downloaded;
  CREDITS records the logo's origin and the screenshot strip's licence.

Deferred to the next engine build: about:credits' URL and
--disable-ffmpeg (the system-libavcodec path is dead on the device).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XM9EDSp83ZFRhggY4RCT9X
2026-10-14 13:57:20 -04:00

301 lines
13 KiB
JavaScript

// Copyright 2012 Hewlett-Packard Development Company, L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Modified by the Jihad Browser project (2026), per Apache-2.0 section 4(b): this file differs from
// HP's isis-browser original. The changes are this repository's git history for this file.
enyo.kind({
name: "CertificateDetail",
kind: enyo.VFlexBox,
published: {
cert: ""
},
components: [
{name: "commonName"},
{kind:"RowGroup", caption:$L("Issued By"), components:[
{name:"displayIssuerCommonName"}
]},
{kind:"RowGroup", caption:$L("Start Date"), components:[
{name:"startDate"}
]},
{kind:"RowGroup", caption:$L("Expiration Date"), components:[
{name:"expirationDate"}
]},
{kind: "Divider", caption: $L("Subject information")},
{kind:"RowGroup", name:"subjectAltNameGroup", caption:$L("Subject Alt Name"), components:[
{name:"subjectAltName"}
]},
{kind:"RowGroup", name:"subjectCountryGroup", caption:$L("Country"), components:[
{name:"subjectCountry"}
]},
{kind:"RowGroup", name:"subjectStateGroup", caption:$L("State/Province"), components:[
{name:"subjectState"}
]},
{kind:"RowGroup", name:"subjectLocationGroup", caption:$L("Location"), components:[
{name:"subjectLocation"}
]},
{kind:"RowGroup", name:"subjectOrganizationGroup", caption:$L("Organization"), components:[
{name:"subjectOrganization"}
]},
{kind:"RowGroup", name:"subjectCommonNameGroup", caption:$L("Common Name"), components:[
{name:"subjectCommonName"}
]},
{kind: "Divider", caption: $L("Issuer Information")},
{kind:"RowGroup", name:"issuerCountryGroup", caption:$L("Country"), components:[
{name:"issuerCountry"}
]},
{kind:"RowGroup", name:"issuerStateGroup", caption:$L("State/Province"), components:[
{name:"issuerState"}
]},
{kind:"RowGroup", name:"issuerLocationGroup", caption:$L("Location"), components:[
{name:"issuerLocation"}
]},
{kind:"RowGroup", name:"issuerOrganizationGroup", caption:$L("Organization"), components:[
{name:"issuerOrganization"}
]},
{kind:"RowGroup", name:"issuerCommonNameGroup", caption:$L("Common Name"), components:[
{name:"issuerCommonName"}
]},
{kind:"RowGroup", caption:$L("Serial Number"), components:[
{name:"serialNumber"}
]},
{kind:"RowGroup", caption:$L("Version"), components:[
{name:"version"}
]},
{kind:"RowGroup", caption:$L("Signature Algorithm"), components:[
{name:"signatureAlgorithm"}
]},
// {kind:"RowGroup", caption:$L("Signature"), components:[
// {name:"signature", kind: "RichText", richContent: false}
// ]},
{kind:"RowGroup", caption:$L("Public Key Algorithm"), components:[
{name:"publicKeyAlgorithm"}
]},
// What the daemon adds for a page that is loaded (the address bar's padlock): the
// certificate's fingerprint, and the connection the page came over.
{kind:"RowGroup", name:"fingerprintGroup", caption:$L("SHA-256 Fingerprint"), showing: false, components:[
{name:"fingerprint", style: "word-wrap: break-word; font-size: 14px;"}
]},
{kind:"RowGroup", name:"connectionGroup", caption:$L("Connection"), showing: false, components:[
{name:"connection"}
]},
{kind:"RowGroup", name:"trustGroup", caption:$L("Trust"), showing: false, components:[
{name:"trust"}
]}
// {kind:"RowGroup", caption:$L("Public Key"), components:[
// {name:"publicKey", kind: "RichText", richContent: false}
// ]}
],
formatCertDate: function(inText) {
var d = new Date(inText);
if (isNaN(d.getTime())) {
return enyo.string.escapeHtml(String(inText));
}
return new enyo.g11n.DateFmt({date:'long'}).format(d);
},
certChanged: function() {
var alternate_name="";
this.cert.displayCommonName = "";
this.cert.displayIssuerCommonName = "";
if(this.cert.subject) {
this.cert.displayCommonName = this.cert.subject.commonname ? this.cert.subject.commonname : this.cert.subject.organization;
}
if(this.cert.issuer) {
this.cert.displayIssuerCommonName = this.cert.issuer.commonname ? this.cert.issuer.commonname : this.cert.issuer.organization;
}
if(this.cert.displayCommonName) {
this.$.commonName.setContent(enyo.string.escapeHtml(this.cert.displayCommonName));
}
else {
for(var j in this.cert.subject.altname){
alternate_name += this.cert.subject.altname[j] + ' ';
}
// (was `this.$.certName`, a control that does not exist: a certificate with neither
// a common name nor an organization threw here and the view never opened)
this.$.commonName.setContent(enyo.string.escapeHtml(alternate_name));
}
// (Set whether or not present: the view is reused, and a certificate lacking a field
// must not show the previous certificate's.)
this.$.displayIssuerCommonName.setContent(enyo.string.escapeHtml(this.cert.displayIssuerCommonName || ""));
// The dates arrive as text. Formatted when they parse; shown as given when they do not
// (the daemon sends the engine's own local-time string, which this WebKit may not parse).
this.$.startDate.setContent(this.cert.startdate ? this.formatCertDate(this.cert.startdate) : "");
this.$.expirationDate.setContent(this.cert.expiredate ? this.formatCertDate(this.cert.expiredate) : "");
if(this.cert.subject) {
alternate_name="";
for(var j in this.cert.subject.altname) {
alternate_name += this.cert.subject.altname[j] + ' ';
}
this.$.subjectAltNameGroup.setShowing(alternate_name ? true : false);
this.$.subjectAltName.setContent(enyo.string.escapeHtml(alternate_name));
this.$.subjectCountryGroup.setShowing(this.cert.subject.country ? true : false)
this.$.subjectCountry.setContent(enyo.string.escapeHtml(this.cert.subject.country));
this.$.subjectStateGroup.setShowing(this.cert.subject.state ? true : false);
this.$.subjectState.setContent(enyo.string.escapeHtml(this.cert.subject.state));
this.$.subjectLocationGroup.setShowing(this.cert.subject.location ? true : false);
this.$.subjectLocation.setContent(enyo.string.escapeHtml(this.cert.subject.location));
this.$.subjectOrganizationGroup.setShowing(this.cert.subject.organization);
this.$.subjectOrganization.setContent(enyo.string.escapeHtml(this.cert.subject.organization));
this.$.subjectCommonNameGroup.setShowing(this.cert.subject.commonname ? true : false);
this.$.subjectCommonName.setContent(enyo.string.escapeHtml(this.cert.subject.commonname));
}
if(this.cert.issuer) {
this.$.issuerCountryGroup.setShowing(this.cert.issuer.country ? true : false);
this.$.issuerCountry.setContent(enyo.string.escapeHtml(this.cert.issuer.country));
this.$.issuerStateGroup.setShowing(this.cert.issuer.state ? true : false);
this.$.issuerState.setContent(enyo.string.escapeHtml(this.cert.issuer.state));
this.$.issuerLocationGroup.setShowing(this.cert.issuer.location ? true : false);
this.$.issuerLocation.setContent(enyo.string.escapeHtml(this.cert.issuer.location));
this.$.issuerOrganizationGroup.setShowing(this.cert.issuer.organization ? true : false);
this.$.issuerOrganization.setContent(enyo.string.escapeHtml(this.cert.issuer.organization));
this.$.issuerCommonNameGroup.setShowing(this.cert.issuer.commonname ? true : false);
this.$.issuerCommonName.setContent(enyo.string.escapeHtml(this.cert.issuer.commonname));
}
this.$.serialNumber.setContent(enyo.string.escapeHtml(this.cert.serialNumber !== undefined ? String(this.cert.serialNumber) : ""));
this.$.version.setContent(enyo.string.escapeHtml(this.cert.version !== undefined ? String(this.cert.version) : ""));
// A view is reused: whatever the last certificate set here must not outlive it.
this.$.signatureAlgorithm.setContent("");
this.$.publicKeyAlgorithm.setContent("");
this.$.fingerprintGroup.setShowing(this.cert.sha256 ? true : false);
this.$.fingerprint.setContent(enyo.string.escapeHtml(this.cert.sha256 ? String(this.cert.sha256) : ""));
var conn = this.cert.connection, bits = [];
if (conn) {
if (conn.protocol) { bits.push(String(conn.protocol)); }
if (conn.cipher) { bits.push(String(conn.cipher)); }
if (conn.keyLength) { bits.push(conn.keyLength + $L("-bit keys")); }
}
this.$.connectionGroup.setShowing(bits.length > 0);
this.$.connection.setContent(enyo.string.escapeHtml(bits.join(", ")));
// Whether the certificate was believed, and whether the page counts as secure.
var warn = [];
if (this.cert.overridden || this.cert.untrusted || this.cert.mismatch || this.cert.badTime) {
warn.push(this.cert.mismatch ? $L("This certificate was issued for a different site.") :
this.cert.badTime ? $L("This certificate is not valid at this time.") :
$L("This certificate could not be verified."));
if (this.cert.overridden) { warn.push($L("You chose to trust it.")); }
}
if (this.cert.broken) { warn.push($L("This page is not fully secure: part of it, or the connection itself, is not protected.")); }
this.$.trustGroup.setShowing(warn.length > 0);
this.$.trust.setContent(enyo.string.escapeHtml(warn.join(" ")));
if(this.cert.signature) {
if(this.cert.signature.algorithm) {
this.$.signatureAlgorithm.setContent(enyo.string.escapeHtml(this.cert.signature.algorithm));
}
// this.$.signature.setValue(enyo.string.escapeHtml(this.cert.signature.hexValue));
}
if(this.cert.publicKey) {
if(this.cert.publicKey.algorithm) {
this.$.publicKeyAlgorithm.setContent(enyo.string.escapeHtml(this.cert.publicKey.algorithm));
}
// this.$.publicKey.setValue(enyo.string.escapeHtml(this.cert.publicKey.hexValue));
}
}
});
enyo.kind({
name: "CertificateDialog",
kind: "ModalDialog",
caption: $L("View Certificate"),
width: "450px",
layoutKind: "VFlexLayout",
published: {
certFile: ""
},
events: {
onCertLoad: "",
onClose: ""
},
components: [
{name: "getCertificateDetails", kind:"PalmService", service:"palm://com.palm.certificatemanager/",
method:"getcertificatedetails",
onResponse:"handleCertificate"
},
{kind: "Scroller", height: "500px", flex: 1, horizontal: false, autoHorizontal: false, components: [
{name: "certDetail", kind: "CertificateDetail"}
]},
{kind: "HFlexBox", pack: "justify", align: "center", components: [
{kind: "Button", caption: $L("Done"), flex: 1, className: "enyo-button-dark", onclick: "doClose"}
]}
],
// WHERE THE DETAILS COME FROM. The stock browser asks com.palm.certificatemanager (the
// service component above, kept for a device where that works). On webOS CE a card gets
// "Service does not exist" from it, so View Certificate never enabled. The daemon therefore
// writes the details of the certificate it is warning about into THIS app's own directory —
// certinfo/<name of the certificate file>.js, one call to window.jihadCertInfo — for as
// long as the warning is open: a card may load a local file only from its own directory,
// and only as a script (measured 2026-10-02; see render/goanna/BrowserPageGoanna.cpp).
certFileChanged: function() {
// this.warn("cert file: ", this.certFile);
this.validateComponents();
if(this.certFile) {
var self = this, asked = this.certFile, done = false, tag = null;
var finish = function(o) {
if (done) { return; }
done = true;
window.jihadCertInfo = null;
if (tag && tag.parentNode) { tag.parentNode.removeChild(tag); }
if (o && self.certFile === asked) {
self.handleCertificate(self, o);
} else if (!o && self.certFile === asked) {
self.$.getCertificateDetails.call({'certificateFilename': asked});
}
};
try {
window.jihadCertInfo = function(o) { finish(o); };
tag = document.createElement("script");
tag.onerror = function() { finish(null); };
tag.src = "certinfo/" + String(asked).replace(/^.*\//, "") + ".js";
document.getElementsByTagName("head")[0].appendChild(tag);
window.setTimeout(function() { finish(null); }, 3000);
} catch (e) {
finish(null);
}
}
},
//* Show a certificate the caller already has — the loaded page's own, which the address
//* bar's padlock asks the daemon for. (certFile, above, is the other way in: the
//* certificate a failed load is asking about.)
showCertificate: function(inCert) {
this.validateComponents();
this.$.certDetail.setCert(inCert);
},
handleCertificate: function(inSender, inResponse) {
// this.warn("cert details: ", enyo.json.stringify(inResponse));
if(inResponse.returnValue) {
this.$.certDetail.setCert(inResponse);
this.doCertLoad();
}
}
});