Files
typoraCracker/example/patch/License.js
2021-12-01 15:21:18 +08:00

1 line
14 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 hi@typora.io"]):(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;