[JavaScript] 纯文本查看 复制代码
require("Env.js");var Dict=require("Dict.js"),electron=require("electron"),shell=electron.shell,app=electron.app,ipc=electron.ipcMain,BrowserWindow=electron.BrowserWindow,isWin="win32"==process.platform,isMac="darwin"==process.platform,isLinux="linux"==process.platform,WindowController=require("WindowController.js"),Raven=require("raven"),errorShown=!1;const mustRequire=function(e){try{return require(e)}catch(e){if(errorShown)return;errorShown=!0;var n=e.message;setTimeout((()=>{errorShown=!1,dialog=require("electron").dialog,dialog.showMessageBox(null,{type:"error",buttons:["OK"],defaultId:0,cancelId:0,title:"A required module cannot be loaded by Typora",message:n.split("\n")[0]+"\n\nPlease check if that file exists or reinstall Typora to fix."}).then((({response:e})=>{process.exit(1)}))}),1500)}};var installDate,lastShown,hasLicense=null,email="",licenseCode="",fingerPrint="";const ActiveResponseCode={SUCCESS:0,OUT_OF_LIMIT:1,INVALIDATE:-1,WRONG_USER:-2},PUB_KEY="-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7nVoGCHqIMJyqgALEUrc\n5JJhap0+HtJqzPE04pz4y+nrOmY7/12f3HvZyyoRsxKdXTZbO0wEHFIh0cRqsuaJ\nPyaOOPbA0BsalofIAY3mRhQQ3vSf+rn3g+w0S+udWmKV9DnmJlpWqizFajU4T/E4\n5ZgMNcXt3E1ips32rdbTR0Nnen9PVITvrbJ3l6CI2BFBImZQZ2P8N+LsqfJsqyVV\nwDkt3mHAVxV7FZbfYWG+8FDSuKQHaCmvgAtChx9hwl3J6RekkqDVa6GIV13D23LS\nqdk0Jb521wFJi/V6QAK6SLBiby5gYN6zQQ5RQpjXtR53MwzTdiAzGEuKdOtrY2Me\nDwIDAQAB\n-----END PUBLIC KEY-----\n\n",DAY_IN_MS=864e5,HOST="https://store.typora.io",decrypt=e=>JSON.parse(Buffer.from(e,"base64").toString("utf-8")),makeHash=function(){var e=Array.from(arguments);const n=require("crypto").createHash("sha256");return e.forEach((e=>{n.update(e)})),n.digest("base64")},readLicenseInfo=()=>{const e=getLicenseLocalStore().get("SLicense");if(!e)return null;const[n,t,i]=e.split("#"),a=decrypt(n);return a.fingerprint!=fingerPrint?null:(Object.assign(a,{failCounts:t,lastRetry:new Date(i)}),a)},writeInstallDate=async e=>{console.log(`writeInstallDate fromBTime=${e}`);var n=new Date;if(e)try{var t=await require("fs-extra").stat(app.getPath("userData")+"/profile.data");n=new Date(t.birthtime),t.birthtime}catch(e){}installDate=n;const i=n.toLocaleDateString("en-US");return getLicenseLocalStore().put("IDate",i),installDate};var licenseLocalStoreInstance=null;const getLicenseLocalStore=function(){if(null==licenseLocalStoreInstance)if(isWin)licenseLocalStoreInstance=WindowsLicenseLocalStore();else{var e=app.setting.prepDatabase(fingerPrint);licenseLocalStoreInstance={put:function(n,t){console.log(`ls put ${n}`),e.getState()[n]=t,e.write()},get:function(n){return e.getState()[n]}}}return licenseLocalStoreInstance};function WindowsLicenseLocalStore(){const e=mustRequire("native-reg");return{get:function(n){const t=e.openKey(e.HKCU,"Software\\Typora",e.Access.READ);if(null==t)return"";const i=e.getValue(t,null,n);return e.closeKey(t),i},put:function(n,t){const i=e.createKey(e.HKCU,"Software\\Typora",e.Access.WRITE);e.setValueSZ(i,n,t),e.closeKey(i)}}}const getFingerPrint=async()=>{if(!fingerPrint){if(isWin){const e=mustRequire("native-reg"),n=e.openKey(e.HKEY.LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Cryptography",e.Access.WOW64_64KEY|e.Access.READ);fingerPrint=e.getValue(n,null,"MachineGuid"),e.closeKey(n)}else fingerPrint=await require("node-machine-id").machineId({original:!0});fingerPrint||Raven.captureMessage("[License] Failed to get fingerPrint"),fingerPrint=makeHash(fingerPrint,"typora").substr(0,10).replace(/[/=+-]/g,"a"),isMac&&(fingerPrint+="darwin")}return fingerPrint};var licenseInitialed=!1;const watchLicense=async e=>{console.log("[watchLicense]"),firstValidateLicense(e),await validateTrail(),!global.betaVersion&&console.log(`[watchLicense] hasLicense: ${hasLicense}`),showLicensePanelIfNeeded(),addToAnalysis()},addToAnalysis=()=>{var e=Raven.getContext().tags;e.hasLicense=hasLicense,Raven.mergeContext(e)},getOS=()=>process.platform.replace(/\d+/,""),renewLicense=async(e,n)=>{(new Date).toLocaleDateString("en-US");const{deviceId:t,lastRetry:i}=e||{};if(!n&&new Date-i<432e5)return;const a={v:getOS()+"|"+app.getVersion(),license:licenseCode,l:t,u:app.setting.generateUUID(),type:global.devVersion?"dev":""};JSON.stringify(a)},getInstallDate=e=>{var n=new Date(getLicenseLocalStore().get("IDate"));if(isNaN(n.getTime()))return e?null:new Date;if(e)return n;var t=1637934234708;return isNaN(t)?t=new Date("2021-10-01"):(t=new Date(t),isNaN(t.getTime())&&(t=new Date("2021-10-01"))),n<t?t:n},getTrailRemains=(e,n)=>{n=n||15;var t=Math.floor((new Date-installDate)/864e5),i=Math.max(0,n-t);return e&&(i>n||isNaN(i))&&(i=n),i},validateTrail=async()=>{var e=(installDate=getInstallDate(!global.devVersion))?getTrailRemains(!1):100;(e>15||isNaN(e))&&(console.log("[validateTrail] Read from incorrupted InstallDate"),await writeInstallDate(!0),e=15),console.log(`[validateTrail] installDate is ${installDate.toLocaleDateString("en-US")}, trail remains: ${e} days`)};function fillLicense(e,n){licenseCode=n,(hasLicense=!(!(email=e)||!licenseCode))&&onFillLicense()}function unfillLicense(e){hasLicense||(e=""),email="",licenseCode="",hasLicense=!1,getLicenseLocalStore().put("SLicense",""),e&&showDialog(Dict.getPanelString("Typora is now deactivated"),Dict.getPanelString(e)),onUnfillLicense()}const firstValidateLicense=e=>{console.log("[License] firstValidateLicense"),licenseInitialed=!0;const n=readLicenseInfo(),{license:t,email:i}=n||{};t&&i?(fillLicense(i,t),renewLicense(n,e),console.log("[License] pass validateLicenseInfoStr")):unfillLicense()},showDialog=(e,n)=>electron.dialog.showMessageBox(null,{type:"error",buttons:["OK"],defaultId:0,cancelId:0,title:e,message:n}),endDevTest=function(){app.expired=!0,showDialog(Dict.getPanelString("Error"),Dict.getPanelString("This beta version of Typora is expired, please download and install a newer version.")).then((()=>{shell.openExternal("https://typora.io/#download"),setTimeout((()=>{process.exit(1)}),1e3)}))},validateDevTest=function(){if(!hasLicense&&!isLinux&&global.devVersion&&global.PRODUCTION_MODE){var e=getInstallDate(),n=new Date;console.log("buildTime is 1637934234708"),(isNaN(1637934234708)||n-1637934234708>20736e6)&&endDevTest(),e-=0,console.log("verInitTime is "+e),!isNaN(e)&&n-e>1728e7&&endDevTest()}},showLicensePanelIfNeeded=function(){shouldShowNoLicenseHint(!0)&&!app.setting.inFirstShow&&(isLinux&&Math.random()<.95||(!lastShown||new Date-lastShown>36e5*(isLinux?4:2)||getTrailRemains(!0,20)<=0)&&showLicensePanel())};var licensePanel=null;const showLicensePanel=async function(e){if(lastShown=new Date,null==licensePanel)return(licensePanel=WindowController.showPanelWindow({width:525,height:420,path:`page-dist/license.html?dayRemains=${getTrailRemains(!0)}&index=${e?1:0}\n\t\t\t\t&hasActivated=${hasLicense||!1}&email=${email}&license=${licenseCode}&lang=${app.setting.getUserLocale()}&needLicense=${shouldShowNoLicenseHint()}`,frame:!1,alwaysOnTop:!errorShown})).on("closed",(function(){licensePanel=null})),void setTimeout((()=>{licensePanel&&!licensePanel.isDestroyed()&&licensePanel.setAlwaysOnTop(!1)}),5e3);licensePanel.focus()};var welcomePanel=null;const showWelcomePanel=async function(){if(lastShown=new Date,null==welcomePanel)return(welcomePanel=WindowController.showPanelWindow({width:760,height:460,path:`page-dist/welcome.html?lang=${app.setting.getUserLocale()}`,frame:!1,alwaysOnTop:!errorShown})).on("closed",(function(){welcomePanel=null})),void setTimeout((()=>{welcomePanel&&!welcomePanel.isDestroyed()&&welcomePanel.setAlwaysOnTop(!1)}),4e3);welcomePanel.focus()},quickValidate=e=>{const n="L23456789ABCDEFGHJKMNPQRSTUVWXYZ";if(!/^([A-Z0-9]{6}-){3}[A-Z0-9]{6}$/.exec(e))return!1;var t=e.replace(/-/g,""),i=t.substr(22);return!t.replace(/[L23456789ABCDEFGHJKMNPQRSTUVWXYZ]/g,"")&&i==(e=>{for(var t="",i=0;i<2;i++){for(var a=0,s=0;s<16;s+=2)a+=n.indexOf(e[i+s]);t+=n[a%=n.length]}return t})(t)},getComputerName=async function(){var e=process.env.USER;switch(e||(e=require("os").userInfo().username),process.platform){case"win32":return process.env.COMPUTERNAME+" | "+e+" | Windows";case"darwin":return new Promise((n=>{require("child_process").exec("scutil --get ComputerName",{timeout:5e3},((t,i)=>{n(!t&&i?i.toString().trim()+" | "+e+" | darwin":require("os").hostname()+" | "+e+" | darwin")}))}));default:return require("os").hostname()+" | "+e+" | Linux"}},doActivation=async function(e,n,t){if(e=(e||"").replace(/^[\s\u200b ]/g,"").replace(/[\s\u200b ]$/g,""),n=(n||"").replace(/^[\s\u200b ]/g,"").replace(/[\s\u200b ]$/g,""),!function(e){return/^[^\s@'"/\\=?]+@[^\s@'"/\\]+\.[^\s@'"/\\]+$/.test(e)}(e))return[!1,"Please input a valid email address"];if(!quickValidate(n))return[!1,"Please input a valid license code"];const i={v:getOS()+"|"+app.getVersion(),license:n,email:e,l:await getComputerName(),f:await getFingerPrint(),u:app.setting.generateUUID(),type:global.devVersion?"dev":"",force:t};JSON.stringify(i);try{const e={data:{code:0,msg:Buffer.from(JSON.stringify({deviceId:i.u,fingerprint:i.f,email:i.email,license:i.license,version:i.v,date:(new Date).toLocaleDateString("en-US")}),"utf-8").toString("base64")}};if(JSON.stringify(e.data),console.log(`[License] response code is ${e.data.code}`),e.data.code==ActiveResponseCode.SUCCESS)return await writeActivationInfo(e.data.msg)?[!0,""]:[!1,"Please input a valid license code"];if(e.data.code==ActiveResponseCode.OUT_OF_LIMIT)return t?await writeActivationInfo(e.data.msg)?[!0,"Your license has exceeded the max devices numbers.\nThe oldest device was unregistered automatically."]:[!1,"Please input a valid license code"]:["confirm",'Your license has exceeded the max devices numbers.\nIf you click "Continue Activation", this device will be activated and the oldest device will be unregistered automatically.'];if(e.data.code==ActiveResponseCode.INVALIDATE)return[!1,"Please input a valid license code"];if(e.data.code==ActiveResponseCode.WRONG_USER)return[!1,"This license code has been used with a different email address."]}catch(e){return e.response&&e.response.code?(console.warn(`[License] error from server ${e.response.code}`),[!1,"Unknown Error. Please contact [email]hi@typora.io[/email]"]):(Raven.captureException(e,{level:"warning"}),console.error(e.stack),[!1,"Failed to access the license server. Please check your network or try again later."])}},writeActivationInfo=async function(e){const n=decrypt(e)||{},{deviceId:t,fingerprint:i,email:a,license:s,version:o,date:r}=n;return i==await getFingerPrint()&&a&&s?(fillLicense(a,s),getLicenseLocalStore().put("SLicense",`${e}#0#${(new Date).toLocaleDateString("en-US")}`),hasLicense=!0,!0):(console.log("[License] validate server return fail"),unfillLicense(),!1)},doDeactivation=async()=>{hasLicense&&email&&licenseCode||console.error("doDeactivation on unregistered device");const{deviceId:e}=readLicenseInfo()||{};unfillLicense()};ipc.handle("addLicense",(async(e,{email:n,license:t,force:i})=>{console.log("handle addLicense");try{return await doActivation(n,t,i)}catch(e){console.error(e.stack)}})),ipc.handle("license.show",((e,n)=>{showLicensePanel(n||!1)})),ipc.handle("license.show.debug",(()=>{licensePanel&&licensePanel.webContents.openDevTools()})),ipc.handle("removeLicense",(async e=>{console.log("handle removeLicense");try{return await doDeactivation()}catch(e){console.error(e.stack)}}));const start=async(e,n)=>{console.log(`start LM in devVersion=${global.devVersion||!1}`);try{await getFingerPrint(),!e&&n||isLinux||(global.devVersion||!n||n.indexOf("dev")>-1)&&(console.log("re-write InstallDate"),await writeInstallDate()),validateDevTest(),watchLicense(e)}catch(e){Raven.captureException(e)}},shouldShowNoLicenseHint=e=>!hasLicense&&(e||!isLinux)&&!global.devVersion,getHasLicense=()=>hasLicense,appendLicenseHintIfNeeded=e=>{licenseInitialed&&shouldShowNoLicenseHint()&&onUnfillLicense(e)};function genClassName(){var e=(new Date).getTime();return"txxxx-xxxx-xxxxy".replace(/[x]/g,(function(n){var t=(e+16*Math.random())%16|0;return e=Math.floor(e/16),t.toString(16)}))}const className=genClassName(),onFillLicense=()=>{BrowserWindow.getAllWindows().forEach((e=>{e.webContents.executeJavaScript(`try{document.querySelector(".${className}").remove();}catch(e){};File.option && (File.option.hasLicense = true);File.megaMenu && File.megaMenu.forceReload();0;`)}))},onUnfillLicense=async e=>{if(isLinux||global.devVersion)return;await Dict.init();const n=`.typora-sourceview-on .${className}{\n\t\tdisplay:none;\n\t}\n\t.${className} {\n\t\tposition: fixed;\n bottom: 2px;\n z-index: 9999;\n left: 70px;\n font-size: 12px;\n line-height: 24px;\n background: rgb(120 120 120 / 30%);\n padding: 0 12px;\n color: var(--text-color);\n border-radius: 4px;\n cursor: pointer;\n\t}\n\t.pin-outline .${className}{\n\t\tleft:calc(var(--sidebar-width) + 70px);\n\t}`,t=`if(window.File.option){\n\t\tFile.option.hasLicense = false; \n\t\tFile.megaMenu && File.megaMenu.forceReload();\n\t\tif(!document.querySelector(".${className}")) {\n\t\t\tconst pos = Math.round(Math.random() * document.body.children.length);\n\t\t\tconst dom = document.createElement("DIV");\n\t\t\tdom.innerText = "${Dict.getPanelString("UNREGISTERED")} ×";\n\t\t\tdom.classList.add("${className}");\n\t\t\tdom.style = "position: fixed !important;bottom: 2px !important; display: block !important; opacity: 1 !important; height: auto !important; width: auto !important; z-index: 9999 !important;"\n\t\t\tdom.setAttribute("role", "button");\n\t\t\tdom.addEventListener("click", () => {\n\t\t\t\tdom.remove();\n\t\t\t\treqnode("electron").ipcRenderer.invoke("license.show");\n\t\t\t});\n\t\t\tdocument.body.insertBefore(dom, document.body.children[pos]);\n\t\t}\n\t};1;`;function i(e){e.webContents.insertCSS(n),e.webContents.executeJavaScript(t)}e?i(e):BrowserWindow.getAllWindows().forEach(i)};exports.shouldShowNoLicenseHint=shouldShowNoLicenseHint,exports.start=start,exports.showLicensePanel=showLicensePanel,exports.showWelcomePanel=showWelcomePanel,exports.appendLicenseHintIfNeeded=appendLicenseHintIfNeeded,exports.getHasLicense=getHasLicense,exports.showLicensePanelIfNeeded=showLicensePanelIfNeeded;