Wed, 31 Dec 2014 07:16:47 +0100
Revert simplistic fix pending revisit of Mozilla integration attempt.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- |
michael@0 | 2 | * |
michael@0 | 3 | * This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 6 | |
michael@0 | 7 | /* |
michael@0 | 8 | * These are helper functions to be included |
michael@0 | 9 | * pippki UI js files. |
michael@0 | 10 | */ |
michael@0 | 11 | |
michael@0 | 12 | function setText(id, value) { |
michael@0 | 13 | var element = document.getElementById(id); |
michael@0 | 14 | if (!element) return; |
michael@0 | 15 | if (element.hasChildNodes()) |
michael@0 | 16 | element.removeChild(element.firstChild); |
michael@0 | 17 | var textNode = document.createTextNode(value); |
michael@0 | 18 | element.appendChild(textNode); |
michael@0 | 19 | } |
michael@0 | 20 | |
michael@0 | 21 | const nsICertificateDialogs = Components.interfaces.nsICertificateDialogs; |
michael@0 | 22 | const nsCertificateDialogs = "@mozilla.org/nsCertificateDialogs;1" |
michael@0 | 23 | |
michael@0 | 24 | function viewCertHelper(parent, cert) { |
michael@0 | 25 | if (!cert) |
michael@0 | 26 | return; |
michael@0 | 27 | |
michael@0 | 28 | var cd = Components.classes[nsCertificateDialogs].getService(nsICertificateDialogs); |
michael@0 | 29 | cd.viewCert(parent, cert); |
michael@0 | 30 | } |
michael@0 | 31 | |
michael@0 | 32 | function getDERString(cert) |
michael@0 | 33 | { |
michael@0 | 34 | var length = {}; |
michael@0 | 35 | var derArray = cert.getRawDER(length); |
michael@0 | 36 | var derString = ''; |
michael@0 | 37 | for (var i = 0; i < derArray.length; i++) { |
michael@0 | 38 | derString += String.fromCharCode(derArray[i]); |
michael@0 | 39 | } |
michael@0 | 40 | return derString; |
michael@0 | 41 | } |
michael@0 | 42 | |
michael@0 | 43 | function getPKCS7String(cert, chainMode) |
michael@0 | 44 | { |
michael@0 | 45 | var length = {}; |
michael@0 | 46 | cert.QueryInterface(Components.interfaces.nsIX509Cert3); |
michael@0 | 47 | var pkcs7Array = cert.exportAsCMS(chainMode, length); |
michael@0 | 48 | var pkcs7String = ''; |
michael@0 | 49 | for (var i = 0; i < pkcs7Array.length; i++) { |
michael@0 | 50 | pkcs7String += String.fromCharCode(pkcs7Array[i]); |
michael@0 | 51 | } |
michael@0 | 52 | return pkcs7String; |
michael@0 | 53 | } |
michael@0 | 54 | |
michael@0 | 55 | function getPEMString(cert) |
michael@0 | 56 | { |
michael@0 | 57 | var derb64 = btoa(getDERString(cert)); |
michael@0 | 58 | // Wrap the Base64 string into lines of 64 characters, |
michael@0 | 59 | // with CRLF line breaks (as specified in RFC 1421). |
michael@0 | 60 | var wrapped = derb64.replace(/(\S{64}(?!$))/g, "$1\r\n"); |
michael@0 | 61 | return "-----BEGIN CERTIFICATE-----\r\n" |
michael@0 | 62 | + wrapped |
michael@0 | 63 | + "\r\n-----END CERTIFICATE-----\r\n"; |
michael@0 | 64 | } |
michael@0 | 65 | |
michael@0 | 66 | function alertPromptService(title, message) |
michael@0 | 67 | { |
michael@0 | 68 | var ps = null; |
michael@0 | 69 | var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]. |
michael@0 | 70 | getService(Components.interfaces.nsIPromptService); |
michael@0 | 71 | ps.alert(window, title, message); |
michael@0 | 72 | } |
michael@0 | 73 | |
michael@0 | 74 | function exportToFile(parent, cert) |
michael@0 | 75 | { |
michael@0 | 76 | var bundle = document.getElementById("pippki_bundle"); |
michael@0 | 77 | if (!cert) |
michael@0 | 78 | return; |
michael@0 | 79 | |
michael@0 | 80 | var nsIFilePicker = Components.interfaces.nsIFilePicker; |
michael@0 | 81 | var fp = Components.classes["@mozilla.org/filepicker;1"]. |
michael@0 | 82 | createInstance(nsIFilePicker); |
michael@0 | 83 | fp.init(parent, bundle.getString("SaveCertAs"), |
michael@0 | 84 | nsIFilePicker.modeSave); |
michael@0 | 85 | var filename = cert.commonName; |
michael@0 | 86 | if (!filename.length) |
michael@0 | 87 | filename = cert.windowTitle; |
michael@0 | 88 | // remove all whitespace from the default filename |
michael@0 | 89 | fp.defaultString = filename.replace(/\s*/g,''); |
michael@0 | 90 | fp.defaultExtension = "crt"; |
michael@0 | 91 | fp.appendFilter(bundle.getString("CertFormatBase64"), "*.crt; *.pem"); |
michael@0 | 92 | fp.appendFilter(bundle.getString("CertFormatBase64Chain"), "*.crt; *.pem"); |
michael@0 | 93 | fp.appendFilter(bundle.getString("CertFormatDER"), "*.der"); |
michael@0 | 94 | fp.appendFilter(bundle.getString("CertFormatPKCS7"), "*.p7c"); |
michael@0 | 95 | fp.appendFilter(bundle.getString("CertFormatPKCS7Chain"), "*.p7c"); |
michael@0 | 96 | fp.appendFilters(nsIFilePicker.filterAll); |
michael@0 | 97 | var res = fp.show(); |
michael@0 | 98 | if (res != nsIFilePicker.returnOK && res != nsIFilePicker.returnReplace) |
michael@0 | 99 | return; |
michael@0 | 100 | |
michael@0 | 101 | var content = ''; |
michael@0 | 102 | switch (fp.filterIndex) { |
michael@0 | 103 | case 1: |
michael@0 | 104 | content = getPEMString(cert); |
michael@0 | 105 | var chain = cert.getChain(); |
michael@0 | 106 | for (var i = 1; i < chain.length; i++) |
michael@0 | 107 | content += getPEMString(chain.queryElementAt(i, Components.interfaces.nsIX509Cert)); |
michael@0 | 108 | break; |
michael@0 | 109 | case 2: |
michael@0 | 110 | content = getDERString(cert); |
michael@0 | 111 | break; |
michael@0 | 112 | case 3: |
michael@0 | 113 | content = getPKCS7String(cert, Components.interfaces.nsIX509Cert3.CMS_CHAIN_MODE_CertOnly); |
michael@0 | 114 | break; |
michael@0 | 115 | case 4: |
michael@0 | 116 | content = getPKCS7String(cert, Components.interfaces.nsIX509Cert3.CMS_CHAIN_MODE_CertChainWithRoot); |
michael@0 | 117 | break; |
michael@0 | 118 | case 0: |
michael@0 | 119 | default: |
michael@0 | 120 | content = getPEMString(cert); |
michael@0 | 121 | break; |
michael@0 | 122 | } |
michael@0 | 123 | var msg; |
michael@0 | 124 | var written = 0; |
michael@0 | 125 | try { |
michael@0 | 126 | var file = Components.classes["@mozilla.org/file/local;1"]. |
michael@0 | 127 | createInstance(Components.interfaces.nsILocalFile); |
michael@0 | 128 | file.initWithPath(fp.file.path); |
michael@0 | 129 | var fos = Components.classes["@mozilla.org/network/file-output-stream;1"]. |
michael@0 | 130 | createInstance(Components.interfaces.nsIFileOutputStream); |
michael@0 | 131 | // flags: PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE |
michael@0 | 132 | fos.init(file, 0x02 | 0x08 | 0x20, 00644, 0); |
michael@0 | 133 | written = fos.write(content, content.length); |
michael@0 | 134 | fos.close(); |
michael@0 | 135 | } |
michael@0 | 136 | catch(e) { |
michael@0 | 137 | switch (e.result) { |
michael@0 | 138 | case Components.results.NS_ERROR_FILE_ACCESS_DENIED: |
michael@0 | 139 | msg = bundle.getString("writeFileAccessDenied"); |
michael@0 | 140 | break; |
michael@0 | 141 | case Components.results.NS_ERROR_FILE_IS_LOCKED: |
michael@0 | 142 | msg = bundle.getString("writeFileIsLocked"); |
michael@0 | 143 | break; |
michael@0 | 144 | case Components.results.NS_ERROR_FILE_NO_DEVICE_SPACE: |
michael@0 | 145 | case Components.results.NS_ERROR_FILE_DISK_FULL: |
michael@0 | 146 | msg = bundle.getString("writeFileNoDeviceSpace"); |
michael@0 | 147 | break; |
michael@0 | 148 | default: |
michael@0 | 149 | msg = e.message; |
michael@0 | 150 | break; |
michael@0 | 151 | } |
michael@0 | 152 | } |
michael@0 | 153 | if (written != content.length) { |
michael@0 | 154 | if (!msg.length) |
michael@0 | 155 | msg = bundle.getString("writeFileUnknownError"); |
michael@0 | 156 | alertPromptService(bundle.getString("writeFileFailure"), |
michael@0 | 157 | bundle.getFormattedString("writeFileFailed", |
michael@0 | 158 | [fp.file.path, msg])); |
michael@0 | 159 | } |
michael@0 | 160 | } |