Repository: QTGate/QTGate-Desktop-Client Branch: master Commit: 6b52a041d1e8 Files: 64 Total size: 1.4 MB Directory structure: gitextract_mixerr74/ ├── .travis.yml ├── LICENSE ├── README.md ├── app/ │ ├── CoNET.d.ts │ ├── localWebServer.js │ ├── localWebServer.ts │ ├── main.js │ ├── main.ts │ ├── package.json.npm │ ├── public/ │ │ ├── css/ │ │ │ ├── c3.css │ │ │ └── page.css │ │ └── scripts/ │ │ ├── CanadaSvg.js │ │ ├── Cleave.js │ │ ├── CoNETConnect.js │ │ ├── CoNETConnect.ts │ │ ├── appCosearch.js │ │ ├── appCosearch.ts │ │ ├── appsManager.js │ │ ├── appsManager.ts │ │ ├── connectInformationMessage.js │ │ ├── connectInformationMessage.ts │ │ ├── encryptoClass.js │ │ ├── encryptoClass.ts │ │ ├── home.js │ │ ├── home.ts │ │ ├── imapForm.js │ │ ├── imapForm.ts │ │ ├── jquery.cookie.js │ │ ├── keyPairGenerateForm.js │ │ ├── keyPairGenerateForm.ts │ │ ├── keyPairPassword.js │ │ ├── keyPairPassword.ts │ │ ├── knockout.animate.js │ │ ├── knockout.js │ │ ├── showHTMLComplete.js │ │ ├── showHTMLComplete.ts │ │ ├── siteShare.js │ │ ├── siteShare.ts │ │ └── socket.io.js │ ├── tools/ │ │ ├── 1231B119.pem │ │ ├── coNETConnect.js │ │ ├── coNETConnect.ts │ │ ├── compress.js │ │ ├── compress.ts │ │ ├── imap.js │ │ ├── imap.ts │ │ ├── initSystem.js │ │ └── initSystem.ts │ └── views/ │ ├── Shared/ │ │ ├── CoNETConnectInfo.pug │ │ ├── CoSearchLayout.pug │ │ ├── appHtml.pug │ │ ├── header.pug │ │ └── mainMenu.pug │ ├── home/ │ │ ├── Wrt.pug │ │ ├── coSearchImage.html │ │ ├── customProxy.pug │ │ └── index.pug │ └── shared/ │ └── coreLayout.pug ├── build/ │ └── icon.icns ├── index.html ├── index.js ├── index.ts ├── package.json └── tsconfig.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .travis.yml ================================================ sudo: false language: node_js os: - linux before_install: - nvm install 8.7.0 - nvm use 8.7.0 - npm i electron-builder ================================================ FILE: LICENSE ================================================ The MIT License (MIT) Copyright (c) 2018 CoNET Technology Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ ### This is the beginning of CoNET project ### now migrate to ## The new era of CoNET ### New Link here: https://bitbucket.org/matheus_moraes_pinheiro/conet ## Homepage https://conet.network [![Build Status](https://travis-ci.org/QTGate/QTGate-Desktop-Client.svg?branch=master)](https://travis-ci.org/QTGate/QTGate-Desktop-Client) [![Gitter](https://img.shields.io/badge/chat-on%20gitter-blue.svg)](https://gitter.im/QTGate/Lobby) [![Known Vulnerabilities](https://snyk.io/test/github/qtgate/qtgate-desktop-client/badge.svg)](https://snyk.io/test/github/qtgate/qtgate-desktop-client) [![Telegram](https://img.shields.io/badge/telebot-community%20group-blue.svg)](https://t.me/joinchat/IpX64hGK_95XDTXit42vOg) ![http protocol](/resources/CoPlatform4.png?raw=true) ================================================ FILE: app/CoNET.d.ts ================================================ /*! * Copyright 2018 CoNET Technology Inc. All Rights Reserved. * * 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. */ interface ReadonlyArray { /** * Returns the value of the first element in the array where predicate is true, and undefined * otherwise. * @param predicate find calls predicate once for each element of the array, in ascending * order, until it finds one where predicate returns true. If such an element is found, find * immediately returns that element value. Otherwise, find returns undefined. * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ find(predicate: (this: void, value: T, index: number, obj: ReadonlyArray) => value is S, thisArg?: any): S | undefined; find(predicate: (value: T, index: number, obj: ReadonlyArray) => boolean, thisArg?: any): T | undefined; /** * Returns the index of the first element in the array where predicate is true, and -1 * otherwise. * @param predicate find calls predicate once for each element of the array, in ascending * order, until it finds one where predicate returns true. If such an element is found, * findIndex immediately returns that element index. Otherwise, findIndex returns -1. * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ findIndex(predicate: (value: T, index: number, obj: ReadonlyArray) => boolean, thisArg?: any): number; } interface Map { clear(): void; delete(key: K): boolean; forEach(callbackfn: (value: V, key: K, map: Map) => void, thisArg?: any): void; get(key: K): V | undefined; has(key: K): boolean; set(key: K, value: V): this; readonly size: number; } interface MapConstructor { new (): Map; new (entries?: ReadonlyArray<[K, V]>): Map; readonly prototype: Map; } declare var Map: MapConstructor; interface ReadonlyMap { forEach(callbackfn: (value: V, key: K, map: ReadonlyMap) => void, thisArg?: any): void; get(key: K): V | undefined; has(key: K): boolean; readonly size: number; } interface WeakMap { delete(key: K): boolean; get(key: K): V | undefined; has(key: K): boolean; set(key: K, value: V): this; } interface WeakMapConstructor { new (): WeakMap; new (entries?: ReadonlyArray<[K, V]>): WeakMap; readonly prototype: WeakMap; } declare var WeakMap: WeakMapConstructor; interface Set { add(value: T): this; clear(): void; delete(value: T): boolean; forEach(callbackfn: (value: T, value2: T, set: Set) => void, thisArg?: any): void; has(value: T): boolean; readonly size: number; } interface SetConstructor { new (): Set; new (values?: ReadonlyArray): Set; readonly prototype: Set; } declare var Set: SetConstructor; interface ReadonlySet { forEach(callbackfn: (value: T, value2: T, set: ReadonlySet) => void, thisArg?: any): void; has(value: T): boolean; readonly size: number; } interface WeakSet { add(value: T): this; delete(value: T): boolean; has(value: T): boolean; } interface WeakSetConstructor { new (): WeakSet; new (values?: ReadonlyArray): WeakSet; readonly prototype: WeakSet; } declare var WeakSet: WeakSetConstructor; interface imapConnect { imapServer: string imapUserName: string imapUserPassword: string imapPortNumber: number|number[] imapSsl: boolean imapIgnoreCertificate: boolean } interface keypair { publicKey?: string privateKey?: string keyLength: number nikeName: string createDate: string email: string passwordOK: boolean verified: boolean publicKeyID: string showLoginPasswordField?: KnockoutObservable < boolean > delete_btn_view?: KnockoutObservable < boolean > delete_btn_click?: () => void showConform?: KnockoutObservable < boolean > deleteKeyPairNext?: () => void _password: string CoNET_publicKey?: string keyPairPassword?: KnockoutObservable < keyPairPassword > showDeleteKeyPairNoite?: KnockoutObservable < boolean > } interface StringValidator { isAcceptable(s: string): boolean; } interface INewKeyPair { email: string nikeName: string password: string } interface keyPair { publicKey: string; privateKey: string; } interface imapData { email: string } interface requestPoolData { timeout: any } interface regionV1 { regionName: string testHostIp: string testUrl: string testHost: string freeUser: boolean VoE: boolean } interface IinputData extends imapConnect { account:string email: string smtpServer:string smtpUserName:string smtpUserPassword:string smtpPortNumber:number|number[] smtpSsl:boolean smtpIgnoreCertificate: boolean imapTestResult: boolean language: string clientFolder: string serverFolder: string timeZoneOffset: number randomPassword: string uuid: string clientIpAddress: string ciphers: string confirmRisk: boolean sendToQTGate: boolean } interface CoPromo { datePromo: number pricePromo: number promoDetail: string[] promoFor: string[] } interface iTransferData { startDate: string transferDayLimit: number transferMonthly: number account: string resetTime: string usedDayTransfer: number productionPackage: string usedMonthlyTransfer: number availableDayTransfer: number availableMonthlyTransfer: number usedMonthlyOverTransfer: number uploaded?: number downloaded?: number power: number timeZoneOffset: number expire: string isAnnual: boolean paidID: string[] totalMonth: number paidAmount: number automatically: boolean promo: CoPromo[] } interface multipleGateway { gateWayIpAddress: string gateWayPort: number dockerName: string password: string } interface QTGate_DnsAddress { dnsName: string, ipv4: string, url: string } interface IConnectCommand { region: string account: string imapData: IinputData connectType: number transferData?: iTransferData error?: number dockerName?: string randomPassword?: string runningDocker?: string AllDataToGateway?: boolean fingerprint: string gateWayIpAddress: string gateWayPort?: number totalUserPower?: number requestContainerEachPower?: number connectPeer?: string requestRegions?: string[] multipleGateway?: multipleGateway[] requestMultipleGateway?: number containerUUID?: string peerUuid?: string localServerIp?: string[] localServerPort: string webWrt?: boolean requestPortNumber: string globalIpAddress: string } interface QTGateAPIRequestCommand { command: string subCom: string myIpServer?: QTGate_DnsAddress [] account?: string error: number requestSerial?: string Args: any fingerprint?: string dataTransfer?: iTransferData requestTimes?: number region?: string CallBack?: any } interface QTGateCommand { account: string QTGateVersion: string command: string imapData?: IinputData language: string error: Error callback: any publicKey: string } interface IQTGateRegionsSetup { title: string } interface QTGateRegions { icon: string content: string[] description: string[] meta: string[] canVoe: KnockoutObservable < boolean > canVoH: KnockoutObservable < boolean > available: KnockoutObservable < boolean > selected: KnockoutObservable < boolean > showExtraContent: KnockoutObservable < boolean > QTGateRegionsSetup: IQTGateRegionsSetup[] qtRegion: string error: KnockoutObservable showRegionConnectProcessBar: KnockoutObservable < boolean > showConnectedArea: KnockoutObservable < boolean > ping: KnockoutObservable downloadSpeed: KnockoutObservable freeUser: KnockoutObservable < boolean > } interface domainData { dns: dnsAddress[] expire: number } interface dnsAddress { address: string family: number expire: Date connect: Date [] } interface VE_IPptpStream1 { type?: string; buffer: string; host: string; port: number; cmd: number; ATYP: number; uuid?: string; length?:number; randomBuffer?: any ssl: boolean } interface proxyServerInfo { serverAddress: string serverPort: number password: string allToGateway: boolean localPort: number } interface iQTGatePayment { cardNumber?: string cardExpirationYear?: string cardPostcode?: string cardcvc?: string tokenID?: string isAnnual: boolean plan: string Amount: number autoRenew: boolean } interface twitter_entities_media { } interface twitter_entities_urls { display_url: string expanded_url: string indices: string[] url: string } interface twitter_entities { hashtags: any[] media: twitter_entities_media[] symbols: any[] urls: twitter_entities_urls[] } interface tweetCountSummary { } interface twitter_post { order: number contributors: any coordinates: any created_at: string QTGate_created_at: KnockoutComputed< string > entities: any favorite_count: number favorite_count_ko : KnockoutObservable < number > favorited_ko: KnockoutObservable < boolean > favoritedLoader_ko: KnockoutObservable < boolean > favorited: boolean geo: any id: number id_str: string in_reply_to_screen_name: any in_reply_to_status_id: any in_reply_to_status_id_str: any in_reply_to_user_id: any in_reply_to_user_id_str: any is_quote_status: boolean quoted_status: twitter_post lang: string full_text: string full_text_split_line: string retweeted_status: twitter_post place: any possibly_sensitive: boolean possibly_sensitive_appealable: boolean retweet_count: number retweeted: twitter_post extended_entities: twitter_extended_entities source: string text: string truncated: boolean user: Twitter_verify_credentials tweetCountSummary: tweetCountSummary showUser: KnockoutObservable < boolean > CoNET_totalTwitter: number CoNET_currentTwitter: number } interface twitter_size { h: number resize: string w: number } interface twitter_media_video_info_variants { bitrate: number content_type: string url: string } interface twitter_media_video_info { aspect_ratio: number [] duration_millis: number variants: twitter_media_video_info_variants[] QTDownload: string } interface twitter_media { display_url?: string expanded_url?: string id?: number id_str?: string indices?: number [] media_url?: string media_url_https?: string sizes?: { large: twitter_size medium: twitter_size small: twitter_size thumb: twitter_size } type?: string // photo url?: string video_info: twitter_media_video_info } interface twitter_extended_entities extends twitter_post { media: twitter_media[] } interface twitter_mediaData { total_bytes: number media_type: string rawData: string media_id_string: string } interface twitter_postData { text: string images: string[] media_data: twitter_mediaData[] videoSize: number videoFileName: string uuid: string } interface twitter_uploadImageInitData_imageObj { image_type: string w: number h: number } interface twitter_uploadImageInitData { media_id: number media_id_string: string size: number expires_after_secs: number image: twitter_uploadImageInitData_imageObj } interface twitter_uploadImageInitData_status_processing_info { state: string // in_progress, failed, succeeded check_after_secs: number progress_percent: number error?: { code: number name: string message: string } } interface twitter_uploadImageInitData_status { media_id: number media_id_string: string expires_after_secs: number processing_info: twitter_uploadImageInitData_status_processing_info } interface TwitterAccount { consumer_key: string consumer_secret: string access_token_key: string access_token_secret: string twitter_verify_credentials?: Twitter_verify_credentials } interface Twitter_verify_credentials { id: number id_str: string name: string screen_name: string location: string description: string url: string entities: any protected: boolean followers_count: number friends_count: number listed_count: number created_at: string favourites_count: number utc_offset: number time_zone: string geo_enabled: boolean verified: boolean statuses_count: number lang: string status: Titter_status contributors_enabled: boolean is_translator: boolean is_translation_enabled: boolean profile_background_color: string profile_background_image_url: string profile_background_image_url_https: string profile_background_tile: boolean profile_image_url: string profile_image_url_https: string profile_banner_url: string profile_link_color: string profile_sidebar_border_color: string profile_sidebar_fill_color: string profile_text_color: string profile_use_background_image: boolean has_extended_profile: boolean default_profile: boolean default_profile_image: boolean following: boolean follow_request_sent: boolean notifications: boolean translator_type: string } interface Titter_status { created_at: string id: number id_str: string text: string truncated: boolean entities: any source: string in_reply_to_status_id: any in_reply_to_status_id_str: any in_reply_to_user_id: any in_reply_to_user_id_str: any in_reply_to_screen_name: any geo: any coordinates: any place: any contributors: any retweeted_status: Titter_status is_quote_status: boolean retweet_count: number favorite_count: number favorited: boolean retweeted: boolean possibly_sensitive: boolean lang: string } interface twitter_text_parseTweet { weightedLength: number valid: boolean permillage: number validRangeStart: number validRangeEnd: number displayRangeStart: number displayRangeEnd: number } interface install_config { alreadyInit: boolean multiLogin: boolean firstRun: boolean version: string newVersion?: string newVersionCheckFault?: boolean newVersionDownloadFault?: number newVerReady?: boolean keypair: keypair iterations: number salt?: any keylen?: number digest?: string freeUser: boolean connectedImapDataUuid: string account: string serverGlobalIpAddress: string serverPort: number connectedQTGateServer: boolean // true when connect to QTGate network lastConnectType: number localIpAddress: any[] } interface Jimp { read( ...args: any): any } declare namespace SemanticUI { } declare namespace SocketIOClient { interface Emitter { emit11 emit22 } } interface DateConstructor { isLeapYear: ( year: number ) => boolean getDaysInMonth: (year: number, month: number ) => number } interface Date { isLeapYear: ()=> boolean getDaysInMonth: () => number addMonths: ( n: number ) => Date } interface coSearch_Object { command: string args: string[] screenSize_x: number screenSize_y: number } interface JQuery extends Iterable { //css(properties: JQuery.PlainObject string | number | void | undefined)>): this; /** * Get the computed style properties for the first element in the set of matched elements. * * @param propertyName A CSS property. * An array of one or more CSS properties. * @see {@link https://api.jquery.com/css/} * @since 1.0 */ //css(propertyName: string): string; /** * Get the computed style properties for the first element in the set of matched elements. * * @param propertyNames An array of one or more CSS properties. * @see {@link https://api.jquery.com/css/} * @since 1.9 */ //css(propertyNames: string[]): JQuery.PlainObject; progress(k?:any ): any transition(k?:any): any dropdown(k?:any):any popup(k?:any): any shape(k?:any):any dimmer(k?:any):any checkbox(k?:any): any } interface JQueryStatic { //'langEH', this.tLang(), { expires: 180, path: '/' } cookie( ...obj:any): any } ================================================ FILE: app/localWebServer.js ================================================ "use strict"; /*! * Copyright 2018 CoNET Technology Inc. All Rights Reserved. * * 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. */ Object.defineProperty(exports, "__esModule", { value: true }); const Express = require("express"); const Path = require("path"); const HTTP = require("http"); const SocketIo = require("socket.io"); const Tool = require("./tools/initSystem"); const Async = require("async"); const Fs = require("fs"); const Util = require("util"); const Uuid = require("node-uuid"); const Imap = require("./tools/imap"); const coNETConnect_1 = require("./tools/coNETConnect"); const Crypto = require("crypto"); const mime = require("mime-types"); Express.static.mime.define({ 'multipart/related': ['mht'] }); //Express.static.mime.define({ 'message/rfc822' : ['mhtml','mht'] }) Express.static.mime.define({ 'application/x-mimearchive': ['mhtml', 'mht'] }); Express.static.mime.define({ 'multipart/related': ['mhtml', 'mht'] }); let logFileFlag = 'w'; const conetImapAccount = /^qtgate_test\d\d?@icloud.com$/i; const saveLog = (err) => { if (!err) { return; } const data = `${new Date().toUTCString()}: ${typeof err === 'object' ? (err['message'] ? err['message'] : '') : err}\r\n`; console.log(data); return Fs.appendFile(Tool.ErrorLogFile, data, { flag: logFileFlag }, () => { return logFileFlag = 'a'; }); }; const saveServerStartup = (localIpaddress) => { const info = `\n*************************** CoNET Platform [ ${Tool.CoNET_version} ] server start up *****************************\n` + `Access url: http://${localIpaddress}:${Tool.LocalServerPortNumber}\n`; saveLog(info); }; const saveServerStartupError = (err) => { const info = `\n*************************** CoNET Platform [ ${Tool.CoNET_version} ] server startup falied *****************************\n` + `platform ${process.platform}\n` + `${err['message']}\n`; saveLog(info); }; const imapErrorCallBack = (message) => { if (message && message.length) { if (/auth|login|log in|Too many simultaneous|UNAVAILABLE/i.test(message)) { return 1; } if (/ECONNREFUSED/i.test(message)) { return 5; } if (/OVERQUOTA/i.test(message)) { return 6; } if (/certificate/i.test(message)) { return 2; } if (/timeout|ENOTFOUND/i.test(message)) { return 0; } return 5; } return -1; }; class localServer { constructor(cmdResponse, test) { this.cmdResponse = cmdResponse; this.expressServer = Express(); this.httpServer = HTTP.createServer(this.expressServer); this.socketServer = SocketIo(this.httpServer); this.socketServer_CoSearch = this.socketServer.of('/CoSearch'); this.config = null; this.keyPair = null; this.savedPasswrod = ''; this.imapConnectData = null; this.localConnected = new Map(); this.CoNETConnectCalss = null; this.openPgpKeyOption = null; this.sessionHashPool = []; this.Pbkdf2Password = null; this.nodeList = [{ email: 'node@Kloak.app', keyID: '', key: '' }]; this.requestPool = new Map(); //Express.static.mime.define({ 'message/rfc822' : ['mhtml','mht'] }) //Express.static.mime.define ({ 'multipart/related' : ['mhtml','mht'] }) Express.static.mime.define({ 'application/x-mimearchive': ['mhtml', 'mht'] }); this.expressServer.set('views', Path.join(__dirname, 'views')); this.expressServer.set('view engine', 'pug'); this.expressServer.use(Express.static(Tool.QTGateFolder)); this.expressServer.use(Express.static(Path.join(__dirname, 'public'))); this.expressServer.use(Express.static(Path.join(__dirname, 'html'))); this.expressServer.get('/', (req, res) => { res.render('home', { title: 'home', proxyErr: false }); }); this.socketServer.on('connection', socker => { return this.socketServerConnected(socker); }); this.httpServer.once('error', err => { console.log(`httpServer error`, err); saveServerStartupError(err); return process.exit(1); }); Async.series([ next => Tool.checkSystemFolder(next), next => Tool.checkConfig(next) ], (err, data) => { if (err) { return saveServerStartupError(err); } this.config = data['1']; if (!test) { this.httpServer.listen(Tool.LocalServerPortNumber, () => { return saveServerStartup(`localhost`); }); } }); } catchCmd(mail, uuid) { if (!this.imapConnectData.sendToQTGate) { this.imapConnectData.sendToQTGate = true; Tool.saveEncryptoData(Tool.imapDataFileName1, this.imapConnectData, this.config, this.savedPasswrod, err => { }); } console.log(`Get response from CoNET uuid [${uuid}] length [${mail.length}]`); const socket = this.requestPool.get(uuid); if (!socket) { return console.log(`Get cmd that have no matched socket \n\n`, mail); } socket.emit('doingRequest', mail, uuid); } tryConnectCoNET(socket, sessionHash) { console.log(`doing tryConnectCoNET`); // have CoGate connect if (this.CoNETConnectCalss) { return this.CoNETConnectCalss.Ping(); } let sendMail = false; const _exitFunction = err => { console.trace(`makeConnect on _exitFunction err this.CoNETConnectCalss destroy!`, err); this.CoNETConnectCalss = null; }; const makeConnect = () => { return this.CoNETConnectCalss = new coNETConnect_1.default(this.imapConnectData, this.socketServer, !this.imapConnectData.sendToQTGate, this.nodeList[0].email, this.openPgpKeyOption, this.keyPair.publicKey, (mail, uuid) => { return this.catchCmd(mail, uuid); }, _exitFunction); }; return makeConnect(); } listenAfterPassword(socket, sessionHash) { socket.on('checkImap', (emailAddress, password, timeZone, tLang, CallBack1) => { CallBack1(); console.log(`localServer on checkImap!`); const imapServer = Tool.getImapSmtpHost(emailAddress); this.imapConnectData = { email: this.config.account, account: this.config.account, smtpServer: imapServer.smtp, smtpUserName: emailAddress, smtpPortNumber: imapServer.SmtpPort, smtpSsl: imapServer.smtpSsl, smtpIgnoreCertificate: false, smtpUserPassword: password, imapServer: imapServer.imap, imapPortNumber: imapServer.ImapPort, imapSsl: imapServer.imapSsl, imapUserName: emailAddress, imapIgnoreCertificate: false, imapUserPassword: password, timeZoneOffset: timeZone, language: tLang, imapTestResult: null, clientFolder: Uuid.v4(), serverFolder: Uuid.v4(), randomPassword: Uuid.v4(), uuid: Uuid.v4(), confirmRisk: false, clientIpAddress: null, ciphers: null, sendToQTGate: false }; return this.doingCheckImap(socket); }); socket.on('tryConnectCoNET', CallBack1 => { const uuid = Uuid.v4(); CallBack1(uuid); const _callBack = (...data) => { socket.emit(uuid, ...data); }; console.log(`socket on tryConnectCoNET!\n\n`); if (!this.imapConnectData) { console.log(`socket.on ( 'tryConnectCoNET') !this.imapConnectData \n\n `); return _callBack('systemError'); } if (!this.imapConnectData.confirmRisk) { this.imapConnectData.confirmRisk = true; return Tool.saveEncryptoData(Tool.imapDataFileName1, this.imapConnectData, this.config, this.savedPasswrod, err => { return this.tryConnectCoNET(socket, sessionHash); }); } return this.tryConnectCoNET(socket, sessionHash); }); socket.on('sendRequestMail', CallBack1 => { CallBack1(); if (!this.CoNETConnectCalss) { return console.log(`localServer on sendRequestMail Error! have no this.CoNETConnectCalss!`); } socket.emit('tryConnectCoNETStage', null, 2, false); if (this.CoNETConnectCalss) { console.log(`localWebServer on sendRequestMail !`); return this.CoNETConnectCalss.sendRequestMail(); } console.log(`localWebServer on sendRequestMail have no CoNETConnectCalss create CoNETConnectCalss`); return this.tryConnectCoNET(socket, sessionHash); }); socket.on('checkActiveEmailSubmit', (text, CallBack1) => { const uuid = Uuid.v4(); CallBack1(uuid); const _callBack = (...data) => { socket.emit(uuid, ...data); }; const key = Buffer.from(text, 'base64').toString(); console.log(`checkActiveEmailSubmit`, key); if (key && key.length) { console.log(`active key success! \n[${key}]`); this.keyPair.publicKey = this.config.keypair.publicKey = key; this.keyPair.verified = this.config.keypair.verified = true; this.imapConnectData.sendToQTGate = true; _callBack(); Tool.saveEncryptoData(Tool.imapDataFileName1, this.imapConnectData, this.config, this.savedPasswrod, err => { if (err) { saveLog(`Tool.saveConfig return Error: [${err.message}]`); } }); return Tool.saveConfig(this.config, err => { if (err) { saveLog(`Tool.saveConfig return Error: [${err.message}]`); } }); } }); socket.on('doingRequest', (uuid, request, CallBack1) => { const _uuid = Uuid.v4(); CallBack1(_uuid); const _callBack = (...data) => { socket.emit(_uuid, ...data); }; this.requestPool.set(uuid, socket); console.log(`on doingRequest uuid = [${uuid}]\n${request}\n`); if (this.CoNETConnectCalss) { saveLog(`doingRequest on ${uuid}`); return this.CoNETConnectCalss.requestCoNET_v1(uuid, request, _callBack); } saveLog(`doingRequest on ${uuid} but have not CoNETConnectCalss need restart! socket.emit ( 'systemErr' )`); socket.emit('systemErr'); }); socket.on('getFilesFromImap', (files, CallBack1) => { const uuid = Uuid.v4(); CallBack1(uuid); const _callBack = (...data) => { socket.emit(uuid, ...data); }; if (typeof files !== 'string' || !files.length) { return _callBack(new Error('invalidRequest')); } const _files = files.split(','); console.log(`socket.on ('getFilesFromImap') _files = [${_files}] _files.length = [${_files.length}]`); let ret = ''; return Async.eachSeries(_files, (n, next) => { console.log(`Async.eachSeries _files[${n}]`); return this.CoNETConnectCalss.getFile(n, (err, data) => { if (err) { return next(err); } ret += data.toString(); return next(); }); }, err => { if (err) { return _callBack(err); } //console.log (`******************** getFilesFromImap success all [${ ret.length }] fies!\n\n${ ret }\n\n`) return _callBack(null, ret); }); }); socket.on('sendMedia', (uuid, rawData, CallBack1) => { const _uuid = Uuid.v4(); CallBack1(_uuid); const _callBack = (...data) => { socket.emit(_uuid, ...data); }; return this.CoNETConnectCalss.sendDataToANewUuidFolder(Buffer.from(rawData).toString('base64'), uuid, uuid, _callBack); }); socket.on('mime', (_mime, CallBack1) => { const _uuid = Uuid.v4(); CallBack1(_uuid); const _callBack = (...data) => { socket.emit(_uuid, ...data); }; let y = mime.lookup(_mime); if (!y) { return _callBack(new Error('no mime')); } return _callBack(null, y); }); /* socket.on ('getUrl', ( url: string, CallBack ) => { const uu = new URLSearchParams ( url ) if ( !uu || typeof uu.get !== 'function' ) { console.log (`getUrl [${ url }] have not any URLSearchParams`) return CallBack () } return CallBack ( null, uu.get('imgrefurl'), uu.get('/imgres?imgurl')) }) */ } doingCheckImap(socket) { this.imapConnectData.imapTestResult = false; return Async.series([ next => Imap.imapAccountTest(this.imapConnectData, err => { if (err) { return next(err); } console.log(`imapAccountTest success!`, typeof next); socket.emit('imapTest'); return next(); }), next => Tool.smtpVerify(this.imapConnectData, next) ], (err) => { if (err) { console.log(`doingCheckImap Async.series Error!`, err); return socket.emit('smtpTest', imapErrorCallBack(err.message)); } this.imapConnectData.imapTestResult = true; return Tool.saveEncryptoData(Tool.imapDataFileName1, this.imapConnectData, this.config, this.savedPasswrod, err => { console.log(`socket.emit ( 'imapTestFinish' )`); socket.emit('imapTestFinish', this.imapConnectData); }); }); } socketServerConnected(socket) { const clientName = `[${socket.id}][ ${socket.conn.remoteAddress}]`; let sessionHash = ''; const clientObj = { listenAfterPasswd: false, socket: socket, login: false }; saveLog(`socketServerConnected ${clientName} connect ${this.localConnected.size}`); socket.once('init', Callback1 => { const uuid = Uuid.v4(); Callback1(uuid); const ret = Tool.emitConfig(this.config, false); //console.log ( Util.inspect( ret, false, 3, true )) //console.log ( `typeof Callback1 [${ typeof Callback1 }]`) return socket.emit(uuid, null, ret); }); socket.once('agreeClick', () => { this.config.firstRun = false; return Tool.saveConfig(this.config, saveLog); }); socket.on('checkPemPassword', (password, CallBack1) => { const uuid = Uuid.v4(); CallBack1(uuid); this.sessionHashPool.push(sessionHash = Crypto.randomBytes(10).toString('hex')); const passwordFail = (imap) => { //onsole.log (`passwordFail this.Pbkdf2Password = [${ this.Pbkdf2Password }]`) return socket.emit(uuid, null, imap, this.Pbkdf2Password, sessionHash); }; if (!this.config.keypair || !this.config.keypair.publicKey) { console.log(`checkPemPassword !this.config.keypair`); return passwordFail(true); } if (!password || password.length < 5) { console.log(`! password `); return passwordFail(true); } if (this.savedPasswrod && this.savedPasswrod.length) { if (this.savedPasswrod !== password) { console.log(`savedPasswrod !== password `); return passwordFail(true); } this.listenAfterPassword(socket, sessionHash); return passwordFail(this.imapConnectData); } return Async.waterfall([ next => Tool.getPbkdf2(this.config, password, next), (Pbkdf2Password, next) => { this.Pbkdf2Password = Pbkdf2Password.toString('hex'); Tool.getKeyPairInfo(this.config.keypair.publicKey, this.config.keypair.privateKey, this.Pbkdf2Password, next); }, (key, next) => { //console.log ( `checkPemPassword Tool.getKeyPairInfo success!`) if (!key.passwordOK) { this.Pbkdf2Password = null; saveLog(`[${clientName}] on checkPemPassword had try password! [${password}]`); return passwordFail(true); } //console.log (`checkPemPassword this.Pbkdf2Password = [${ this.Pbkdf2Password}]`) this.savedPasswrod = password; this.keyPair = key; clientObj.listenAfterPasswd = clientObj.login = true; this.localConnected.set(clientName, clientObj); return Tool.makeGpgKeyOption(this.config, this.savedPasswrod, next); }, (option_KeyOption, next) => { console.log(`checkPemPassword Tool.makeGpgKeyOption success!`); this.openPgpKeyOption = option_KeyOption; return Tool.readEncryptoFile(Tool.imapDataFileName1, password, this.config, next); } ], (err, data) => { console.log(`checkPemPassword Async.waterfall success!`); if (err) { if (!(err.message && /no such file/i.test(err.message))) { passwordFail(err); return saveLog(`Tool.makeGpgKeyOption return err [${err && err.message ? err.message : null}]`); } } // console.log (`this.sessionHashPool.push!\n${ this.sessionHashPool }\n${ this.sessionHashPool.length }`) this.listenAfterPassword(socket, sessionHash); try { this.imapConnectData = JSON.parse(data); } catch (ex) { return passwordFail(ex); } this.localConnected.set(clientName, clientObj); return passwordFail(this.imapConnectData); }); }); socket.on('deleteKeyPairNext', CallBack1 => { CallBack1(); console.log(`on deleteKeyPairNext`); const thisConnect = this.localConnected.get(clientName); if (this.localConnected.size > 1 && thisConnect && !thisConnect.login) { console.log(`this.localConnected = [${Util.inspect(this.localConnected, false, 2, true)}], thisConnect.login = [${thisConnect.login}]`); return this.socketServer.emit('deleteKeyPairNoite'); } const info = `socket on deleteKeyPairNext, delete key pair now.`; saveLog(info); this.config = Tool.InitConfig(); this.config.firstRun = false; this.keyPair = null; Tool.saveConfig(this.config, saveLog); if (this.CoNETConnectCalss) { this.CoNETConnectCalss.destroy(2); this.CoNETConnectCalss = null; } sessionHash = ''; Tool.deleteImapFile(); return this.socketServer.emit('init', null, this.config); }); socket.on('NewKeyPair', (preData, CallBack1) => { const uuid = Uuid.v4(); CallBack1(uuid); const _callBack = (...data) => { socket.emit(uuid, ...data); }; // already have key pair if (this.config.keypair && this.config.keypair.createDate) { return saveLog(`[${clientName}] on NewKeyPair but system already have keypair: ${this.config.keypair.publicKeyID} stop and return keypair.`); } this.savedPasswrod = preData.password; return Tool.getPbkdf2(this.config, this.savedPasswrod, (err, Pbkdf2Password) => { if (err) { saveLog(`NewKeyPair getPbkdf2 Error: [${err.message}]`); return _callBack('systemError'); } preData.password = Pbkdf2Password.toString('hex'); //console.log (`preData.password = [${ preData.password }]`) return Tool.newKeyPair(preData.email, preData.nikeName, preData.password, (err, retData) => { if (err) { console.log(err); _callBack(); return saveLog(`CreateKeyPairProcess return err: [${err.message}]`); } if (!retData) { const info = `newKeyPair return null key!`; saveLog(info); console.log(info); return _callBack(); } if (!clientObj.listenAfterPasswd) { clientObj.listenAfterPasswd = clientObj.login = true; this.localConnected.set(clientName, clientObj); this.sessionHashPool.push(sessionHash = Crypto.randomBytes(10).toString('hex')); //console.log ( `this.sessionHashPool.push!\n${ this.sessionHashPool }\n${ this.sessionHashPool.length }`) this.listenAfterPassword(socket, sessionHash); } return Tool.getKeyPairInfo(retData.publicKey, retData.privateKey, preData.password, (err, key) => { if (err) { const info = `Tool.getKeyPairInfo Error [${err.message ? err.message : 'null err message '}]`; return _callBack('systemError'); } this.keyPair = this.config.keypair = key; this.config.account = this.config.keypair.email; return Tool.makeGpgKeyOption(this.config, this.savedPasswrod, (err, data) => { if (err) { return saveLog(err.message); } this.openPgpKeyOption = data; Tool.saveConfig(this.config, saveLog); return _callBack(null, this.config.keypair, sessionHash); }); }); }); }); }); } } exports.default = localServer; ================================================ FILE: app/localWebServer.ts ================================================ /*! * Copyright 2018 CoNET Technology Inc. All Rights Reserved. * * 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. */ import * as Express from 'express' import * as Path from 'path' import * as HTTP from 'http' import * as SocketIo from 'socket.io' import * as Tool from './tools/initSystem' import * as Async from 'async' import * as Fs from 'fs' import * as Util from 'util' import * as Uuid from 'node-uuid' import * as Imap from './tools/imap' import CoNETConnectCalss from './tools/coNETConnect' import * as Crypto from 'crypto' import * as mime from 'mime-types' Express.static.mime.define({ 'multipart/related': ['mht'] }) //Express.static.mime.define({ 'message/rfc822' : ['mhtml','mht'] }) Express.static.mime.define({ 'application/x-mimearchive' : ['mhtml','mht'] }) Express.static.mime.define({ 'multipart/related' : ['mhtml','mht'] }) interface localConnect { socket: SocketIO.Socket login: boolean listenAfterPasswd: boolean } let logFileFlag = 'w' const conetImapAccount = /^qtgate_test\d\d?@icloud.com$/i const saveLog = ( err: {} | string ) => { if ( !err ) { return } const data = `${ new Date().toUTCString () }: ${ typeof err === 'object' ? ( err['message'] ? err['message'] : '' ) : err }\r\n` console.log ( data ) return Fs.appendFile ( Tool.ErrorLogFile, data, { flag: logFileFlag }, () => { return logFileFlag = 'a' }) } const saveServerStartup = ( localIpaddress: string ) => { const info = `\n*************************** CoNET Platform [ ${ Tool.CoNET_version } ] server start up *****************************\n` + `Access url: http://${localIpaddress}:${ Tool.LocalServerPortNumber }\n` saveLog ( info ) } const saveServerStartupError = ( err: {} ) => { const info = `\n*************************** CoNET Platform [ ${ Tool.CoNET_version } ] server startup falied *****************************\n` + `platform ${ process.platform }\n` + `${ err['message'] }\n` saveLog ( info ) } const imapErrorCallBack = ( message: string ) => { if ( message && message.length ) { if ( /auth|login|log in|Too many simultaneous|UNAVAILABLE/i.test( message )) { return 1 } if ( /ECONNREFUSED/i.test ( message )) { return 5 } if (/OVERQUOTA/i.test ( message )) { return 6 } if ( /certificate/i.test ( message )) { return 2 } if ( /timeout|ENOTFOUND/i.test ( message )) { return 0 } return 5 } return -1 } export default class localServer { private expressServer = Express() private httpServer = HTTP.createServer ( this.expressServer ) private socketServer = SocketIo ( this.httpServer ) private socketServer_CoSearch = this.socketServer.of ('/CoSearch') public config: install_config = null public keyPair: keypair = null public savedPasswrod: string = '' public imapConnectData: IinputData = null public localConnected: Map < string, localConnect > = new Map () private CoNETConnectCalss: CoNETConnectCalss = null private openPgpKeyOption = null private sessionHashPool = [] private Pbkdf2Password = null private nodeList = [{ email: 'node@Kloak.app', keyID:'', key: '' }] private requestPool: Map < string, SocketIO.Socket > = new Map() private catchCmd ( mail: string, uuid: string ) { if ( !this.imapConnectData.sendToQTGate ) { this.imapConnectData.sendToQTGate = true Tool.saveEncryptoData ( Tool.imapDataFileName1, this.imapConnectData, this.config, this.savedPasswrod, err => { }) } console.log ( `Get response from CoNET uuid [${ uuid }] length [${ mail.length }]`) const socket = this.requestPool.get ( uuid ) if ( !socket ) { return console.log (`Get cmd that have no matched socket \n\n`, mail ) } socket.emit ( 'doingRequest', mail, uuid ) } private tryConnectCoNET ( socket: SocketIO.Socket, sessionHash: string ) { console.log (`doing tryConnectCoNET`) // have CoGate connect if ( this.CoNETConnectCalss ) { return this.CoNETConnectCalss.Ping() } let sendMail = false const _exitFunction = err => { console.trace ( `makeConnect on _exitFunction err this.CoNETConnectCalss destroy!`, err ) this.CoNETConnectCalss = null } const makeConnect = () => { return this.CoNETConnectCalss = new CoNETConnectCalss ( this.imapConnectData, this.socketServer, !this.imapConnectData.sendToQTGate, this.nodeList[0].email, this.openPgpKeyOption, this.keyPair.publicKey, ( mail, uuid ) => { return this.catchCmd ( mail, uuid ) }, _exitFunction ) } return makeConnect () } private listenAfterPassword ( socket: SocketIO.Socket, sessionHash: string ) { socket.on ( 'checkImap', ( emailAddress: string, password: string, timeZone, tLang, CallBack1 ) => { CallBack1() console.log (`localServer on checkImap!`) const imapServer = Tool.getImapSmtpHost( emailAddress ) this.imapConnectData = { email: this.config.account, account: this.config.account, smtpServer: imapServer.smtp, smtpUserName: emailAddress, smtpPortNumber: imapServer.SmtpPort, smtpSsl: imapServer.smtpSsl, smtpIgnoreCertificate: false, smtpUserPassword: password, imapServer: imapServer.imap, imapPortNumber: imapServer.ImapPort, imapSsl: imapServer.imapSsl, imapUserName: emailAddress, imapIgnoreCertificate: false, imapUserPassword: password, timeZoneOffset: timeZone, language: tLang, imapTestResult: null, clientFolder: Uuid.v4(), serverFolder: Uuid.v4(), randomPassword: Uuid.v4(), uuid: Uuid.v4(), confirmRisk: false, clientIpAddress: null, ciphers: null, sendToQTGate: false } return this.doingCheckImap ( socket ) }) socket.on ( 'tryConnectCoNET', CallBack1 => { const uuid = Uuid.v4() CallBack1( uuid ) const _callBack = ( ...data ) => { socket.emit ( uuid, ...data ) } console.log (`socket on tryConnectCoNET!\n\n`) if ( !this.imapConnectData ) { console.log (`socket.on ( 'tryConnectCoNET') !this.imapConnectData \n\n `) return _callBack ( 'systemError' ) } if ( !this.imapConnectData.confirmRisk ) { this.imapConnectData.confirmRisk = true return Tool.saveEncryptoData ( Tool.imapDataFileName1, this.imapConnectData, this.config, this.savedPasswrod, err => { return this.tryConnectCoNET ( socket, sessionHash ) }) } return this.tryConnectCoNET ( socket, sessionHash ) }) socket.on ( 'sendRequestMail', CallBack1 => { CallBack1 () if ( !this.CoNETConnectCalss ) { return console.log (`localServer on sendRequestMail Error! have no this.CoNETConnectCalss!`) } socket.emit ( 'tryConnectCoNETStage', null, 2, false ) if ( this.CoNETConnectCalss ) { console.log (`localWebServer on sendRequestMail !`) return this.CoNETConnectCalss.sendRequestMail () } console.log (`localWebServer on sendRequestMail have no CoNETConnectCalss create CoNETConnectCalss`) return this.tryConnectCoNET ( socket, sessionHash ) }) socket.on ( 'checkActiveEmailSubmit', ( text, CallBack1 ) => { const uuid = Uuid.v4() CallBack1( uuid ) const _callBack = ( ...data ) => { socket.emit ( uuid, ...data ) } const key = Buffer.from ( text, 'base64' ).toString () console.log (`checkActiveEmailSubmit`, key ) if ( key && key.length ) { console.log ( `active key success! \n[${ key }]`) this.keyPair.publicKey = this.config.keypair.publicKey = key this.keyPair.verified = this.config.keypair.verified = true this.imapConnectData.sendToQTGate = true _callBack () Tool.saveEncryptoData ( Tool.imapDataFileName1, this.imapConnectData, this.config, this.savedPasswrod, err => { if ( err ) { saveLog (`Tool.saveConfig return Error: [${ err.message }]`) } }) return Tool.saveConfig ( this.config, err => { if ( err ) { saveLog (`Tool.saveConfig return Error: [${ err.message }]`) } }) } }) socket.on ( 'doingRequest', ( uuid, request, CallBack1 ) => { const _uuid = Uuid.v4() CallBack1 ( _uuid ) const _callBack = ( ...data ) => { socket.emit ( _uuid, ...data ) } this.requestPool.set ( uuid, socket ) console.log (`on doingRequest uuid = [${ uuid }]\n${ request }\n`) if ( this.CoNETConnectCalss ) { saveLog (`doingRequest on ${ uuid }`) return this.CoNETConnectCalss.requestCoNET_v1 ( uuid, request, _callBack ) } saveLog ( `doingRequest on ${ uuid } but have not CoNETConnectCalss need restart! socket.emit ( 'systemErr' )`) socket.emit ( 'systemErr' ) }) socket.on ( 'getFilesFromImap', ( files: string, CallBack1 ) => { const uuid = Uuid.v4() CallBack1( uuid ) const _callBack = ( ...data ) => { socket.emit ( uuid, ...data ) } if ( typeof files !== 'string' || !files.length ) { return _callBack ( new Error ('invalidRequest')) } const _files = files.split (',') console.log (`socket.on ('getFilesFromImap') _files = [${ _files }] _files.length = [${ _files.length }]` ) let ret = '' return Async.eachSeries ( _files, ( n, next ) => { console.log (`Async.eachSeries _files[${ n }]`) return this.CoNETConnectCalss.getFile ( n, ( err, data ) => { if ( err ) { return next ( err ) } ret += data.toString () return next () }) }, err => { if ( err ) { return _callBack ( err ) } //console.log (`******************** getFilesFromImap success all [${ ret.length }] fies!\n\n${ ret }\n\n`) return _callBack ( null, ret ) }) }) socket.on ( 'sendMedia', ( uuid, rawData, CallBack1 ) => { const _uuid = Uuid.v4() CallBack1( _uuid ) const _callBack = ( ...data ) => { socket.emit ( _uuid, ...data ) } return this.CoNETConnectCalss.sendDataToANewUuidFolder ( Buffer.from ( rawData ).toString ( 'base64' ), uuid, uuid, _callBack ) }) socket.on ( 'mime', ( _mime, CallBack1 ) => { const _uuid = Uuid.v4() CallBack1( _uuid ) const _callBack = ( ...data ) => { socket.emit ( _uuid, ...data ) } let y = mime.lookup( _mime ) if ( !y ) { return _callBack ( new Error ('no mime')) } return _callBack ( null, y ) }) /* socket.on ('getUrl', ( url: string, CallBack ) => { const uu = new URLSearchParams ( url ) if ( !uu || typeof uu.get !== 'function' ) { console.log (`getUrl [${ url }] have not any URLSearchParams`) return CallBack () } return CallBack ( null, uu.get('imgrefurl'), uu.get('/imgres?imgurl')) }) */ } private doingCheckImap ( socket: SocketIO.Socket ) { this.imapConnectData.imapTestResult = false return Async.series ([ next => Imap.imapAccountTest ( this.imapConnectData, err => { if ( err ) { return next ( err ) } console.log (`imapAccountTest success!`, typeof next ) socket.emit ( 'imapTest' ) return next () }), next => Tool.smtpVerify ( this.imapConnectData, next ) ], ( err: Error ) => { if ( err ) { console.log (`doingCheckImap Async.series Error!`, err ) return socket.emit ( 'smtpTest', imapErrorCallBack ( err.message )) } this.imapConnectData.imapTestResult = true return Tool.saveEncryptoData ( Tool.imapDataFileName1, this.imapConnectData, this.config, this.savedPasswrod, err => { console.log (`socket.emit ( 'imapTestFinish' )`) socket.emit ( 'imapTestFinish' , this.imapConnectData ) }) }) } private socketServerConnected ( socket: SocketIO.Socket ) { const clientName = `[${ socket.id }][ ${ socket.conn.remoteAddress }]` let sessionHash = '' const clientObj: localConnect = { listenAfterPasswd: false, socket: socket, login: false } saveLog ( `socketServerConnected ${ clientName } connect ${ this.localConnected.size }`) socket.once ( 'init', Callback1 => { const uuid = Uuid.v4() Callback1 ( uuid ) const ret = Tool.emitConfig ( this.config, false ) //console.log ( Util.inspect( ret, false, 3, true )) //console.log ( `typeof Callback1 [${ typeof Callback1 }]`) return socket.emit ( uuid, null, ret ) }) socket.once ( 'agreeClick', () => { this.config.firstRun = false return Tool.saveConfig ( this.config, saveLog ) }) socket.on ( 'checkPemPassword', ( password: string, CallBack1 ) => { const uuid = Uuid.v4() CallBack1 ( uuid ) this.sessionHashPool.push ( sessionHash = Crypto.randomBytes ( 10 ).toString ('hex')) const passwordFail = ( imap ) => { //onsole.log (`passwordFail this.Pbkdf2Password = [${ this.Pbkdf2Password }]`) return socket.emit ( uuid, null, imap, this.Pbkdf2Password, sessionHash ) } if ( !this.config.keypair || !this.config.keypair.publicKey ) { console.log ( `checkPemPassword !this.config.keypair` ) return passwordFail ( true ) } if ( !password || password.length < 5 ) { console.log (`! password `) return passwordFail ( true ) } if ( this.savedPasswrod && this.savedPasswrod.length ) { if ( this.savedPasswrod !== password ) { console.log ( `savedPasswrod !== password `) return passwordFail ( true ) } this.listenAfterPassword ( socket, sessionHash ) return passwordFail ( this.imapConnectData ) } return Async.waterfall ([ next => Tool.getPbkdf2 ( this.config, password, next ), ( Pbkdf2Password: Buffer, next ) => { this.Pbkdf2Password = Pbkdf2Password.toString ( 'hex' ) Tool.getKeyPairInfo ( this.config.keypair.publicKey, this.config.keypair.privateKey, this.Pbkdf2Password, next ) }, ( key, next ) => { //console.log ( `checkPemPassword Tool.getKeyPairInfo success!`) if ( ! key.passwordOK ) { this.Pbkdf2Password = null saveLog ( `[${ clientName }] on checkPemPassword had try password! [${ password }]` ) return passwordFail ( true ) } //console.log (`checkPemPassword this.Pbkdf2Password = [${ this.Pbkdf2Password}]`) this.savedPasswrod = password this.keyPair = key clientObj.listenAfterPasswd = clientObj.login = true this.localConnected.set ( clientName, clientObj ) return Tool.makeGpgKeyOption ( this.config, this.savedPasswrod, next ) }, ( option_KeyOption, next ) => { console.log (`checkPemPassword Tool.makeGpgKeyOption success!`) this.openPgpKeyOption = option_KeyOption return Tool.readEncryptoFile ( Tool.imapDataFileName1, password, this.config, next ) }], ( err: Error, data: string ) => { console.log (`checkPemPassword Async.waterfall success!`) if ( err ) { if ( !( err.message && /no such file/i.test( err.message ))) { passwordFail ( err ) return saveLog ( `Tool.makeGpgKeyOption return err [${ err && err.message ? err.message : null }]` ) } } // console.log (`this.sessionHashPool.push!\n${ this.sessionHashPool }\n${ this.sessionHashPool.length }`) this.listenAfterPassword ( socket, sessionHash ) try { this.imapConnectData = JSON.parse ( data ) } catch ( ex ) { return passwordFail ( ex ) } this.localConnected.set ( clientName, clientObj ) return passwordFail ( this.imapConnectData ) }) }) socket.on ( 'deleteKeyPairNext', CallBack1 => { CallBack1() console.log ( `on deleteKeyPairNext` ) const thisConnect = this.localConnected.get ( clientName ) if ( this.localConnected.size > 1 && thisConnect && ! thisConnect.login ) { console.log (`this.localConnected = [${ Util.inspect( this.localConnected, false, 2, true )}], thisConnect.login = [${ thisConnect.login }]`) return this.socketServer.emit ( 'deleteKeyPairNoite' ) } const info = `socket on deleteKeyPairNext, delete key pair now.` saveLog ( info ) this.config = Tool.InitConfig () this.config.firstRun = false this.keyPair = null Tool.saveConfig ( this.config, saveLog ) if ( this.CoNETConnectCalss ) { this.CoNETConnectCalss.destroy ( 2 ) this.CoNETConnectCalss = null } sessionHash = '' Tool.deleteImapFile () return this.socketServer.emit ( 'init', null, this.config ) }) socket.on ( 'NewKeyPair', ( preData: INewKeyPair, CallBack1 ) => { const uuid = Uuid.v4() CallBack1( uuid ) const _callBack = ( ...data ) => { socket.emit ( uuid, ...data ) } // already have key pair if ( this.config.keypair && this.config.keypair.createDate ) { return saveLog (`[${ clientName }] on NewKeyPair but system already have keypair: ${ this.config.keypair.publicKeyID } stop and return keypair.`) } this.savedPasswrod = preData.password return Tool.getPbkdf2 ( this.config, this.savedPasswrod, ( err, Pbkdf2Password: Buffer ) => { if ( err ) { saveLog ( `NewKeyPair getPbkdf2 Error: [${ err.message }]`) return _callBack ('systemError') } preData.password = Pbkdf2Password.toString ( 'hex' ) //console.log (`preData.password = [${ preData.password }]`) return Tool.newKeyPair( preData.email, preData.nikeName, preData.password, ( err, retData )=> { if ( err ) { console.log ( err ) _callBack () return saveLog (`CreateKeyPairProcess return err: [${ err.message }]`) } if ( ! retData ) { const info = `newKeyPair return null key!` saveLog ( info ) console.log ( info ) return _callBack ( ) } if ( !clientObj.listenAfterPasswd ) { clientObj.listenAfterPasswd = clientObj.login = true this.localConnected.set ( clientName, clientObj ) this.sessionHashPool.push ( sessionHash = Crypto.randomBytes (10).toString ('hex')) //console.log ( `this.sessionHashPool.push!\n${ this.sessionHashPool }\n${ this.sessionHashPool.length }`) this.listenAfterPassword ( socket, sessionHash ) } return Tool.getKeyPairInfo ( retData.publicKey, retData.privateKey, preData.password, ( err, key ) => { if ( err ) { const info = `Tool.getKeyPairInfo Error [${ err.message ? err.message : 'null err message '}]` return _callBack ( 'systemError' ) } this.keyPair = this.config.keypair = key this.config.account = this.config.keypair.email return Tool.makeGpgKeyOption ( this.config, this.savedPasswrod, ( err, data ) => { if ( err ) { return saveLog ( err.message ) } this.openPgpKeyOption = data Tool.saveConfig ( this.config, saveLog ) return _callBack ( null, this.config.keypair, sessionHash ) }) }) }) }) }) } constructor( private cmdResponse: ( cmd: QTGateAPIRequestCommand ) => void, test: boolean ) { //Express.static.mime.define({ 'message/rfc822' : ['mhtml','mht'] }) //Express.static.mime.define ({ 'multipart/related' : ['mhtml','mht'] }) Express.static.mime.define ({ 'application/x-mimearchive' : ['mhtml','mht'] }) this.expressServer.set ( 'views', Path.join ( __dirname, 'views' )) this.expressServer.set ( 'view engine', 'pug' ) this.expressServer.use ( Express.static ( Tool.QTGateFolder )) this.expressServer.use ( Express.static ( Path.join ( __dirname, 'public' ))) this.expressServer.use ( Express.static ( Path.join ( __dirname, 'html' ))) this.expressServer.get ( '/', ( req, res ) => { res.render( 'home', { title: 'home', proxyErr: false }) }) this.socketServer.on ( 'connection', socker => { return this.socketServerConnected ( socker ) }) this.httpServer.once ( 'error', err => { console.log (`httpServer error`, err ) saveServerStartupError ( err ) return process.exit (1) }) Async.series ([ next => Tool.checkSystemFolder ( next ), next => Tool.checkConfig ( next ) ], ( err, data ) => { if ( err ) { return saveServerStartupError ( err ) } this.config = data['1'] if ( !test ) { this.httpServer.listen ( Tool.LocalServerPortNumber, () => { return saveServerStartup ( `localhost`) }) } }) } } ================================================ FILE: app/main.js ================================================ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const localWebServer_1 = require("./localWebServer"); const test = /^true$/.test(process.argv[2]) ? true : false; const _start = process.argv[3] || false; exports.start = (cmd, _test) => { const localServer = new localWebServer_1.default(cmd, _test); }; if (_start) { exports.start(null, false); } ================================================ FILE: app/main.ts ================================================ /*! * Copyright 2018 CoNET Technology Inc. All Rights Reserved. * * 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. */ declare const process: any import LocalServer from './localWebServer' const test = /^true$/.test ( process.argv[2] ) ? true : false const _start = process.argv [3] || false export const start = ( cmd: () => void, _test ) => { const localServer = new LocalServer ( cmd, _test ) } if ( _start ) { start ( null, false ) } ================================================ FILE: app/package.json.npm ================================================ { "name": "conet", "version": "3.0.20", "license": "MIT", "description": "CoNET", "repository": { "type": "git", "url": "git+https://github.com/QTGate/CoNET.git" }, "author": { "name": "CoNET Technology Inc.", "email": "info@CoNETTech.ca" }, "main": "./main", "bugs": { "url": "https://github.com/QTGate/CoNET/issues" }, "homepage": "https://www.CoNETTech.ca", "dependencies": { "async": "^3.1.0", "cookie-parser": "^1.4.4", "express": "^4.17.1", "jimp": "^0.8.5", "jszip": "^3.2.2", "mime-types": "^2.1.24", "node-uuid": "^1.4.8", "nodemailer": "^6.3.1", "openpgp": "^4.6.2", "pug": "^2.0.4", "socket.io": "^2.3.0", "socket.io-client": "^2.3.0" }, "scripts": { "start": "node main false true" }, "devDependencies": { "@types/async": "^3.0.3", "@types/cleave.js": "^1.4.1", "@types/cookie-parser": "^1.4.2", "@types/express": "^4.17.1", "@types/jcanvas": "^15.2.2", "@types/jquery": "^3.3.31", "@types/jquery.cookie": "^1.4.31", "@types/knockout": "^3.4.66", "@types/openpgp": "^4.4.7", "@types/semantic-ui": "^2.2.7", "@types/socket.io": "^2.1.4", "@types/socket.io-client": "^1.4.32", "source-map-support": "^0.5.16" } } ================================================ FILE: app/public/css/c3.css ================================================ .c3 svg{font:10px sans-serif;-webkit-tap-highlight-color:transparent}.c3 line,.c3 path{fill:none;stroke:#000}.c3 text{-webkit-user-select:none;-moz-user-select:none;user-select:none}.c3-bars path,.c3-event-rect,.c3-legend-item-tile,.c3-xgrid-focus,.c3-ygrid{shape-rendering:crispEdges}.c3-chart-arc path{stroke:#fff}.c3-chart-arc text{fill:#fff;font-size:13px}.c3-grid line{stroke:#aaa}.c3-grid text{fill:#aaa}.c3-xgrid,.c3-ygrid{stroke-dasharray:3 3}.c3-text.c3-empty{fill:grey;font-size:2em}.c3-line{stroke-width:1px}.c3-circle._expanded_{stroke-width:1px;stroke:#fff}.c3-selected-circle{fill:#fff;stroke-width:2px}.c3-bar{stroke-width:0}.c3-bar._expanded_{fill-opacity:1;fill-opacity:.75}.c3-target.c3-focused{opacity:1}.c3-target.c3-focused path.c3-line,.c3-target.c3-focused path.c3-step{stroke-width:2px}.c3-target.c3-defocused{opacity:.3!important}.c3-region{fill:#4682b4;fill-opacity:.1}.c3-brush .extent{fill-opacity:.1}.c3-legend-item{font-size:12px}.c3-legend-item-hidden{opacity:.15}.c3-legend-background{opacity:.75;fill:#fff;stroke:#d3d3d3;stroke-width:1}.c3-title{font:14px sans-serif}.c3-tooltip-container{z-index:10}.c3-tooltip{border-collapse:collapse;border-spacing:0;background-color:#fff;empty-cells:show;-webkit-box-shadow:7px 7px 12px -9px #777;-moz-box-shadow:7px 7px 12px -9px #777;box-shadow:7px 7px 12px -9px #777;opacity:.9}.c3-tooltip tr{border:1px solid #ccc}.c3-tooltip th{background-color:#aaa;font-size:14px;padding:2px 5px;text-align:left;color:#fff}.c3-tooltip td{font-size:13px;padding:3px 6px;background-color:#fff;border-left:1px dotted #999}.c3-tooltip td>span{display:inline-block;width:10px;height:10px;margin-right:6px}.c3-tooltip td.value{text-align:right}.c3-area{stroke-width:0;opacity:.2}.c3-chart-arcs-title{dominant-baseline:middle;font-size:1.3em}.c3-chart-arcs .c3-chart-arcs-background{fill:#e0e0e0;stroke:none}.c3-chart-arcs .c3-chart-arcs-gauge-unit{fill:#000;font-size:16px}.c3-chart-arcs .c3-chart-arcs-gauge-max{fill:#777}.c3-chart-arcs .c3-chart-arcs-gauge-min{fill:#777}.c3-chart-arc .c3-gauge-value{fill:#000}.c3-chart-arc.c3-target g path{opacity:1}.c3-chart-arc.c3-target.c3-focused g path{opacity:1} ================================================ FILE: app/public/css/page.css ================================================ .bodyCoNETBlue { background: rgba(101,226,245,1); background: -moz-linear-gradient(left, rgba(101,226,245,1) 0%, rgba(125,175,250,1) 100%); background: -webkit-gradient(left top, right top, color-stop(0%, rgba(101,226,245,1)), color-stop(100%, rgba(125,175,250,1))); background: -webkit-linear-gradient(left, rgba(101,226,245,1) 0%, rgba(125,175,250,1) 100%); background: -o-linear-gradient(left, rgba(101,226,245,1) 0%, rgba(125,175,250,1) 100%); background: -ms-linear-gradient(left, rgba(101,226,245,1) 0%, rgba(125,175,250,1) 100%); background: linear-gradient(to right, rgba(101,226,245,1) 0%, rgba(125,175,250,1) 100%); filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#65e2f5', endColorstr='#7daffa', GradientType=1 ); height: unset!important; } .bodyWhite { background: white } .welcome-bg { position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: 9; display: -webkit-box; display: -ms-flexbox; display: flex; -ms-flex-pack: center; justify-content: center; -ms-flex-align: center; align-items: center; } .fade-up { opacity: 0; -webkit-animation: fade-up 1s forwards cubic-bezier(0.2, 2, 0.4, 1); animation: fade-up 1s forwards cubic-bezier(0.2, 2, 0.4, 1); } .languageText { width: 100%; -webkit-transition: opacity 0.4s ease-in-out; -moz-transition: opacity 0.4s ease-in-out; -ms-transition: opacity 0.4s ease-in-out; -o-transition: opacity 0.4s ease-in-out; transition: opacity 0.4s ease-in-out; opacity: 0.6; } #languageArea { z-index: 100; width: 160px; top: 15px; left: 20px; position: fixed; } .languageItem { cursor: pointer; color: white!important; } .languageText:hover { text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.4); opacity: 1; } .welcome { width: 100%; height: 100%; margin-bottom: 10em; display: -webkit-box; display: -ms-flexbox; display: flex; -ms-flex-pack: center; justify-content: center; -ms-flex-align: center; align-items: center; -ms-flex-direction: column; flex-direction: column; } .welcome h1.fade-up { font-weight: 300; font-size: 40px; -webkit-animation-delay: .25s; animation-delay: .25s; } .welcome h2.fade-up { font-weight: 400; color: rgba(255, 255, 255, 0.5); -webkit-animation-delay: .5s; animation-delay: .5s; } #agreement{ background-color: #d3d9db; width: 100%; position: absolute; transition: opacity 0.4s ease-in; top: 0px; } #agreement .firstNodeContent { margin: 0px auto; margin-top: 5em; max-width: 50em; } .detailSegment { margin: 3em; } .agreementButtom { margin: 3em; } .CoContent { width: 95%; position: relative; transition: opacity 0.4s ease-in; margin: auto; } .loginCards { margin: 0px auto!important; margin-top: 5em!important; max-width: 50em; } .CoGateCards { margin: 0px auto!important; margin-top: 1em!important; max-width: 45em; } .searchItems { margin: 0px auto!important; margin-top: 1em!important; max-width: 40em; } .background-clolr-white { background-color: transparent!important; } .displayNono { display: none; } .iconButton { cursor: pointer; -webkit-transition: opacity 0.2s ease-in-out; -moz-transition: opacity 0.2s ease-in-out; -ms-transition: opacity 0.2s ease-in-out; -o-transition: opacity 0.2s ease-in-out; transition: opacity 0.2s ease-in-out; opacity: 0.6!important; } .iconButton:hover { text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.4); opacity: 1!important; } .CoNET_info { text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.4); opacity: 0.7; padding-right: 1em; } .green { color: green!important; } .white { color: white; } .red { color: brown; } .yellow { color: yellow; } .grey { color: gray!important; } .QTGateGatewayCardHeader.active { color: yellowgreen!important; } .QTGateGatewayCardHeader { color: rgba(255,0,0,0.2)!important; } .plans { margin: 20px auto; width: 48em; zoom: 1; } .plans:before, .plans:after { content: ''; display: table; } .plans:after { clear: both; } .plan { float: left; width: 16em; margin: 10px 0; padding: 20px; text-align: center; background: #fafafa; background-clip: padding-box; border: solid #453b5d; border-width: 2px 0 2px 2px; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); } .plan:first-child { border-top-left-radius: 7px; border-bottom-left-radius: 7px; } .shadowText { text-shadow: 10px 10px 30px rgba(0, 0, 0, 0.4); } .shadowText1 { text-shadow: 2px 2px 5px rgba(0, 0, 0, 0.4); } .plan:last-child { border-width: 2px; border-top-right-radius: 7px; border-bottom-right-radius: 7px; } .plan-title { position: relative; margin: -20px -10px 20px; padding: 20px; line-height: 1; font-size: 16px; font-weight: bold; color: #595f6b; border-bottom: 1px dashed #d2d2d2; } .plan-title:before { content: ''; position: absolute; bottom: -1px; left: 0; right: 0; height: 1px; background-size: 3px 1px; background-image: -webkit-linear-gradient(left, white, white 33%, #d2d2d2 34%, #d2d2d2); background-image: -moz-linear-gradient(left, white, white 33%, #d2d2d2 34%, #d2d2d2); background-image: -o-linear-gradient(left, white, white 33%, #d2d2d2 34%, #d2d2d2); background-image: linear-gradient(to right, white, white 33%, #d2d2d2 34%, #d2d2d2); } .plan-price { margin: 0 auto 20px; width: 90px; height: 90px; line-height: 90px; font-size: 19px; font-weight: bold; color: white; background: #595f6b; border-radius: 45px; } .plan-price > span { font-size: 12px; font-weight: normal; color: rgba(255, 255, 255, 0.9); } .plan-features { margin-bottom: 20px; line-height: 2; font-size: 12px; color: #999; text-align: center; } .plan-tall { margin: 0; background-color: white; border-width: 2px; border-radius: 7px; } .plan-tall > .plan-title { font-size: 18px; } .plan-tall > .plan-price { width: 100px; height: 100px; line-height: 100px; font-size: 21px; border-radius: 50px; } .plan-tall > .plan-features { font-size: 13px; } .plan-tall > .plan-button { padding: 0 16px; line-height: 32px; } .plan-tall + .plan { border-left: 0; } .plan-features > li > strong { font-weight: bold; color: #888; padding-right: 1em; } ul.plan-features { list-style-type: none; padding: 0px; } .AppCardTop { max-width: 11em!important; } .AppCardImageArea { background: white!important; } .AppCardImage { max-width: 6em!important; } .AppListHeader { text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.4); } .hideCardImage { opacity: 0.2 } .usDollar { font-weight: lighter; font-style: italic; padding-left: 0.5em; font-size: smaller; } .amount { font-size: large; font-weight: bold; color: darkslategray; } .unavailable { background-color: rgba(0,0,0,.03)!important; opacity: 0.4 } @media only screen and ( max-width: 1144px ) { .TimelinesView { background-color: white; padding: 0em; padding-top: 4em; } #QTGateStartScreen { display: block; } #QTGateStartScreen-Device { display: none; } #TimelinesView { max-width:100%; margin: 0px auto; } .itemContent { max-width: 90%; } } @media only screen and (min-width: 992px) { } @media screen and ( max-width: 801px ) { .TimelinesView { background-color: white; padding: 0em; padding-top: 4em; } #QTGateStartScreen-Device { display: block; } #QTGateStartScreen { display: none; } #TimelinesView { max-width:100%; margin: 0px auto; } .itemContent { max-width: 90%; } } @media screen and ( min-width: 800px ) { #QTGateStartScreen { display: block; } #QTGateStartScreen-Device { display: none; } .TimelinesView { background-color: #e6ecf0; padding: 4em; } #TimelinesView { max-width:590px; margin: 0px auto; } .itemContent { max-width:530px; } } .flapLeft, .flapeRight { position: relative; cursor: pointer; } .flapLeft i:hover, .flapeRight i:hover { background: rgba(255,255,255,0.4); } .flapLeft i, .flapeRight i { color:grey; position: absolute; margin-top: -1em; } .tweetTrashButton { cursor: pointer; color: grey; } .tweetTrashButton:hover { color: red; } .tweetPhotoButton{ background: transparent!important; color: rgba(0, 0, 0, 0.2); cursor: pointer; right: 0.5em; margin-top: 2.5em; } .tweetPhotoButton:hover { color: rgba(0, 0, 0, 0.6); } .newTweetCloseButton{ color: rgba(0, 0, 0, 0.2)!important; cursor: pointer; position: absolute; top: 0.3em; right: 0.3em; } .newTweetCloseButton:hover { color: rgba(0, 0, 0, 0.6)!important; } .approveButtons { position: absolute; } .ui.modal { top: 15em; width: 600px; } #QTGateStartScreen{ height: 100%; } #QTGateStartScreen .VideoBox{ display: block; width: 600px; } #QTGateStartScreen .VideoBox .iframe { width: 550px; height: 310px; overflow: hidden; border-radius: 25px; } #QTGateStartScreen-Drive{ height: 100%; } #QTGateStartScreen-Drive .VideoBox{ display: block; } #QTGateStartScreen-Drive .VideoBox .iframe { overflow: hidden; border-radius: 25px; } .AppCardTop { max-width: 11em!important; } .AppCardImageArea { background: white!important; } .AppCardImage { max-width: 6em!important; } .templateImapAccount { color: blue; } .closeIcon { position: absolute; top: 1em; right: 1em; } .localIP { position: relative; left: 19em; top: 7.8em; color: blue; } .localIPPort { position: relative; left: 3.9em; top: 8.8em; color: blue; } .localNetwork { position: relative; left: 3.9em; top: 8.8em; color: blue; } .WindowsUseInfoLocalServerIp { position: relative; left: 10.4em; top: 12.5em; color: blue; } .WindowsUseInfoPort{ position: relative; left: -1.9em; top: 16.5em; color: blue; } .firefoxUseLocalIp{ position: relative; left: 4.5em; top: 32.2em; color: blue; } .firefoxUseLocalPort{ position: relative; left: -10.6em; top: 33.3em; color: blue; } .iOSUseInfoLocalServerIp{ position: relative; left: 2em; top: 12.6em; color: blue; } .iOSUseInfoPort{ position: relative; left: -13.1em; top: 13.7em; color: blue; } .androidUseInfoLocalServerIp{ position: relative; left: 6em; top: 7.7em; color: blue; } .androidUseInfoPort{ position: relative; left: -9.1em; top: 8.8em;; color: blue; } .videoBackground{ position: absolute; top: 50%; left: 50%; -webkit-transform: translateX(-50%) translateY(-50%); transform: translateX(-50%) translateY(-50%); min-width: 100%; min-height: 100%; width: auto; height: auto; z-index: -1000; overflow: hidden; } .startupView { position: fixed; top: 0; width: 100%; height: 100%; z-index: -1; } .loading { z-index: 9999; } .loaderCoNET { overflow: hidden; padding: 2em; position: relative; } .loaderCoNET-div { width: 20px; height: 20px; position: absolute; background-color: #ccc; top: 45%; border-radius: 50%; } .loaderCoNET-div:nth-child(1) { background-color: rgba(255, 84, 95, 0.274); -webkit-animation: move 2s infinite cubic-bezier(0.2, 0.64, 0.81, 0.23); animation: move 2s infinite cubic-bezier(0.2, 0.64, 0.81, 0.23); } .loaderCoNET-div:nth-child(2) { background-color: rgba(255, 157, 132, 0.315); -webkit-animation: move 2s 150ms infinite cubic-bezier(0.2, 0.64, 0.81, 0.23); animation: move 2s 150ms infinite cubic-bezier(0.2, 0.64, 0.81, 0.23); } .loaderCoNET-div:nth-child(3) { background-color: rgba(240, 231, 151, 0.356); -webkit-animation: move 2s 300ms infinite cubic-bezier(0.2, 0.64, 0.81, 0.23); animation: move 2s 300ms infinite cubic-bezier(0.2, 0.64, 0.81, 0.23); } .loaderCoNET-div:nth-child(4) { background-color: rgba(117, 176, 138, 0.377); -webkit-animation: move 2s 450ms infinite cubic-bezier(0.2, 0.64, 0.81, 0.23); animation: move 2s 450ms infinite cubic-bezier(0.2, 0.64, 0.81, 0.23); } @-webkit-keyframes move { 0% { left: 0%; } 100% { left: 90%; } } @keyframes move { 0% { left: 0%; } 100% { left: 90%; } } play-btn { width: 5em; height: 5em; background: radial-gradient( rgba(140, 0, 255, 0.87) 60%, rgba(140, 0, 255, 0.87) 62%); border-radius: 50%; position: relative; display: block; margin: 100px auto; box-shadow: 0px 0px 25px 3px rgba(140, 0, 255, 0.87); } /* triangle */ .play-btn::after { content: ""; position: absolute; left: 50%; top: 50%; -webkit-transform: translateX(-40%) translateY(-50%); transform: translateX(-40%) translateY(-50%); transform-origin: center center; width: 0; height: 0; border-top: 15px solid transparent; border-bottom: 15px solid transparent; border-left: 25px solid rgba(227, 196, 252, 0.616); z-index: 100; -webkit-transition: all 400ms cubic-bezier(0.55, 0.055, 0.675, 0.19); transition: all 400ms cubic-bezier(0.55, 0.055, 0.675, 0.19); } /* pulse wave */ .play-btn:before { content: ""; position: absolute; width: 150%; height: 150%; -webkit-animation-delay: 0s; animation-delay: 0s; -webkit-animation: pulsate1 2s; animation: pulsate1 2s; -webkit-animation-direction: forwards; animation-direction: forwards; -webkit-animation-iteration-count: infinite; animation-iteration-count: infinite; -webkit-animation-timing-function: steps; animation-timing-function: steps; opacity: 1; border-radius: 50%; border: 5px solid rgba(216, 119, 211, 0.75); top: -30%; left: -30%; background: rgba(216, 119, 211, 0.75); } @-webkit-keyframes pulsate1 { 0% { -webkit-transform: scale(0.6); transform: scale(0.6); opacity: 1; box-shadow: inset 0px 0px 25px 3px rgba(140, 0, 255, 0.87), 0px 0px 25px 10px rgba(140, 0, 255, 0.87); } 100% { -webkit-transform: scale(1); transform: scale(1); opacity: 0; box-shadow: none; } } @keyframes pulsate1 { 0% { -webkit-transform: scale(0.6); transform: scale(0.6); opacity: 1; box-shadow: inset 0px 0px 25px 3px rgba(140, 0, 255, 0.87), 0px 0px 25px 10px rgba(140, 0, 255, 0.87); } 100% { -webkit-transform: scale(1, 1); transform: scale(1); opacity: 0; box-shadow: none; } } .coSearchBackGroumd { background: #B4E4ED!important; } @keyframes BlurAnimation { to { filter: blur(3px);} } @keyframes coSearchInputAnimation { to { background: white ;} to { box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.2);} } .animationSearchInput { -webkit-animation-name: coSearchInputAnimation; -webkit-animation-duration: 0.5s; animation-name: coSearchInputAnimation; animation-duration: 0.5s; animation-timing-function: ease-in; animation-fill-mode: forwards; } .animationBlur { -webkit-animation-name: BlurAnimation; -webkit-animation-duration: 0.5s; animation-name: BlurAnimation; animation-duration: 0.5s; animation-timing-function: ease-in; animation-fill-mode: forwards; } .backgroundTransparent { background: rgba(255,255,255,0.01)!important; } #coSearchForm { position: absolute; margin-top: -30%; width: 100%; padding: 2em; } #coSearchForm input::-webkit-input-placeholder { color: rgba(0,0,0,0.3) } #coSearchForm input:-moz-placeholder { color: rgba(0,0,0,0.3) } #coSearchForm input::-moz-placeholder { color: rgba(0,0,0,0.3) } #coSearchForm input:-ms-input-placeholder { color: rgba(0,0,0,0.3) } #itemList{ position: absolute; margin-top: -25%; width: 90%; padding: 2em; } #coTranslateForm { position: absolute; margin-top: -10%; width: 90%; padding: 2em; } .space { margin: 1em; } .ui.input.error>input { background-color: #fff6f6!important; border-color: #e0b4b4!important; color: #9f3a38!important; } .ui.input.error>input::-webkit-input-placeholder { color:#e7bdbc!important; } .ui.input.error>input:focus::-moz-placeholder { color:#da9796!important; } .ui.input.error>input:-ms-input-placeholder { color:#e7bdbc!important } .loadingGetResponse::after { border-color: #ab9420d9 transparent transparent!important; } .loadingGetResponse { color: #ab9420d9!important; } .conetResponse { color: #36c576d9!important; } .conetResponse::after { border-color: #36c576d9 transparent transparent!important; } .buttonUnActive { background: #e0e1e288 none!important; } @keyframes svg_Background { to { filter: blur(3px);} to { background: black ;} } .svgBackground_Animation { -webkit-animation-name: svg_Background; -webkit-animation-duration: 0.5s; animation-name: svg_Background; animation-duration: 0.5s; animation-timing-function: ease-in; animation-fill-mode: forwards; } .terminalText { position: relative; display: inline-block; min-width: 360px; } .terminalText::after { content: ""; position: absolute; /* Remove display: inline-block if not required to be on the same line as text etc */ display: inline-block; background-color:grey; top: 14px; margin-left: 2px; width: 10px; /* Set height to the line height of .text */ height: 2px; /* Animation paramaters: blink = animation-name, 1s = animation-duration, step-end = animation-timing-function, infinite = animation-iteration-count */ -webkit-animation: blink 1s step-end infinite; animation: blink 1s step-end infinite; } @-webkit-keyframes blink { 0% { opacity: 1.0; } 50% { opacity: 0.0; } 100% { opacity: 1.0; } } @keyframes blink { 0% { opacity: 1.0; } 50% { opacity: 0.0; } 100% { opacity: 1.0; } } ================================================ FILE: app/public/scripts/CanadaSvg.js ================================================ /* Day */ var dayGroup = document.getElementById("DayGroup"); /* Canoe */ var canoe = document.getElementsByClassName("canoe"); var canoeReflection = document.getElementsByClassName("canoeReflection"); /* Island */ var treesPink = document.getElementsByClassName("treesPink"); var treesOrange = document.getElementsByClassName("treesOrange"); var CoralTriangle1 = document.getElementsByClassName("CoralTriangle1"); var CoralTriangle2 = document.getElementsByClassName("CoralTriangle2"); var CoralTriangle3 = document.getElementsByClassName("CoralTriangle3"); /*Sea */ var waveRight = document.getElementsByClassName("waveRight"); var waveLeft = document.getElementsByClassName("waveLeft"); /* Sky */ var blueCloudLeft = document.getElementsByClassName("blueCloudLeft"); var blueCloudRight = document.getElementsByClassName("blueCloudRight"); var pinkCloud = document.getElementsByClassName("pinkCloud"); var sunRayLeft = document.getElementsByClassName("sunRayLeft"); var sunRayRight = document.getElementsByClassName("sunRayRight"); /*Rflection*/ var treesPinkR = document.getElementsByClassName("treesPinkR"); var treesOrangeR = document.getElementsByClassName("treesOrangeR"); var RCoralTriangle1 = document.getElementsByClassName("RCoralTriangle1"); var RCoralTriangle2 = document.getElementsByClassName("RCoralTriangle2"); var RCoralTriangle3 = document.getElementsByClassName("RCoralTriangle3"); /* --------------------------- */ /* Animation */ //canoe var tlCanoe = new TimelineMax({ repeat:-1, yoyo:true, ease: "easeInOut" }); tlCanoe.fromTo(canoe, 1.5, { y:0 }, { y:4 }) tlCanoe.fromTo(canoeReflection, 1.5, { y:0 }, { y:-4 }, "-=1.5") //Sea var tlwaveLeft = new TimelineMax({ repeat:-1, yoyo:true, ease: "easeInOut" }); tlwaveLeft.fromTo(waveLeft, 5, { x:0 }, { x:35 }) tlwaveLeft.fromTo(waveRight, 5, { x:0 }, { x:-35 }, "-=5") //tree var tlswingingTree = new TimelineMax({ repeat:-1, yoyo:true, ease: "easeInOut" }); tlswingingTree.staggerFromTo(treesPink, 2, { transformOrigin:"50% 0%", rotation:"5deg", }, { rotation:"-5deg", }, .2); var ReflectswingingTree = new TimelineMax({ repeat:-1, yoyo:true, }); ReflectswingingTree.staggerFromTo(treesPinkR, 2, { transformOrigin:"50% 0%", rotation:"-5deg", }, { rotation:"5deg", }, .2); var tlOrangeTrees = new TimelineMax({ repeat:-1, yoyo:true, ease: "easeInOut" }); tlOrangeTrees.fromTo(treesOrange, 2, { transformOrigin:"50% 100%", rotation:"1deg", }, { rotation:"-1deg", }, .2); var ReflectOrangeTrees = new TimelineMax({ repeat:-1, yoyo:true}); ReflectOrangeTrees.fromTo(treesOrangeR, 2, { transformOrigin:"50% 0%", rotation:"-1deg", }, { rotation:"1deg", }, .2); var tlCoralTrees = new TimelineMax({repeat:-1}); tlCoralTrees.set([CoralTriangle1, CoralTriangle3], { transformOrigin: "50% 20%", rotation: "0deg", repeatDelay:2 }) tlCoralTrees.to([CoralTriangle1, CoralTriangle3], 1, { rotation: "6deg", ease: "easeInOut" }) tlCoralTrees.to([CoralTriangle1, CoralTriangle3], 1, { rotation: "-6deg", ease: "easeInOut" }) tlCoralTrees.to([CoralTriangle1, CoralTriangle3], .5, { rotation: "3deg", ease: "easeInOut" }) tlCoralTrees.to([CoralTriangle1, CoralTriangle3], .5, { rotation: "-3deg", ease: "easeInOut" }) tlCoralTrees.to([CoralTriangle1, CoralTriangle3], .4, { rotation: "2.5deg", ease: "easeInOut" }) tlCoralTrees.to([CoralTriangle1, CoralTriangle3], .4, { rotation: "-2.5deg", ease: "easeInOut" }) tlCoralTrees.to([CoralTriangle1, CoralTriangle3], .4, { rotation: "0deg", ease: "easeInOut" }) var tlCoralTree2 = new TimelineMax({repeat:-1}); tlCoralTree2.set(CoralTriangle2, { transformOrigin: "50% 20%", rotation: "0deg", delay:.5, repeatDelay:2.2 }) tlCoralTree2.to(CoralTriangle2, .85, { rotation: "6deg", ease: "easeInOut" }) tlCoralTree2.to(CoralTriangle2, .85, { rotation: "-6deg", ease: "easeInOut" }) tlCoralTree2.to(CoralTriangle2, .5, { rotation: "3deg", ease: "easeInOut" }) tlCoralTree2.to(CoralTriangle2, .5, { rotation: "-3deg", ease: "easeInOut" }) tlCoralTree2.to(CoralTriangle2, .4, { rotation: "2.5deg", ease: "easeInOut" }) tlCoralTree2.to(CoralTriangle2, .4, { rotation: "-2.5deg", ease: "easeInOut" }) tlCoralTree2.to(CoralTriangle2, .4, { rotation: "0deg", ease: "easeInOut" }) //Coral Tirangles Reflection var ReflectCoralTrees = new TimelineMax({repeat:-1}); ReflectCoralTrees.set([RCoralTriangle1, RCoralTriangle3], { transformOrigin: "50% 80%", rotation: "0deg", repeatDelay:2 }) ReflectCoralTrees.to([RCoralTriangle1, RCoralTriangle3], 1, { rotation: "-6deg", ease: "easeInOut" }) ReflectCoralTrees.to([RCoralTriangle1, RCoralTriangle3], 1, { rotation: "6deg", ease: "easeInOut" }) ReflectCoralTrees.to([RCoralTriangle1, RCoralTriangle3], .5, { rotation: "-3deg", ease: "easeInOut" }) ReflectCoralTrees.to([RCoralTriangle1, RCoralTriangle3], .5, { rotation: "3deg", ease: "easeInOut" }) ReflectCoralTrees.to([RCoralTriangle1, RCoralTriangle3], .4, { rotation: "-2.5deg", ease: "easeInOut" }) ReflectCoralTrees.to([RCoralTriangle1, RCoralTriangle3], .4, { rotation: "2.5deg", ease: "easeInOut" }) ReflectCoralTrees.to([RCoralTriangle1, RCoralTriangle3], .4, { rotation: "0deg", ease: "easeInOut" }) var ReflectCoralTree2 = new TimelineMax({repeat:-1}); ReflectCoralTree2.set(CoralTriangle2, { transformOrigin: "50% 80%", rotation: "0deg", delay:.5, repeatDelay:2.2 }) ReflectCoralTree2.to(RCoralTriangle2, .85, { rotation: "-6deg", ease: "easeInOut" }) ReflectCoralTree2.to(RCoralTriangle2, .85, { rotation: "6deg", ease: "easeInOut" }) ReflectCoralTree2.to(RCoralTriangle2, .5, { rotation: "-3deg", ease: "easeInOut" }) ReflectCoralTree2.to(RCoralTriangle2, .5, { rotation: "3deg", ease: "easeInOut" }) ReflectCoralTree2.to(RCoralTriangle2, .4, { rotation: "-2.5deg", ease: "easeInOut" }) ReflectCoralTree2.to(RCoralTriangle2, .4, { rotation: "2.5deg", ease: "easeInOut" }) ReflectCoralTree2.to(RCoralTriangle2, .4, { rotation: "0deg", ease: "easeInOut" }) //sky var tlblueCloud = new TimelineMax({ repeat:-1, yoyo:true, }); tlblueCloud.fromTo(blueCloudLeft, 5.5, { x:0 }, { x:55, ease: "linear" }) tlblueCloud.fromTo(blueCloudRight, 5.5, { x:0 }, { x:-55, ease: "linear" }, "-=5") var tlpinkCloud = new TimelineMax({ repeat:-1, yoyo:true, ease: "easeInOut" }); tlpinkCloud.staggerFromTo(pinkCloud, 20, { x:0 }, { x:300 }, 1.5) var tlsunRays = new TimelineMax({ repeat:-1, yoyo:true, }); tlsunRays.fromTo(sunRayLeft, 4.5, { x:0 }, { x:25, ease:"linear" }) tlsunRays.fromTo(sunRayRight, 4.5, { x:0 }, { x:-25, ease:"linear" }, "-=5"); ================================================ FILE: app/public/scripts/Cleave.js ================================================ /*! * cleave.js - 1.3.8 * https://github.com/nosir/cleave.js * Apache License Version 2.0 * * Copyright (C) 2012-2018 Max Huang https://github.com/nosir/ */ !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.Cleave=t():e.Cleave=t()}(this,function(){return function(e){function t(n){if(r[n])return r[n].exports;var i=r[n]={exports:{},id:n,loaded:!1};return e[n].call(i.exports,i,i.exports,t),i.loaded=!0,i.exports}var r={};return t.m=e,t.c=r,t.p="",t(0)}([function(e,t,r){(function(t){"use strict";var n=function(e,t){var r=this;if("string"==typeof e?r.element=document.querySelector(e):r.element="undefined"!=typeof e.length&&e.length>0?e[0]:e,!r.element)throw new Error("[cleave.js] Please check the element");t.initValue=r.element.value,r.properties=n.DefaultProperties.assign({},t),r.init()};n.prototype={init:function(){var e=this,t=e.properties;return t.numeral||t.phone||t.creditCard||t.date||0!==t.blocksLength||t.prefix?(t.maxLength=n.Util.getMaxLength(t.blocks),e.isAndroid=n.Util.isAndroid(),e.lastInputValue="",e.onChangeListener=e.onChange.bind(e),e.onKeyDownListener=e.onKeyDown.bind(e),e.onFocusListener=e.onFocus.bind(e),e.onCutListener=e.onCut.bind(e),e.onCopyListener=e.onCopy.bind(e),e.element.addEventListener("input",e.onChangeListener),e.element.addEventListener("keydown",e.onKeyDownListener),e.element.addEventListener("focus",e.onFocusListener),e.element.addEventListener("cut",e.onCutListener),e.element.addEventListener("copy",e.onCopyListener),e.initPhoneFormatter(),e.initDateFormatter(),e.initNumeralFormatter(),void((t.initValue||t.prefix&&!t.noImmediatePrefix)&&e.onInput(t.initValue))):void e.onInput(t.initValue)},initNumeralFormatter:function(){var e=this,t=e.properties;t.numeral&&(t.numeralFormatter=new n.NumeralFormatter(t.numeralDecimalMark,t.numeralIntegerScale,t.numeralDecimalScale,t.numeralThousandsGroupStyle,t.numeralPositiveOnly,t.stripLeadingZeroes,t.delimiter))},initDateFormatter:function(){var e=this,t=e.properties;t.date&&(t.dateFormatter=new n.DateFormatter(t.datePattern),t.blocks=t.dateFormatter.getBlocks(),t.blocksLength=t.blocks.length,t.maxLength=n.Util.getMaxLength(t.blocks))},initPhoneFormatter:function(){var e=this,t=e.properties;if(t.phone)try{t.phoneFormatter=new n.PhoneFormatter(new t.root.Cleave.AsYouTypeFormatter(t.phoneRegionCode),t.delimiter)}catch(r){throw new Error("[cleave.js] Please include phone-type-formatter.{country}.js lib")}},onKeyDown:function(e){var t=this,r=t.properties,i=e.which||e.keyCode,a=n.Util,o=t.element.value;return a.isAndroidBackspaceKeydown(t.lastInputValue,o)&&(i=8),t.lastInputValue=o,8===i&&a.isDelimiter(o.slice(-r.delimiterLength),r.delimiter,r.delimiters)?void(r.backspace=!0):void(r.backspace=!1)},onChange:function(){this.onInput(this.element.value)},onFocus:function(){var e=this,t=e.properties;n.Util.fixPrefixCursor(e.element,t.prefix,t.delimiter,t.delimiters)},onCut:function(e){this.copyClipboardData(e),this.onInput("")},onCopy:function(e){this.copyClipboardData(e)},copyClipboardData:function(e){var t=this,r=t.properties,i=n.Util,a=t.element.value,o="";o=r.copyDelimiter?a:i.stripDelimiters(a,r.delimiter,r.delimiters);try{e.clipboardData?e.clipboardData.setData("Text",o):window.clipboardData.setData("Text",o),e.preventDefault()}catch(l){}},onInput:function(e){var t=this,r=t.properties,i=n.Util;return r.numeral||!r.backspace||i.isDelimiter(e.slice(-r.delimiterLength),r.delimiter,r.delimiters)||(e=i.headStr(e,e.length-r.delimiterLength)),r.phone?(!r.prefix||r.noImmediatePrefix&&!e.length?r.result=r.phoneFormatter.format(e):r.result=r.prefix+r.phoneFormatter.format(e).slice(r.prefix.length),void t.updateValueState()):r.numeral?(!r.prefix||r.noImmediatePrefix&&!e.length?r.result=r.numeralFormatter.format(e):r.result=r.prefix+r.numeralFormatter.format(e),void t.updateValueState()):(r.date&&(e=r.dateFormatter.getValidatedDate(e)),e=i.stripDelimiters(e,r.delimiter,r.delimiters),e=i.getPrefixStrippedValue(e,r.prefix,r.prefixLength,r.result),e=r.numericOnly?i.strip(e,/[^\d]/g):e,e=r.uppercase?e.toUpperCase():e,e=r.lowercase?e.toLowerCase():e,!r.prefix||r.noImmediatePrefix&&!e.length||(e=r.prefix+e,0!==r.blocksLength)?(r.creditCard&&t.updateCreditCardPropsByValue(e),e=i.headStr(e,r.maxLength),r.result=i.getFormattedValue(e,r.blocks,r.blocksLength,r.delimiter,r.delimiters,r.delimiterLazyShow),void t.updateValueState()):(r.result=e,void t.updateValueState()))},updateCreditCardPropsByValue:function(e){var t,r=this,i=r.properties,a=n.Util;a.headStr(i.result,4)!==a.headStr(e,4)&&(t=n.CreditCardDetector.getInfo(e,i.creditCardStrictMode),i.blocks=t.blocks,i.blocksLength=i.blocks.length,i.maxLength=a.getMaxLength(i.blocks),i.creditCardType!==t.type&&(i.creditCardType=t.type,i.onCreditCardTypeChanged.call(r,i.creditCardType)))},updateValueState:function(){var e=this,t=n.Util,r=e.properties;if(e.element){var i=e.element.selectionEnd,a=e.element.value,o=r.result;if(i=t.getNextCursorPosition(i,a,o,r.delimiter,r.delimiters),e.isAndroid)return void window.setTimeout(function(){e.element.value=o,t.setSelection(e.element,i,r.document,!1),e.callOnValueChanged()},1);e.element.value=o,t.setSelection(e.element,i,r.document,!1),e.callOnValueChanged()}},callOnValueChanged:function(){var e=this,t=e.properties;t.onValueChanged.call(e,{target:{value:t.result,rawValue:e.getRawValue()}})},setPhoneRegionCode:function(e){var t=this,r=t.properties;r.phoneRegionCode=e,t.initPhoneFormatter(),t.onChange()},setRawValue:function(e){var t=this,r=t.properties;e=void 0!==e&&null!==e?e.toString():"",r.numeral&&(e=e.replace(".",r.numeralDecimalMark)),r.backspace=!1,t.element.value=e,t.onInput(e)},getRawValue:function(){var e=this,t=e.properties,r=n.Util,i=e.element.value;return t.rawValueTrimPrefix&&(i=r.getPrefixStrippedValue(i,t.prefix,t.prefixLength,t.result)),i=t.numeral?t.numeralFormatter.getRawValue(i):r.stripDelimiters(i,t.delimiter,t.delimiters)},getISOFormatDate:function(){var e=this,t=e.properties;return t.date?t.dateFormatter.getISOFormatDate():""},getFormattedValue:function(){return this.element.value},destroy:function(){var e=this;e.element.removeEventListener("input",e.onChangeListener),e.element.removeEventListener("keydown",e.onKeyDownListener),e.element.removeEventListener("focus",e.onFocusListener),e.element.removeEventListener("cut",e.onCutListener),e.element.removeEventListener("copy",e.onCopyListener)},toString:function(){return"[Cleave Object]"}},n.NumeralFormatter=r(1),n.DateFormatter=r(2),n.PhoneFormatter=r(3),n.CreditCardDetector=r(4),n.Util=r(5),n.DefaultProperties=r(6),("object"==typeof t&&t?t:window).Cleave=n,e.exports=n}).call(t,function(){return this}())},function(e,t){"use strict";var r=function(e,t,n,i,a,o,l){var s=this;s.numeralDecimalMark=e||".",s.numeralIntegerScale=t>0?t:0,s.numeralDecimalScale=n>=0?n:2,s.numeralThousandsGroupStyle=i||r.groupStyle.thousand,s.numeralPositiveOnly=!!a,s.stripLeadingZeroes=o!==!1,s.delimiter=l||""===l?l:",",s.delimiterRE=l?new RegExp("\\"+l,"g"):""};r.groupStyle={thousand:"thousand",lakh:"lakh",wan:"wan",none:"none"},r.prototype={getRawValue:function(e){return e.replace(this.delimiterRE,"").replace(this.numeralDecimalMark,".")},format:function(e){var t,n,i=this,a="";switch(e=e.replace(/[A-Za-z]/g,"").replace(i.numeralDecimalMark,"M").replace(/[^\dM-]/g,"").replace(/^\-/,"N").replace(/\-/g,"").replace("N",i.numeralPositiveOnly?"":"-").replace("M",i.numeralDecimalMark),i.stripLeadingZeroes&&(e=e.replace(/^(-)?0+(?=\d)/,"$1")),n=e,e.indexOf(i.numeralDecimalMark)>=0&&(t=e.split(i.numeralDecimalMark),n=t[0],a=i.numeralDecimalMark+t[1].slice(0,i.numeralDecimalScale)),i.numeralIntegerScale>0&&(n=n.slice(0,i.numeralIntegerScale+("-"===e.slice(0,1)?1:0))),i.numeralThousandsGroupStyle){case r.groupStyle.lakh:n=n.replace(/(\d)(?=(\d\d)+\d$)/g,"$1"+i.delimiter);break;case r.groupStyle.wan:n=n.replace(/(\d)(?=(\d{4})+$)/g,"$1"+i.delimiter);break;case r.groupStyle.thousand:n=n.replace(/(\d)(?=(\d{3})+$)/g,"$1"+i.delimiter)}return n.toString()+(i.numeralDecimalScale>0?a.toString():"")}},e.exports=r},function(e,t){"use strict";var r=function(e){var t=this;t.date=[],t.blocks=[],t.datePattern=e,t.initBlocks()};r.prototype={initBlocks:function(){var e=this;e.datePattern.forEach(function(t){"Y"===t?e.blocks.push(4):e.blocks.push(2)})},getISOFormatDate:function(){var e=this,t=e.date;return t[2]?t[2]+"-"+e.addLeadingZero(t[1])+"-"+e.addLeadingZero(t[0]):""},getBlocks:function(){return this.blocks},getValidatedDate:function(e){var t=this,r="";return e=e.replace(/[^\d]/g,""),t.blocks.forEach(function(n,i){if(e.length>0){var a=e.slice(0,n),o=a.slice(0,1),l=e.slice(n);switch(t.datePattern[i]){case"d":"00"===a?a="01":parseInt(o,10)>3?a="0"+o:parseInt(a,10)>31&&(a="31");break;case"m":"00"===a?a="01":parseInt(o,10)>1?a="0"+o:parseInt(a,10)>12&&(a="12")}r+=a,e=l}}),this.getFixedDateString(r)},getFixedDateString:function(e){var t,r,n,i=this,a=i.datePattern,o=[],l=0,s=0,u=0,c=0,d=0,m=0,p=!1;return 4===e.length&&"y"!==a[0].toLowerCase()&&"y"!==a[1].toLowerCase()&&(c="d"===a[0]?0:2,d=2-c,t=parseInt(e.slice(c,c+2),10),r=parseInt(e.slice(d,d+2),10),o=this.getFixedDate(t,r,0)),8===e.length&&(a.forEach(function(e,t){switch(e){case"d":l=t;break;case"m":s=t;break;default:u=t}}),m=2*u,c=l<=u?2*l:2*l+2,d=s<=u?2*s:2*s+2,t=parseInt(e.slice(c,c+2),10),r=parseInt(e.slice(d,d+2),10),n=parseInt(e.slice(m,m+4),10),p=4===e.slice(m,m+4).length,o=this.getFixedDate(t,r,n)),i.date=o,0===o.length?e:a.reduce(function(e,t){switch(t){case"d":return e+i.addLeadingZero(o[0]);case"m":return e+i.addLeadingZero(o[1]);default:return e+(p?i.addLeadingZeroForYear(o[2]):"")}},"")},getFixedDate:function(e,t,r){return e=Math.min(e,31),t=Math.min(t,12),r=parseInt(r||0,10),(t<7&&t%2===0||t>8&&t%2===1)&&(e=Math.min(e,2===t?this.isLeapYear(r)?29:28:30)),[e,t,r]},isLeapYear:function(e){return e%4===0&&e%100!==0||e%400===0},addLeadingZero:function(e){return(e<10?"0":"")+e},addLeadingZeroForYear:function(e){return(e<10?"000":e<100?"00":e<1e3?"0":"")+e}},e.exports=r},function(e,t){"use strict";var r=function(e,t){var r=this;r.delimiter=t||""===t?t:" ",r.delimiterRE=t?new RegExp("\\"+t,"g"):"",r.formatter=e};r.prototype={setFormatter:function(e){this.formatter=e},format:function(e){var t=this;t.formatter.clear(),e=e.replace(/[^\d+]/g,""),e=e.replace(t.delimiterRE,"");for(var r,n="",i=!1,a=0,o=e.length;ar?n:t;else{var i=this.getFirstDiffIndex(t,e.slice(0,r));e=t+e.slice(i,i+1)+e.slice(r+1)}return e.slice(r)},getFirstDiffIndex:function(e,t){for(var r=0;e.charAt(r)===t.charAt(r);)if(""===e.charAt(r++))return-1;return r},getFormattedValue:function(e,t,r,n,i,a){var o,l="",s=i.length>0;return 0===r?e:(t.forEach(function(t,u){if(e.length>0){var c=e.slice(0,t),d=e.slice(t);o=s?i[a?u-1:u]||o:n,a?(u>0&&(l+=o),l+=c):(l+=c,c.length===t&&u0?r.numeralIntegerScale:0,e.numeralDecimalScale=r.numeralDecimalScale>=0?r.numeralDecimalScale:2,e.numeralDecimalMark=r.numeralDecimalMark||".",e.numeralThousandsGroupStyle=r.numeralThousandsGroupStyle||"thousand",e.numeralPositiveOnly=!!r.numeralPositiveOnly,e.stripLeadingZeroes=r.stripLeadingZeroes!==!1,e.numericOnly=e.creditCard||e.date||!!r.numericOnly,e.uppercase=!!r.uppercase,e.lowercase=!!r.lowercase,e.prefix=e.creditCard||e.date?"":r.prefix||"",e.noImmediatePrefix=!!r.noImmediatePrefix,e.prefixLength=e.prefix.length,e.rawValueTrimPrefix=!!r.rawValueTrimPrefix,e.copyDelimiter=!!r.copyDelimiter,e.initValue=void 0!==r.initValue&&null!==r.initValue?r.initValue.toString():"",e.delimiter=r.delimiter||""===r.delimiter?r.delimiter:r.date?"/":r.numeral?",":(r.phone," "),e.delimiterLength=e.delimiter.length,e.delimiterLazyShow=!!r.delimiterLazyShow,e.delimiters=r.delimiters||[],e.blocks=r.blocks||[],e.blocksLength=e.blocks.length,e.root="object"==typeof t&&t?t:window,e.document=r.document||e.root.document,e.maxLength=0,e.backspace=!1,e.result="",e.onValueChanged=r.onValueChanged||function(){},e}};e.exports=r}).call(t,function(){return this}())}])}); ================================================ FILE: app/public/scripts/CoNETConnect.js ================================================ /*! * Copyright 2018 CoNET Technology Inc. All Rights Reserved. * * 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. */ class CoNETConnect { constructor(email, isKeypairBeSign, confirmRisk, account, ready) { this.email = email; this.isKeypairBeSign = isKeypairBeSign; this.account = account; this.ready = ready; this.showSendImapDataWarning = ko.observable(false); this.showConnectCoNETProcess = ko.observable(true); this.connectStage = ko.observable(0); this.connetcError = ko.observable(-1); this.connectedCoNET = ko.observable(false); this.maynotConnectConet = ko.observable(false); this.Loading = ko.observable(false); this.listenFun = null; this.showTryAgain = ko.observable(false); this.showSendConnectMail = ko.observable(false); this.showNetworkError = ko.observable(false); this.infoTextArray = ko.observableArray([]); this.keyPairSign = ko.observable(null); const self = this; if (!confirmRisk) { this.showSendImapDataWarning(true); } else { this.imapConform(); this.Loading(true); } } listingConnectStage(err, stage, publicKeyMessage) { const self = this; this.showConnectCoNETProcess(true); switch (stage) { case 1: { const index = this.infoTextArray()[this.infoTextArray().length - 1]; if (!index) { return; } index.text('connectedMailServer'); return index.err(false); } /** * waiting pong */ case 2: { return this.infoTextArray.push({ text: ko.observable('waitingPong'), err: ko.observable(null) }); } /** * sendConnectRequestMail */ case 3: { return this.infoTextArray.push({ text: ko.observable('sendConnectRequestMail'), err: ko.observable(null) }); } /** * timeOut error! */ case 0: { self.Loading(false); self.showSendConnectMail(true); return self.infoTextArray.push({ text: ko.observable('timeOut'), err: ko.observable(true) }); } /** * connected node */ case 4: { this.Loading(false); this.showConnectCoNETProcess(false); this.connectedCoNET(true); _view.connectInformationMessage.socketIo.removeListener('tryConnectCoNETStage', this.listenFun); return _view.keyPairCalss.decryptMessage(publicKeyMessage, (err, data) => { if (err) { return self.infoTextArray.push({ text: ko.observable('unKnowError'), err: ko.observable(true) }); } if (!this.isKeypairBeSign) { if (!this.keyPairSign()) { let u = null; return this.keyPairSign(u = new keyPairSign((function () { self.keyPairSign(u = null); self.ready(null); }))); } return; } _view.showIconBar(true); return this.ready(null); }); } /** * connectToMailServer */ case 5: { return this.infoTextArray.push({ text: ko.observable('connectToMailServer'), err: ko.observable(null) }); } /** * Client error! */ case -1: { this.Loading(false); _view.connectInformationMessage.socketIo.removeListener('tryConnectCoNETStage', this.listenFun); return this.infoTextArray.push({ text: ko.observable('systemError'), err: ko.observable(true) }); } /** * network error! */ case -2: { this.Loading(false); this.showNetworkError(true); return this.infoTextArray.push({ text: ko.observable('offline'), err: ko.observable(true) }); } } } returnToImapSetup() { return this.ready(0); } sendConnectMail() { this.Loading(true); this.showTryAgain(false); _view.connectInformationMessage.sockEmit('sendRequestMail', err => { if (err) { return this.listingConnectStage(null, -1, null); } }); } tryAgain() { this.resetAll(); this.infoTextArray([]); return this.imapConform(); } resetAll() { this.showNetworkError(false); this.showSendConnectMail(false); this.showSendImapDataWarning(false); this.showTryAgain(false); } imapConform() { const self = this; this.showSendImapDataWarning(false); this.connetcError(-1); this.Loading(true); //return this.test () this.listenFun = (err, stage, message) => { return self.listingConnectStage(err, stage, message); }; _view.connectInformationMessage.socketIo.on('tryConnectCoNETStage', this.listenFun); _view.connectInformationMessage.sockEmit('tryConnectCoNET', err => { if (err) { return this.listingConnectStage(null, -1, null); } }); } /** * test unit */ test() { /** * localServerError */ /* this.listingConnectStage ( null, 5 ) setTimeout (() => { this.listingConnectStage ( null, -1 ) }, 3000 ) /** */ /** * connect to mail server error */ /* this.listingConnectStage ( null, 5 ) setTimeout (() => { this.listingConnectStage ( null, -2 ) }, 3000 ) /** */ /** * waiting pong */ /* this.listingConnectStage ( null, 5 ) setTimeout (() => { this.listingConnectStage ( null, 1 ) this.listingConnectStage ( null, 2 ) }, 3000 ) /** */ /** * waiting pong error automatic send request mail */ /* this.listingConnectStage ( null, 5 ) setTimeout (() => { this.listingConnectStage ( null, 1 ) this.listingConnectStage ( null, 2 ) setTimeout (() => { this.listingConnectStage ( null, 3 ) }) }, 3000 ) /** */ /** * waiting pong error automatic send request mail and timeout error */ /* this.listingConnectStage ( null, 5 ) setTimeout (() => { this.listingConnectStage ( null, 1 ) this.listingConnectStage ( null, 2 ) setTimeout (() => { this.listingConnectStage ( null, 3 ) setTimeout (() => { this.listingConnectStage ( null, 0 ) }, 2000 ) }) }, 3000 ) /** */ } } ================================================ FILE: app/public/scripts/CoNETConnect.ts ================================================ /*! * Copyright 2018 CoNET Technology Inc. All Rights Reserved. * * 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. */ interface connectInfo { text: KnockoutObservable < string > err: KnockoutObservable < boolean > } class CoNETConnect { public showSendImapDataWarning = ko.observable ( false ) public showConnectCoNETProcess = ko.observable ( true ) public connectStage = ko.observable ( 0 ) public connetcError = ko.observable ( -1 ) public connectedCoNET = ko.observable ( false ) public maynotConnectConet = ko.observable ( false ) public Loading = ko.observable ( false ) public listenFun = null public showTryAgain = ko.observable ( false ) public showSendConnectMail = ko.observable ( false ) public showNetworkError = ko.observable ( false ) public infoTextArray: KnockoutObservableArray < connectInfo > = ko.observableArray ([]) public keyPairSign: KnockoutObservable< keyPairSign > = ko.observable ( null ) constructor ( public email: string, private isKeypairBeSign: boolean, confirmRisk: boolean, public account: string, private ready: ( err ) => void ) { const self = this if ( !confirmRisk ) { this.showSendImapDataWarning ( true ) } else { this.imapConform () this.Loading ( true ) } } public listingConnectStage ( err, stage, publicKeyMessage ) { const self = this this.showConnectCoNETProcess ( true ) switch ( stage ) { case 1: { const index = this.infoTextArray ()[ this.infoTextArray ().length -1 ] if ( !index ) { return } index.text ( 'connectedMailServer' ) return index.err ( false ) } /** * waiting pong */ case 2: { return this.infoTextArray.push ({ text: ko.observable ('waitingPong'), err: ko.observable ( null )}) } /** * sendConnectRequestMail */ case 3: { return this.infoTextArray.push ({ text: ko.observable ('sendConnectRequestMail'), err: ko.observable ( null )}) } /** * timeOut error! */ case 0: { self.Loading ( false ) self.showSendConnectMail ( true ) return self.infoTextArray.push ({ text: ko.observable ( 'timeOut' ), err: ko.observable ( true )}) } /** * connected node */ case 4: { this.Loading ( false ) this.showConnectCoNETProcess ( false ) this.connectedCoNET ( true ) _view.connectInformationMessage.socketIo.removeListener ( 'tryConnectCoNETStage', this.listenFun ) return _view.keyPairCalss.decryptMessage ( publicKeyMessage, ( err, data ) => { if ( err ) { return self.infoTextArray.push ({ text: ko.observable ( 'unKnowError' ), err: ko.observable ( true )}) } if ( ! this.isKeypairBeSign ) { if ( ! this.keyPairSign ()) { let u = null return this.keyPairSign ( u = new keyPairSign (( function () { self.keyPairSign ( u = null ) self.ready ( null ) }))) } return } _view.showIconBar ( true ) return this.ready ( null ) }) } /** * connectToMailServer */ case 5: { return this.infoTextArray.push ({ text: ko.observable ( 'connectToMailServer' ), err: ko.observable ( null ) }) } /** * Client error! */ case -1: { this.Loading ( false ) _view.connectInformationMessage.socketIo.removeListener ( 'tryConnectCoNETStage', this.listenFun ) return this.infoTextArray.push ({ text: ko.observable ( 'systemError' ), err: ko.observable ( true ) }) } /** * network error! */ case -2: { this.Loading ( false ) this.showNetworkError ( true ) return this.infoTextArray.push ({ text: ko.observable ( 'offline' ), err: ko.observable ( true ) }) } } } public returnToImapSetup () { return this.ready ( 0 ) } public sendConnectMail () { this.Loading ( true ) this.showTryAgain ( false ) _view.connectInformationMessage.sockEmit ( 'sendRequestMail', err => { if ( err ) { return this.listingConnectStage ( null, -1, null ) } }) } public tryAgain () { this.resetAll () this.infoTextArray ([]) return this.imapConform () } private resetAll () { this.showNetworkError ( false ) this.showSendConnectMail ( false ) this.showSendImapDataWarning ( false ) this.showTryAgain ( false ) } public imapConform () { const self = this this.showSendImapDataWarning ( false ) this.connetcError ( -1 ) this.Loading ( true ) //return this.test () this.listenFun = ( err, stage, message ) => { return self.listingConnectStage ( err, stage, message ) } _view.connectInformationMessage.socketIo.on ( 'tryConnectCoNETStage', this.listenFun ) _view.connectInformationMessage.sockEmit ( 'tryConnectCoNET', err => { if ( err ) { return this.listingConnectStage ( null, -1, null ) } }) } /** * test unit */ private test () { /** * localServerError */ /* this.listingConnectStage ( null, 5 ) setTimeout (() => { this.listingConnectStage ( null, -1 ) }, 3000 ) /** */ /** * connect to mail server error */ /* this.listingConnectStage ( null, 5 ) setTimeout (() => { this.listingConnectStage ( null, -2 ) }, 3000 ) /** */ /** * waiting pong */ /* this.listingConnectStage ( null, 5 ) setTimeout (() => { this.listingConnectStage ( null, 1 ) this.listingConnectStage ( null, 2 ) }, 3000 ) /** */ /** * waiting pong error automatic send request mail */ /* this.listingConnectStage ( null, 5 ) setTimeout (() => { this.listingConnectStage ( null, 1 ) this.listingConnectStage ( null, 2 ) setTimeout (() => { this.listingConnectStage ( null, 3 ) }) }, 3000 ) /** */ /** * waiting pong error automatic send request mail and timeout error */ /* this.listingConnectStage ( null, 5 ) setTimeout (() => { this.listingConnectStage ( null, 1 ) this.listingConnectStage ( null, 2 ) setTimeout (() => { this.listingConnectStage ( null, 3 ) setTimeout (() => { this.listingConnectStage ( null, 0 ) }, 2000 ) }) }, 3000 ) /** */ } } ================================================ FILE: app/public/scripts/appCosearch.js ================================================ let appScript = { info: { totalResults: ['大约有', '約', 'About', '大約有'], totalResults1: ['条记录', '件', 'results', '條記錄'], moreResults: ['更多结果', '結果をさらに表示', 'More Results', '更多結果'], searchToolBarMenu: [ [ '网站', 'ウェイブ', 'Website', '網頁' ], [ '新闻', 'ニュース', 'News', '新聞' ], [ '图片', '画像', 'Picture', '圖片' ], [ '视频', 'ビデオ', 'Video', '視頻' ] ] }, showMain: ko.observable(true), showWebPage: ko.observable(null), htmlIframe: ko.observable(false), showSnapshop: ko.observable(false), searchItemsArray: ko.observable(), hasFocusShowTool: ko.observable(false), backGroundBlue: ko.observable(false), searchItem: ko.observable(null), showMainSearchForm: ko.observable(true), showSearchSetupForm: ko.observable(false), showSearchError: ko.observable(false), showInputLoading: ko.observable(false), errorMessageIndex: ko.observable(-1), searchInputText: ko.observable(''), hasFocus: ko.observable(false), passwordError: ko.observable(false), searchSetupIcon: ko.observable(bingIcon), password: ko.observable(''), searchInputTextActionShow: ko.observable(false), SearchInputNextHasFocus: ko.observable(false), showSearchesRelated: ko.observable(false), searchItemList: ko.observableArray([]), loadingGetResponse: ko.observable(false), conetResponse: ko.observable(false), searchInputTextShow: ko.observable(''), currentlyShowItems: ko.observable(0), newsButtonShowLoading: ko.observable(false), newsItemsArray: ko.observable(), newsButtonShowError: ko.observable(false), newsButtonErrorIndex: ko.observable(null), newsLoadingGetResponse: ko.observable(false), newsConetResponse: ko.observable(false), nextButtonShowError: ko.observable(false), moreResultsButtomLoading: ko.observable(false), imageButtonShowLoading: ko.observable(false), imageButtonShowError: ko.observable(false), imageButtonErrorIndex: ko.observable(-1), imageLoadingGetResponse: ko.observable(false), imageConetResponse: ko.observable(false), imageItemsArray: ko.observable(), searchSimilarImagesList: ko.observableArray([]), showSearchSimilarImagesResult: ko.observable(false), imageSearchItemArray: ko.observable(), videoButtonShowLoading: ko.observable(false), videoItemsArray: ko.observable(), videoButtonShowError: ko.observable(false), videoButtonErrorIndex: ko.observable(-1), videoLoadingGetResponse: ko.observable(false), videoConetResponse: ko.observable(false), nextButtonErrorIndex: ko.observable(false), nextButtonConetResponse: ko.observable(false), nextButtonLoadingGetResponse: ko.observable(false), // ['originImage'] initSearchData: (self) => { self.searchItem(null); self.searchItemList([]); self.showInputLoading(true); self.showSearchesRelated(false); self.newsItemsArray(null); self.imageItemsArray(null); self.showSearchesRelated(null); self.videoItemsArray(null); self.imageSearchItemArray(null); }, showResultItems: (self, items) => { self.searchItem(items); self.searchItemList(items.Result); $('.selection.dropdown').dropdown(); }, searchSetupClick: (self, event) => { self.showSearchSetupForm(true); self.backGroundBlue(true); /* $('#coSearchBackGround').one ( 'click', function() { self.backGroundClick () $('#coSearchForm').off ('click') }) $('#coSearchForm').one ( 'click', function() { self.backGroundClick () $('#coSearchBackGround').off ('click') }) */ return false; }, searchInputCloseError: (self, event) => { self.showSearchError(false); self.errorMessageIndex(null); }, returnSearchResultItemsInit: (items) => { let i = 0; const y = []; items.Result.forEach(n => { i++; n['showLoading'] = ko.observable(false); n['conetResponse'] = ko.observable(false); n['loadingGetResponse'] = ko.observable(false); n['snapshotReady'] = ko.observable(false); n['snapshotClass'] = null; n['snapshotData'] = null; n['snapshotUuid'] = null; n['id'] = uuid_generate(); n['showError'] = ko.observable(false); n['errorIndex'] = ko.observable(-1); if (!n['newsBrand']) { n['newsBrand'] = null; } if (n.imageInfo) { if (!n.imageInfo['videoTime']) { n.imageInfo['videoTime'] = null; } } n['webUrlHref'] = n.clickUrl; n['imgUrlHref'] = n.imgSrc; n['showImageLoading'] = ko.observable(false); n['showImageError'] = ko.observable(false); n['snapshotImageReady'] = ko.observable(false); n['loadingImageGetResponse'] = ko.observable(false); n['conetImageResponse'] = ko.observable(false); n['imageErrorIndex'] = ko.observable(-1); }); }, search_form: (self, event) => { if (self.showInputLoading()) { return; } if (!_view.CanadaBackground()) { _view.CanadaBackground(true); } if (!self.showMainSearchForm()) { self.showMainSearchForm(true); } const search_text = self.searchInputText(); const width = window.innerWidth; const height = window.outerHeight; self.initSearchData(self); const com = { command: 'CoSearch', Args: null, error: null, subCom: null }; /** * web page address */ if (/^http[s]?:\/\//.test(search_text)) { com.Args = [search_text, width, height]; com.subCom = 'getSnapshop'; } else { com.Args = ['google', search_text]; com.subCom = 'webSearch'; } const errorProcess = (err) => { self.showInputLoading(false); self.searchInputText(''); self.errorMessageIndex(_view.connectInformationMessage.getErrorIndex(err)); return self.showSearchError(true); }; /** * * test Unit */ return _view.keyPairCalss.emitRequest(com, (err, com) => { if (err) { return errorProcess(err); } if (!com) { return self.loadingGetResponse(true); } if (com.error === -1) { self.loadingGetResponse(false); return self.conetResponse(true); } if (com.error) { return errorProcess(com.error); } if (com.subCom === 'webSearch') { self.showInputLoading(false); const args = com.Args; self.searchInputTextShow(search_text); self.returnSearchResultItemsInit(args.param); self.searchItemsArray(args.param); self.showResultItems(self, args.param); _view.CanadaBackground(false); return self.showMainSearchForm(false); } const arg = com.Args[0]; const uuid = arg.split(',')[0].split('.')[0]; return _view.connectInformationMessage.sockEmit('getFilesFromImap', arg, (err, buffer) => { if (err) { return errorProcess(err); } return _view.keyPairCalss.decryptMessageToZipStream(buffer, (err, data) => { if (err) { return errorProcess(err); } self.showInputLoading(false); _view.CanadaBackground(false); self.showMainSearchForm(false); self.showMain(false); self.showSnapshop(true); let y = null; self.showWebPage(y = new showWebPageClass(search_text, buffer, uuid, () => { self.showWebPage(y = null); self.showMain(true); self.showSnapshop(false); _view.CanadaBackground(true); self.showMainSearchForm(true); })); }); }); }); }, searchSetup: (key, self, event) => { self.showSearchSetupForm(false); self.backGroundBlue(false); switch (key) { case 'b': { return self.searchSetupIcon(bingIcon); } case 'd': { return self.searchSetupIcon(duckduckgoIcon); } case 'y': { return self.searchSetupIcon(YahooIcon); } default: { self.searchSetupIcon(googleIcon); } } }, startup: (self) => { self.password.subscribe((_text) => { self.passwordError(false); }); self.hasFocus.subscribe((_result) => { if (_result) { self.hasFocusShowTool(true); return self.backGroundBlue(true); } /* if ( self.showMain () ) { if ( !self.searchInputText().length ) { self.searchInputTextActionShow ( false ) return self.backGroundBlue ( _result ) } self.searchInputTextActionShow ( true ) _result = false return true } if ( !_result ) { return true } if ( _result ) { if ( !self.showSubViewToolBar ()) { self.showSubViewToolBar ( true ) } } return true */ }); self.searchInputText.subscribe((_text) => { self.searchInputTextActionShow(_text.length > 0); }); self.SearchInputNextHasFocus.subscribe((hasFocus) => { if (hasFocus) { self.showSearchesRelated(true); } }); _view.showIconBar(false); _view.CanadaBackground(true); }, nextButtonErrorClick: (self) => { self.nextButtonShowError(false); self.nextButtonErrorIndex(null); }, webItemsClick: (self, event) => { self.currentlyShowItems(0); self.showResultItems(self, self.searchItemsArray()); }, searchNext: (self, event) => { const nextLink = self.searchItem().nextPage; if (self.moreResultsButtomLoading() || !nextLink) { return; } self.moreResultsButtomLoading(true); function showError(err) { self.moreResultsButtomLoading(false); self.nextButtonErrorIndex(_view.connectInformationMessage.getErrorIndex(err)); self.nextButtonShowError(true); } let currentArray = null; const com = { command: 'CoSearch', Args: ['google', nextLink], error: null, subCom: null }; switch (self.currentlyShowItems()) { // google search case 0: { com.subCom = 'searchNext'; currentArray = self.searchItemsArray(); break; } // news case 1: { com.subCom = 'newsNext'; currentArray = self.newsItemsArray(); break; } case 2: { com.subCom = 'imageSearchNext'; currentArray = self.imageSearchItemArray(); break; } default: { com.subCom = 'videoNext'; currentArray = self.videoItemsArray(); break; } } /** */ return _view.keyPairCalss.emitRequest(com, (err, com) => { if (err) { return showError(err); } if (!com) { return self.nextButtonLoadingGetResponse(true); } if (com.error === -1) { self.nextButtonLoadingGetResponse(false); return self.nextButtonConetResponse(true); } if (com.error) { return showError(com.error); } self.moreResultsButtomLoading(false); self.nextButtonLoadingGetResponse(false); self.nextButtonConetResponse(false); const args = com.Args; self.returnSearchResultItemsInit(args.param); currentArray.Result.push(...args.param.Result); currentArray.nextPage = args.param.nextPage; return self.showResultItems(self, currentArray); }); }, createNewsResult: (self, newsResult) => { const newsItems = JSON.parse(JSON.stringify(self.searchItemsArray())); newsItems.Result = newsResult.Result; newsItems.nextPage = newsResult.nextPage; newsItems.totalResults = newsResult.totalResults; return newsItems; }, newsButtonClick: (self, event) => { if (self.newsButtonShowLoading()) { return; } if (self.newsButtonShowError()) { self.newsButtonShowError(false); return self.newsButtonErrorIndex(null); } self.newsButtonShowLoading(true); const errorProcess = (err) => { self.newsButtonShowLoading(false); self.newsLoadingGetResponse(false); self.newsConetResponse(false); self.newsButtonErrorIndex(_view.connectInformationMessage.getErrorIndex(err)); return self.newsButtonShowError(true); }; if (!self.newsItemsArray()) { if (!self.searchItemsArray().action || !self.searchItemsArray().action.news) { return errorProcess('invalidRequest'); } const com = { command: 'CoSearch', Args: ['google', self.searchItemsArray().action.news], error: null, subCom: 'newsNext' }; return _view.keyPairCalss.emitRequest(com, (err, com) => { if (err) { return errorProcess(err); } if (!com) { return self.newsLoadingGetResponse(true); } if (com.error === -1) { self.newsLoadingGetResponse(false); return self.newsConetResponse(true); } if (com.error) { return errorProcess(com.error); } self.newsButtonShowLoading(false); self.newsConetResponse(false); self.newsLoadingGetResponse(false); const args = com.Args; self.newsItemsArray(self.createNewsResult(self, args.param)); self.returnSearchResultItemsInit(self.newsItemsArray()); }); } self.currentlyShowItems(1); self.newsButtonShowLoading(false); return self.showResultItems(self, self.newsItemsArray()); }, imageButtonClick: (self, event) => { if (self.imageButtonShowLoading()) { return; } if (self.imageButtonShowError()) { self.imageButtonShowError(false); return self.imageButtonErrorIndex(null); } const errorProcess = (err) => { self.imageButtonShowLoading(false); self.imageLoadingGetResponse(false); self.imageConetResponse(false); self.imageButtonErrorIndex(_view.connectInformationMessage.getErrorIndex(err)); return self.imageButtonShowError(true); }; if (!self.imageItemsArray()) { const imageLink = self.searchItemsArray() && self.searchItemsArray().action && self.searchItemsArray().action.image ? self.searchItemsArray().action.image : self.imageSearchItemArray().searchesRelated[1]; const com = { command: 'CoSearch', Args: ['google', imageLink], error: null, subCom: 'imageNext' }; self.imageButtonShowLoading(true); return _view.keyPairCalss.emitRequest(com, (err, com) => { if (err) { return errorProcess(err); } if (!com) { self.imageConetResponse(false); return self.imageLoadingGetResponse(true); } if (com.error === -1) { self.imageLoadingGetResponse(false); return self.imageConetResponse(true); } const args = com.Args; if (com.error) { return errorProcess(com.error); } if (!args.param || !args.param.Result || !args.param.Result.length) { return errorProcess('timeOut'); } self.imageButtonShowLoading(false); self.imageConetResponse(false); self.imageLoadingGetResponse(false); self.imageItemsArray(args.param); self.returnSearchResultItemsInit(self.imageItemsArray()); }); /** */ } self.searchSimilarImagesList(self.imageItemsArray().Result); self.showMain(false); self.showSearchSimilarImagesResult(true); }, getSnapshotClick: (self, index) => { const currentItem = self.searchItemList()[index]; currentItem.showLoading(true); const showError = err => { currentItem.showLoading(false); currentItem.loadingGetResponse(false); currentItem.conetResponse(false); currentItem.errorIndex(_view.connectInformationMessage.getErrorIndex(err)); currentItem.showError(true); const currentElm = $(`#${currentItem.id}`); return currentElm.popup({ on: 'click', inline: true, onHidden: function () { currentItem.showError(false); currentItem.errorIndex(null); } }); }; const callBack = (err, com) => { if (err) { return showError(err); } if (!com) { currentItem.loadingGetResponse(true); return currentItem.conetResponse(false); } if (com.error === -1) { currentItem.loadingGetResponse(false); return currentItem.conetResponse(true); } if (com.error) { return showError(com.error); } const arg = com.Args[0]; currentItem.snapshotUuid = arg.split(',')[0].split('.')[0]; return _view.connectInformationMessage.sockEmit('getFilesFromImap', arg, (err, buffer) => { if (err) { return showError(err); } return _view.keyPairCalss.decryptMessageToZipStream(buffer, (err, data) => { if (err) { return showError(err); } currentItem.snapshotReady(true); currentItem.showLoading(false); currentItem.loadingGetResponse(false); currentItem.conetResponse(false); return currentItem.snapshotData = buffer; }); }); }; const url = currentItem.url; const width = $(window).width(); const height = $(window).height(); const com = { command: 'CoSearch', Args: [url, width, height], error: null, subCom: 'getSnapshop' }; return _view.keyPairCalss.emitRequest(com, callBack); }, showSnapshotClick: (self, index) => { self.showMain(false); self.showSnapshop(true); const currentItem = self.searchItemList()[index]; let y = null; self.showWebPage(y = new showWebPageClass(currentItem.url, currentItem.snapshotData, currentItem.snapshotUuid, () => { self.showWebPage(y = null); self.showMain(true); self.showSnapshop(false); })); }, searchesRelatedSelect: (self, index) => { self.searchInputText(self.searchItem().searchesRelated[index].text); self.showSearchesRelated(false); }, closeSimilarImagesResult: (self) => { self.searchSimilarImagesList([]); self.showMain(true); self.showSearchSimilarImagesResult(false); }, videoButtonClick: (self) => { if (self.videoButtonShowLoading()) { return; } if (self.videoButtonShowError()) { self.videoButtonShowError(false); return self.imageButtonErrorIndex(null); } const errorProcess = (err) => { self.videoButtonShowLoading(false); self.videoLoadingGetResponse(false); self.videoConetResponse(false); self.videoButtonErrorIndex(_view.connectInformationMessage.getErrorIndex(err)); return self.videoButtonShowError(true); }; if (!self.videoItemsArray()) { if (!self.searchItemsArray().action || !self.searchItemsArray().action.video) { return errorProcess('invalidRequest'); } const com = { command: 'CoSearch', Args: ['google', self.searchItemsArray().action.video], error: null, subCom: 'videoNext' }; self.videoButtonShowLoading(true); return _view.keyPairCalss.emitRequest(com, (err, com) => { if (err) { return errorProcess(err); } if (!com) { self.videoConetResponse(false); return self.videoLoadingGetResponse(true); } if (com.error === -1) { self.videoLoadingGetResponse(false); return self.videoConetResponse(true); } if (com.error) { return errorProcess(com.error); } self.videoButtonShowLoading(false); self.videoLoadingGetResponse(false); self.videoConetResponse(false); const args = com.Args; self.videoItemsArray(self.createNewsResult(self, args.param)); self.returnSearchResultItemsInit(self.videoItemsArray()); }); /** */ } self.currentlyShowItems(3); return self.showResultItems(self, self.videoItemsArray()); }, getPictureBase64MaxSize_mediaData: (mediaData, imageMaxWidth, imageMaxHeight, CallBack) => { const media = mediaData.split(','); const type = media[0].split(';')[0].split(':')[1]; const _media = Buffer.from(media[1], 'base64'); const ret = { total_bytes: media[1].length, media_type: 'image/png', rawData: media[1], media_id_string: null }; //if ( mediaData.length > maxImageLength) { const exportImage = (_type, img) => { return img.getBuffer(_type, (err, _buf) => { if (err) { return CallBack(err); } ret.rawData = _buf.toString('base64'); ret.total_bytes = _buf.length; return CallBack(null, ret); }); }; return Jimp.read(_media, (err, image) => { if (err) { return CallBack(err); } const uu = image.bitmap; if (uu.height + uu.width > imageMaxHeight + imageMaxWidth) { if (uu.height > uu.widt) { image.resize(Jimp.AUTO, imageMaxHeight); } else { image.resize(imageMaxWidth, Jimp.AUTO); } } // to PNG return image.deflateStrategy(2, () => { return exportImage(ret.media_type, image); }); }); //} //return CallBack ( null, ret ) }, imageSearch: (ee) => { const self = _view.appsManager().appScript(); const errorProcess = (err) => { self.showInputLoading(false); self.searchInputText(''); self.errorMessageIndex(_view.connectInformationMessage.getErrorIndex(err)); return self.showSearchError(true); }; const showItems = (iResult) => { self.showInputLoading(false); self.currentlyShowItems(2); self.returnSearchResultItemsInit(iResult); self.imageSearchItemArray(iResult); self.searchInputText(iResult.searchesRelated[0]); self.showResultItems(self, self.imageSearchItemArray()); }; if (!ee || !ee.files || !ee.files.length) { return; } const file = ee.files[0]; if (!file || !file.type.match(/^image.(png$|jpg$|jpeg$|gif$)/)) { return; } const reader = new FileReader(); reader.onload = e => { const rawData = reader.result.toString(); self.showInputLoading(true); self.searchInputText(' '); self.searchItem(null); self.searchItemList([]); return self.getPictureBase64MaxSize_mediaData(rawData, 1024, 1024, (err, data) => { if (err) { return errorProcess(err); } const uuid = uuid_generate() + '.png'; return _view.keyPairCalss.encrypt(data.rawData, (err, textData) => { if (err) { return errorProcess(err); } self.initSearchData(self); return _view.connectInformationMessage.sockEmit('sendMedia', uuid, textData, err => { if (err) { return errorProcess(err); } const com = { command: 'CoSearch', Args: ['google', uuid], error: null, subCom: 'imageSearch' }; return _view.keyPairCalss.emitRequest(com, (err, com) => { if (err) { return errorProcess(err); } if (!com) { return self.loadingGetResponse(true); } if (com.error === -1) { self.loadingGetResponse(false); return self.conetResponse(true); } if (com.error) { return errorProcess(com.error); } _view.CanadaBackground(false); self.showMainSearchForm(false); return showItems(com.Args.param); }); }); }); }); }; if (!_view.CanadaBackground()) { _view.CanadaBackground(true); } if (!self.showMainSearchForm()) { self.showMainSearchForm(true); } return reader.readAsDataURL(file); }, imagesResultClick: (self, index, image) => { const _img = self.searchSimilarImagesList()[index]; const currentElm = $(`#${_img.id}-1`); /** * * get web side * */ if (_img.showError()) { return _img.showError(false); } if (_img.showImageError()) { return _img.showImageError(false); } if (image === 'link') { if (_img.showLoading()) { return; } const url = _img.webUrlHref; if (_img['snapshotData']) { self.showMain(false); self.showSnapshop(true); self.showSearchSimilarImagesResult(false); let y = null; return self.showWebPage(y = new showWebPageClass(url, _img['snapshotData'], _img['snapshotUuid'], () => { self.showWebPage(y = null); self.showMain(true); self.showSnapshop(false); self.showSearchSimilarImagesResult(true); })); } const errorProcess = (err) => { _img.errorIndex(_view.connectInformationMessage.getErrorIndex(err)); _img.showLoading(false); _img.snapshotReady(false); _img.loadingGetResponse(false); _img.conetResponse(false); const currentElm = $(`#${_img.id}`); currentElm.popup({ on: 'click', inline: true, onHidden: function () { _img.showError(false); _img.errorIndex(null); } }); return _img.showError(true); }; _img.showLoading(true); const callBack = (err, com) => { if (err) { return errorProcess(err); } if (!com) { _img.loadingGetResponse(true); return _img.conetResponse(false); } if (com.error === -1) { _img.loadingGetResponse(false); return _img.conetResponse(true); } if (com.error) { return errorProcess(com.error); } const arg = com.Args[0]; _img['snapshotUuid'] = arg.split(',')[0].split('.')[0]; return _view.connectInformationMessage.sockEmit('getFilesFromImap', arg, (err, buffer) => { if (err) { return errorProcess(err); } return _view.keyPairCalss.decryptMessageToZipStream(buffer, (err, data) => { if (err) { return errorProcess(err); } _img.snapshotReady(true); _img.showLoading(false); _img.loadingGetResponse(false); _img.conetResponse(false); return _img['snapshotData'] = buffer; }); }); }; const width = $(window).width(); const height = $(window).height(); const com = { command: 'CoSearch', Args: [url, width, height], error: null, subCom: 'getSnapshop' }; return _view.keyPairCalss.emitRequest(com, callBack); } /** * n['showImageLoading'] = ko.observable ( false ) n['snapshotImageReady'] = ko.observable ( false ) n['loadingImageGetResponse'] = ko.observable ( false ) n['conetImageResponse'] = ko.observable ( false ) n['showImageError'] = ko.observable ( false ) n['imageErrorIndex'] = ko.observable (-1) */ if (image === 'img') { if (_img.showImageLoading()) { return; } if (_img['imgOriginalData']) { const uu = 1; return; } const errorProcess = (err) => { _img.imageErrorIndex(_view.connectInformationMessage.getErrorIndex(err)); _img.showImageLoading(false); _img.snapshotImageReady(false); _img.loadingImageGetResponse(false); _img.conetImageResponse(false); _img.showImageError(true); currentElm.popup({ inline: true, onHidden: function () { _img.showImageError(false); } }); return; }; const callBack = (err, com) => { if (err) { return errorProcess(err); } if (!com) { _img.loadingGetResponse(true); return _img.conetResponse(false); } if (com.error === -1) { _img.loadingGetResponse(false); return _img.conetResponse(true); } if (com.error) { return errorProcess(com.error); } const arg = com.Args[0]; _img['snapshotUuid'] = arg.split(',')[0].split('.')[0]; return _view.connectInformationMessage.sockEmit('getFilesFromImap', arg, (err, buffer) => { if (err) { return errorProcess(err); } return _view.keyPairCalss.decryptMessageToZipStream(buffer, (err, data) => { if (err) { return errorProcess(err); } _img.snapshotReady(true); _img.showLoading(false); _img.loadingGetResponse(false); _img.conetResponse(false); return _img['snapshotData'] = buffer; }); }); }; const com = { command: 'CoSearch', Args: [_img.imgUrlHref], error: null, subCom: 'getFile' }; return _view.keyPairCalss.emitRequest(com, callBack); setTimeout(() => { _img.loadingImageGetResponse(true); setTimeout(() => { _img.loadingImageGetResponse(false); _img.conetImageResponse(true); setTimeout(() => { _img.loadingImageGetResponse(false); _img.conetImageResponse(false); _img.snapshotImageReady(true); _img.showImageLoading(false); }, 1000); }, 1000); }, 1000); _img.showImageLoading(true); } } }; ================================================ FILE: app/public/scripts/appCosearch.ts ================================================ let appScript = { info: { totalResults: ['大约有','約','About','大約有'], totalResults1: ['条记录','件','results','條記錄'], moreResults: ['更多结果','結果をさらに表示','More Results','更多結果'], searchToolBarMenu: [ [ '网站','ウェイブ','Website','網頁' ],[ '新闻','ニュース','News','新聞' ],[ '图片','画像','Picture','圖片' ],[ '视频','ビデオ','Video','視頻' ] ] }, showMain: ko.observable ( true ), showWebPage: ko.observable ( null ), htmlIframe: ko.observable ( false ), showSnapshop: ko.observable ( false ), searchItemsArray: ko.observable (), hasFocusShowTool: ko.observable ( false ), backGroundBlue: ko.observable ( false ), searchItem: ko.observable ( null ), showMainSearchForm: ko.observable ( true ), showSearchSetupForm: ko.observable ( false ), showSearchError: ko.observable ( false ), showInputLoading: ko.observable ( false ), errorMessageIndex: ko.observable ( -1 ), searchInputText: ko.observable (''), hasFocus: ko.observable ( false ), passwordError: ko.observable ( false ), searchSetupIcon: ko.observable ( bingIcon ), password: ko.observable (''), searchInputTextActionShow: ko.observable ( false ), SearchInputNextHasFocus: ko.observable ( false ), showSearchesRelated: ko.observable ( false ), searchItemList: ko.observableArray ([]), loadingGetResponse: ko.observable ( false ), conetResponse: ko.observable ( false ), searchInputTextShow: ko.observable (''), currentlyShowItems: ko.observable ( 0 ), newsButtonShowLoading: ko.observable ( false ), newsItemsArray: ko.observable (), newsButtonShowError: ko.observable ( false ), newsButtonErrorIndex: ko.observable ( null ), newsLoadingGetResponse: ko.observable ( false ), newsConetResponse: ko.observable ( false ), nextButtonShowError: ko.observable ( false ), moreResultsButtomLoading: ko.observable ( false ), imageButtonShowLoading: ko.observable ( false ), imageButtonShowError: ko.observable ( false ), imageButtonErrorIndex: ko.observable ( -1 ), imageLoadingGetResponse: ko.observable ( false ), imageConetResponse: ko.observable ( false ), imageItemsArray: ko.observable (), searchSimilarImagesList: ko.observableArray ([]), showSearchSimilarImagesResult: ko.observable ( false ), imageSearchItemArray: ko.observable (), videoButtonShowLoading: ko.observable ( false ), videoItemsArray: ko.observable (), videoButtonShowError: ko.observable ( false ), videoButtonErrorIndex: ko.observable ( -1 ), videoLoadingGetResponse: ko.observable ( false ), videoConetResponse: ko.observable ( false ), nextButtonErrorIndex: ko.observable ( false ), nextButtonConetResponse: ko.observable ( false ), nextButtonLoadingGetResponse: ko.observable ( false ), // ['originImage'] initSearchData: ( self ) => { self.searchItem ( null ) self.searchItemList ([]) self.showInputLoading ( true ) self.showSearchesRelated ( false ) self.newsItemsArray ( null ) self.imageItemsArray ( null ) self.showSearchesRelated ( null ) self.videoItemsArray ( null ) self.imageSearchItemArray ( null ) }, showResultItems: ( self, items ) => { self.searchItem ( items ) self.searchItemList ( items.Result ) $('.selection.dropdown').dropdown() }, searchSetupClick: ( self, event ) => { self.showSearchSetupForm ( true ) self.backGroundBlue ( true ) /* $('#coSearchBackGround').one ( 'click', function() { self.backGroundClick () $('#coSearchForm').off ('click') }) $('#coSearchForm').one ( 'click', function() { self.backGroundClick () $('#coSearchBackGround').off ('click') }) */ return false }, searchInputCloseError: ( self, event ) => { self.showSearchError ( false ) self.errorMessageIndex (null) }, returnSearchResultItemsInit: ( items ) => { let i = 0 const y = [] items.Result.forEach ( n => { i++ n['showLoading'] = ko.observable ( false ) n['conetResponse'] = ko.observable ( false ) n['loadingGetResponse'] = ko.observable ( false ) n['snapshotReady'] = ko.observable ( false ) n['snapshotClass'] = null n['snapshotData'] = null n['snapshotUuid'] = null n['id'] = uuid_generate () n['showError'] = ko.observable ( false ) n['errorIndex'] = ko.observable ( -1 ) if ( !n['newsBrand'] ) { n['newsBrand'] = null } if ( n.imageInfo ) { if ( !n.imageInfo['videoTime'] ) { n.imageInfo['videoTime'] = null } } n['webUrlHref'] = n.clickUrl n['imgUrlHref'] = n.imgSrc n['showImageLoading'] = ko.observable ( false ) n['showImageError'] = ko.observable ( false ) n['snapshotImageReady'] = ko.observable ( false ) n['loadingImageGetResponse'] = ko.observable ( false ) n['conetImageResponse'] = ko.observable ( false ) n['imageErrorIndex'] = ko.observable (-1) }) }, search_form: ( self, event ) => { if ( self.showInputLoading()) { return } if ( !_view.CanadaBackground ()) { _view.CanadaBackground ( true ) } if ( !self.showMainSearchForm()) { self.showMainSearchForm( true ) } const search_text = self.searchInputText () const width = window.innerWidth const height = window.outerHeight self.initSearchData ( self ) const com: QTGateAPIRequestCommand = { command: 'CoSearch', Args: null, error: null, subCom: null } /** * web page address */ if ( /^http[s]?:\/\//.test( search_text )) { com.Args = [ search_text, width, height ] com.subCom = 'getSnapshop' } else { com.Args = [ 'google', search_text ] com.subCom = 'webSearch' } const errorProcess = ( err ) => { self.showInputLoading ( false ) self.searchInputText ( '' ) self.errorMessageIndex ( _view.connectInformationMessage.getErrorIndex( err )) return self.showSearchError ( true ) } /** * * test Unit */ return _view.keyPairCalss.emitRequest ( com, ( err, com: QTGateAPIRequestCommand ) => { if ( err ) { return errorProcess ( err ) } if ( !com ) { return self.loadingGetResponse ( true ) } if ( com.error === -1 ) { self.loadingGetResponse ( false ) return self.conetResponse ( true ) } if ( com.error ) { return errorProcess ( com.error ) } if ( com.subCom === 'webSearch') { self.showInputLoading ( false ) const args = com.Args self.searchInputTextShow ( search_text ) self.returnSearchResultItemsInit ( args.param ) self.searchItemsArray ( args.param ) self.showResultItems ( self, args.param ) _view.CanadaBackground ( false ) return self.showMainSearchForm ( false ) } const arg: string = com.Args[0] const uuid = arg.split(',')[0].split ('.')[0] return _view.connectInformationMessage.sockEmit ( 'getFilesFromImap', arg, ( err, buffer: string ) => { if ( err ) { return errorProcess ( err ) } return _view.keyPairCalss.decryptMessageToZipStream ( buffer, ( err, data ) => { if ( err ) { return errorProcess ( err ) } self.showInputLoading ( false ) _view.CanadaBackground ( false ) self.showMainSearchForm ( false ) self.showMain ( false ) self.showSnapshop ( true ) let y = null self.showWebPage ( y = new showWebPageClass ( search_text, buffer, uuid , () => { self.showWebPage ( y = null ) self.showMain ( true ) self.showSnapshop ( false ) _view.CanadaBackground ( true ) self.showMainSearchForm ( true ) })) }) }) }) }, searchSetup: ( key: string, self, event ) => { self.showSearchSetupForm ( false ) self.backGroundBlue ( false ) switch ( key ) { case 'b': { return self.searchSetupIcon ( bingIcon ) } case 'd': { return self.searchSetupIcon ( duckduckgoIcon ) } case 'y': { return self.searchSetupIcon ( YahooIcon ) } default: { self.searchSetupIcon ( googleIcon ) } } }, startup: ( self ) => { self.password.subscribe (( _text: string ) => { self.passwordError ( false ) }) self.hasFocus.subscribe (( _result: boolean ) => { if ( _result ) { self.hasFocusShowTool ( true ) return self.backGroundBlue ( true ) } /* if ( self.showMain () ) { if ( !self.searchInputText().length ) { self.searchInputTextActionShow ( false ) return self.backGroundBlue ( _result ) } self.searchInputTextActionShow ( true ) _result = false return true } if ( !_result ) { return true } if ( _result ) { if ( !self.showSubViewToolBar ()) { self.showSubViewToolBar ( true ) } } return true */ }) self.searchInputText.subscribe (( _text: string ) => { self.searchInputTextActionShow ( _text.length > 0 ) }) self.SearchInputNextHasFocus.subscribe (( hasFocus: boolean ) => { if ( hasFocus ) { self.showSearchesRelated ( true ) } }) _view.showIconBar ( false ) _view.CanadaBackground ( true ) }, nextButtonErrorClick: ( self ) => { self.nextButtonShowError ( false ) self.nextButtonErrorIndex ( null ) }, webItemsClick: ( self, event ) => { self.currentlyShowItems ( 0 ) self.showResultItems ( self, self.searchItemsArray ()) }, searchNext: ( self, event ) => { const nextLink = self.searchItem().nextPage if ( self.moreResultsButtomLoading () || !nextLink ) { return } self.moreResultsButtomLoading ( true ) function showError ( err ) { self.moreResultsButtomLoading ( false ) self.nextButtonErrorIndex ( _view.connectInformationMessage.getErrorIndex ( err )) self.nextButtonShowError ( true ) } let currentArray = null const com: QTGateAPIRequestCommand = { command: 'CoSearch', Args: [ 'google', nextLink ], error: null, subCom: null } switch ( self.currentlyShowItems ()) { // google search case 0: { com.subCom = 'searchNext' currentArray = self.searchItemsArray() break } // news case 1: { com.subCom = 'newsNext' currentArray = self.newsItemsArray() break } case 2: { com.subCom = 'imageSearchNext' currentArray = self.imageSearchItemArray() break } default: { com.subCom = 'videoNext' currentArray = self.videoItemsArray() break } } /** */ return _view.keyPairCalss.emitRequest ( com, ( err, com: QTGateAPIRequestCommand ) => { if ( err ) { return showError ( err ) } if ( !com ) { return self.nextButtonLoadingGetResponse ( true ) } if ( com.error === -1 ) { self.nextButtonLoadingGetResponse ( false ) return self.nextButtonConetResponse ( true ) } if ( com.error ) { return showError ( com.error ) } self.moreResultsButtomLoading ( false ) self.nextButtonLoadingGetResponse ( false ) self.nextButtonConetResponse ( false ) const args = com.Args self.returnSearchResultItemsInit ( args.param ) currentArray.Result.push ( ...args.param.Result ) currentArray.nextPage = args.param.nextPage return self.showResultItems ( self, currentArray ) }) }, createNewsResult: ( self, newsResult ) => { const newsItems = JSON.parse ( JSON.stringify ( self.searchItemsArray ())) newsItems.Result = newsResult.Result newsItems.nextPage = newsResult.nextPage newsItems.totalResults = newsResult.totalResults return newsItems }, newsButtonClick: ( self, event ) => { if ( self.newsButtonShowLoading ()) { return } if ( self.newsButtonShowError ()) { self.newsButtonShowError( false ) return self.newsButtonErrorIndex ( null ) } self.newsButtonShowLoading ( true ) const errorProcess = ( err ) => { self.newsButtonShowLoading ( false ) self.newsLoadingGetResponse ( false ) self.newsConetResponse ( false ) self.newsButtonErrorIndex ( _view.connectInformationMessage.getErrorIndex( err )) return self.newsButtonShowError ( true ) } if ( ! self.newsItemsArray() ) { if ( !self.searchItemsArray().action || !self.searchItemsArray().action.news ) { return errorProcess ('invalidRequest') } const com: QTGateAPIRequestCommand = { command: 'CoSearch', Args: [ 'google', self.searchItemsArray().action.news ], error: null, subCom: 'newsNext' } return _view.keyPairCalss.emitRequest ( com,( err, com: QTGateAPIRequestCommand ) => { if ( err ) { return errorProcess ( err ) } if ( !com ) { return self.newsLoadingGetResponse ( true ) } if ( com.error === -1 ) { self.newsLoadingGetResponse ( false ) return self.newsConetResponse ( true ) } if ( com.error ) { return errorProcess ( com.error ) } self.newsButtonShowLoading ( false ) self.newsConetResponse ( false ) self.newsLoadingGetResponse ( false ) const args = com.Args self.newsItemsArray ( self.createNewsResult( self, args.param )) self.returnSearchResultItemsInit ( self.newsItemsArray () ) }) } self.currentlyShowItems(1) self.newsButtonShowLoading ( false ) return self.showResultItems ( self, self.newsItemsArray() ) }, imageButtonClick: ( self, event ) => { if ( self.imageButtonShowLoading ()) { return } if ( self.imageButtonShowError ()) { self.imageButtonShowError ( false ) return self.imageButtonErrorIndex ( null ) } const errorProcess = ( err ) => { self.imageButtonShowLoading ( false ) self.imageLoadingGetResponse ( false ) self.imageConetResponse ( false ) self.imageButtonErrorIndex ( _view.connectInformationMessage.getErrorIndex( err )) return self.imageButtonShowError ( true ) } if ( ! self.imageItemsArray() ) { const imageLink = self.searchItemsArray() && self.searchItemsArray().action && self.searchItemsArray().action.image ? self.searchItemsArray().action.image : self.imageSearchItemArray().searchesRelated[1] const com: QTGateAPIRequestCommand = { command: 'CoSearch', Args: [ 'google', imageLink ], error: null, subCom: 'imageNext' } self.imageButtonShowLoading ( true ) return _view.keyPairCalss.emitRequest ( com,( err, com: QTGateAPIRequestCommand ) => { if ( err ) { return errorProcess ( err ) } if ( !com ) { self.imageConetResponse ( false ) return self.imageLoadingGetResponse ( true ) } if ( com.error === -1 ) { self.imageLoadingGetResponse ( false ) return self.imageConetResponse ( true ) } const args = com.Args if ( com.error ) { return errorProcess ( com.error ) } if ( !args.param || !args.param.Result || !args.param.Result.length ) { return errorProcess ( 'timeOut' ) } self.imageButtonShowLoading ( false ) self.imageConetResponse ( false ) self.imageLoadingGetResponse ( false ) self.imageItemsArray ( args.param ) self.returnSearchResultItemsInit ( self.imageItemsArray () ) }) /** */ } self.searchSimilarImagesList( self.imageItemsArray().Result ) self.showMain ( false ) self.showSearchSimilarImagesResult ( true ) }, getSnapshotClick: ( self, index ) => { const currentItem = self.searchItemList()[ index ] currentItem.showLoading ( true ) const showError = err => { currentItem.showLoading ( false ) currentItem.loadingGetResponse ( false ) currentItem.conetResponse ( false ) currentItem.errorIndex ( _view.connectInformationMessage.getErrorIndex ( err )) currentItem.showError ( true ) const currentElm = $(`#${ currentItem.id }`) return currentElm.popup ({ on: 'click', inline: true, onHidden: function () { currentItem.showError ( false ) currentItem.errorIndex ( null ) } }) } const callBack = ( err?, com?: QTGateAPIRequestCommand ) => { if ( err ) { return showError ( err ) } if ( !com ) { currentItem.loadingGetResponse ( true ) return currentItem.conetResponse ( false ) } if ( com.error === -1 ) { currentItem.loadingGetResponse ( false ) return currentItem.conetResponse ( true ) } if ( com.error ) { return showError ( com.error ) } const arg: string = com.Args[0] currentItem.snapshotUuid = arg.split(',')[0].split ('.')[0] return _view.connectInformationMessage.sockEmit ( 'getFilesFromImap', arg, ( err, buffer: string ) => { if ( err ) { return showError ( err ) } return _view.keyPairCalss.decryptMessageToZipStream ( buffer, ( err, data ) => { if ( err ) { return showError ( err ) } currentItem.snapshotReady ( true ) currentItem.showLoading ( false ) currentItem.loadingGetResponse ( false ) currentItem.conetResponse ( false ) return currentItem.snapshotData = buffer }) }) } const url = currentItem.url const width = $(window).width() const height = $(window).height() const com: QTGateAPIRequestCommand = { command: 'CoSearch', Args: [ url, width, height ], error: null, subCom: 'getSnapshop' } return _view.keyPairCalss.emitRequest ( com, callBack ) }, showSnapshotClick: ( self, index ) => { self.showMain ( false ) self.showSnapshop ( true ) const currentItem = self.searchItemList()[ index ] let y = null self.showWebPage ( y = new showWebPageClass ( currentItem.url, currentItem.snapshotData, currentItem.snapshotUuid , () => { self.showWebPage ( y = null ) self.showMain ( true ) self.showSnapshop ( false ) })) }, searchesRelatedSelect: ( self, index ) => { self.searchInputText ( self.searchItem().searchesRelated[index].text ) self.showSearchesRelated ( false ) }, closeSimilarImagesResult: ( self ) => { self.searchSimilarImagesList ([]) self.showMain ( true ) self.showSearchSimilarImagesResult ( false ) }, videoButtonClick: ( self ) => { if ( self.videoButtonShowLoading ()) { return } if ( self.videoButtonShowError ()) { self.videoButtonShowError ( false ) return self.imageButtonErrorIndex ( null ) } const errorProcess = ( err ) => { self.videoButtonShowLoading ( false ) self.videoLoadingGetResponse ( false ) self.videoConetResponse ( false ) self.videoButtonErrorIndex ( _view.connectInformationMessage.getErrorIndex ( err )) return self.videoButtonShowError ( true ) } if ( ! self.videoItemsArray() ) { if ( !self.searchItemsArray().action || !self.searchItemsArray().action.video ) { return errorProcess ('invalidRequest') } const com: QTGateAPIRequestCommand = { command: 'CoSearch', Args: [ 'google', self.searchItemsArray().action.video ], error: null, subCom: 'videoNext' } self.videoButtonShowLoading ( true ) return _view.keyPairCalss.emitRequest ( com,( err, com: QTGateAPIRequestCommand ) => { if ( err ) { return errorProcess ( err ) } if ( !com ) { self.videoConetResponse ( false ) return self.videoLoadingGetResponse ( true ) } if ( com.error === -1 ) { self.videoLoadingGetResponse ( false ) return self.videoConetResponse ( true ) } if ( com.error ) { return errorProcess ( com.error ) } self.videoButtonShowLoading ( false ) self.videoLoadingGetResponse ( false ) self.videoConetResponse ( false ) const args = com.Args self.videoItemsArray ( self.createNewsResult( self, args.param )) self.returnSearchResultItemsInit ( self.videoItemsArray () ) }) /** */ } self.currentlyShowItems(3) return self.showResultItems ( self, self.videoItemsArray() ) }, getPictureBase64MaxSize_mediaData: ( mediaData: string, imageMaxWidth: number, imageMaxHeight: number, CallBack ) => { const media = mediaData.split(',') const type = media[0].split(';')[0].split (':')[1] const _media = Buffer.from ( media[1], 'base64') const ret: twitter_mediaData = { total_bytes: media[1].length, media_type: 'image/png', rawData: media[1], media_id_string: null } //if ( mediaData.length > maxImageLength) { const exportImage = ( _type, img ) => { return img.getBuffer ( _type, ( err, _buf: Buffer ) => { if ( err ) { return CallBack ( err ) } ret.rawData = _buf.toString( 'base64' ) ret.total_bytes = _buf.length return CallBack ( null, ret ) }) } return Jimp.read ( _media, ( err, image ) => { if ( err ) { return CallBack ( err ) } const uu = image.bitmap if ( uu.height + uu.width > imageMaxHeight + imageMaxWidth ) { if ( uu.height > uu.widt ) { image.resize ( Jimp.AUTO, imageMaxHeight ) } else { image.resize ( imageMaxWidth, Jimp.AUTO ) } } // to PNG return image.deflateStrategy ( 2, () => { return exportImage ( ret.media_type, image ) }) }) //} //return CallBack ( null, ret ) }, imageSearch: ( ee ) => { const self = _view.appsManager().appScript() const errorProcess = ( err ) => { self.showInputLoading ( false ) self.searchInputText ( '' ) self.errorMessageIndex ( _view.connectInformationMessage.getErrorIndex( err )) return self.showSearchError ( true ) } const showItems = ( iResult ) => { self.showInputLoading ( false ) self.currentlyShowItems ( 2 ) self.returnSearchResultItemsInit ( iResult ) self.imageSearchItemArray ( iResult ) self.searchInputText ( iResult.searchesRelated[0]) self.showResultItems ( self, self.imageSearchItemArray ()) } if ( !ee || !ee.files || !ee.files.length ) { return } const file = ee.files[0] if ( !file || !file.type.match ( /^image.(png$|jpg$|jpeg$|gif$)/ )) { return } const reader = new FileReader() reader.onload = e => { const rawData = reader.result.toString() self.showInputLoading ( true ) self.searchInputText (' ') self.searchItem ( null ) self.searchItemList ([]) return self.getPictureBase64MaxSize_mediaData ( rawData, 1024, 1024, ( err, data ) => { if ( err ) { return errorProcess ( err ) } const uuid = uuid_generate() + '.png' return _view.keyPairCalss.encrypt ( data.rawData, ( err, textData ) => { if ( err ) { return errorProcess ( err ) } self.initSearchData ( self ) return _view.connectInformationMessage.sockEmit ( 'sendMedia', uuid, textData, err => { if ( err ) { return errorProcess ( err ) } const com: QTGateAPIRequestCommand = { command: 'CoSearch', Args: [ 'google', uuid ], error: null, subCom: 'imageSearch' } return _view.keyPairCalss.emitRequest ( com, ( err, com: QTGateAPIRequestCommand ) => { if ( err ) { return errorProcess ( err ) } if ( !com ) { return self.loadingGetResponse ( true ) } if ( com.error === -1 ) { self.loadingGetResponse ( false ) return self.conetResponse ( true ) } if ( com.error ) { return errorProcess ( com.error ) } _view.CanadaBackground ( false ) self.showMainSearchForm( false ) return showItems ( com.Args.param ) }) }) }) }) } if ( !_view.CanadaBackground ()) { _view.CanadaBackground ( true ) } if ( !self.showMainSearchForm()) { self.showMainSearchForm( true ) } return reader.readAsDataURL ( file ) }, imagesResultClick: ( self, index: number, image: string ) => { const _img = self.searchSimilarImagesList ()[ index ] const currentElm = $(`#${ _img.id }-1`) /** * * get web side * */ if ( _img.showError()) { return _img.showError ( false ) } if ( _img.showImageError ()) { return _img.showImageError ( false ) } if ( image === 'link' ) { if ( _img.showLoading() ) { return } const url = _img.webUrlHref if ( _img['snapshotData'] ) { self.showMain ( false ) self.showSnapshop ( true ) self.showSearchSimilarImagesResult ( false ) let y = null return self.showWebPage ( y = new showWebPageClass ( url, _img['snapshotData'], _img['snapshotUuid'] , () => { self.showWebPage ( y = null ) self.showMain ( true ) self.showSnapshop ( false ) self.showSearchSimilarImagesResult ( true ) })) } const errorProcess = ( err ) => { _img.errorIndex ( _view.connectInformationMessage.getErrorIndex( err )) _img.showLoading ( false ) _img.snapshotReady ( false ) _img.loadingGetResponse ( false ) _img.conetResponse ( false ) const currentElm = $(`#${ _img.id }`) currentElm.popup ({ on: 'click', inline: true, onHidden: function () { _img.showError ( false ) _img.errorIndex ( null ) } }) return _img.showError ( true ) } _img.showLoading ( true ) const callBack = ( err?, com?: QTGateAPIRequestCommand ) => { if ( err ) { return errorProcess ( err ) } if ( !com ) { _img.loadingGetResponse ( true ) return _img.conetResponse ( false ) } if ( com.error === -1 ) { _img.loadingGetResponse ( false ) return _img.conetResponse ( true ) } if ( com.error ) { return errorProcess ( com.error ) } const arg: string = com.Args[0] _img['snapshotUuid'] = arg.split(',')[0].split ('.')[0] return _view.connectInformationMessage.sockEmit ( 'getFilesFromImap', arg, ( err, buffer: string ) => { if ( err ) { return errorProcess ( err ) } return _view.keyPairCalss.decryptMessageToZipStream ( buffer, ( err, data ) => { if ( err ) { return errorProcess ( err ) } _img.snapshotReady ( true ) _img.showLoading ( false ) _img.loadingGetResponse ( false ) _img.conetResponse ( false ) return _img['snapshotData'] = buffer }) }) } const width = $(window).width() const height = $(window).height() const com: QTGateAPIRequestCommand = { command: 'CoSearch', Args: [ url, width, height ], error: null, subCom: 'getSnapshop' } return _view.keyPairCalss.emitRequest ( com, callBack ) } /** * n['showImageLoading'] = ko.observable ( false ) n['snapshotImageReady'] = ko.observable ( false ) n['loadingImageGetResponse'] = ko.observable ( false ) n['conetImageResponse'] = ko.observable ( false ) n['showImageError'] = ko.observable ( false ) n['imageErrorIndex'] = ko.observable (-1) */ if ( image === 'img') { if ( _img.showImageLoading() ) { return } if ( _img['imgOriginalData'] ) { const uu = 1 return } const errorProcess = ( err ) => { _img.imageErrorIndex (_view.connectInformationMessage.getErrorIndex( err )) _img.showImageLoading ( false ) _img.snapshotImageReady ( false ) _img.loadingImageGetResponse ( false ) _img.conetImageResponse ( false ) _img.showImageError ( true ) currentElm.popup ({ inline: true, onHidden: function () { _img.showImageError ( false ) } }) return } const callBack = ( err?, com?: QTGateAPIRequestCommand ) => { if ( err ) { return errorProcess ( err ) } if ( !com ) { _img.loadingGetResponse ( true ) return _img.conetResponse ( false ) } if ( com.error === -1 ) { _img.loadingGetResponse ( false ) return _img.conetResponse ( true ) } if ( com.error ) { return errorProcess ( com.error ) } const arg: string = com.Args[0] _img['snapshotUuid'] = arg.split(',')[0].split ('.')[0] return _view.connectInformationMessage.sockEmit ( 'getFilesFromImap', arg, ( err, buffer: string ) => { if ( err ) { return errorProcess ( err ) } return _view.keyPairCalss.decryptMessageToZipStream ( buffer, ( err, data ) => { if ( err ) { return errorProcess ( err ) } _img.snapshotReady ( true ) _img.showLoading ( false ) _img.loadingGetResponse ( false ) _img.conetResponse ( false ) return _img['snapshotData'] = buffer }) }) } const com: QTGateAPIRequestCommand = { command: 'CoSearch', Args: [ _img.imgUrlHref ], error: null, subCom: 'getFile' } return _view.keyPairCalss.emitRequest ( com, callBack ) setTimeout (() => { _img.loadingImageGetResponse ( true ) setTimeout (() => { _img.loadingImageGetResponse ( false ) _img.conetImageResponse ( true ) setTimeout (() => { _img.loadingImageGetResponse ( false ) _img.conetImageResponse ( false ) _img.snapshotImageReady ( true ) _img.showImageLoading ( false ) }, 1000 ) }, 1000 ) }, 1000 ) _img.showImageLoading ( true ) } } } declare const TimelineMax ================================================ FILE: app/public/scripts/appsManager.js ================================================ const _mainMenuObj111 = { nodeName: ['CoNET官方节点', 'CoNET公式パブリックノード', 'CoNET official public node', 'CoNET官方節點'], nodeAddress: 'QTGate@CoNETTech.ca', mainMenuItem: [ /* , { imgSrc: 'data:image/png;base64,', headerText: ['','','',''], headerTextColor: '', textColor: '', meta: ['','','',''], description: [ '','','','' ], extra: [ '','','','' ] }, */ { imgSrc: 'data:image/png;base64,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', headerText: [ 'CoSearch', 'CoSearch', 'CoSearch', 'CoSearch' ], headerTextColor: '', textColor: '', meta: [ '网站图片检索,任意网页快照,谷歌翻译,多媒体下载链接', 'ウェブと画像検索、ページのスクリーンショット、メディアファイルのダウンロードリンク、Google通訳', 'Web or images search. Web page screenshot. Media file download link, Google translate.', '網站圖片檢索,任意網頁快照,谷歌翻譯,多媒體下載鏈接' ], description: [ '当前为Bate版,检索引擎只能选择Google,无翻译和多媒体下载链接功能', 'ベータバージョン、検索エンジンはGoogleオンリー、通訳とマルチメディアファイルダウンロードリンクはまだです', 'This is beta version, earch engine Google only, Google translate and media file download link coming soon.', '當前為Bate版,檢索引擎只能選擇Google,無翻譯和多媒體下載連接功能' ], extra: [ '', '', '', '' ], "active": true }, { imgSrc: '', headerText: [ 'CoMSG', 'CoMSG', 'CoMSG', 'CoMSG' ], headerTextColor: '', textColor: '', meta: [ '点对点私密信息,支持多媒体及文件推送,会议室无上限设置', 'ポイントツーポイント暗号化メッセージ、マルチメディアとファイルの転送ができます、無制限のグループ会話', 'End to End encrypted message. Support for multimedia and all other type files, unlimit group message.', '點對點私密信息,支持多媒體及文件推送,會議室無上限設置' ], description: [ '敬请期待', '準備中', 'Coming soon.', '敬請期待' ], extra: [ '', '', '', '' ], "active": false }, { imgSrc: '', headerText: [ 'CoBox', 'CoBox', 'CoBox', 'CoBox' ], headerTextColor: '', textColor: '', meta: [ '文件加密后打成碎片,分别存放到多个免费邮箱,高隐私无限量存储', 'ファイルを暗号化して破砕して、多数のフリーEmailにそれぞれを保存する強いプライバシーストレージ', "Encrypted and split a file to multiple parts, append to multiple email's draft. High privacy and security storage system.", '使用綑綁多個免費郵箱剩餘容量,存儲加密後打成碎片,高隱私無限量文件存儲' ], description: [ '敬请期待', '準備中', 'Coming soon.', '敬請期待' ], extra: [ '', '', '', '' ], "active": false } ] }; const appHtml = ``; const appMenuData = 'appmenu'; class appsManager { constructor(exit) { this.exit = exit; this.mainPages = ko.observable(null); this.mainLoading = ko.observable(true); this.loadingError = ko.observable(null); this.mainHtml = ko.observable(''); this.appHtml = ko.observable(false); this.appScript = ko.observable(); this.showMain = ko.observable(false); this.showMainMenu = ko.observable(true); this.loadingGetResponse = ko.observable(false); this.conetResponse = ko.observable(false); this.showSnapshop = ko.observable(false); this.appMenu = this.getAppMenu(); this.runningAppHtml = ko.observable(null); this.showAppMain = ko.observable(false); this.AppObj = {}; this.appLoadingError = ko.observable(false); this.appLoadingErrorIndex = ko.observable(null); /*** * * debug temp */ this.showTempMain = ko.observable(false); this.tempAppHtml = ko.observable(false); /** * */ this.mainScript = ko.observable(null); _view.sectionLogin(false); this.updateAppsManu(); } getAppMenu() { const uu = window.localStorage.getItem(appMenuData); try { return JSON.parse(uu); } catch (ex) { return null; } } initMenuArray(mainMenuArray) { mainMenuArray.forEach(n => { n['loading'] = ko.observable(false); n['loadingGetResponse'] = ko.observable(false); n['conetResponse'] = ko.observable(false); }); } showLoadingGetResponse(item) { item.loadingGetResponse(true); item.conetResponse(false); } showConetResponse(item) { item.loadingGetResponse(false); item.conetResponse(true); } getAppObject(mainMenuItem) { for (let i = 0; i < mainMenuItem.length; i++) { const uu = mainMenuItem[i]; if (uu.active) { const objName = `APP-${i}`; const kk = window.localStorage.getItem(objName); try { this.AppObj[objName] = JSON.parse(kk); } catch (ex) { } } } } updateAppsManu(_self = null) { const self = _self || this; self.appLoadingError(false); /** * * DEBUG use Temp Pug * */ const _mainMenuObj = _mainMenuObj111; self.initMenuArray(_mainMenuObj.mainMenuItem); _mainMenuObj['_mainMenuItem'] = ko.observableArray(_mainMenuObj.mainMenuItem); self.mainLoading(false); self.showTempMain(true); return self.mainScript(_mainMenuObj); /** */ const viewMainMenuu = () => { self.mainHtml(self.appMenu[1]); const _mainMenuObj = JSON.parse(self.appMenu[2]); self.initMenuArray(_mainMenuObj.mainMenuItem); _mainMenuObj['_mainMenuItem'] = ko.observableArray(_mainMenuObj.mainMenuItem); self.mainScript(_mainMenuObj); self.showMain(true); self.mainLoading(false); self.mainLoading(false); self.conetResponse(false); _view.connectInformationMessage.hideMessage(); this.getAppObject(_mainMenuObj.mainMenuItem); }; if (this.appMenu && this.appMenu.length) { viewMainMenuu(); } const showError = (err) => { self.mainLoading(false); //_view.connectInformationMessage.hideMessage() self.loadingError(_view.connectInformationMessage.getErrorIndex(err)); self.loadingGetResponse(false); return self.conetResponse(false); }; const com = { command: 'mainMenu', Args: this.appMenu && this.appMenu[0] ? this.appMenu[0] : null, error: null, subCom: null }; return _view.keyPairCalss.emitRequest(com, (err, com) => { if (err) { return showError(err); } if (!com) { self.conetResponse(false); return self.loadingGetResponse(true); } if (com.error === -1) { self.loadingGetResponse(false); return self.conetResponse(true); } if (com.error) { return showError(com.error); } _view.connectInformationMessage.hideMessage(); if (!com.Args || !com.Args.length) { return; } this.appMenu = com.Args; if (typeof Storage !== "undefined") { window.localStorage.setItem(appMenuData, JSON.stringify(com.Args)); } return viewMainMenuu(); }); } mainNemuError() { this.exit(); } appClick(appIndex) { const self = this; const item = self.mainScript().mainMenuItem[appIndex]; self.mainScript()._mainMenuItem([item]); item.loading(true); const runningApp = (obj) => { _view.bodyBlue(false); _view.showIconBar(false); this.showMainMenu(false); /** * * DEBUG APP use Temp pug * */ this.tempAppHtml(true); appScript.startup(appScript); this.appScript(appScript); _view.CanadaBackground(true); return; /** */ /** * * Use appHtml */ /* this.runningAppHtml ( appHtml ) this.appHtml ( true ) this.showAppMain ( true ) appScript.startup ( appScript ) this.appScript ( appScript ) /** */ this.runningAppHtml(obj[1]); this.appHtml(true); eval(obj[2]); appScript.startup(appScript); this.appScript(appScript); this.showAppMain(true); }; const AppName = `APP-${appIndex}`; let obj = this.AppObj[AppName]; /** * * use Debug * */ return runningApp(null); /** end Debug */ if (obj) { runningApp(obj); } const com = { command: AppName, Args: obj && obj[0] ? obj[0] : null, error: null, subCom: null }; const showError = (err) => { item.loading(false); self.appLoadingErrorIndex(_view.connectInformationMessage.getErrorIndex(err)); return self.appLoadingError(true); }; return _view.keyPairCalss.emitRequest(com, (err, com) => { if (err) { return showError(err); } if (!com) { self.conetResponse(false); return self.loadingGetResponse(true); } if (com.error === -1) { self.loadingGetResponse(false); return self.conetResponse(true); } if (com.error) { return showError(com.error); } _view.connectInformationMessage.hideMessage(); if (!com.Args || !com.Args.length) { return; } obj = com.Args; if (typeof Storage !== "undefined") { window.localStorage.setItem(AppName, JSON.stringify(com.Args)); } return runningApp(obj); }); } } ================================================ FILE: app/public/scripts/appsManager.ts ================================================ const _mainMenuObj111 = { nodeName: ['CoNET官方节点','CoNET公式パブリックノード','CoNET official public node','CoNET官方節點'], nodeAddress: 'QTGate@CoNETTech.ca', mainMenuItem :[ /* , { imgSrc: 'data:image/png;base64,', headerText: ['','','',''], headerTextColor: '', textColor: '', meta: ['','','',''], description: [ '','','','' ], extra: [ '','','','' ] }, */ { imgSrc: 'data:image/png;base64,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', headerText: [ 'CoSearch','CoSearch','CoSearch','CoSearch' ], headerTextColor: '', textColor: '', meta: [ '网站图片检索,任意网页快照,谷歌翻译,多媒体下载链接', 'ウェブと画像検索、ページのスクリーンショット、メディアファイルのダウンロードリンク、Google通訳', 'Web or images search. Web page screenshot. Media file download link, Google translate.', '網站圖片檢索,任意網頁快照,谷歌翻譯,多媒體下載鏈接' ], description: [ '当前为Bate版,检索引擎只能选择Google,无翻译和多媒体下载链接功能', 'ベータバージョン、検索エンジンはGoogleオンリー、通訳とマルチメディアファイルダウンロードリンクはまだです', 'This is beta version, earch engine Google only, Google translate and media file download link coming soon.', '當前為Bate版,檢索引擎只能選擇Google,無翻譯和多媒體下載連接功能' ], extra: [ '','','','' ], "active": true },{ imgSrc: '', headerText: [ 'CoMSG','CoMSG','CoMSG','CoMSG' ], headerTextColor: '', textColor: '', meta: [ '点对点私密信息,支持多媒体及文件推送,会议室无上限设置', 'ポイントツーポイント暗号化メッセージ、マルチメディアとファイルの転送ができます、無制限のグループ会話', 'End to End encrypted message. Support for multimedia and all other type files, unlimit group message.', '點對點私密信息,支持多媒體及文件推送,會議室無上限設置' ], description: [ '敬请期待','準備中','Coming soon.','敬請期待' ], extra: [ '','','','' ], "active": false },{ imgSrc: '', headerText: [ 'CoBox','CoBox','CoBox','CoBox' ], headerTextColor: '', textColor: '', meta: [ '文件加密后打成碎片,分别存放到多个免费邮箱,高隐私无限量存储', 'ファイルを暗号化して破砕して、多数のフリーEmailにそれぞれを保存する強いプライバシーストレージ', "Encrypted and split a file to multiple parts, append to multiple email's draft. High privacy and security storage system.", '使用綑綁多個免費郵箱剩餘容量,存儲加密後打成碎片,高隱私無限量文件存儲' ], description: [ '敬请期待','準備中','Coming soon.','敬請期待' ], extra: [ '','','','' ], "active": false } ] } const appHtml = `` const appMenuData = 'appmenu' declare const Jimp class appsManager { public mainPages = ko.observable( null ) public mainLoading = ko.observable ( true ) public loadingError = ko.observable ( null ) public mainHtml = ko.observable ( '' ) public appHtml = ko.observable ( false ) public appScript = ko.observable () public showMain = ko.observable ( false ) public showMainMenu = ko.observable ( true ) public loadingGetResponse = ko.observable ( false ) public conetResponse = ko.observable ( false ) public showSnapshop = ko.observable ( false ) private appMenu = this.getAppMenu () public runningAppHtml = ko.observable ( null ) public showAppMain = ko.observable ( false ) public AppObj = {} public appLoadingError = ko.observable ( false ) public appLoadingErrorIndex = ko.observable (null) /*** * * debug temp */ public showTempMain = ko.observable ( false ) public tempAppHtml = ko.observable ( false ) /** * */ public mainScript = ko.observable (null) private getAppMenu () { const uu = window.localStorage.getItem ( appMenuData ) try { return JSON.parse ( uu ) } catch ( ex ) { return null } } private initMenuArray ( mainMenuArray ) { mainMenuArray.forEach ( n => { n['loading'] = ko.observable ( false ) n['loadingGetResponse'] = ko.observable ( false ) n['conetResponse'] = ko.observable ( false ) }) } private showLoadingGetResponse ( item ) { item.loadingGetResponse ( true ) item.conetResponse ( false ) } private showConetResponse ( item ) { item.loadingGetResponse ( false ) item.conetResponse ( true ) } private getAppObject ( mainMenuItem ) { for ( let i = 0; i < mainMenuItem.length; i ++ ) { const uu = mainMenuItem[i] if ( uu.active ) { const objName = `APP-${ i }` const kk = window.localStorage.getItem ( objName ) try { this.AppObj[ objName ] = JSON.parse ( kk ) } catch ( ex ) { } } } } public updateAppsManu ( _self = null ) { const self = _self || this self.appLoadingError ( false ) /** * * DEBUG use Temp Pug * */ const _mainMenuObj = _mainMenuObj111 self.initMenuArray ( _mainMenuObj.mainMenuItem ) _mainMenuObj['_mainMenuItem'] = ko.observableArray ( _mainMenuObj.mainMenuItem ) self.mainLoading ( false ) self.showTempMain ( true ) return self.mainScript ( _mainMenuObj ) /** */ const viewMainMenuu = () => { self.mainHtml ( self.appMenu [1] ) const _mainMenuObj = JSON.parse ( self.appMenu [2] ) self.initMenuArray ( _mainMenuObj.mainMenuItem ) _mainMenuObj['_mainMenuItem'] = ko.observableArray ( _mainMenuObj.mainMenuItem ) self.mainScript ( _mainMenuObj ) self.showMain ( true ) self.mainLoading ( false ) self.mainLoading ( false ) self.conetResponse ( false ) _view.connectInformationMessage.hideMessage() this.getAppObject ( _mainMenuObj.mainMenuItem ) } if ( this.appMenu && this.appMenu.length ) { viewMainMenuu () } const showError = ( err ) => { self.mainLoading ( false ) //_view.connectInformationMessage.hideMessage() self.loadingError ( _view.connectInformationMessage.getErrorIndex ( err ) ) self.loadingGetResponse ( false ) return self.conetResponse ( false ) } const com: QTGateAPIRequestCommand = { command: 'mainMenu', Args: this.appMenu && this.appMenu[0] ? this.appMenu[0]: null , error: null, subCom: null } return _view.keyPairCalss.emitRequest ( com,( err, com: QTGateAPIRequestCommand ) => { if ( err ) { return showError ( err ) } if ( !com ) { self.conetResponse ( false ) return self.loadingGetResponse ( true ) } if ( com.error === -1 ) { self.loadingGetResponse ( false ) return self.conetResponse ( true ) } if ( com.error ) { return showError ( com.error ) } _view.connectInformationMessage.hideMessage () if ( !com.Args || !com.Args.length ) { return } this.appMenu = com.Args if ( typeof Storage !== "undefined" ) { window.localStorage.setItem ( appMenuData, JSON.stringify ( com.Args )) } return viewMainMenuu () }) } public mainNemuError () { this.exit () } public appClick ( appIndex: number ) { const self = this const item = self.mainScript().mainMenuItem[ appIndex ] self.mainScript()._mainMenuItem ([ item ]) item.loading ( true ) const runningApp = ( obj ) => { _view.bodyBlue ( false ) _view.showIconBar ( false ) this.showMainMenu ( false ) /** * * DEBUG APP use Temp pug * */ this.tempAppHtml ( true ) appScript.startup ( appScript ) this.appScript ( appScript ) _view.CanadaBackground ( true ) return /** */ /** * * Use appHtml */ /* this.runningAppHtml ( appHtml ) this.appHtml ( true ) this.showAppMain ( true ) appScript.startup ( appScript ) this.appScript ( appScript ) /** */ this.runningAppHtml ( obj[1] ) this.appHtml ( true ) eval ( obj[2]) appScript.startup ( appScript ) this.appScript ( appScript ) this.showAppMain ( true ) } const AppName = `APP-${ appIndex }` let obj = this.AppObj[ AppName ] /** * * use Debug * */ return runningApp ( null ) /** end Debug */ if ( obj ) { runningApp ( obj ) } const com: QTGateAPIRequestCommand = { command: AppName, Args: obj && obj[0] ? obj[0]: null, error: null, subCom: null } const showError = ( err ) => { item.loading ( false ) self.appLoadingErrorIndex ( _view.connectInformationMessage.getErrorIndex ( err )) return self.appLoadingError ( true ) } return _view.keyPairCalss.emitRequest ( com, ( err, com: QTGateAPIRequestCommand ) => { if ( err ) { return showError ( err ) } if ( !com ) { self.conetResponse ( false ) return self.loadingGetResponse ( true ) } if ( com.error === -1 ) { self.loadingGetResponse ( false ) return self.conetResponse ( true ) } if ( com.error ) { return showError ( com.error ) } _view.connectInformationMessage.hideMessage () if ( !com.Args || !com.Args.length ) { return } obj = com.Args if ( typeof Storage !== "undefined" ) { window.localStorage.setItem ( AppName, JSON.stringify ( com.Args )) } return runningApp ( obj ) }) } constructor ( private exit: () => void ) { _view.sectionLogin ( false ) this.updateAppsManu() } } ================================================ FILE: app/public/scripts/connectInformationMessage.js ================================================ /*! * Copyright 2018 CoNET Technology Inc. All Rights Reserved. * * 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. */ const messageBoxDefine = { LoadingPage: ['正在解密数据和加载页面', '暗号化したデータを復号化とページの読み込み中。', 'Decrypting data and loading page.', '正在解密数据和加载頁面'], offline: ['无互联网,邮件服务器无法到达!', 'インターネットがないか、メールサーバーへ接続ができません!', 'Have no Internet, can not connect to mail server!', '無互聯網,郵件伺服器無法到達!'], systemError: ['CoNET客户端故障,请重启后再试', '端末故障です、CoNETを再起動してください', 'CoNET client error! Restart CoNET please!', 'CoNET客戶端故障,請重啟後再試'], reConnectCoNET: ['CoNET链接已中断', 'CoNETとの接続が中断され', 'CoNET connection lost.', 'CoNET的鏈接已中斷' ], connectingToCoNET: ['正在连接CoNET...', 'CoNETへ接続中...', 'Connecting to CoNET...', '正在連結CoNET...' ], connectedToCoNET: ['无IP地址成功连接CoNET', 'IPなしでCoNETに接続しました', 'Success to connect CoNET without IP address.', '無IP地址成功連結CoNET' ], maximumRequest: [ '您的请求已达最大值,请稍后再试', 'レクエスト回数は制限にかかった、後ほど改めてお試しください', 'Request maximum error. Try again later.', '您的請求已達最大值,請稍後再試' ], invalidRequest: [ '无效请求', '無効なレクエスト', 'Invalid request.', '無效請求' ], unKnowError: [ '未知错误,请再试!如果持续发生请重启CoNET客户端或重新安装', '不明なエラーが発生、もしこんな状況が続くであれば、CoNET端末を再起動するか、CoNET端末を再インストールしてください。', 'Oops. Unknown error. Try again or restart CoNET client, if still same error please re-install CoNET.', '未知错误,请再试!如果持续发生请重启CoNET客户端或重新安装' ], NodeInBusy: [ '节点目前繁忙,请稍后再试', 'ノードは忙しいです。しばらくしてからもう一度お試しください', 'Node is currently busy, please try again later', '节点目前繁忙,请稍后再试' ], PgpMessageFormatError: [ '内容格式错误,请复制从“-----BEGIN PGP MESSAGE----- (开始,一直到)-----END PGP MESSAGE-----” 结束的完整内容,粘贴在此输入框中。', 'フォーマットエラー、コピーするのは「-----BEGIN PGP MESSAGE-----」から「-----END PGP MESSAGE-----」まで全ての内容をしてください。', 'Format error! Copy all content from [-----BEGIN PGP MESSAGE-----] ... to [-----END PGP MESSAGE-----]. Paste into this text box.', '內容格式錯誤,請複制從“-----BEGIN PGP MESSAGE----- (開始,一直到)-----END PGP MESSAGE-----” 結束的完整內容,粘貼在此輸入框中。' ], PgpDecryptError: [ '提供的内容不能被解密,请确认这是在您收到的最后一封从CoNET发送过来的激活信。如果还是没法完成激活,请删除您的密钥重新生成和设定。', 'この内容で暗号化解除ができませんでした。鍵ペアEmailアカンウトメールボックス再検査し、CoNETから最後のを選んでください。または鍵ペアを削除して、鍵ペア再発行してください。', 'Decrypt message failed. Find the lasest mail from CoNET in your key pair email mailbox. Or delete this key pair and rebuild new key pair please.', '提供的內容不能被解密,請確認這是在您收到的最後一封從CoNET發送過來的激活信。如果還是沒法完成激活,請刪除您的密鑰重新生成和設定。' ], pageLoadingError: [ '页面加载发生错误', 'エラーが発生してページの読み込みが完了できません', 'Loading page has error.', '頁面加載發生錯誤' ], connectToMailServer: [ '正在连接邮件服务器: ', 'メールサーバーへ接続をしています: ', 'Connect to mail server: ', '正在連接郵件伺服器: ' ], connectedMailServer: [ '正在连接邮件服务器: 完成', 'メールサーバーへ接続をしています: 完成', 'Connect to mail server: success.', '正在連接郵件伺服器: 完成' ], waitingPong: [ '正在等待节点响应: ', 'ノートのレスポンスを待っています: ', 'Waiting for a response from node: ', '正在等待節點響應: ' ], waitingPongTimeOver: [ '正在等待节点响应: 超时错误!', 'ノートのレスポンスを待っています: タイムオーバーエラー!', 'Waiting for a response from node: Over time error!', '正在等待節點響應: 響應超時錯誤!' ], sendConnectRequestMail: [ '客户端向节点发出联机请求邮件,完成需要额外的时间,请耐心等待', '接続メールをノートへ送信しました、完了まで時間がかかります、しばらくお待ち下さい', 'Sending connection request email to node. Please wait a moment', '客戶端向節點發出聯機請求郵件,完成需要額外的時間,請耐心等待' ], timeOut: [ '节点无响应,可能正在忙碌中,请稍后再试', 'ノートの応答がなかったです、忙しいかもしれませんが、後ほどもう一度してみてください。', 'Node have not responding to requests, try again later.', '節點無響應,可能正在忙碌中,請稍後再試' ], }; class connectInformationMessage { constructor(url = "/") { this.url = url; this.offlineInfo = ko.observable(false); this.showNegative = ko.observable(false); this.showGreen = ko.observable(false); this.messageArray = ko.observable(null); this.socketIoOnline = true; this.socketIo = io(`${this.url}`, { reconnectionAttempts: 5, timeout: 500, autoConnect: true }); this.first = true; const self = this; this.offlineInfo.subscribe(function (vv) { if (this.first) { return; } const div = $('#offlineInfo'); if (vv) { return div.transition('fly down'); } div.transition('fly down'); }); this.first = false; this.socketIo.on('reconnect_failed', () => { this.socketIoOnline = false; self.showErrorMessage('systemError'); }); this.socketIo.on('reconnect', attempt => { this.socketIoOnline = true; this.hideMessage(); }); this.socketIo.on('systemErr', err => { self.showErrorMessage(err); }); } sockEmit(eventName, ...args) { const self = this; if (!this.socketIoOnline) { return this.showErrorMessage('systemError'); } const argLength = args.length - 1; let _CallBack = null; if (argLength > -1 && typeof (args[argLength]) === 'function') { _CallBack = args.pop(); } const _timeout = setTimeout(() => { if (_CallBack) { _CallBack(new Error('systemErr')); return _CallBack = null; } return this.showSystemError(); }, 3000); return this.socketIo.emit(eventName, ...args, uuid => { clearTimeout(_timeout); return this.socketIo.once(uuid, (err, ...data) => { if (err) { self.showErrorMessage(err); } if (_CallBack) { return _CallBack(err, ...data); } }); }); } showErrorMessage(err) { if (!err) { return; } const errMes = (typeof err === "string") ? messageBoxDefine[err] : messageBoxDefine[err.message] || err.message; if (!errMes) { return; } this.hideMessage(); this.messageArray(errMes); this.showNegative(true); this.offlineInfo(true); } showSystemError() { return this.showErrorMessage('systemError'); } showRestartCoNET_Connect() { this.showErrorMessage('reConnectCoNET'); } hideMessage() { this.offlineInfo(false); this.messageArray(null); this.showNegative(false); } getErrorIndex(err) { if (!err) { return 'unKnowError'; } if (typeof err !== 'object') { return messageBoxDefine[err] ? err : 'unKnowError'; } return messageBoxDefine[err['message']] ? err['message'] : 'unKnowError'; } } ================================================ FILE: app/public/scripts/connectInformationMessage.ts ================================================ /*! * Copyright 2018 CoNET Technology Inc. All Rights Reserved. * * 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. */ const messageBoxDefine = { LoadingPage: ['正在解密数据和加载页面','暗号化したデータを復号化とページの読み込み中。','Decrypting data and loading page.','正在解密数据和加载頁面'], offline: ['无互联网,邮件服务器无法到达!','インターネットがないか、メールサーバーへ接続ができません!','Have no Internet, can not connect to mail server!','無互聯網,郵件伺服器無法到達!'], systemError: ['CoNET客户端故障,请重启后再试','端末故障です、CoNETを再起動してください','CoNET client error! Restart CoNET please!','CoNET客戶端故障,請重啟後再試'], reConnectCoNET: ['CoNET链接已中断','CoNETとの接続が中断され','CoNET connection lost.','CoNET的鏈接已中斷' ], connectingToCoNET: ['正在连接CoNET...','CoNETへ接続中...','Connecting to CoNET...','正在連結CoNET...' ], connectedToCoNET: ['无IP地址成功连接CoNET','IPなしでCoNETに接続しました','Success to connect CoNET without IP address.','無IP地址成功連結CoNET' ], maximumRequest: [ '您的请求已达最大值,请稍后再试', 'レクエスト回数は制限にかかった、後ほど改めてお試しください', 'Request maximum error. Try again later.', '您的請求已達最大值,請稍後再試' ], invalidRequest: [ '无效请求', '無効なレクエスト', 'Invalid request.', '無效請求' ], unKnowError: [ '未知错误,请再试!如果持续发生请重启CoNET客户端或重新安装', '不明なエラーが発生、もしこんな状況が続くであれば、CoNET端末を再起動するか、CoNET端末を再インストールしてください。', 'Oops. Unknown error. Try again or restart CoNET client, if still same error please re-install CoNET.', '未知错误,请再试!如果持续发生请重启CoNET客户端或重新安装' ], NodeInBusy: [ '节点目前繁忙,请稍后再试','ノードは忙しいです。しばらくしてからもう一度お試しください','Node is currently busy, please try again later','节点目前繁忙,请稍后再试' ], PgpMessageFormatError: [ '内容格式错误,请复制从“-----BEGIN PGP MESSAGE----- (开始,一直到)-----END PGP MESSAGE-----” 结束的完整内容,粘贴在此输入框中。', 'フォーマットエラー、コピーするのは「-----BEGIN PGP MESSAGE-----」から「-----END PGP MESSAGE-----」まで全ての内容をしてください。', 'Format error! Copy all content from [-----BEGIN PGP MESSAGE-----] ... to [-----END PGP MESSAGE-----]. Paste into this text box.', '內容格式錯誤,請複制從“-----BEGIN PGP MESSAGE----- (開始,一直到)-----END PGP MESSAGE-----” 結束的完整內容,粘貼在此輸入框中。' ], PgpDecryptError: [ '提供的内容不能被解密,请确认这是在您收到的最后一封从CoNET发送过来的激活信。如果还是没法完成激活,请删除您的密钥重新生成和设定。', 'この内容で暗号化解除ができませんでした。鍵ペアEmailアカンウトメールボックス再検査し、CoNETから最後のを選んでください。または鍵ペアを削除して、鍵ペア再発行してください。', 'Decrypt message failed. Find the lasest mail from CoNET in your key pair email mailbox. Or delete this key pair and rebuild new key pair please.', '提供的內容不能被解密,請確認這是在您收到的最後一封從CoNET發送過來的激活信。如果還是沒法完成激活,請刪除您的密鑰重新生成和設定。' ], pageLoadingError: [ '页面加载发生错误','エラーが発生してページの読み込みが完了できません','Loading page has error.','頁面加載發生錯誤' ], connectToMailServer: [ '正在连接邮件服务器: ', 'メールサーバーへ接続をしています: ', 'Connect to mail server: ', '正在連接郵件伺服器: ' ], connectedMailServer: [ '正在连接邮件服务器: 完成', 'メールサーバーへ接続をしています: 完成', 'Connect to mail server: success.', '正在連接郵件伺服器: 完成' ], waitingPong :[ '正在等待节点响应: ', 'ノートのレスポンスを待っています: ', 'Waiting for a response from node: ', '正在等待節點響應: ' ], waitingPongTimeOver :[ '正在等待节点响应: 超时错误!', 'ノートのレスポンスを待っています: タイムオーバーエラー!', 'Waiting for a response from node: Over time error!', '正在等待節點響應: 響應超時錯誤!' ], sendConnectRequestMail :[ '客户端向节点发出联机请求邮件,完成需要额外的时间,请耐心等待', '接続メールをノートへ送信しました、完了まで時間がかかります、しばらくお待ち下さい', 'Sending connection request email to node. Please wait a moment', '客戶端向節點發出聯機請求郵件,完成需要額外的時間,請耐心等待' ], timeOut: [ '节点无响应,可能正在忙碌中,请稍后再试', 'ノートの応答がなかったです、忙しいかもしれませんが、後ほどもう一度してみてください。', 'Node have not responding to requests, try again later.', '節點無響應,可能正在忙碌中,請稍後再試' ], } class connectInformationMessage { public offlineInfo = ko.observable ( false ) public showNegative = ko.observable ( false ) public showGreen = ko.observable ( false ) public messageArray = ko.observable ( null ) public socketIoOnline = true public socketIo = io ( `${ this.url }`, { reconnectionAttempts: 5, timeout: 500, autoConnect: true }) private first = true constructor ( private url: string = "/") { const self = this this.offlineInfo.subscribe ( function (vv) { if ( this.first ) { return } const div = $('#offlineInfo') if ( vv ) { return div.transition('fly down') } div.transition('fly down') }) this.first = false this.socketIo.on ( 'reconnect_failed', () => { this.socketIoOnline = false self.showErrorMessage ( 'systemError' ) }) this.socketIo.on ( 'reconnect', attempt => { this.socketIoOnline = true this.hideMessage () }) this.socketIo.on ( 'systemErr', err => { self.showErrorMessage ( err ) }) } public sockEmit ( eventName: string, ...args ) { const self = this if ( ! this.socketIoOnline ) { return this.showErrorMessage ( 'systemError' ) } const argLength = args.length - 1 let _CallBack = null if ( argLength > -1 && typeof ( args[ argLength ]) === 'function' ) { _CallBack = args.pop () } const _timeout = setTimeout(() => { if ( _CallBack ) { _CallBack( new Error ('systemErr')) return _CallBack = null } return this.showSystemError() }, 3000 ) return this.socketIo.emit ( eventName, ...args, uuid => { clearTimeout ( _timeout ) return this.socketIo.once ( uuid, ( err, ...data ) => { if ( err ) { self.showErrorMessage ( err ) } if ( _CallBack ) { return _CallBack ( err, ...data ) } }) }) } public showErrorMessage ( err ) { if ( !err ) { return } const errMes = ( typeof err === "string" ) ? messageBoxDefine[ err ] : messageBoxDefine[ err.message ] || err.message if ( !errMes ) { return } this.hideMessage() this.messageArray ( errMes ) this.showNegative ( true ) this.offlineInfo ( true ) } public showSystemError () { return this.showErrorMessage ( 'systemError' ) } public showRestartCoNET_Connect () { this.showErrorMessage ( 'reConnectCoNET' ) } public hideMessage() { this.offlineInfo ( false ) this.messageArray ( null ) this.showNegative ( false ) } public getErrorIndex ( err ) { if ( ! err ) { return 'unKnowError' } if ( typeof err !== 'object' ) { return messageBoxDefine [ err ] ? err : 'unKnowError' } return messageBoxDefine [ err['message']] ? err['message'] : 'unKnowError' } } ================================================ FILE: app/public/scripts/encryptoClass.js ================================================ const requestTimeOut = 1000 * 180; class encryptoClass { constructor(_keypair) { this._keypair = _keypair; this.requestPool = new Map(); this.makeKeyReady = async () => { //this.CoNET_publicKey = ( await openpgp.key.readArmored ( CoNET_publicKey )).keys this._privateKey = (await openpgp.key.readArmored(this._keypair.privateKey)).keys; await this._privateKey[0].decrypt(this._keypair._password); }; this.decryptMessage = (encryptoText, CallBack) => { return this.decryptMessageToZipStream(encryptoText, async (err, _data) => { if (err) { return CallBack(err); } let ret = null; const data = Buffer.from(_data, 'base64').toString(); if (/^-----BEGIN PGP/i.test(data)) { CallBack(); return this.CoNET_publicKey = (await openpgp.key.readArmored(data)).keys; } try { ret = JSON.parse(data); } catch (ex) { return CallBack(ex); } return CallBack(null, ret); }); }; this.onDoingRequest = async (encryptoText, uuid) => { const request = this.requestPool.get(uuid); if (!request) { return; } return this.decryptMessage(encryptoText, (err, obj) => { if (err) { return _view.connectInformationMessage.showErrorMessage(err); } if (obj.error !== -1) { clearTimeout(request.timeOut); } return request.CallBack(null, obj); }); }; this.makeKeyReady(); _view.connectInformationMessage.socketIo.on('doingRequest', (encryptoText, uuid) => { return this.onDoingRequest(encryptoText, uuid); }); } decryptMessageToZipStream(encryptoText, CallBack) { const option = { privateKeys: this._privateKey, publicKeys: this.CoNET_publicKey, message: null }; let ret = null; return openpgp.message.readArmored(encryptoText).then(data => { option.message = data; return openpgp.decrypt(option); }).then(_plaintext => { return CallBack(null, _plaintext.data); }) .catch(ex => { return CallBack(ex); }); } encrypt(message, CallBack) { const option = { privateKeys: this._privateKey, publicKeys: this.CoNET_publicKey, message: openpgp.message.fromText(message), compression: openpgp.enums.compression.zip }; const self = this; return openpgp.encrypt(option).then(ciphertext => { return CallBack(null, ciphertext.data); }).catch(err => { return CallBack('systemError'); }); } emitRequest(cmd, CallBack) { const uuid = cmd.requestSerial = uuid_generate(); const self = this; const option = { privateKeys: this._privateKey, publicKeys: this.CoNET_publicKey, message: openpgp.message.fromText(JSON.stringify(cmd)), compression: openpgp.enums.compression.zip }; this.requestPool.set(uuid, { CallBack: CallBack, cmd: cmd, timeOut: setTimeout(() => { self.requestPool.delete(uuid); return CallBack(new Error('timeOut')); }, requestTimeOut) }); return openpgp.encrypt(option).then(ciphertext => { return _view.connectInformationMessage.sockEmit('doingRequest', uuid, ciphertext.data, err => { return CallBack(err); }); }).catch(err => { return CallBack('systemError'); }); } } ================================================ FILE: app/public/scripts/encryptoClass.ts ================================================ declare const openpgp: any const requestTimeOut = 1000 * 180 class encryptoClass { private _privateKey private CoNET_publicKey private requestPool: Map < string, { CallBack: ( err?: Error, cmd?: QTGateAPIRequestCommand ) => void, cmd: QTGateAPIRequestCommand, timeOut: NodeJS.Timeout } > = new Map () private makeKeyReady = async() => { //this.CoNET_publicKey = ( await openpgp.key.readArmored ( CoNET_publicKey )).keys this._privateKey = ( await openpgp.key.readArmored ( this._keypair.privateKey )).keys await this._privateKey[0].decrypt ( this._keypair._password ) } public decryptMessage = ( encryptoText: string, CallBack ) => { return this.decryptMessageToZipStream ( encryptoText, async ( err, _data ) => { if ( err ) { return CallBack ( err ) } let ret = null const data = Buffer.from ( _data, 'base64').toString () if ( /^-----BEGIN PGP/i.test ( data )) { CallBack () return this.CoNET_publicKey = ( await openpgp.key.readArmored( data )).keys } try { ret = JSON.parse ( data ) } catch ( ex ) { return CallBack ( ex ) } return CallBack ( null, ret ) }) } public decryptMessageToZipStream ( encryptoText: string, CallBack ) { const option = { privateKeys: this._privateKey, publicKeys: this.CoNET_publicKey, message: null } let ret = null return openpgp.message.readArmored ( encryptoText ).then ( data => { option.message = data return openpgp.decrypt( option ) }).then ( _plaintext => { return CallBack ( null, _plaintext.data ) }) .catch ( ex => { return CallBack ( ex ) }) } private onDoingRequest = async ( encryptoText: string, uuid: string ) => { const request = this.requestPool.get ( uuid ) if ( !request ) { return } return this.decryptMessage ( encryptoText, ( err, obj: QTGateAPIRequestCommand ) => { if ( err ) { return _view.connectInformationMessage.showErrorMessage ( err ) } if ( obj.error !== -1 ) { clearTimeout ( request.timeOut ) } return request.CallBack ( null, obj ) }) } constructor ( private _keypair: keypair ) { this.makeKeyReady () _view.connectInformationMessage.socketIo.on ( 'doingRequest', ( encryptoText: string, uuid: string ) => { return this.onDoingRequest ( encryptoText, uuid ) }) } public encrypt ( message, CallBack ) { const option = { privateKeys: this._privateKey, publicKeys: this.CoNET_publicKey, message: openpgp.message.fromText ( message ), compression: openpgp.enums.compression.zip } const self = this return openpgp.encrypt ( option ).then ( ciphertext => { return CallBack ( null, ciphertext.data ) }).catch ( err => { return CallBack ( 'systemError' ) }) } public emitRequest ( cmd: QTGateAPIRequestCommand, CallBack ) { const uuid = cmd.requestSerial = uuid_generate() const self = this const option = { privateKeys: this._privateKey, publicKeys: this.CoNET_publicKey, message: openpgp.message.fromText ( JSON.stringify ( cmd )), compression: openpgp.enums.compression.zip } this.requestPool.set ( uuid, { CallBack: CallBack, cmd: cmd, timeOut: setTimeout(() => { self.requestPool.delete ( uuid ) return CallBack ( new Error ( 'timeOut' )) }, requestTimeOut )}) return openpgp.encrypt ( option ).then ( ciphertext => { return _view.connectInformationMessage.sockEmit ( 'doingRequest' , uuid, ciphertext.data, err => { return CallBack ( err ) }) }).catch ( err => { return CallBack ( 'systemError' ) }) } } ================================================ FILE: app/public/scripts/home.js ================================================ /*! * Copyright 2018 CoNET Technology Inc. All Rights Reserved. * * 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. */ const InitKeyPair = function () { const keyPair = { publicKey: null, privateKey: null, keyLength: null, nikeName: null, createDate: null, email: null, passwordOK: false, verified: false, publicKeyID: null, _password: null }; return keyPair; }; const makeKeyPairData = function (view, keypair) { const length = keypair.publicKeyID.length; keypair.publicKeyID = keypair.publicKeyID.substr(length - 16); let keyPairPasswordClass = new keyPairPassword(function (_imapData, passwd, sessionHash) { // password OK keypair.keyPairPassword(keyPairPasswordClass = null); keypair.passwordOK = true; keypair._password = passwd; keypair.showLoginPasswordField(false); view.keyPairCalss = new encryptoClass(keypair); view.showKeyPair(false); if (_imapData && _imapData.imapTestResult) { return view.imapSetupClassExit(_imapData, sessionHash); } let uu = null; return view.imapSetup(uu = new imapForm(keypair.email, _imapData, function (imapData) { view.imapSetup(uu = null); view.imapSetupClassExit(imapData, sessionHash); })); }); keypair.keyPairPassword = ko.observable(keyPairPasswordClass); keypair.showLoginPasswordField = ko.observable(false); keypair.delete_btn_view = ko.observable(true); keypair.showConform = ko.observable(false); keypair['showDeleteKeyPairNoite'] = ko.observable(false); keypair.delete_btn_click = function () { keypair.delete_btn_view(false); return keypair.showConform(true); }; keypair.deleteKeyPairNext = function () { view.connectInformationMessage.sockEmit('deleteKeyPairNext', () => { view.showIconBar(false); view.connectedCoNET(false); view.connectToCoNET(false); view.CoNETConnect(view.CoNETConnectClass = null); view.imapSetup(view.imapFormClass = null); keypair.showDeleteKeyPairNoite(false); return keypair.delete_btn_view(false); }); }; }; const initPopupArea = function () { const popItem = $('.activating.element').popup('hide'); const inline = popItem.hasClass('inline'); return popItem.popup({ on: 'focus', movePopup: false, position: 'top left', inline: inline }); }; class showWebPageClass { constructor(showUrl, zipBase64Stream, zipBase64StreamUuid, exit) { this.showUrl = showUrl; this.zipBase64Stream = zipBase64Stream; this.zipBase64StreamUuid = zipBase64StreamUuid; this.exit = exit; this.showLoading = ko.observable(true); this.htmlIframe = ko.observable(null); this.showErrorMessage = ko.observable(false); this.showHtmlCodePage = ko.observable(false); this.showImgPage = ko.observable(true); this.png = ko.observable(''); const self = this; _view.showIconBar(false); _view.keyPairCalss.decryptMessageToZipStream(zipBase64Stream, (err, data) => { if (err) { return self.showErrorMessageProcess(); } showHTMLComplete(zipBase64StreamUuid, data, (err, data) => { if (err) { return self.showErrorMessageProcess(); } _view.bodyBlue(false); const getData = (filename, _data) => { const regex = new RegExp(`${filename}`, 'g'); const index = html.indexOf(`${filename}`); if (index > -1) { if (/js$/.test(filename)) { _data = _data.replace(/^data:text\/plain;/, 'data:application/javascript;'); } else if (/css$/.test(filename)) { _data = _data.replace(/^data:text\/plain;/, 'data:text/css;'); } else if (/html$|htm$/.test(filename)) { _data = _data.replace(/^data:text\/plain;/, 'data:text/html;'); } else if (/pdf$/.test(filename)) { _data = _data.replace(/^data:text\/plain;/, 'data:text/html;'); } else { const kkk = _data; } html = html.replace(regex, _data); } }; let html = data.html; data.folder.forEach(n => { getData(n.filename, n.data); }); self.png(data.img); const htmlBolb = new Blob([html], { type: 'text/html' }); const _url = window.URL.createObjectURL(htmlBolb); const fileReader = new FileReader(); fileReader.onloadend = evt => { return window.URL.revokeObjectURL(_url); }; self.showLoading(false); self.htmlIframe(_url); }); }); } showErrorMessageProcess() { this.showLoading(false); this.showErrorMessage(true); } close() { this.showImgPage(false); this.showHtmlCodePage(false); this.png(null); this.exit(); } imgClick() { this.showHtmlCodePage(false); this.showImgPage(true); } htmlClick() { this.showHtmlCodePage(true); this.showImgPage(false); } } var view_layout; (function (view_layout) { class view { constructor() { this.connectInformationMessage = new connectInformationMessage('/'); this.sectionLogin = ko.observable(false); this.sectionAgreement = ko.observable(false); this.sectionWelcome = ko.observable(true); this.isFreeUser = ko.observable(true); this.QTTransferData = ko.observable(false); this.LocalLanguage = 'up'; this.menu = Menu; this.modalContent = ko.observable(''); this.keyPairGenerateForm = ko.observable(); this.tLang = ko.observable(initLanguageCookie()); this.languageIndex = ko.observable(lang[this.tLang()]); this.localServerConfig = ko.observable(); this.keyPair = ko.observable(InitKeyPair()); this.hacked = ko.observable(false); this.imapSetup = ko.observable(); this.showIconBar = ko.observable(false); this.connectToCoNET = ko.observable(false); this.connectedCoNET = ko.observable(false); this.showKeyPair = ko.observable(false); this.CoNETConnectClass = null; this.imapFormClass = null; this.CoNETConnect = ko.observable(null); this.bodyBlue = ko.observable(true); this.CanadaBackground = ko.observable(false); this.keyPairCalss = null; this.appsManager = ko.observable(null); this.AppList = ko.observable(false); this.imapData = null; this.newVersion = ko.observable(null); this.sessionHash = ''; this.showLanguageSelect = ko.observable(true); this.socketListen(); this.CanadaBackground.subscribe(val => { if (val) { $.ajax({ url: '/scripts/CanadaSvg.js' }).done(data => { eval(data); }); } }); } afterInitConfig() { this.keyPair(this.localServerConfig().keypair); if (this.keyPair() && this.keyPair().keyPairPassword() && typeof this.keyPair().keyPairPassword().inputFocus === 'function') { this.keyPair().keyPairPassword().inputFocus(true); this.sectionLogin(false); } } initConfig(config) { const self = this; this.showKeyPair(true); if (config.keypair && config.keypair.publicKeyID) { /** * * Key pair ready * */ makeKeyPairData(this, config.keypair); if (!config.keypair.passwordOK) { config.keypair.showLoginPasswordField(true); } } else { /** * * No key pair * */ this.svgDemo_showLanguage(); this.clearImapData(); config.keypair = null; let _keyPairGenerateForm = new keyPairGenerateForm(function (_keyPair, sessionHash) { /** * key pair ready */ makeKeyPairData(self, _keyPair); _keyPair.passwordOK = true; let keyPairPassword = _keyPair.keyPairPassword(); _keyPair.keyPairPassword(keyPairPassword = null); config.keypair = _keyPair; self.keyPair(_keyPair); self.showKeyPair(false); initPopupArea(); let uu = null; self.keyPairCalss = new encryptoClass(self.keyPair()); self.imapSetup(uu = new imapForm(config.account, null, function (imapData) { self.imapSetup(uu = null); return self.imapSetupClassExit(imapData, sessionHash); })); return self.keyPairGenerateForm(_keyPairGenerateForm = null); }); this.keyPairGenerateForm(_keyPairGenerateForm); } this.localServerConfig(config); this.afterInitConfig(); } clearImapData() { let imap = this.imapSetup(); this.imapSetup(imap = null); } socketListen() { let self = this; this.connectInformationMessage.sockEmit('init', (err, config) => { if (err) { return; } return self.initConfig(config); }); this.connectInformationMessage.socketIo.on('init', (err, config) => { if (err) { return; } return self.initConfig(config); }); } // change language selectItem(that, site) { const tindex = lang[this.tLang()]; let index = tindex + 1; if (index > 3) { index = 0; } this.languageIndex(index); this.tLang(lang[index]); $.cookie('langEH', this.tLang(), { expires: 180, path: '/' }); const obj = $("span[ve-data-bind]"); obj.each(function (index, element) { const ele = $(element); const data = ele.attr('ve-data-bind'); if (data && data.length) { ele.text(eval(data)); } }); $('.languageText').shape(`flip ${this.LocalLanguage}`); $('.KnockoutAnimation').transition('jiggle'); return initPopupArea(); } // start click openClick() { clearTimeout(this.demoTimeout); if (this.demoMainElm && typeof this.demoMainElm.remove === 'function') { this.demoMainElm.remove(); this.demoMainElm = null; } if (!this.connectInformationMessage.socketIoOnline) { return this.connectInformationMessage.showSystemError(); } this.sectionWelcome(false); /* if ( this.localServerConfig().firstRun ) { return this.sectionAgreement ( true ) } */ this.sectionLogin(true); return initPopupArea(); } deletedKeypairResetView() { this.imapSetup(null); } agreeClick() { this.connectInformationMessage.sockEmit('agreeClick'); this.sectionAgreement(false); this.localServerConfig().firstRun = false; return this.openClick(); } refresh() { if (typeof require === 'undefined') { this.modalContent(infoDefine[this.languageIndex()].emailConform.formatError[11]); return this.hacked(true); } const { remote } = require('electron'); if (remote && remote.app && typeof remote.app.quit === 'function') { return remote.app.quit(); } } showKeyInfoClick() { this.sectionLogin(true); this.showKeyPair(true); this.AppList(false); this.appsManager(null); } imapSetupClassExit(_imapData, sessionHash) { const self = this; this.imapData = _imapData; this.sessionHash = sessionHash; return this.CoNETConnect(this.CoNETConnectClass = new CoNETConnect(_imapData.imapUserName, this.keyPair().verified, _imapData.confirmRisk, this.keyPair().email, function ConnectReady(err) { if (typeof err === 'number' && err > -1) { self.CoNETConnect(this.CoNETConnectClass = null); return self.imapSetup(this.imapFormClass = new imapForm(_imapData.account, null, function (imapData) { self.imapSetup(this.imapFormClass = null); return self.imapSetupClassExit(imapData, sessionHash); })); } self.connectedCoNET(true); self.homeClick(); })); } reFreshLocalServer() { location.reload(); } homeClick() { this.AppList(true); this.sectionLogin(false); const connectMainMenu = () => { let am = null; this.appsManager(am = new appsManager(() => { am = null; return connectMainMenu(); })); }; connectMainMenu(); this.showKeyPair(false); $('.dimmable').dimmer({ on: 'hover' }); $('.comeSoon').popup({ on: 'focus', movePopup: false, position: 'top left', inline: true }); _view.connectInformationMessage.socketIo.removeEventListener('tryConnectCoNETStage', this.CoNETConnectClass.listenFun); } /** * * T/t = Translate (t is relative, T is absolute) R/r = rotate(r is relative, R is absolute) S/s = scale(s is relative, S is absolute) */ svgDemo_showLanguage() { if (!this.sectionWelcome()) { return; } let i = 0; const changeLanguage = () => { if (++i === 1) { backGround_mask_circle.attr({ stroke: "#FF000090", }); return setTimeout(() => { changeLanguage(); }, 1000); } if (i > 5 || !this.sectionWelcome()) { main.remove(); return this.demoMainElm = main = null; } this.selectItem(); this.demoTimeout = setTimeout(() => { changeLanguage(); }, 2000); }; const width = window.innerWidth; const height = window.outerHeight; let main = this.demoMainElm = Snap(width, height); const backGround_mask_circle = main.circle(width / 2, height / 2, width / 1.7).attr({ fill: '#00000000', stroke: "#FF000020", strokeWidth: 5, }); const wT = width / 2 - 35; const wY = 30 - height / 2; backGround_mask_circle.animate({ transform: `t${wT} ${wY}`, r: 60 }, 3000, mina.easeout, changeLanguage); } } view_layout.view = view; })(view_layout || (view_layout = {})); const _view = new view_layout.view(); ko.applyBindings(_view, document.getElementById('body')); $(`.${_view.tLang()}`).addClass('active'); ================================================ FILE: app/public/scripts/home.ts ================================================ /*! * Copyright 2018 CoNET Technology Inc. All Rights Reserved. * * 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. */ const InitKeyPair = function () { const keyPair: keypair = { publicKey: null, privateKey: null, keyLength: null, nikeName: null, createDate: null, email: null, passwordOK: false, verified: false, publicKeyID: null, _password: null } return keyPair } const makeKeyPairData = function ( view: view_layout.view, keypair: keypair ) { const length = keypair.publicKeyID.length keypair.publicKeyID = keypair.publicKeyID.substr ( length - 16 ) let keyPairPasswordClass = new keyPairPassword ( function ( _imapData: IinputData, passwd: string, sessionHash: string ) { // password OK keypair.keyPairPassword ( keyPairPasswordClass = null ) keypair.passwordOK = true keypair._password = passwd keypair.showLoginPasswordField ( false ) view.keyPairCalss = new encryptoClass ( keypair ) view.showKeyPair ( false ) if ( _imapData && _imapData.imapTestResult ) { return view.imapSetupClassExit ( _imapData, sessionHash ) } let uu = null return view.imapSetup ( uu = new imapForm ( keypair.email, _imapData, function ( imapData: IinputData ) { view.imapSetup ( uu = null ) view.imapSetupClassExit ( imapData, sessionHash ) })) }) keypair.keyPairPassword = ko.observable( keyPairPasswordClass ) keypair.showLoginPasswordField = ko.observable ( false ) keypair.delete_btn_view = ko.observable ( true ) keypair.showConform = ko.observable ( false ) keypair['showDeleteKeyPairNoite'] = ko.observable ( false ) keypair.delete_btn_click = function () { keypair.delete_btn_view ( false ) return keypair.showConform ( true ) } keypair.deleteKeyPairNext = function () { view.connectInformationMessage.sockEmit ( 'deleteKeyPairNext', () => { view.showIconBar ( false ) view.connectedCoNET ( false ) view.connectToCoNET ( false ) view.CoNETConnect (view.CoNETConnectClass = null) view.imapSetup ( view.imapFormClass = null ) keypair.showDeleteKeyPairNoite ( false ) return keypair.delete_btn_view ( false ) }) } } const initPopupArea = function () { const popItem = $( '.activating.element' ).popup('hide') const inline = popItem.hasClass ('inline') return popItem.popup({ on: 'focus', movePopup: false, position: 'top left', inline: inline }) } class showWebPageClass { public showLoading = ko.observable ( true ) public htmlIframe = ko.observable ( null ) public showErrorMessage = ko.observable ( false ) public showHtmlCodePage = ko.observable ( false ) public showImgPage = ko.observable ( true ) public showErrorMessageProcess () { this.showLoading ( false ) this.showErrorMessage ( true ) } public png = ko.observable ('') public close () { this.showImgPage ( false ) this.showHtmlCodePage ( false ) this.png ( null ) this.exit () } public imgClick () { this.showHtmlCodePage ( false ) this.showImgPage ( true ) } public htmlClick () { this.showHtmlCodePage ( true ) this.showImgPage ( false ) } constructor ( public showUrl: string, private zipBase64Stream: string, private zipBase64StreamUuid: string, private exit: ()=> void ) { const self = this _view.showIconBar ( false ) _view.keyPairCalss.decryptMessageToZipStream ( zipBase64Stream, ( err, data ) => { if ( err ) { return self.showErrorMessageProcess () } showHTMLComplete ( zipBase64StreamUuid, data, ( err, data: { img: string, html: string, folder: [ { filename: string, data: string }]} ) => { if ( err ) { return self.showErrorMessageProcess () } _view.bodyBlue ( false ) const getData = ( filename: string, _data: string ) => { const regex = new RegExp (`${ filename }`,'g') const index = html.indexOf ( `${ filename }` ) if ( index > -1 ) { if ( /js$/.test ( filename )) { _data = _data.replace ( /^data:text\/plain;/, 'data:application/javascript;') } else if ( /css$/.test ( filename )) { _data = _data.replace ( /^data:text\/plain;/, 'data:text/css;') } else if ( /html$|htm$/.test ( filename )) { _data = _data.replace ( /^data:text\/plain;/, 'data:text/html;') } else if ( /pdf$/.test ( filename )) { _data = _data.replace ( /^data:text\/plain;/, 'data:text/html;') } else { const kkk = _data } html = html.replace ( regex, _data ) } } let html = data.html data.folder.forEach ( n => { getData ( n.filename, n.data ) }) self.png ( data.img ) const htmlBolb = new Blob ([ html ], { type: 'text/html'}) const _url = window.URL.createObjectURL ( htmlBolb ) const fileReader = new FileReader() fileReader.onloadend = evt => { return window.URL.revokeObjectURL ( _url ) } self.showLoading ( false ) self.htmlIframe ( _url ) }) }) } } module view_layout { export class view { public connectInformationMessage = new connectInformationMessage( '/' ) public sectionLogin = ko.observable ( false ) public sectionAgreement = ko.observable ( false ) public sectionWelcome = ko.observable ( true ) public isFreeUser = ko.observable ( true ) public QTTransferData = ko.observable ( false ) public LocalLanguage = 'up' public menu = Menu public modalContent = ko.observable ('') public keyPairGenerateForm: KnockoutObservable< keyPairGenerateForm> = ko.observable () public tLang = ko.observable ( initLanguageCookie ()) public languageIndex = ko.observable ( lang [ this.tLang() ]) public localServerConfig: KnockoutObservable < install_config > = ko.observable () public keyPair: KnockoutObservable < keypair > = ko.observable ( InitKeyPair ()) public hacked = ko.observable ( false ) public imapSetup: KnockoutObservable < imapForm > = ko.observable () public showIconBar = ko.observable ( false ) public connectToCoNET = ko.observable ( false ) public connectedCoNET = ko.observable ( false ) public showKeyPair = ko.observable ( false ) public CoNETConnectClass: CoNETConnect = null public imapFormClass: imapForm = null public CoNETConnect: KnockoutObservable < CoNETConnect > = ko.observable ( null ) public bodyBlue = ko.observable ( true ) public CanadaBackground = ko.observable ( false ) public keyPairCalss: encryptoClass = null public appsManager: KnockoutObservable< appsManager > = ko.observable ( null ) public AppList = ko.observable ( false ) public imapData: IinputData = null public newVersion = ko.observable ( null ) public sessionHash = '' public showLanguageSelect = ko.observable ( true ) private demoTimeout private demoMainElm private afterInitConfig ( ) { this.keyPair ( this.localServerConfig ().keypair ) if ( this.keyPair() && this.keyPair().keyPairPassword() && typeof this.keyPair().keyPairPassword().inputFocus ==='function' ) { this.keyPair().keyPairPassword().inputFocus( true ) this.sectionLogin ( false ) } } private initConfig ( config: install_config ) { const self = this this.showKeyPair ( true ) if ( config.keypair && config.keypair.publicKeyID ) { /** * * Key pair ready * */ makeKeyPairData ( this, config.keypair ) if ( ! config.keypair.passwordOK ) { config.keypair.showLoginPasswordField ( true ) } } else { /** * * No key pair * */ this.svgDemo_showLanguage () this.clearImapData () config.keypair = null let _keyPairGenerateForm = new keyPairGenerateForm ( function ( _keyPair: keypair, sessionHash: string ) { /** * key pair ready */ makeKeyPairData ( self, _keyPair ) _keyPair.passwordOK = true let keyPairPassword = _keyPair.keyPairPassword () _keyPair.keyPairPassword ( keyPairPassword = null ) config.keypair = _keyPair self.keyPair ( _keyPair ) self.showKeyPair ( false ) initPopupArea () let uu = null self.keyPairCalss = new encryptoClass ( self.keyPair () ) self.imapSetup ( uu = new imapForm ( config.account, null, function ( imapData: IinputData ) { self.imapSetup ( uu = null ) return self.imapSetupClassExit ( imapData, sessionHash ) })) return self.keyPairGenerateForm ( _keyPairGenerateForm = null ) }) this.keyPairGenerateForm ( _keyPairGenerateForm ) } this.localServerConfig ( config ) this.afterInitConfig () } private clearImapData () { let imap = this.imapSetup() this.imapSetup( imap = null ) } private socketListen () { let self = this this.connectInformationMessage.sockEmit ( 'init', ( err, config: install_config) => { if ( err ) { return } return self.initConfig ( config ) }) this.connectInformationMessage.socketIo.on ('init', ( err, config: install_config ) => { if ( err ) { return } return self.initConfig ( config ) }) } constructor () { this.socketListen () this.CanadaBackground.subscribe ( val => { if ( val ) { $.ajax ({ url:'/scripts/CanadaSvg.js' }).done ( data => { eval ( data ) }) } }) } // change language public selectItem ( that?: any, site?: () => number ) { const tindex = lang [ this.tLang ()] let index = tindex + 1 if ( index > 3 ) { index = 0 } this.languageIndex ( index ) this.tLang( lang [ index ]) $.cookie ( 'langEH', this.tLang(), { expires: 180, path: '/' }) const obj = $( "span[ve-data-bind]" ) obj.each ( function ( index, element ) { const ele = $( element ) const data = ele.attr ( 've-data-bind' ) if ( data && data.length ) { ele.text ( eval ( data )) } }) $('.languageText').shape (`flip ${ this.LocalLanguage }`) $('.KnockoutAnimation').transition('jiggle') return initPopupArea() } // start click public openClick () { clearTimeout ( this.demoTimeout ) if ( this.demoMainElm && typeof this.demoMainElm.remove === 'function' ) { this.demoMainElm.remove() this.demoMainElm = null } if ( !this.connectInformationMessage.socketIoOnline ) { return this.connectInformationMessage.showSystemError () } this.sectionWelcome ( false ) /* if ( this.localServerConfig().firstRun ) { return this.sectionAgreement ( true ) } */ this.sectionLogin ( true ) return initPopupArea () } public deletedKeypairResetView () { this.imapSetup (null) } public agreeClick () { this.connectInformationMessage.sockEmit ( 'agreeClick' ) this.sectionAgreement ( false ) this.localServerConfig().firstRun = false return this.openClick() } public refresh () { if ( typeof require === 'undefined' ) { this.modalContent ( infoDefine[ this.languageIndex() ].emailConform.formatError [ 11 ] ) return this.hacked ( true ) } const { remote } = require ('electron') if ( remote && remote.app && typeof remote.app.quit === 'function' ) { return remote.app.quit() } } public showKeyInfoClick () { this.sectionLogin ( true ) this.showKeyPair ( true ) this.AppList ( false ) this.appsManager ( null ) } public imapSetupClassExit ( _imapData: IinputData, sessionHash: string ) { const self = this this.imapData = _imapData this.sessionHash = sessionHash return this.CoNETConnect ( this.CoNETConnectClass = new CoNETConnect ( _imapData.imapUserName, this.keyPair().verified, _imapData.confirmRisk, this.keyPair().email, function ConnectReady ( err ) { if ( typeof err ==='number' && err > -1 ) { self.CoNETConnect ( this.CoNETConnectClass = null ) return self.imapSetup ( this.imapFormClass = new imapForm ( _imapData.account, null, function ( imapData: IinputData ) { self.imapSetup ( this.imapFormClass = null ) return self.imapSetupClassExit ( imapData, sessionHash ) })) } self.connectedCoNET ( true ) self.homeClick () })) } public reFreshLocalServer () { location.reload() } public homeClick () { this.AppList ( true ) this.sectionLogin ( false ) const connectMainMenu = () => { let am = null this.appsManager ( am = new appsManager (() => { am = null return connectMainMenu () })) } connectMainMenu () this.showKeyPair ( false ) $('.dimmable').dimmer ({ on: 'hover' }) $('.comeSoon').popup ({ on: 'focus', movePopup: false, position: 'top left', inline: true }) _view.connectInformationMessage.socketIo.removeEventListener ('tryConnectCoNETStage', this.CoNETConnectClass.listenFun ) } /** * * T/t = Translate (t is relative, T is absolute) R/r = rotate(r is relative, R is absolute) S/s = scale(s is relative, S is absolute) */ private svgDemo_showLanguage () { if ( !this.sectionWelcome()) { return } let i = 0 const changeLanguage = () => { if ( ++i === 1 ) { backGround_mask_circle.attr ({ stroke: "#FF000090", }) return setTimeout (() => { changeLanguage() }, 1000 ) } if ( i > 5 || !this.sectionWelcome() ) { main.remove() return this.demoMainElm = main = null } this.selectItem () this.demoTimeout = setTimeout (() => { changeLanguage () }, 2000 ) } const width = window.innerWidth const height = window.outerHeight let main = this.demoMainElm = Snap( width, height ) const backGround_mask_circle = main.circle( width / 2, height / 2, width / 1.7 ).attr({ fill:'#00000000', stroke: "#FF000020", strokeWidth: 5, }) const wT = width/2 - 35 const wY = 30 - height / 2 backGround_mask_circle.animate ({ transform: `t${ wT } ${ wY }`, r: 60 }, 3000, mina.easeout, changeLanguage ) } } } const _view = new view_layout.view () ko.applyBindings ( _view , document.getElementById ( 'body' )) $(`.${ _view.tLang()}`).addClass('active') ================================================ FILE: app/public/scripts/imapForm.js ================================================ /*! * Copyright 2018 CoNET Technology Inc. All Rights Reserved. * * 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. */ const availableImapServer = /imap\-mail\.outlook\.com$|imap\.mail\.yahoo\.(com|co\.jp|co\.uk|au)$|imap\.mail\.me\.com$|imap\.gmail\.com$|gmx\.(com|us|net)$|imap\.zoho\.com$/i; /** * getImapSmtpHost * @param email * @return Imap & Smtp info */ const getImapSmtpHost = function (_email) { const email = _email.toLowerCase(); const yahoo = function (domain) { if (/yahoo.co.jp$/i.test(domain)) return 'yahoo.co.jp'; if (/((.*\.){0,1}yahoo|yahoogroups|yahooxtra|yahoogruppi|yahoogrupper)(\..{2,3}){1,2}$/.test(domain)) return 'yahoo.com'; if (/(^hotmail|^outlook|^live|^msn)(\..{2,3}){1,2}$/.test(domain)) return 'hotmail.com'; if (/^(me|^icould|^mac)\.com/.test(domain)) return 'me.com'; return domain; }; const emailSplit = email.split('@'); if (emailSplit.length !== 2) return null; const domain = yahoo(emailSplit[1]); const ret = { imap: 'imap.' + domain, smtp: 'smtp.' + domain, SmtpPort: [465, 587, 994], ImapPort: 993, imapSsl: true, smtpSsl: true, haveAppPassword: false, ApplicationPasswordInformationUrl: [''] }; switch (domain) { // yahoo domain have two different // the yahoo.co.jp is different other yahoo.* case 'yahoo.co.jp': { ret.imap = 'imap.mail.yahoo.co.jp'; ret.smtp = 'smtp.mail.yahoo.co.jp'; } break; // gmail case 'google.com': case 'googlemail.com': case 'gmail': { ret.haveAppPassword = true; ret.ApplicationPasswordInformationUrl = [ 'https://support.google.com/accounts/answer/185833?hl=zh-Hans', 'https://support.google.com/accounts/answer/185833?hl=ja', 'https://support.google.com/accounts/answer/185833?hl=en' ]; } break; case 'gandi.net': ret.imap = ret.smtp = 'mail.gandi.net'; break; // yahoo.com case 'rocketmail.com': case 'y7mail.com': case 'ymail.com': case 'yahoo.com': { ret.imap = 'imap.mail.yahoo.com'; ret.smtp = (/^bizmail.yahoo.com$/.test(emailSplit[1])) ? 'smtp.bizmail.yahoo.com' : 'smtp.mail.yahoo.com'; ret.haveAppPassword = true; ret.ApplicationPasswordInformationUrl = [ 'https://help.yahoo.com/kb/SLN15241.html', 'https://help.yahoo.com/kb/SLN15241.html', 'https://help.yahoo.com/kb/SLN15241.html' ]; } break; case 'mail.ee': ret.smtp = 'mail.ee'; ret.imap = 'mail.inbox.ee'; break; // gmx.com case 'gmx.co.uk': case 'gmx.de': case 'gmx.us': case 'gmx.com': { ret.smtp = 'mail.gmx.com'; ret.imap = 'imap.gmx.com'; } break; // aim.com case 'aim.com': { ret.imap = 'imap.aol.com'; } break; // outlook.com case 'windowslive.com': case 'hotmail.com': case 'outlook.com': { ret.imap = 'imap-mail.outlook.com'; ret.smtp = 'smtp-mail.outlook.com'; } break; // apple mail case 'icloud.com': case 'mac.com': case 'me.com': { ret.imap = 'imap.mail.me.com'; ret.smtp = 'smtp.mail.me.com'; } break; // 163.com case '126.com': case '163.com': { ret.imap = 'appleimap.' + domain; ret.smtp = 'applesmtp.' + domain; } break; case 'sina.com': case 'yeah.net': { ret.smtpSsl = false; } break; } return ret; }; class keyPairSign { constructor(exit) { this.exit = exit; this.signError = ko.observable(false); this.conformButtom = ko.observable(false); this.requestActivEmailrunning = ko.observable(false); this.showSentActivEmail = ko.observable(-1); this.conformText = ko.observable(''); this.conformTextError = ko.observable(false); this.requestError = ko.observable(-1); this.conformTextErrorNumber = ko.observable(-1); this.activeing = ko.observable(false); this.showRequestActivEmailButtonError = ko.observable(false); const self = this; this.conformText.subscribe(function (newValue) { if (!newValue || !newValue.length) { self.conformButtom(false); } else { self.conformButtom(true); } }); } checkActiveEmailSubmit() { const self = this; this.conformTextError(false); this.activeing(true); let text = this.conformText(); const showFromatError = (err) => { self.activeing(false); self.conformTextErrorNumber(_view.connectInformationMessage.getErrorIndex(err)); self.conformTextError(true); return $('.activating.element1').popup({ on: 'click', onHidden: function () { self.conformTextError(false); } }); }; if (!text || !text.length || !/^-+BEGIN PGP MESSAGE-+\n/.test(text)) { return showFromatError('PgpMessageFormatError'); } // support Outlook mail /* if ( / /.test ( text )) { text = text.replace ( / PGP MESSAGE/g, '__PGP__MESSAGE').replace (/ /g, '\r\n').replace (/__/g, ' ' ) text = text.replace ( / MESSAGE-----/,' MESSAGE-----\r\n' ) } /** */ return _view.keyPairCalss.decryptMessage(text, (err, obj) => { if (err) { return showFromatError('PgpDecryptError'); } const com = { command: 'activePassword', Args: [obj], error: null, subCom: null }; return _view.keyPairCalss.emitRequest(com, (err, com) => { if (err) { return showFromatError(err); } if (com) { if (com.error) { return showFromatError(com.error); } return _view.connectInformationMessage.sockEmit('checkActiveEmailSubmit', com.Args[0], (err, data) => { const config = _view.localServerConfig(); config.keypair.verified = true; _view.keyPair(config.keypair); _view.sectionLogin(false); self.exit(); }); } }); }); /* return _view.connectInformationMessage.sockEmit ( 'checkActiveEmailSubmit', text, function ( err, req: QTGateAPIRequestCommand ) { self.activeing ( false ) if ( err !== null && err > -1 || req && req.error != null && req.error > -1 ) { self.conformTextErrorNumber ( err !== null && err > -1 ? err : req.error ) self.conformTextError ( true ) } if (!req ) { const config = _view.localServerConfig() config.keypair.verified = true _view.localServerConfig ( config ) _view.keyPair ( config.keypair ) _view.sectionLogin ( false ) self.exit () } }) */ } clearError() { _view.connectInformationMessage.hideMessage(); this.showRequestActivEmailButtonError(false); } requestActivEmail() { const self = this; this.requestActivEmailrunning(true); const com = { command: 'requestActivEmail', Args: [], error: null, subCom: null }; const errorProcess = (err) => { this.requestActivEmailrunning(false); this.showRequestActivEmailButtonError(true); _view.connectInformationMessage.showErrorMessage(err); }; _view.keyPairCalss.emitRequest(com, (err, com) => { if (err) { return errorProcess(err); } if (!com) { return; } if (com.error) { return errorProcess(err); } if (com.Args[0] && com.Args[0].length) { return _view.connectInformationMessage.sockEmit('checkActiveEmailSubmit', com.Args[0], () => { const config = _view.localServerConfig(); config.keypair.verified = true; _view.keyPair(config.keypair); _view.sectionLogin(false); self.exit(); }); } self.conformButtom(false); self.showSentActivEmail(1); const u = self.showSentActivEmail(); }); /* return _view.connectInformationMessage.sockEmit ( 'requestActivEmail', function ( err ) { self.requestActivEmailrunning ( false ) if ( err !== null && err > -1 ) { return self.requestError ( err ) } self.conformButtom ( false ),[h] self.showSentActivEmail (1) const u = self.showSentActivEmail() }) */ } } class imapForm { constructor(account, imapData, exit) { this.account = account; this.exit = exit; this.emailAddress = ko.observable(''); this.password = ko.observable(''); this.emailAddressShowError = ko.observable(false); this.passwordShowError = ko.observable(false); this.EmailAddressErrorType = ko.observable(0); this.showForm = ko.observable(true); this.checkProcessing = ko.observable(false); this.checkImapError = ko.observable(-1); this.showCheckProcess = ko.observable(false); this.checkImapStep = ko.observable(0); const self = this; if (imapData) { this.emailAddress(imapData.imapUserName); this.password(imapData.imapUserPassword); } this.emailAddress.subscribe(function (newValue) { return self.checkEmailAddress(newValue); }); this.password.subscribe(function (newValue) { return self.clearError(); }); } clearError() { this.emailAddressShowError(false); this.EmailAddressErrorType(0); this.passwordShowError(false); } checkImapSetup() { let self = this; this.checkProcessing(true); this.checkImapStep(0); const imapTest = function (err) { if (err !== null && err > -1) { return errorProcess(err); } self.checkImapStep(5); }; const smtpTest = function (err) { if (err !== null && err > -1) { return errorProcess(err); } self.checkImapStep(2); }; const imapTestFinish = function (IinputData) { removeAllListen(); return self.exit(IinputData); }; const removeAllListen = function () { _view.connectInformationMessage.socketIo.removeEventListener('smtpTest', smtpTest); _view.connectInformationMessage.socketIo.removeEventListener('imapTest', imapTest); _view.connectInformationMessage.socketIo.removeEventListener('imapTestFinish', imapTestFinish); }; const errorProcess = function (err) { removeAllListen(); return self.checkImapError(err); }; _view.connectInformationMessage.socketIo.once('smtpTest', smtpTest); _view.connectInformationMessage.socketIo.once('imapTest', imapTest); _view.connectInformationMessage.socketIo.once('imapTestFinish', imapTestFinish); _view.connectInformationMessage.sockEmit('checkImap', self.emailAddress(), self.password(), new Date().getTimezoneOffset(), _view.tLang()); } checkEmailAddress(email) { this.clearError(); if (checkEmail(email).length) { this.EmailAddressErrorType(0); this.emailAddressShowError(true); return initPopupArea(); } const imapServer = getImapSmtpHost(email); if (!availableImapServer.test(imapServer.imap)) { this.EmailAddressErrorType(2); this.emailAddressShowError(true); return initPopupArea(); } } imapAccountGoCheckClick() { const self = this; this.checkEmailAddress(this.emailAddress()); if (this.emailAddressShowError() || !this.password().length) { return; } this.showForm(false); this.showCheckProcess(true); this.checkImapError(-1); return this.checkImapSetup(); } returnImapSetup() { this.showForm(true); this.showCheckProcess(false); this.checkImapError(-1); } } ================================================ FILE: app/public/scripts/imapForm.ts ================================================ /*! * Copyright 2018 CoNET Technology Inc. All Rights Reserved. * * 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. */ const availableImapServer = /imap\-mail\.outlook\.com$|imap\.mail\.yahoo\.(com|co\.jp|co\.uk|au)$|imap\.mail\.me\.com$|imap\.gmail\.com$|gmx\.(com|us|net)$|imap\.zoho\.com$/i /** * getImapSmtpHost * @param email * @return Imap & Smtp info */ const getImapSmtpHost = function ( _email: string ) { const email = _email.toLowerCase() const yahoo = function ( domain: string ) { if ( /yahoo.co.jp$/i.test ( domain )) return 'yahoo.co.jp'; if ( /((.*\.){0,1}yahoo|yahoogroups|yahooxtra|yahoogruppi|yahoogrupper)(\..{2,3}){1,2}$/.test ( domain )) return 'yahoo.com'; if ( /(^hotmail|^outlook|^live|^msn)(\..{2,3}){1,2}$/.test ( domain )) return 'hotmail.com'; if ( /^(me|^icould|^mac)\.com/.test ( domain )) return 'me.com' return domain } const emailSplit = email.split ( '@' ) if ( emailSplit.length !== 2 ) return null const domain = yahoo ( emailSplit [1] ) const ret = { imap: 'imap.' + domain, smtp: 'smtp.' + domain, SmtpPort: [465,587,994], ImapPort: 993, imapSsl: true, smtpSsl: true, haveAppPassword: false, ApplicationPasswordInformationUrl: [''] } switch ( domain ) { // yahoo domain have two different // the yahoo.co.jp is different other yahoo.* case 'yahoo.co.jp': { ret.imap = 'imap.mail.yahoo.co.jp'; ret.smtp = 'smtp.mail.yahoo.co.jp' } break; // gmail case 'google.com': case 'googlemail.com': case 'gmail': { ret.haveAppPassword = true; ret.ApplicationPasswordInformationUrl = [ 'https://support.google.com/accounts/answer/185833?hl=zh-Hans', 'https://support.google.com/accounts/answer/185833?hl=ja', 'https://support.google.com/accounts/answer/185833?hl=en' ] } break; case 'gandi.net': ret.imap = ret.smtp = 'mail.gandi.net' break // yahoo.com case 'rocketmail.com': case 'y7mail.com': case 'ymail.com': case 'yahoo.com': { ret.imap = 'imap.mail.yahoo.com' ret.smtp = (/^bizmail.yahoo.com$/.test(emailSplit[1])) ? 'smtp.bizmail.yahoo.com' : 'smtp.mail.yahoo.com' ret.haveAppPassword = true; ret.ApplicationPasswordInformationUrl = [ 'https://help.yahoo.com/kb/SLN15241.html', 'https://help.yahoo.com/kb/SLN15241.html', 'https://help.yahoo.com/kb/SLN15241.html' ] } break; case 'mail.ee': ret.smtp = 'mail.ee' ret.imap = 'mail.inbox.ee' break // gmx.com case 'gmx.co.uk': case 'gmx.de': case 'gmx.us': case 'gmx.com' : { ret.smtp = 'mail.gmx.com' ret.imap = 'imap.gmx.com' } break; // aim.com case 'aim.com': { ret.imap = 'imap.aol.com' } break; // outlook.com case 'windowslive.com': case 'hotmail.com': case 'outlook.com': { ret.imap = 'imap-mail.outlook.com' ret.smtp = 'smtp-mail.outlook.com' } break; // apple mail case 'icloud.com': case 'mac.com': case 'me.com': { ret.imap = 'imap.mail.me.com' ret.smtp = 'smtp.mail.me.com' } break; // 163.com case '126.com': case '163.com': { ret.imap = 'appleimap.' + domain ret.smtp = 'applesmtp.' + domain } break; case 'sina.com': case 'yeah.net': { ret.smtpSsl = false } break; } return ret } class keyPairSign { public signError = ko.observable ( false ) public conformButtom = ko.observable ( false ) public requestActivEmailrunning = ko.observable ( false ) public showSentActivEmail = ko.observable ( -1 ) public conformText = ko.observable ('') public conformTextError = ko.observable ( false ) public requestError = ko.observable (-1) public conformTextErrorNumber = ko.observable ( -1 ) public activeing = ko.observable ( false ) public showRequestActivEmailButtonError = ko.observable ( false ) constructor ( private exit: () => void ) { const self = this this.conformText.subscribe ( function ( newValue ) { if ( !newValue || !newValue.length ) { self.conformButtom ( false ) } else { self.conformButtom ( true ) } }) } public checkActiveEmailSubmit () { const self = this this.conformTextError ( false ) this.activeing ( true ) let text = this.conformText() const showFromatError = ( err ) => { self.activeing ( false ) self.conformTextErrorNumber ( _view.connectInformationMessage.getErrorIndex ( err )) self.conformTextError ( true ) return $( '.activating.element1' ).popup({ on: 'click', onHidden: function () { self.conformTextError ( false ) } }) } if ( ! text || ! text.length || !/^-+BEGIN PGP MESSAGE-+\n/.test ( text )) { return showFromatError ( 'PgpMessageFormatError' ) } // support Outlook mail /* if ( / /.test ( text )) { text = text.replace ( / PGP MESSAGE/g, '__PGP__MESSAGE').replace (/ /g, '\r\n').replace (/__/g, ' ' ) text = text.replace ( / MESSAGE-----/,' MESSAGE-----\r\n' ) } /** */ return _view.keyPairCalss.decryptMessage ( text, ( err, obj ) => { if ( err ) { return showFromatError ( 'PgpDecryptError' ) } const com: QTGateAPIRequestCommand = { command: 'activePassword', Args: [ obj ], error: null, subCom: null } return _view.keyPairCalss.emitRequest ( com, ( err, com: QTGateAPIRequestCommand ) => { if ( err ) { return showFromatError ( err ) } if ( com ) { if ( com.error ) { return showFromatError ( com.error ) } return _view.connectInformationMessage.sockEmit ('checkActiveEmailSubmit', com.Args [0], ( err, data ) => { const config = _view.localServerConfig() config.keypair.verified = true _view.keyPair ( config.keypair ) _view.sectionLogin ( false ) self.exit () }) } }) }) /* return _view.connectInformationMessage.sockEmit ( 'checkActiveEmailSubmit', text, function ( err, req: QTGateAPIRequestCommand ) { self.activeing ( false ) if ( err !== null && err > -1 || req && req.error != null && req.error > -1 ) { self.conformTextErrorNumber ( err !== null && err > -1 ? err : req.error ) self.conformTextError ( true ) } if (!req ) { const config = _view.localServerConfig() config.keypair.verified = true _view.localServerConfig ( config ) _view.keyPair ( config.keypair ) _view.sectionLogin ( false ) self.exit () } }) */ } public clearError () { _view.connectInformationMessage.hideMessage() this.showRequestActivEmailButtonError ( false ) } public requestActivEmail () { const self = this this.requestActivEmailrunning ( true ) const com: QTGateAPIRequestCommand = { command: 'requestActivEmail', Args: [], error: null, subCom: null } const errorProcess = ( err ) => { this.requestActivEmailrunning ( false ) this.showRequestActivEmailButtonError ( true ) _view.connectInformationMessage.showErrorMessage ( err ) } _view.keyPairCalss.emitRequest ( com,( err, com: QTGateAPIRequestCommand ) => { if ( err ) { return errorProcess ( err ) } if ( !com ) { return } if ( com.error ) { return errorProcess ( err ) } if ( com.Args[0] && com.Args[0].length ) { return _view.connectInformationMessage.sockEmit ('checkActiveEmailSubmit', com.Args [0], () => { const config = _view.localServerConfig() config.keypair.verified = true _view.keyPair ( config.keypair ) _view.sectionLogin ( false ) self.exit () }) } self.conformButtom ( false ) self.showSentActivEmail (1) const u = self.showSentActivEmail() }) /* return _view.connectInformationMessage.sockEmit ( 'requestActivEmail', function ( err ) { self.requestActivEmailrunning ( false ) if ( err !== null && err > -1 ) { return self.requestError ( err ) } self.conformButtom ( false ),[h] self.showSentActivEmail (1) const u = self.showSentActivEmail() }) */ } } class imapForm { public emailAddress = ko.observable ('') public password = ko.observable ('') public emailAddressShowError = ko.observable ( false ) public passwordShowError = ko.observable ( false ) public EmailAddressErrorType = ko.observable ( 0 ) public showForm = ko.observable ( true ) public checkProcessing = ko.observable ( false ) public checkImapError = ko.observable (-1) public showCheckProcess = ko.observable ( false ) public checkImapStep = ko.observable (0) private clearError () { this.emailAddressShowError ( false ) this.EmailAddressErrorType (0) this.passwordShowError ( false ) } private checkImapSetup () { let self = this this.checkProcessing ( true ) this.checkImapStep (0) const imapTest = function ( err ) { if ( err !== null && err > -1 ) { return errorProcess ( err ) } self.checkImapStep (5) } const smtpTest = function ( err ) { if ( err !== null && err > -1 ) { return errorProcess ( err ) } self.checkImapStep (2) } const imapTestFinish = function ( IinputData: IinputData ) { removeAllListen () return self.exit ( IinputData ) } const removeAllListen = function () { _view.connectInformationMessage.socketIo.removeEventListener ( 'smtpTest', smtpTest ) _view.connectInformationMessage.socketIo.removeEventListener ( 'imapTest', imapTest ) _view.connectInformationMessage.socketIo.removeEventListener ( 'imapTestFinish', imapTestFinish ) } const errorProcess = function ( err ) { removeAllListen () return self.checkImapError ( err ) } _view.connectInformationMessage.socketIo.once ( 'smtpTest', smtpTest ) _view.connectInformationMessage.socketIo.once ( 'imapTest', imapTest ) _view.connectInformationMessage.socketIo.once ( 'imapTestFinish', imapTestFinish ) _view.connectInformationMessage.sockEmit ( 'checkImap', self.emailAddress (), self.password (), new Date ().getTimezoneOffset (), _view.tLang ()) } private checkEmailAddress ( email: string ) { this.clearError () if ( checkEmail ( email ).length ) { this.EmailAddressErrorType (0) this.emailAddressShowError ( true ) return initPopupArea () } const imapServer = getImapSmtpHost ( email ) if ( !availableImapServer.test ( imapServer.imap )) { this.EmailAddressErrorType (2) this.emailAddressShowError ( true ) return initPopupArea () } } constructor ( private account: string, imapData: IinputData, private exit: ( IinputData: IinputData ) => void ) { const self = this if ( imapData ) { this.emailAddress ( imapData.imapUserName ) this.password ( imapData.imapUserPassword ) } this.emailAddress.subscribe ( function ( newValue ) { return self.checkEmailAddress ( newValue ) }) this.password.subscribe ( function ( newValue ) { return self.clearError () }) } public imapAccountGoCheckClick () { const self = this this.checkEmailAddress ( this.emailAddress() ) if ( this.emailAddressShowError() || !this.password().length ) { return } this.showForm ( false ) this.showCheckProcess ( true ) this.checkImapError ( -1 ) return this.checkImapSetup () } public returnImapSetup () { this.showForm ( true ) this.showCheckProcess ( false ) this.checkImapError ( -1 ) } } ================================================ FILE: app/public/scripts/jquery.cookie.js ================================================ /*! * jQuery Cookie Plugin v1.4.1 * https://github.com/carhartl/jquery-cookie * * Copyright 2013 Klaus Hartl * Released under the MIT license */ (function (factory) { if (typeof define === 'function' && define.amd) { // AMD define(['jquery'], factory); } else if (typeof exports === 'object') { // CommonJS factory(require('jquery')); } else { // Browser globals factory(jQuery); } }(function ($) { var pluses = /\+/g; function encode(s) { return config.raw ? s : encodeURIComponent(s); } function decode(s) { return config.raw ? s : decodeURIComponent(s); } function stringifyCookieValue(value) { return encode(config.json ? JSON.stringify(value) : String(value)); } function parseCookieValue(s) { if (s.indexOf('"') === 0) { // This is a quoted cookie as according to RFC2068, unescape... s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\'); } try { // Replace server-side written pluses with spaces. // If we can't decode the cookie, ignore it, it's unusable. // If we can't parse the cookie, ignore it, it's unusable. s = decodeURIComponent(s.replace(pluses, ' ')); return config.json ? JSON.parse(s) : s; } catch(e) {} } function read(s, converter) { var value = config.raw ? s : parseCookieValue(s); return $.isFunction(converter) ? converter(value) : value; } var config = $.cookie = function (key, value, options) { // Write if (value !== undefined && !$.isFunction(value)) { options = $.extend({}, config.defaults, options); if (typeof options.expires === 'number') { var days = options.expires, t = options.expires = new Date(); t.setTime(+t + days * 864e+5); } return (document.cookie = [ encode(key), '=', stringifyCookieValue(value), options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE options.path ? '; path=' + options.path : '', options.domain ? '; domain=' + options.domain : '', options.secure ? '; secure' : '' ].join('')); } // Read var result = key ? undefined : {}; // To prevent the for loop in the first place assign an empty array // in case there are no cookies at all. Also prevents odd result when // calling $.cookie(). var cookies = document.cookie ? document.cookie.split('; ') : []; for (var i = 0, l = cookies.length; i < l; i++) { var parts = cookies[i].split('='); var name = decode(parts.shift()); var cookie = parts.join('='); if (key && key === name) { // If second argument (value) is a function it's a converter... result = read(cookie, value); break; } // Prevent storing a cookie that we couldn't decode. if (!key && (cookie = read(cookie)) !== undefined) { result[name] = cookie; } } return result; }; config.defaults = {}; $.removeCookie = function (key, options) { if ($.cookie(key) === undefined) { return false; } // Must not alter options, thus extending a fresh object... $.cookie(key, '', $.extend({}, options, { expires: -1 })); return !$.cookie(key); }; })); ================================================ FILE: app/public/scripts/keyPairGenerateForm.js ================================================ /*! * Copyright 2018 CoNET Technology Inc. All Rights Reserved. * * 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. */ /** * check email address * @param email * @param return Valid = '' Err = errorMessage */ const insideChinaEmail = /(\@|\.)(sina|sohu|qq|126|163|tom)\.com|(\.|\@)yeah\.net/i; const getNickName = function (email) { var ret = ''; if (email.length) { ret = email.split('@')[0]; ret = ret.charAt(0).toUpperCase() + ret.slice(1); } return ret; }; class IsNullValidator { isAcceptable(s) { if (s === undefined) { return true; } if (s === null) { return true; } if (s.length == 0) { return true; } } } class EmailValidator { isAcceptable(s) { return EmailRegexp.test(s); } } const testVal = new IsNullValidator(); const testEmail = new EmailValidator(); const checkEmail = function (email) { if (testVal.isAcceptable(email)) { return 'required'; } if (!testEmail.isAcceptable(email)) { return 'EmailAddress'; } return ''; }; class keyPairGenerateForm { constructor(exit) { this.exit = exit; this.EmailAddressError = ko.observable(false); this.SystemAdministratorEmailAddress = ko.observable(''); this.showInsideFireWallEmail = ko.observable(false); this.NickNameError = ko.observable(false); this.passwordError = ko.observable(false); this.SystemAdministratorNickName = ko.observable(''); this.systemSetup_systemPassword = ko.observable(''); this.showKeyPairPorcess = ko.observable(false); this.delete_btn_view = ko.observable(false); this.doingProcessBarTime = null; this.keyPairGenerateFormMessage = ko.observable(false); this.message_cancel = ko.observable(false); this.message_keyPairGenerateError = ko.observable(false); this.message_keyPairGenerateSuccess = ko.observable(false); this.showKeyPairForm = ko.observable(true); this.showKeyInfomation = ko.observable(false); const self = this; this.SystemAdministratorEmailAddress.subscribe(function (newValue) { return self.checkEmailAddress(newValue); }); this.SystemAdministratorNickName.subscribe(function (newValue) { return self.checkNickname(newValue); }); /* this.systemSetup_systemPassword.subscribe ( function ( newValue ) { return self.checkPassword ( newValue ) }) */ } checkEmailAddress(email) { $('.ui.checkbox').checkbox(); this.EmailAddressError(false); this.NickNameError(false); if (!email || !email.length) { this.EmailAddressError(true); return initPopupArea(); } if (conetImapAccount.test(email)) { this.EmailAddressError(true); return initPopupArea(); } if (checkEmail(email).length) { this.EmailAddressError(true); return initPopupArea(); } if (!this.SystemAdministratorNickName().length) { this.SystemAdministratorNickName(getNickName(email)); } if (insideChinaEmail.test(email)) { this.showInsideFireWallEmail(true); } return true; } checkNickname(nickname) { this.NickNameError(false); if (!nickname || !nickname.length) { initPopupArea(); this.NickNameError(true); } return true; } checkPassword(password) { this.passwordError(false); if (!password || password.length < 5) { this.passwordError(true); initPopupArea(); } return true; } stopDoingProcessBar() { clearTimeout(this.doingProcessBarTime); this.showKeyPairPorcess(false); return $('.keyPairProcessBar').progress({ percent: 0 }); } form_AdministratorEmail_submit() { const self = this; this.checkEmailAddress(this.SystemAdministratorEmailAddress()); this.checkNickname(this.SystemAdministratorNickName()); this.checkPassword(this.systemSetup_systemPassword()); if (this.passwordError() || this.EmailAddressError() || this.NickNameError()) { return false; } this.showKeyPairPorcess(true); this.showKeyPairForm(false); const email = this.SystemAdministratorEmailAddress(); const sendData = { password: this.systemSetup_systemPassword(), nikeName: this.SystemAdministratorNickName(), email: email }; let percent = 1; $('.keyPairProcessBar').progress('reset'); const timeSet = 10000; const doingProcessBar = function () { clearTimeout(self.doingProcessBarTime); self.doingProcessBarTime = setTimeout(function () { $('.keyPairProcessBar').progress({ percent: percent++ }); if (percent < 100) return doingProcessBar(); }, timeSet); }; _view.connectInformationMessage.sockEmit('NewKeyPair', sendData, function (err, keyPair, newKeyPairCallBack) { self.stopDoingProcessBar(); self.keyPairGenerateFormMessage(true); if (!keyPair) { return self.message_keyPairGenerateError(true); } self.exit(keyPair, newKeyPairCallBack); return self.message_keyPairGenerateSuccess(true); }); return doingProcessBar(); } CloseKeyPairGenerateFormMessage() { this.message_cancel(false); this.message_keyPairGenerateError(false); this.message_keyPairGenerateSuccess(false); this.keyPairGenerateFormMessage(false); return this.showKeyPairForm(true); } } ================================================ FILE: app/public/scripts/keyPairGenerateForm.ts ================================================ /*! * Copyright 2018 CoNET Technology Inc. All Rights Reserved. * * 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. */ /** * check email address * @param email * @param return Valid = '' Err = errorMessage */ const insideChinaEmail = /(\@|\.)(sina|sohu|qq|126|163|tom)\.com|(\.|\@)yeah\.net/i const getNickName = function ( email: string ) { var ret = '' if ( email.length ){ ret = email.split ('@')[0] ret = ret.charAt (0).toUpperCase () + ret.slice(1) } return ret } class IsNullValidator implements StringValidator { isAcceptable ( s: string ) { if ( s === undefined ) { return true } if ( s === null ) { return true } if ( s.length == 0 ) { return true } } } class EmailValidator implements StringValidator { isAcceptable ( s: string ) { return EmailRegexp.test( s ) } } const testVal = new IsNullValidator() const testEmail = new EmailValidator() const checkEmail = function ( email: string ) { if ( testVal.isAcceptable ( email )) { return 'required' } if ( ! testEmail.isAcceptable ( email )) { return 'EmailAddress' } return '' } class keyPairGenerateForm { public EmailAddressError = ko.observable ( false ) public SystemAdministratorEmailAddress = ko.observable ('') public showInsideFireWallEmail = ko.observable ( false ) public NickNameError = ko.observable ( false ) public passwordError = ko.observable ( false ) public SystemAdministratorNickName = ko.observable ('') public systemSetup_systemPassword = ko.observable ('') public showKeyPairPorcess = ko.observable ( false ) public delete_btn_view = ko.observable ( false ) public doingProcessBarTime = null public keyPairGenerateFormMessage = ko.observable ( false ) public message_cancel = ko.observable ( false ) public message_keyPairGenerateError = ko.observable ( false ) public message_keyPairGenerateSuccess = ko.observable ( false ) public showKeyPairForm = ko.observable ( true ) public showKeyInfomation = ko.observable ( false ) private checkEmailAddress ( email: string ) { $ ('.ui.checkbox').checkbox() this.EmailAddressError ( false ) this.NickNameError ( false ) if ( ! email || ! email.length ) { this.EmailAddressError ( true ) return initPopupArea () } if ( conetImapAccount.test ( email )) { this.EmailAddressError ( true ) return initPopupArea () } if ( checkEmail ( email ).length ) { this.EmailAddressError ( true ) return initPopupArea () } if ( ! this.SystemAdministratorNickName ().length ){ this.SystemAdministratorNickName ( getNickName ( email )) } if ( insideChinaEmail.test ( email )) { this.showInsideFireWallEmail ( true ) } return true } private checkNickname ( nickname: string ) { this.NickNameError ( false ) if ( !nickname || !nickname.length ) { initPopupArea () this.NickNameError ( true ) } return true } private checkPassword ( password: string ) { this.passwordError(false) if ( !password || password.length < 5 ) { this.passwordError ( true ) initPopupArea () } return true } private stopDoingProcessBar () { clearTimeout ( this.doingProcessBarTime ) this.showKeyPairPorcess ( false ) return $('.keyPairProcessBar').progress ({ percent: 0 }) } constructor ( private exit: ( keyPair, sessionHash: string ) => void ) { const self = this this.SystemAdministratorEmailAddress.subscribe ( function ( newValue ) { return self.checkEmailAddress ( newValue ) }) this.SystemAdministratorNickName.subscribe ( function ( newValue ) { return self.checkNickname ( newValue ) }) /* this.systemSetup_systemPassword.subscribe ( function ( newValue ) { return self.checkPassword ( newValue ) }) */ } public form_AdministratorEmail_submit () { const self = this this.checkEmailAddress ( this.SystemAdministratorEmailAddress ()) this.checkNickname ( this.SystemAdministratorNickName ()) this.checkPassword ( this.systemSetup_systemPassword ()) if ( this.passwordError() || this.EmailAddressError() || this.NickNameError()) { return false } this.showKeyPairPorcess ( true ) this.showKeyPairForm ( false ) const email = this.SystemAdministratorEmailAddress () const sendData: INewKeyPair = { password: this.systemSetup_systemPassword (), nikeName: this.SystemAdministratorNickName (), email: email } let percent = 1 $('.keyPairProcessBar').progress ('reset') const timeSet = 10000 const doingProcessBar = function () { clearTimeout ( self.doingProcessBarTime ) self.doingProcessBarTime = setTimeout ( function () { $('.keyPairProcessBar').progress ({ percent: percent++ }) if ( percent < 100 ) return doingProcessBar () }, timeSet ) } _view.connectInformationMessage.sockEmit ( 'NewKeyPair', sendData, function ( err, keyPair, newKeyPairCallBack ) { self.stopDoingProcessBar () self.keyPairGenerateFormMessage ( true ) if ( !keyPair ) { return self.message_keyPairGenerateError ( true ) } self.exit ( keyPair, newKeyPairCallBack ) return self.message_keyPairGenerateSuccess ( true ) }) return doingProcessBar () } public CloseKeyPairGenerateFormMessage () { this.message_cancel ( false ) this.message_keyPairGenerateError ( false ) this.message_keyPairGenerateSuccess ( false ) this.keyPairGenerateFormMessage ( false ) return this.showKeyPairForm ( true ) } } ================================================ FILE: app/public/scripts/keyPairPassword.js ================================================ /*! * Copyright 2018 CoNET Technology Inc. All Rights Reserved. * * 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. */ class keyPairPassword { constructor(exit) { this.exit = exit; this.showPasswordErrorMessage = ko.observable(false); this.systemSetup_systemPassword = ko.observable(''); this.passwordChecking = ko.observable(false); this.inputFocus = ko.observable(false); const self = this; this.systemSetup_systemPassword.subscribe(function (newValue) { if (!newValue || !newValue.length) { return; } self.showPasswordErrorMessage(false); }); } showPasswordError() { this.showPasswordErrorMessage(true); this.systemSetup_systemPassword(''); return initPopupArea(); } keyPair_checkPemPasswordClick() { const self = this; this.showPasswordErrorMessage(false); if (!this.systemSetup_systemPassword() || this.systemSetup_systemPassword().length < 5) { return this.showPasswordError(); } this.passwordChecking(true); return _view.connectInformationMessage.sockEmit('checkPemPassword', this.systemSetup_systemPassword(), function (err, _imapData, passwd, sessionHash) { self.passwordChecking(false); if (err || typeof _imapData === 'boolean' && _imapData) { return self.showPasswordError(); } return self.exit(_imapData, passwd, sessionHash); }); } } ================================================ FILE: app/public/scripts/keyPairPassword.ts ================================================ /*! * Copyright 2018 CoNET Technology Inc. All Rights Reserved. * * 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. */ class keyPairPassword { public showPasswordErrorMessage = ko.observable ( false ) public systemSetup_systemPassword = ko.observable ('') public passwordChecking = ko.observable ( false ) public inputFocus = ko.observable ( false ) constructor ( private exit: ( imapDat: imapData, passwd: string, sessionHash: string ) => void ) { const self = this this.systemSetup_systemPassword.subscribe ( function ( newValue ) { if ( !newValue || !newValue.length ) { return } self.showPasswordErrorMessage ( false ) }) } private showPasswordError() { this.showPasswordErrorMessage ( true ) this.systemSetup_systemPassword ('') return initPopupArea() } public keyPair_checkPemPasswordClick () { const self = this this.showPasswordErrorMessage ( false ) if ( !this.systemSetup_systemPassword() || this.systemSetup_systemPassword().length < 5 ) { return this.showPasswordError () } this.passwordChecking ( true ) return _view.connectInformationMessage.sockEmit ( 'checkPemPassword', this.systemSetup_systemPassword(), function ( err: boolean, _imapData: imapData, passwd: string, sessionHash: string ) { self.passwordChecking ( false ) if ( err || typeof _imapData === 'boolean' && _imapData ) { return self.showPasswordError() } return self.exit ( _imapData, passwd, sessionHash ) }) } } ================================================ FILE: app/public/scripts/knockout.animate.js ================================================ (function (factory) { if (typeof require === "function" && typeof exports === "object" && typeof module === "object") { factory(require("knockout"), exports); } else if (typeof define === "function" && define["amd"]) { define(["knockout", "exports"], factory); } else { factory(ko, ko.mapping = {}); } }(function (ko, exports) { var animations = [ "bounce", "flash", "pulse", "rubberBand", "shake", "swing", "tada", "wobble", "bounceIn", "bounceInDown", "bounceInLeft", "bounceInRight", "bounceInUp", "bounceOut", "bounceOutDown", "bounceOutLeft", "bounceOutRight", "bounceOutUp", "fadeIn", "fadeInDown", "fadeInDownBig", "fadeInLeft", "fadeInLeftBig", "fadeInRight", "fadeInRightBig", "fadeInUp", "fadeInUpBig", "fadeOut", "fadeOutDown", "fadeOutDownBig", "fadeOutLeft", "fadeOutLeftBig", "fadeOutRight", "fadeOutRightBig", "fadeOutUp", "fadeOutUpBig", "flip", "flipInX", "flipInY", "flipOutX", "flipOutY", "lightSpeedIn", "lightSpeedOut", "rotateIn", "rotateInDownLeft", "rotateInDownRight", "rotateInUpLeft", "rotateInUpRight", "rotateOut", "rotateOutDownLeft", "rotateOutDownRight", "rotateOutUpLeft", "rotateOutUpRight", "hinge", "rollIn", "rollOut", "zoomIn", "slideInDown", "slideInLeft","slideInRight","slideInUp", "slideOutDown","slideOutLeft","slideOutRight","slideOutUp", "zoomInDown", "zoomInLeft", "zoomInRight", "zoomInUp", "zoomOut", "zoomOutDown", "zoomOutLeft", "zoomOutRight", "zoomOutUp"], baseAnimateClass = "animated", pfx = ["webkit", "moz", "MS", "o", ""]; const hideClass = 'displayNono' function addPrefixedEvent(element, type, callback) { for (var p = 0; p < pfx.length; p++) { if (!pfx[p]) type = type.toLowerCase(); element.addEventListener(pfx[p]+type, callback, false); } } function removePrefixedEvent(element, type, fun) { for (var p = 0; p < pfx.length; p++) { if (!pfx[p]) type = type.toLowerCase(); element.removeEventListener(pfx[p]+type, fun); } } function hasClass(ele,cls) { return ele.className.match(new RegExp('(\\s|^)'+cls+'(\\s|$)')); } function addClass(ele,cls) { if (!hasClass(ele,cls)){ ele.className = ele.className ? ele.className + " " + cls : cls; } } function removeClass(ele,cls) { if (hasClass(ele,cls)) { var reg = new RegExp('(\\s|^)'+cls+'(\\s|$)'); ele.className = ele.className.replace(reg,' ').trim(); } } function doAnimationWork(element, animation, callback, state, delay ){ const _element = $(element); if ( _element.hasClass ( hideClass )) { if ( /out/i.test ( animation )) { return ; } } setTimeout ( function() { addClass(element, baseAnimateClass); addClass(element, animation); removeClass(element, 'displayNono'); const EventFun = function ( event ) { removePrefixedEvent(element, "AnimationEnd", EventFun ); removeClass(element, baseAnimateClass); removeClass(element, animation); if (typeof callback === 'function'){ callback(event, state); } if ( /out/i.test (animation)) { $(element).addClass('displayNono') } } addPrefixedEvent(element, "AnimationEnd", EventFun ); }, delay ); } ko.bindingHandlers.animate = { init: function(element, valueAccessor){ var data = ko.unwrap(valueAccessor()), animation, state, toggle, animationOn, animationOff, handler; if (!data.animation){ throw new Error('Animation property must be defined'); } if (!data.state){ throw new Error('State property must be defined'); } animation = ko.unwrap(data.animation); animationOn = typeof animation === 'object' ? animation[0] : animation; animationOff = typeof animation === 'object' ? animation[1] : animation; if (animationOn && animations.indexOf(animationOn) === -1){ throw new Error('Invalid first animation'); } if (animationOff && animations.indexOf(animationOff) === -1){ throw new Error('Invalid second animation'); } }, update: function(element, valueAccessor){ var data = ko.unwrap(valueAccessor()), animation, state, toggle, animationOn, animationOff, handler, delay; if (!data.animation){ throw new Error('Animation property must be defined'); } /* if (!data.state){ throw new Error('State property must be defined'); } */ animation = ko.unwrap(data.animation); state = ko.unwrap( data.state ); const _element = $(element); animationOn = typeof animation === 'object' ? animation[0] : animation; animationOff = typeof animation === 'object' ? animation[1] : animation; if ( _element.hasClass ( hideClass )) { return } delay = data.delay || 0; toggle = animationOn !== animationOff; handler = ko.unwrap(data.handler) || undefined; if ( state ){ return doAnimationWork(element, animationOn, handler, state, delay); } doAnimationWork(element, animationOff, handler, state, delay); } }; })); ================================================ FILE: app/public/scripts/knockout.js ================================================ /*! * Knockout JavaScript library v3.5.1 * (c) The Knockout.js team - http://knockoutjs.com/ * License: MIT (http://www.opensource.org/licenses/mit-license.php) */ (function() {(function(n){var A=this||(0,eval)("this"),w=A.document,R=A.navigator,v=A.jQuery,H=A.JSON;v||"undefined"===typeof jQuery||(v=jQuery);(function(n){"function"===typeof define&&define.amd?define(["exports","require"],n):"object"===typeof exports&&"object"===typeof module?n(module.exports||exports):n(A.ko={})})(function(S,T){function K(a,c){return null===a||typeof a in W?a===c:!1}function X(b,c){var d;return function(){d||(d=a.a.setTimeout(function(){d=n;b()},c))}}function Y(b,c){var d;return function(){clearTimeout(d); d=a.a.setTimeout(b,c)}}function Z(a,c){c&&"change"!==c?"beforeChange"===c?this.pc(a):this.gb(a,c):this.qc(a)}function aa(a,c){null!==c&&c.s&&c.s()}function ba(a,c){var d=this.qd,e=d[r];e.ra||(this.Qb&&this.mb[c]?(d.uc(c,a,this.mb[c]),this.mb[c]=null,--this.Qb):e.I[c]||d.uc(c,a,e.J?{da:a}:d.$c(a)),a.Ja&&a.gd())}var a="undefined"!==typeof S?S:{};a.b=function(b,c){for(var d=b.split("."),e=a,f=0;fa.a.A(c,b)&&c.push(b)});return c},Mb:function(a, b,c){var d=[];if(a)for(var e=0,l=a.length;ee?d&&b.push(c):d||b.splice(e,1)},Ba:g,extend:c,setPrototypeOf:d,Ab:g?d:c,P:b,Ga:function(a,b,c){if(!a)return a;var d={},e;for(e in a)f.call(a,e)&&(d[e]= b.call(c,a[e],e,a));return d},Tb:function(b){for(;b.firstChild;)a.removeNode(b.firstChild)},Yb:function(b){b=a.a.la(b);for(var c=(b[0]&&b[0].ownerDocument||w).createElement("div"),d=0,e=b.length;dp?a.setAttribute("selected",b):a.selected=b},Db:function(a){return null===a||a===n?"":a.trim? a.trim():a.toString().replace(/^[\s\xa0]+|[\s\xa0]+$/g,"")},Ud:function(a,b){a=a||"";return b.length>a.length?!1:a.substring(0,b.length)===b},vd:function(a,b){if(a===b)return!0;if(11===a.nodeType)return!1;if(b.contains)return b.contains(1!==a.nodeType?a.parentNode:a);if(b.compareDocumentPosition)return 16==(b.compareDocumentPosition(a)&16);for(;a&&a!=b;)a=a.parentNode;return!!a},Sb:function(b){return a.a.vd(b,b.ownerDocument.documentElement)},kd:function(b){return!!a.a.Lb(b,a.a.Sb)},R:function(a){return a&& a.tagName&&a.tagName.toLowerCase()},Ac:function(b){return a.onError?function(){try{return b.apply(this,arguments)}catch(c){throw a.onError&&a.onError(c),c;}}:b},setTimeout:function(b,c){return setTimeout(a.a.Ac(b),c)},Gc:function(b){setTimeout(function(){a.onError&&a.onError(b);throw b;},0)},B:function(b,c,d){var e=a.a.Ac(d);d=l[c];if(a.options.useOnlyNativeEvents||d||!v)if(d||"function"!=typeof b.addEventListener)if("undefined"!=typeof b.attachEvent){var k=function(a){e.call(b,a)},f="on"+c;b.attachEvent(f, k);a.a.K.za(b,function(){b.detachEvent(f,k)})}else throw Error("Browser doesn't support addEventListener or attachEvent");else b.addEventListener(c,e,!1);else t||(t="function"==typeof v(b).on?"on":"bind"),v(b)[t](c,e)},Fb:function(b,c){if(!b||!b.nodeType)throw Error("element must be a DOM node when calling triggerEvent");var d;"input"===a.a.R(b)&&b.type&&"click"==c.toLowerCase()?(d=b.type,d="checkbox"==d||"radio"==d):d=!1;if(a.options.useOnlyNativeEvents||!v||d)if("function"==typeof w.createEvent)if("function"== typeof b.dispatchEvent)d=w.createEvent(k[c]||"HTMLEvents"),d.initEvent(c,!0,!0,A,0,0,0,0,0,!1,!1,!1,!1,0,b),b.dispatchEvent(d);else throw Error("The supplied element doesn't support dispatchEvent");else if(d&&b.click)b.click();else if("undefined"!=typeof b.fireEvent)b.fireEvent("on"+c);else throw Error("Browser doesn't support triggering events");else v(b).trigger(c)},f:function(b){return a.O(b)?b():b},bc:function(b){return a.O(b)?b.v():b},Eb:function(b,c,d){var l;c&&("object"===typeof b.classList? (l=b.classList[d?"add":"remove"],a.a.D(c.match(q),function(a){l.call(b.classList,a)})):"string"===typeof b.className.baseVal?e(b.className,"baseVal",c,d):e(b,"className",c,d))},Bb:function(b,c){var d=a.a.f(c);if(null===d||d===n)d="";var e=a.h.firstChild(b);!e||3!=e.nodeType||a.h.nextSibling(e)?a.h.va(b,[b.ownerDocument.createTextNode(d)]):e.data=d;a.a.Ad(b)},Yc:function(a,b){a.name=b;if(7>=p)try{var c=a.name.replace(/[&<>'"]/g,function(a){return"&#"+a.charCodeAt(0)+";"});a.mergeAttributes(w.createElement(""),!1)}catch(d){}},Ad:function(a){9<=p&&(a=1==a.nodeType?a:a.parentNode,a.style&&(a.style.zoom=a.style.zoom))},wd:function(a){if(p){var b=a.style.width;a.style.width=0;a.style.width=b}},Pd:function(b,c){b=a.a.f(b);c=a.a.f(c);for(var d=[],e=b;e<=c;e++)d.push(e);return d},la:function(a){for(var b=[],c=0,d=a.length;c",""],d=[3,"","
"],e=[1,""],f={thead:c,tbody:c,tfoot:c,tr:[2,"","
"],td:d,th:d,option:e,optgroup:e},g=8>=a.a.W;a.a.ua=function(c,d){var e;if(v)if(v.parseHTML)e=v.parseHTML(c,d)||[];else{if((e=v.clean([c],d))&&e[0]){for(var l=e[0];l.parentNode&&11!==l.parentNode.nodeType;)l=l.parentNode; l.parentNode&&l.parentNode.removeChild(l)}}else{(e=d)||(e=w);var l=e.parentWindow||e.defaultView||A,p=a.a.Db(c).toLowerCase(),q=e.createElement("div"),t;t=(p=p.match(/^(?:\x3c!--.*?--\x3e\s*?)*?<([a-z]+)[\s>]/))&&f[p[1]]||b;p=t[0];t="ignored
"+t[1]+c+t[2]+"
";"function"==typeof l.innerShiv?q.appendChild(l.innerShiv(t)):(g&&e.body.appendChild(q),q.innerHTML=t,g&&q.parentNode.removeChild(q));for(;p--;)q=q.lastChild;e=a.a.la(q.lastChild.childNodes)}return e};a.a.Md=function(b,c){var d=a.a.ua(b, c);return d.length&&d[0].parentElement||a.a.Yb(d)};a.a.fc=function(b,c){a.a.Tb(b);c=a.a.f(c);if(null!==c&&c!==n)if("string"!=typeof c&&(c=c.toString()),v)v(b).html(c);else for(var d=a.a.ua(c,b.ownerDocument),e=0;eb){if(5E3<= ++c){h=f;a.a.Gc(Error("'Too much recursion' after processing "+c+" task groups."));break}b=f}try{d()}catch(p){a.a.Gc(p)}}}function c(){b();h=f=e.length=0}var d,e=[],f=0,g=1,h=0;A.MutationObserver?d=function(a){var b=w.createElement("div");(new MutationObserver(a)).observe(b,{attributes:!0});return function(){b.classList.toggle("foo")}}(c):d=w&&"onreadystatechange"in w.createElement("script")?function(a){var b=w.createElement("script");b.onreadystatechange=function(){b.onreadystatechange=null;w.documentElement.removeChild(b); b=null;a()};w.documentElement.appendChild(b)}:function(a){setTimeout(a,0)};return{scheduler:d,zb:function(b){f||a.na.scheduler(c);e[f++]=b;return g++},cancel:function(a){a=a-(g-f);a>=h&&ad[0]?p+d[0]: d[0]),p);for(var p=1===g?p:Math.min(c+(d[1]||0),p),g=c+g-2,h=Math.max(p,g),U=[],L=[],n=2;cc;c++)b=b();return b})};a.toJSON=function(b,c,d){b=a.ad(b);return a.a.hc(b,c,d)};d.prototype={constructor:d,save:function(b,c){var d=a.a.A(this.keys, b);0<=d?this.values[d]=c:(this.keys.push(b),this.values.push(c))},get:function(b){b=a.a.A(this.keys,b);return 0<=b?this.values[b]:n}}})();a.b("toJS",a.ad);a.b("toJSON",a.toJSON);a.Wd=function(b,c,d){function e(c){var e=a.xb(b,d).extend({ma:"always"}),h=e.subscribe(function(a){a&&(h.s(),c(a))});e.notifySubscribers(e.v());return h}return"function"!==typeof Promise||c?e(c.bind(d)):new Promise(e)};a.b("when",a.Wd);(function(){a.w={M:function(b){switch(a.a.R(b)){case "option":return!0===b.__ko__hasDomDataOptionValue__? a.a.g.get(b,a.c.options.$b):7>=a.a.W?b.getAttributeNode("value")&&b.getAttributeNode("value").specified?b.value:b.text:b.value;case "select":return 0<=b.selectedIndex?a.w.M(b.options[b.selectedIndex]):n;default:return b.value}},cb:function(b,c,d){switch(a.a.R(b)){case "option":"string"===typeof c?(a.a.g.set(b,a.c.options.$b,n),"__ko__hasDomDataOptionValue__"in b&&delete b.__ko__hasDomDataOptionValue__,b.value=c):(a.a.g.set(b,a.c.options.$b,c),b.__ko__hasDomDataOptionValue__=!0,b.value="number"=== typeof c?c:"");break;case "select":if(""===c||null===c)c=n;for(var e=-1,f=0,g=b.options.length,h;f=h){c.push(p&&q.length?{key:p,value:q.join("")}:{unknown:p||q.join("")});p=h=0;q=[];continue}}else if(58===u){if(!h&&!p&&1===q.length){p=q.pop();continue}}else if(47===u&&1arguments.length){if(b=w.body,!b)throw Error("ko.applyBindings: could not find document.body; has the document been loaded?"); }else if(!b||1!==b.nodeType&&8!==b.nodeType)throw Error("ko.applyBindings: first parameter should be your view model; second parameter should be a DOM node");k(q(a,c),b)};a.Dc=function(b){return!b||1!==b.nodeType&&8!==b.nodeType?n:a.Td(b)};a.Ec=function(b){return(b=a.Dc(b))?b.$data:n};a.b("bindingHandlers",a.c);a.b("bindingEvent",a.i);a.b("bindingEvent.subscribe",a.i.subscribe);a.b("bindingEvent.startPossiblyAsyncContentBinding",a.i.Cb);a.b("applyBindings",a.vc);a.b("applyBindingsToDescendants",a.Oa); a.b("applyBindingAccessorsToNode",a.ib);a.b("applyBindingsToNode",a.ld);a.b("contextFor",a.Dc);a.b("dataFor",a.Ec)})();(function(b){function c(c,e){var k=Object.prototype.hasOwnProperty.call(f,c)?f[c]:b,l;k?k.subscribe(e):(k=f[c]=new a.T,k.subscribe(e),d(c,function(b,d){var e=!(!d||!d.synchronous);g[c]={definition:b,Gd:e};delete f[c];l||e?k.notifySubscribers(b):a.na.zb(function(){k.notifySubscribers(b)})}),l=!0)}function d(a,b){e("getConfig",[a],function(c){c?e("loadComponent",[a,c],function(a){b(a, c)}):b(null,null)})}function e(c,d,f,l){l||(l=a.j.loaders.slice(0));var g=l.shift();if(g){var q=g[c];if(q){var t=!1;if(q.apply(g,d.concat(function(a){t?f(null):null!==a?f(a):e(c,d,f,l)}))!==b&&(t=!0,!g.suppressLoaderExceptions))throw Error("Component loaders must supply values by invoking the callback, not by returning values synchronously.");}else e(c,d,f,l)}else f(null)}var f={},g={};a.j={get:function(d,e){var f=Object.prototype.hasOwnProperty.call(g,d)?g[d]:b;f?f.Gd?a.u.G(function(){e(f.definition)}): a.na.zb(function(){e(f.definition)}):c(d,e)},Bc:function(a){delete g[a]},oc:e};a.j.loaders=[];a.b("components",a.j);a.b("components.get",a.j.get);a.b("components.clearCachedDefinition",a.j.Bc)})();(function(){function b(b,c,d,e){function g(){0===--B&&e(h)}var h={},B=2,u=d.template;d=d.viewModel;u?f(c,u,function(c){a.j.oc("loadTemplate",[b,c],function(a){h.template=a;g()})}):g();d?f(c,d,function(c){a.j.oc("loadViewModel",[b,c],function(a){h[m]=a;g()})}):g()}function c(a,b,d){if("function"===typeof b)d(function(a){return new b(a)}); else if("function"===typeof b[m])d(b[m]);else if("instance"in b){var e=b.instance;d(function(){return e})}else"viewModel"in b?c(a,b.viewModel,d):a("Unknown viewModel value: "+b)}function d(b){switch(a.a.R(b)){case "script":return a.a.ua(b.text);case "textarea":return a.a.ua(b.value);case "template":if(e(b.content))return a.a.Ca(b.content.childNodes)}return a.a.Ca(b.childNodes)}function e(a){return A.DocumentFragment?a instanceof DocumentFragment:a&&11===a.nodeType}function f(a,b,c){"string"===typeof b.require? T||A.require?(T||A.require)([b.require],function(a){a&&"object"===typeof a&&a.Xd&&a["default"]&&(a=a["default"]);c(a)}):a("Uses require, but no AMD loader is present"):c(b)}function g(a){return function(b){throw Error("Component '"+a+"': "+b);}}var h={};a.j.register=function(b,c){if(!c)throw Error("Invalid configuration for "+b);if(a.j.tb(b))throw Error("Component "+b+" is already registered");h[b]=c};a.j.tb=function(a){return Object.prototype.hasOwnProperty.call(h,a)};a.j.unregister=function(b){delete h[b]; a.j.Bc(b)};a.j.Fc={getConfig:function(b,c){c(a.j.tb(b)?h[b]:null)},loadComponent:function(a,c,d){var e=g(a);f(e,c,function(c){b(a,e,c,d)})},loadTemplate:function(b,c,f){b=g(b);if("string"===typeof c)f(a.a.ua(c));else if(c instanceof Array)f(c);else if(e(c))f(a.a.la(c.childNodes));else if(c.element)if(c=c.element,A.HTMLElement?c instanceof HTMLElement:c&&c.tagName&&1===c.nodeType)f(d(c));else if("string"===typeof c){var h=w.getElementById(c);h?f(d(h)):b("Cannot find element with ID "+c)}else b("Unknown element type: "+ c);else b("Unknown template value: "+c)},loadViewModel:function(a,b,d){c(g(a),b,d)}};var m="createViewModel";a.b("components.register",a.j.register);a.b("components.isRegistered",a.j.tb);a.b("components.unregister",a.j.unregister);a.b("components.defaultLoader",a.j.Fc);a.j.loaders.push(a.j.Fc);a.j.dd=h})();(function(){function b(b,e){var f=b.getAttribute("params");if(f){var f=c.parseBindingsString(f,e,b,{valueAccessors:!0,bindingParams:!0}),f=a.a.Ga(f,function(c){return a.o(c,null,{l:b})}),g=a.a.Ga(f, function(c){var e=c.v();return c.ja()?a.o({read:function(){return a.a.f(c())},write:a.Za(e)&&function(a){c()(a)},l:b}):e});Object.prototype.hasOwnProperty.call(g,"$raw")||(g.$raw=f);return g}return{$raw:{}}}a.j.getComponentNameForNode=function(b){var c=a.a.R(b);if(a.j.tb(c)&&(-1!=c.indexOf("-")||"[object HTMLUnknownElement]"==""+b||8>=a.a.W&&b.tagName===c))return c};a.j.tc=function(c,e,f,g){if(1===e.nodeType){var h=a.j.getComponentNameForNode(e);if(h){c=c||{};if(c.component)throw Error('Cannot use the "component" binding on a custom element matching a component'); var m={name:h,params:b(e,f)};c.component=g?function(){return m}:m}}return c};var c=new a.ga;9>a.a.W&&(a.j.register=function(a){return function(b){return a.apply(this,arguments)}}(a.j.register),w.createDocumentFragment=function(b){return function(){var c=b(),f=a.j.dd,g;for(g in f);return c}}(w.createDocumentFragment))})();(function(){function b(b,c,d){c=c.template;if(!c)throw Error("Component '"+b+"' has no template");b=a.a.Ca(c);a.h.va(d,b)}function c(a,b,c){var d=a.createViewModel;return d?d.call(a, b,c):b}var d=0;a.c.component={init:function(e,f,g,h,m){function k(){var a=l&&l.dispose;"function"===typeof a&&a.call(l);q&&q.s();p=l=q=null}var l,p,q,t=a.a.la(a.h.childNodes(e));a.h.Ea(e);a.a.K.za(e,k);a.o(function(){var g=a.a.f(f()),h,u;"string"===typeof g?h=g:(h=a.a.f(g.name),u=a.a.f(g.params));if(!h)throw Error("No component name specified");var n=a.i.Cb(e,m),z=p=++d;a.j.get(h,function(d){if(p===z){k();if(!d)throw Error("Unknown component '"+h+"'");b(h,d,e);var f=c(d,u,{element:e,templateNodes:t}); d=n.createChildContext(f,{extend:function(a){a.$component=f;a.$componentTemplateNodes=t}});f&&f.koDescendantsComplete&&(q=a.i.subscribe(e,a.i.pa,f.koDescendantsComplete,f));l=f;a.Oa(d,e)}})},null,{l:e});return{controlsDescendantBindings:!0}}};a.h.ea.component=!0})();var V={"class":"className","for":"htmlFor"};a.c.attr={update:function(b,c){var d=a.a.f(c())||{};a.a.P(d,function(c,d){d=a.a.f(d);var g=c.indexOf(":"),g="lookupNamespaceURI"in b&&0=a.a.W&&c in V?(c=V[c],h?b.removeAttribute(c):b[c]=d):h||(g?b.setAttributeNS(g,c,d):b.setAttribute(c,d));"name"===c&&a.a.Yc(b,h?"":d)})}};(function(){a.c.checked={after:["value","attr"],init:function(b,c,d){function e(){var e=b.checked,f=g();if(!a.S.Ya()&&(e||!m&&!a.S.qa())){var k=a.u.G(c);if(l){var q=p?k.v():k,z=t;t=f;z!==f?e&&(a.a.Na(q,f,!0),a.a.Na(q,z,!1)):a.a.Na(q,f,e);p&&a.Za(k)&&k(q)}else h&&(f===n?f=e:e||(f=n)),a.m.eb(k, d,"checked",f,!0)}}function f(){var d=a.a.f(c()),e=g();l?(b.checked=0<=a.a.A(d,e),t=e):b.checked=h&&e===n?!!d:g()===d}var g=a.xb(function(){if(d.has("checkedValue"))return a.a.f(d.get("checkedValue"));if(q)return d.has("value")?a.a.f(d.get("value")):b.value}),h="checkbox"==b.type,m="radio"==b.type;if(h||m){var k=c(),l=h&&a.a.f(k)instanceof Array,p=!(l&&k.push&&k.splice),q=m||l,t=l?g():n;m&&!b.name&&a.c.uniqueName.init(b,function(){return!0});a.o(e,null,{l:b});a.a.B(b,"click",e);a.o(f,null,{l:b}); k=n}}};a.m.wa.checked=!0;a.c.checkedValue={update:function(b,c){b.value=a.a.f(c())}}})();a.c["class"]={update:function(b,c){var d=a.a.Db(a.a.f(c()));a.a.Eb(b,b.__ko__cssValue,!1);b.__ko__cssValue=d;a.a.Eb(b,d,!0)}};a.c.css={update:function(b,c){var d=a.a.f(c());null!==d&&"object"==typeof d?a.a.P(d,function(c,d){d=a.a.f(d);a.a.Eb(b,c,d)}):a.c["class"].update(b,c)}};a.c.enable={update:function(b,c){var d=a.a.f(c());d&&b.disabled?b.removeAttribute("disabled"):d||b.disabled||(b.disabled=!0)}};a.c.disable= {update:function(b,c){a.c.enable.update(b,function(){return!a.a.f(c())})}};a.c.event={init:function(b,c,d,e,f){var g=c()||{};a.a.P(g,function(g){"string"==typeof g&&a.a.B(b,g,function(b){var k,l=c()[g];if(l){try{var p=a.a.la(arguments);e=f.$data;p.unshift(e);k=l.apply(e,p)}finally{!0!==k&&(b.preventDefault?b.preventDefault():b.returnValue=!1)}!1===d.get(g+"Bubble")&&(b.cancelBubble=!0,b.stopPropagation&&b.stopPropagation())}})})}};a.c.foreach={Rc:function(b){return function(){var c=b(),d=a.a.bc(c); if(!d||"number"==typeof d.length)return{foreach:c,templateEngine:a.ba.Ma};a.a.f(c);return{foreach:d.data,as:d.as,noChildContext:d.noChildContext,includeDestroyed:d.includeDestroyed,afterAdd:d.afterAdd,beforeRemove:d.beforeRemove,afterRender:d.afterRender,beforeMove:d.beforeMove,afterMove:d.afterMove,templateEngine:a.ba.Ma}}},init:function(b,c){return a.c.template.init(b,a.c.foreach.Rc(c))},update:function(b,c,d,e,f){return a.c.template.update(b,a.c.foreach.Rc(c),d,e,f)}};a.m.Ra.foreach=!1;a.h.ea.foreach= !0;a.c.hasfocus={init:function(b,c,d){function e(e){b.__ko_hasfocusUpdating=!0;var f=b.ownerDocument;if("activeElement"in f){var g;try{g=f.activeElement}catch(l){g=f.body}e=g===b}f=c();a.m.eb(f,d,"hasfocus",e,!0);b.__ko_hasfocusLastValue=e;b.__ko_hasfocusUpdating=!1}var f=e.bind(null,!0),g=e.bind(null,!1);a.a.B(b,"focus",f);a.a.B(b,"focusin",f);a.a.B(b,"blur",g);a.a.B(b,"focusout",g);b.__ko_hasfocusLastValue=!1},update:function(b,c){var d=!!a.a.f(c());b.__ko_hasfocusUpdating||b.__ko_hasfocusLastValue=== d||(d?b.focus():b.blur(),!d&&b.__ko_hasfocusLastValue&&b.ownerDocument.body.focus(),a.u.G(a.a.Fb,null,[b,d?"focusin":"focusout"]))}};a.m.wa.hasfocus=!0;a.c.hasFocus=a.c.hasfocus;a.m.wa.hasFocus="hasfocus";a.c.html={init:function(){return{controlsDescendantBindings:!0}},update:function(b,c){a.a.fc(b,c())}};(function(){function b(b,d,e){a.c[b]={init:function(b,c,h,m,k){var l,p,q={},t,x,n;if(d){m=h.get("as");var u=h.get("noChildContext");n=!(m&&u);q={as:m,noChildContext:u,exportDependencies:n}}x=(t= "render"==h.get("completeOn"))||h.has(a.i.pa);a.o(function(){var h=a.a.f(c()),m=!e!==!h,u=!p,r;if(n||m!==l){x&&(k=a.i.Cb(b,k));if(m){if(!d||n)q.dataDependency=a.S.o();r=d?k.createChildContext("function"==typeof h?h:c,q):a.S.qa()?k.extend(null,q):k}u&&a.S.qa()&&(p=a.a.Ca(a.h.childNodes(b),!0));m?(u||a.h.va(b,a.a.Ca(p)),a.Oa(r,b)):(a.h.Ea(b),t||a.i.ma(b,a.i.H));l=m}},null,{l:b});return{controlsDescendantBindings:!0}}};a.m.Ra[b]=!1;a.h.ea[b]=!0}b("if");b("ifnot",!1,!0);b("with",!0)})();a.c.let={init:function(b, c,d,e,f){c=f.extend(c);a.Oa(c,b);return{controlsDescendantBindings:!0}}};a.h.ea.let=!0;var Q={};a.c.options={init:function(b){if("select"!==a.a.R(b))throw Error("options binding applies only to SELECT elements");for(;0g)var m=a.a.g.Z(),k=a.a.g.Z(),l=function(b){var c=this.activeElement;(c=c&&a.a.g.get(c,k))&&c(b)},p=function(b,c){var d=b.ownerDocument;a.a.g.get(d,m)||(a.a.g.set(d,m,!0),a.a.B(d,"selectionchange",l));a.a.g.set(b,k,c)};a.c.textInput={init:function(b,c,k){function l(c,d){a.a.B(b,c,d)}function m(){var d=a.a.f(c());if(null===d||d===n)d="";L!==n&&d===L?a.a.setTimeout(m,4):b.value!==d&&(y=!0,b.value=d,y=!1,v=b.value)}function r(){w||(L=b.value,w=a.a.setTimeout(z, 4))}function z(){clearTimeout(w);L=w=n;var d=b.value;v!==d&&(v=d,a.m.eb(c(),k,"textInput",d))}var v=b.value,w,L,A=9==a.a.W?r:z,y=!1;g&&l("keypress",z);11>g&&l("propertychange",function(a){y||"value"!==a.propertyName||A(a)});8==g&&(l("keyup",z),l("keydown",z));p&&(p(b,A),l("dragend",r));(!g||9<=g)&&l("input",A);5>e&&"textarea"===a.a.R(b)?(l("keydown",r),l("paste",r),l("cut",r)):11>d?l("keydown",r):4>f?(l("DOMAutoComplete",z),l("dragdrop",z),l("drop",z)):h&&"number"===b.type&&l("keydown",r);l("change", z);l("blur",z);a.o(m,null,{l:b})}};a.m.wa.textInput=!0;a.c.textinput={preprocess:function(a,b,c){c("textInput",a)}}})();a.c.uniqueName={init:function(b,c){if(c()){var d="ko_unique_"+ ++a.c.uniqueName.rd;a.a.Yc(b,d)}}};a.c.uniqueName.rd=0;a.c.using={init:function(b,c,d,e,f){var g;d.has("as")&&(g={as:d.get("as"),noChildContext:d.get("noChildContext")});c=f.createChildContext(c,g);a.Oa(c,b);return{controlsDescendantBindings:!0}}};a.h.ea.using=!0;a.c.value={init:function(b,c,d){var e=a.a.R(b),f="input"== e;if(!f||"checkbox"!=b.type&&"radio"!=b.type){var g=[],h=d.get("valueUpdate"),m=!1,k=null;h&&("string"==typeof h?g=[h]:g=a.a.wc(h),a.a.Pa(g,"change"));var l=function(){k=null;m=!1;var e=c(),f=a.w.M(b);a.m.eb(e,d,"value",f)};!a.a.W||!f||"text"!=b.type||"off"==b.autocomplete||b.form&&"off"==b.form.autocomplete||-1!=a.a.A(g,"propertychange")||(a.a.B(b,"propertychange",function(){m=!0}),a.a.B(b,"focus",function(){m=!1}),a.a.B(b,"blur",function(){m&&l()}));a.a.D(g,function(c){var d=l;a.a.Ud(c,"after")&& (d=function(){k=a.w.M(b);a.a.setTimeout(l,0)},c=c.substring(5));a.a.B(b,c,d)});var p;p=f&&"file"==b.type?function(){var d=a.a.f(c());null===d||d===n||""===d?b.value="":a.u.G(l)}:function(){var f=a.a.f(c()),g=a.w.M(b);if(null!==k&&f===k)a.a.setTimeout(p,0);else if(f!==g||g===n)"select"===e?(g=d.get("valueAllowUnset"),a.w.cb(b,f,g),g||f===a.w.M(b)||a.u.G(l)):a.w.cb(b,f)};if("select"===e){var q;a.i.subscribe(b,a.i.H,function(){q?d.get("valueAllowUnset")?p():l():(a.a.B(b,"change",l),q=a.o(p,null,{l:b}))}, null,{notifyImmediately:!0})}else a.a.B(b,"change",l),a.o(p,null,{l:b})}else a.ib(b,{checkedValue:c})},update:function(){}};a.m.wa.value=!0;a.c.visible={update:function(b,c){var d=a.a.f(c()),e="none"!=b.style.display;d&&!e?b.style.display="":!d&&e&&(b.style.display="none")}};a.c.hidden={update:function(b,c){a.c.visible.update(b,function(){return!a.a.f(c())})}};(function(b){a.c[b]={init:function(c,d,e,f,g){return a.c.event.init.call(this,c,function(){var a={};a[b]=d();return a},e,f,g)}}})("click"); a.ca=function(){};a.ca.prototype.renderTemplateSource=function(){throw Error("Override renderTemplateSource");};a.ca.prototype.createJavaScriptEvaluatorBlock=function(){throw Error("Override createJavaScriptEvaluatorBlock");};a.ca.prototype.makeTemplateSource=function(b,c){if("string"==typeof b){c=c||w;var d=c.getElementById(b);if(!d)throw Error("Cannot find template with ID "+b);return new a.C.F(d)}if(1==b.nodeType||8==b.nodeType)return new a.C.ia(b);throw Error("Unknown template type: "+b);};a.ca.prototype.renderTemplate= function(a,c,d,e){a=this.makeTemplateSource(a,e);return this.renderTemplateSource(a,c,d,e)};a.ca.prototype.isTemplateRewritten=function(a,c){return!1===this.allowTemplateRewriting?!0:this.makeTemplateSource(a,c).data("isRewritten")};a.ca.prototype.rewriteTemplate=function(a,c,d){a=this.makeTemplateSource(a,d);c=c(a.text());a.text(c);a.data("isRewritten",!0)};a.b("templateEngine",a.ca);a.kc=function(){function b(b,c,d,h){b=a.m.ac(b);for(var m=a.m.Ra,k=0;k]*))?)*\s+)data-bind\s*=\s*(["'])([\s\S]*?)\3/gi, d=/\x3c!--\s*ko\b\s*([\s\S]*?)\s*--\x3e/g;return{xd:function(b,c,d){c.isTemplateRewritten(b,d)||c.rewriteTemplate(b,function(b){return a.kc.Ld(b,c)},d)},Ld:function(a,f){return a.replace(c,function(a,c,d,e,l){return b(l,c,d,f)}).replace(d,function(a,c){return b(c,"\x3c!-- ko --\x3e","#comment",f)})},md:function(b,c){return a.aa.Xb(function(d,h){var m=d.nextSibling;m&&m.nodeName.toLowerCase()===c&&a.ib(m,b,h)})}}}();a.b("__tr_ambtns",a.kc.md);(function(){a.C={};a.C.F=function(b){if(this.F=b){var c= a.a.R(b);this.ab="script"===c?1:"textarea"===c?2:"template"==c&&b.content&&11===b.content.nodeType?3:4}};a.C.F.prototype.text=function(){var b=1===this.ab?"text":2===this.ab?"value":"innerHTML";if(0==arguments.length)return this.F[b];var c=arguments[0];"innerHTML"===b?a.a.fc(this.F,c):this.F[b]=c};var b=a.a.g.Z()+"_";a.C.F.prototype.data=function(c){if(1===arguments.length)return a.a.g.get(this.F,b+c);a.a.g.set(this.F,b+c,arguments[1])};var c=a.a.g.Z();a.C.F.prototype.nodes=function(){var b=this.F; if(0==arguments.length){var e=a.a.g.get(b,c)||{},f=e.lb||(3===this.ab?b.content:4===this.ab?b:n);if(!f||e.jd){var g=this.text();g&&g!==e.bb&&(f=a.a.Md(g,b.ownerDocument),a.a.g.set(b,c,{lb:f,bb:g,jd:!0}))}return f}e=arguments[0];this.ab!==n&&this.text("");a.a.g.set(b,c,{lb:e})};a.C.ia=function(a){this.F=a};a.C.ia.prototype=new a.C.F;a.C.ia.prototype.constructor=a.C.ia;a.C.ia.prototype.text=function(){if(0==arguments.length){var b=a.a.g.get(this.F,c)||{};b.bb===n&&b.lb&&(b.bb=b.lb.innerHTML);return b.bb}a.a.g.set(this.F, c,{bb:arguments[0]})};a.b("templateSources",a.C);a.b("templateSources.domElement",a.C.F);a.b("templateSources.anonymousTemplate",a.C.ia)})();(function(){function b(b,c,d){var e;for(c=a.h.nextSibling(c);b&&(e=b)!==c;)b=a.h.nextSibling(e),d(e,b)}function c(c,d){if(c.length){var e=c[0],f=c[c.length-1],g=e.parentNode,h=a.ga.instance,m=h.preprocessNode;if(m){b(e,f,function(a,b){var c=a.previousSibling,d=m.call(h,a);d&&(a===e&&(e=d[0]||b),a===f&&(f=d[d.length-1]||c))});c.length=0;if(!e)return;e===f?c.push(e): (c.push(e,f),a.a.Ua(c,g))}b(e,f,function(b){1!==b.nodeType&&8!==b.nodeType||a.vc(d,b)});b(e,f,function(b){1!==b.nodeType&&8!==b.nodeType||a.aa.cd(b,[d])});a.a.Ua(c,g)}}function d(a){return a.nodeType?a:0a.a.W?0:b.nodes)?b.nodes():null)return a.a.la(c.cloneNode(!0).childNodes);b=b.text();return a.a.ua(b,e)};a.ba.Ma=new a.ba;a.gc(a.ba.Ma);a.b("nativeTemplateEngine",a.ba);(function(){a.$a=function(){var a=this.Hd=function(){if(!v||!v.tmpl)return 0;try{if(0<=v.tmpl.tag.tmpl.open.toString().indexOf("__"))return 2}catch(a){}return 1}(); this.renderTemplateSource=function(b,e,f,g){g=g||w;f=f||{};if(2>a)throw Error("Your version of jQuery.tmpl is too old. Please upgrade to jQuery.tmpl 1.0.0pre or later.");var h=b.data("precompiled");h||(h=b.text()||"",h=v.template(null,"{{ko_with $item.koBindingContext}}"+h+"{{/ko_with}}"),b.data("precompiled",h));b=[e.$data];e=v.extend({koBindingContext:e},f.templateOptions);e=v.tmpl(h,b,e);e.appendTo(g.createElement("div"));v.fragments={};return e};this.createJavaScriptEvaluatorBlock=function(a){return"{{ko_code ((function() { return "+ a+" })()) }}"};this.addTemplate=function(a,b){w.write(" script( src='/scripts/jquery.min.js', type="text/javascript" ) script( src='/scripts/TweenMax.min.js', type="text/javascript" ) script( src='/scripts/CanadaBackground.js', type="text/javascript" ) script( src='/scripts/jquery.cookie.js', type="text/javascript" ) script( src='/scripts/semantic.min.js', type="text/javascript" ) script( src='/scripts/knockout.js', type="text/javascript" ) script( src='/scripts/knockout.animate.js', type="text/javascript" ) script( src='/scripts/Cleave.js', type="text/javascript" ) script( src='/scripts/socket.io.js', type="text/javascript" ) script( src='/scripts/siteShare.js', type="text/javascript" ) script( src='/scripts/connectInformationMessage.js', type="text/javascript" ) script( src='/scripts/CoSearch.js', type="text/javascript" ) block ScriptBlock ================================================ FILE: app/views/Shared/appHtml.pug ================================================ #CoSearch .backGroundSetup( data-bind = " style: { background: searchItem() ? 'white' : '#B4E4ED' }" style = "height: 100em; ") .main form#coSearchForm.ui.form( data-bind = " style: { 'margin-top': showSearchSetupForm() ? '15em' : '25em' }, event: { 'submit': search_form }, submitBubble: false" style = "100%;" ) .field .ui.search .ui.input.huge.icon( data-bind = "css : { animationSearchInput: hasFocus, 'error': showSearchError(), 'loading disabled': showInputLoading }" style = "width: 100%;border-radius: 500rem;" ) input( style = "color:rgba(0,0,0,0.5); border-radius: 500rem; width: 100%;" type = "text" data-bind = "attr: { placeholder: showSearchError() ? ( messageBoxDefine [ errorMessageIndex() ][ $root.languageIndex() ]): infoDefine[ $root.languageIndex() ].coSearch.searchInputPlaceholder }, css : { backgroundTransparent: ! backGroundBlue ()}, textInput: searchInputText, hasFocus: hasFocus") i.icon.link.circular( data-bind = " html: searchSetupIcon (), click: searchSetupClick " style = "box-shadow: 0 0 0 0.1em ; color: #42c8f4!important;" ) i.icon.image.outline.link.circular( data-bind = " click: function (){ document.getElementById('imageInput1').click() }, style: { 'margin-top' : hasFocus ? '2px' : '0px' }" style = "box-shadow: 0 0 0 0.1em; color: #42c8f4!important;") input( onchange = "_view.appsManager().appScript().imageSearch( this )" id = "imageInput1" type = "file" accept = 'image/gif,image/jpeg,image/jpg,image/png' style="opacity:0" ) i.icon.search.link.circular( style = "box-shadow: 0 0 0 0.1em; color: #4285f4!important;" data-bind = "click: search_form, css: { 'loadingGetResponse': loadingGetResponse, 'conetResponse': conetResponse } ") i.icon.language.circular.link( style="box-shadow: 0 0 0 0.1em;color: #7742b9!important;margin-right: 2.5em" ) i.icon.link.circular.red.close( data-bind = " click: searchInputCloseError ") .SetupForm( style = "margin: 5em;") //-h3.ui.header.shadowText1( data-bind = " text: infoDefine[ languageIndex() ].coSearch.coSearchConfigMenu[ 0 ]" style = " color: white;") .ui.link.cards .card.AppCardTop( data-bind = " click: function( self, event ) { searchSetup ('g', self, event )} " style = " background: #ffffff82;") .content .card.AppCardTop( data-bind = " click: function( self, event ) { searchSetup ('b', self, event )} " style = " background: #ffffff82;") .content .card.AppCardTop( data-bind = " click: function( self, event ) { searchSetup ('y', self, event )} " style = " background: #ffffff82;") .content .card.AppCardTop( data-bind = " click: function( self, event ) { searchSetup ('d', self, event)} " style = " background: #ffffff82;") .content .listItems( style = "margin:1em;" ) .ui.top.fixed.menu.borderless .item( style = "width: 90%;" ) form.ui.form( data-bind = "event: { 'submit': search_form }" style = "width: 100%;" ) .field .ui.search .ui.input.icon( data-bind = "css : { 'error': showSearchError(), 'loading disabled': showInputLoading }") input( style="color:rgba(0,0,0,0.5);border-radius: 500rem!important;" type="text" data-bind = " textInput: searchInputText, hasFocus: SearchInputNextHasFocus, attr: { placeholder: showSearchError() ? ( messageBoxDefine [ errorMessageIndex() ][ $root.languageIndex() ]): infoDefine[ $root.languageIndex() ].coSearch.searchInputPlaceholder }" ) i.icon.circular.search.link.icon( data-bind = "click: search_form" style="color: #4285f4!important;" ) i.icon.image.outline.link.circular( data-bind = " click: function (){ document.getElementById('imageInput1').click() } " style = "color: #4285f4!important;") .hideInput( style="position: absolute;") input( onchange = "_view.appsManager().appScript().imageSearch( this )" id = "imageInput1" type = "file" accept = 'image/gif,image/jpeg,image/jpg,image/png' style="opacity:0;width: 0px;height: 0px;" ) i.icon.link.circular.red.close( data-bind = " click: searchInputCloseError ") .field( style = "margin-left: 1em;" ) a.basic.ui.label.yellow.small( data-bind = " click: webItemsClick " style = "padding-right: 1em;" ) i.icon.rss span( data-bind = "text: info.searchToolBarMenu[0][ $root.languageIndex() ] ") a.basic.ui.label.small( style = "padding-right: 1em;" data-bind = " click: newsButtonClick , style: { cursor: newsButtonShowLoading() ? 'unset' : 'pointer' }, css: { 'disabled': newsButtonShowLoading(), 'olive': newsItemsArray() && !newsButtonShowLoading(), 'grey': !newsItemsArray() && !newsButtonShowError(), 'red': newsButtonShowError() }") i.icon.info.red span( data-bind = " text: messageBoxDefine[ newsButtonErrorIndex()][ $root.languageIndex() ] ") i.icon.newspaper.outline i.icon.notched.circle.loading( data-bind = " css: { 'loadingGetResponse': newsLoadingGetResponse, 'conetResponse': newsConetResponse }") span( data-bind = "text: info.searchToolBarMenu[1][ $root.languageIndex() ] " ) a.basic.ui.label.small( data-bind = "click: imageButtonClick, style: { cursor: imageButtonShowLoading() ? 'unset' : 'pointer' }, css: { teal: imageItemsArray() && !imageButtonShowLoading(), grey: !imageItemsArray() && !imageButtonShowError(), red: imageButtonShowError() }" style = "padding-right: 1em;" ) i.icon.info.red span( data-bind = " text: messageBoxDefine [ imageButtonErrorIndex()][ $root.languageIndex() ] ") i.icon.image.outline i.icon.notched.circle.loading( data-bind = " css: { 'loadingGetResponse': imageLoadingGetResponse, 'conetResponse': imageConetResponse }") span( data-bind = "text: info.searchToolBarMenu[2][ $root.languageIndex() ] " ) a.basic.ui.label.blue.small( data-bind = "click: videoButtonClick,style: { cursor: videoButtonShowLoading() ? 'unset' : 'pointer' }, css: { blue: videoItemsArray() && !videoButtonShowLoading(), grey: !videoItemsArray() && !videoButtonShowError(), red: videoButtonShowError() }" style = "padding-right: 1em;") i.icon.info.red span( data-bind = " text: messageBoxDefine [ videoButtonErrorIndex()] [ $root.languageIndex() ]") i.icon.video i.icon.notched.circle.loading span( data-bind = "text: info.searchToolBarMenu[3][ $root.languageIndex() ] " ) .field( style = "margin-left: 1em;" ) .ui.grey.header( data-bind = "text: infoDefine[ $root.languageIndex() ].coSearch.SearchesRelated[0] + searchInputTextShow() + infoDefine[ $root.languageIndex() ].coSearch.SearchesRelated[1]" style="margin-bottom: 1em;" ) .related.ui.grid( style = "padding-bottom: 1em;" ) a.five.wide.column( href = "#" data-bind = "text: text, click: function () { $parents[0].searchesRelatedSelect ( $parents[0], $index())}" style="padding-top: 0.2rem;padding-bottom: 0.2rem;") .items( data-bind=" style: { 'margin-top': showSearchesRelated() && !searchItem()['originImage'] ? '15.5em' : '7.5em', 'padding-top': showSearchesRelated() && !searchItem()['originImage'] ? '1em': '1em' }, click: function () { showSearchesRelated ( false ); return true;}" ) .AppList.CoContent.content .ui.items.searchItems .totalResults.ui.grey.header .sub.header span.totalResults1( data-bind = " text: info.totalResults[ $root.languageIndex() ]" ) span.totalResults2( data-bind = " text: searchItem().totalResults" style="margin: 0.5em;" ) span.totalResults3( data-bind = " text: info.totalResults1[ $root.languageIndex() ]" ) .imageResultInfo.item .image img( data-bind = " attr: { src: img }") .content .meta( data-bind = " text: infoDefine[ $root.languageIndex() ].coSearch.imageSize ") .description( data-bind = " text: size" style = "color: gray;" ) .meta .notSimilarImagesShowError i.icon.notched.circle.loading( data-bind = " css: { 'loadingGetResponse': $parents[0].imageLoadingGetResponse, 'conetResponse': $parents[0].imageConetResponse }") i.icon.file.image.outline.orange.link( data-bind = "click: function () { $parents[0].imageButtonClick ( $parents[0] )}") a.ui( data-bind = "style: { 'color': $parents[0].imageItemsArray() && $parents[0].imageItemsArray().Result ? '#f2711c': '#4183c4'}, text: infoDefine[ $root.languageIndex() ].coSearch.similarImages, click: function () { $parents[0].imageButtonClick( $parents[0] )}" ) span i.icon.info.circle.red.link( data-bind = "click: function () { $parents[0].imageButtonClick( $parents[0] )}" ) a.ui( data-bind = "text: messageBoxDefine [ $parents[0].imageButtonErrorIndex()][ $root.languageIndex() ], click: function () { $parents[0].imageButtonClick( $parents[0] )} " style = "color: #990000a8!important;") .space .space .item .image.ui.top.aligned( data-bind = "style: { height: imageInfo['videoTime'] ? '90px' : 'auto' }" style = " width:150px ") img( data-bind = "attr: { src: imageInfo.img }") .ui.bottom.right.attached.label.tiny( data-bind = "text: imageInfo['videoTime'] " style = " background-color: #3130307a!important;; color: rgba(255, 252, 252, 0.77)!important;;") .content .header a( data-bind = "text: title, attr: { href: url } " style="font-weight: normal;font-size: medium;" target = "_blank" ) .meta( style="margin:unset;") span i.icon.object.group.grey.link( data-bind = "click: function() { $parents[0].getSnapshotClick( $parents[0], $index ())}") i.icon.notched.circle.loading( data-bind = "css: { 'loadingGetResponse': loadingGetResponse, 'conetResponse': conetResponse }") i.icon.file.image.outline.olive.link( data-bind = "click: function() { $parents[0].showSnapshotClick( $parents[0], $index())}" ) i.icon.info.circle.red.link( data-bind = "attr: { id: id, 'data-content': messageBoxDefine [ errorIndex()] [ $root.languageIndex() ]}") span( data-bind="text: urlShow, style: { color: snapshotReady() ? 'orange' : ( showError() ? 'red' : 'green') } " style="margin-top: 0.5em; margin-bottom: 0.5em; font-size: small;" ) .description( style = " color: grey; ") p span a.ui.image.mini( data-bind = "click: function() { $parents[0].getSnapshotClick( $parents[0], $index ())}" href="#") img( data-bind="attr: { src: newsBrandImg }") //-i.icon.object.group.grey.link( data-bind = "click: function() { $parents[0].getSnapshotClick( $parents[0], $index ())}") i.icon.notched.circle.loading( data-bind = "css: { 'loadingGetResponse': loadingGetResponse, 'conetResponse': conetResponse }" ) i.icon.file.image.outline.olive.link( data-bind = "click: function() { $parents[0].showSnapshotClick( $parents[0], $index())}" ) i.icon.info.circle.red.link( data-bind = "attr: { id: id, 'data-content': messageBoxDefine [ errorIndex()] [ $root.languageIndex()]}") span( data-bind = " text: newsBrand " style = "font-weight: bolder; color: #906363db;" ) span( data-bind = "text: ' - ' + timeNumber + ' ' + infoDefine[ $root.languageIndex() ].coSearch.timeUnit[ timeUnit ]" style = "font-weight: bolder; color: #906363db;") span( data-bind = "text: ' - ' + infoDefine[ $root.languageIndex() ].coSearch.TimeTolocalTime ( time )" style = "font-weight: bolder; color: #906363db;") span( data-bind = "text: timeNumber + ' ' + infoDefine[ $root.languageIndex() ].coSearch.timeUnit[ timeUnit ] + ' - '" style = "font-weight: bolder; color: #906363db;") span( data-bind = "text: infoDefine[ $root.languageIndex() ].coSearch.TimeTolocalTime ( time ) + ' - '" style = "font-weight: bolder; color: #906363db;") span( data-bind = "text: description" style = "color: grey") .space .space button.ui.large.button( data-bind = "css: { 'loading buttonUnActive': moreResultsButtomLoading, negative: nextButtonShowError, 'loadingGetResponse': nextButtonLoadingGetResponse, 'conetResponse': nextButtonConetResponse },text: info.moreResults[ $root.languageIndex() ], click: searchNext" style="margin-top: 1em;margin-bottom: 2em;" ) button.ui.large.button.negative( data-bind = "text: messageBoxDefine [ nextButtonErrorIndex()][ $root.languageIndex() ], click: nextButtonErrorClick " style="background-color: #b94835e3;margin-top: 1em;margin-bottom: 2em;") .space .space #subPage( data-bind = " with: showWebPage ") .ui.top.fixed.menu.borderless .item( style = "width: 90%;" ) form.ui.form( style = "width: 100%;" data-bind = "css: { 'error': showErrorMessage }" ) .field( style = "width: 100%;" ) .ui.left.icon.input( data-bind = "css : { 'loading': showLoading }" style = "width: 100%;" ) i.icon.close.link.circular( data-bind = "click: close " style="color: #4285f4!important;") input( style = "color: rgba ( 0,0,0,0.5 );" readonly data-bind = "value: showUrl" ) i.icon.link.image.circular( data-bind = " click: imgClick " style="left: auto; right: .5em; color:#947b66!important;" ) i.icon.link.code.circular( data-bind = " click: htmlClick " style="left: auto; right: .5em; color:#346b0b!important;" ) .field p( data-bind = " text: messageBoxDefine ['LoadingPage'][$root.languageIndex()]" style = "color: grey;") .field .loaderCoNET( style = " margin-top: 3em;") .loaderCoNET-div .loaderCoNET-div .loaderCoNET-div .loaderCoNET-div .ui.error.message span i.icon.exclamation.triangle.red.link span( data-bind=" text: messageBoxDefine ['pageLoadingError'][$root.languageIndex()]") iframe( data-bind = " attr: { src: htmlIframe() } " style = "border: none;width: 100%; height: -webkit-fill-available;margin-top: 7em;" sandbox = "allow-forms" ) img( data-bind = " attr: { src: png }" style = "border: none;margin: 7em 1em 1em 1em;") .closeButton( style = "z-index: 999;top: 1.3em; left: 1em; position: fixed; width: 2em;" ) i.icon.left.chevron.link.circular.teal( data-bind = "click: closeSimilarImagesResult " ) .ui.six.doubling.cards( data-bind = " foreach: searchSimilarImagesList " style="margin: 2em; margin-top: 3em;") .card a.ui.right.corner.label( data-bind = "click: function() { return $parents[0].imagesResultClick( $parents[0], $index (), 'img')}, class: showImageError() ? 'red' : ( snapshotImageReady() ? 'teal': 'grey')" ) i.icon.object.group.link i.icon.notched.circle.loading( data-bind = "css: { 'loadingGetResponse': loadingImageGetResponse, 'conetResponse': conetImageResponse }") i.icon.info.circle.link( data-bind = "attr: { id: id + '-1', 'data-content': messageBoxDefine [ imageErrorIndex()] [ $root.languageIndex() ] }") a.ui.image( data-bind = "attr: { 'href': imgUrlHref }" target = "_blank" ) //-( data-bind = "click: function() { return $parents[0].imagesResultClick( $parents[0], $index (), 'image')}") img( data-bind = "attr: { src: imgSrc }") .content .meta span.data( data-bind = "text: infoDefine[ $root.languageIndex() ].coSearch.imageSize" ) span.data( data-bind = "text: size" ) .description( data-bind = "text: description " ) .extra.content span i.icon.object.group.link( data-bind = "class: snapshotReady() ? 'olive': 'grey', click: function() { return $parents[0].imagesResultClick( $parents[0], $index (), 'link')}") i.icon.notched.circle.loading( data-bind = "css: { 'loadingGetResponse': loadingGetResponse, 'conetResponse': conetResponse }") i.icon.info.circle.red.link( data-bind = "attr: { id: id, 'data-content': messageBoxDefine [ errorIndex()] [ $root.languageIndex() ]}") a( data-bind = "text: webUrl, attr: { 'href': webUrlHref }" target = "_blank" ) ================================================ FILE: app/views/Shared/header.pug ================================================ head title CoNET Platform meta(charset = 'utf-8' ) meta(name = "viewport" content = "width=device-width, initial-scale=1, maximum-scale = 1, user-scalable = no") meta(name="author" content="CoNET Technology Inc.|CoNET技術株式会社|CoNET技術有限公司") meta(name="msapplication-TileColor" content="#ffffff") meta(name="msapplication-TileImage" content="/images/128x128.png") meta(name="theme-color" content="#ffffff") link(rel="apple-touch-icon" sizes="16x16" href="/images/16x16.png") link(rel="apple-touch-icon" sizes="32x32" href="/images/32x32.png") link(rel="apple-touch-icon" sizes="24x24" href="/images/24x24.png") link(rel="apple-touch-icon" sizes="64x64" href="/images/64x64.png") link(rel="apple-touch-icon" sizes="96x96" href="/images/96x96.png") link(rel="apple-touch-icon" sizes="128x128" href="/images/128x128.png") link(rel="apple-touch-icon" sizes="256x256" href="/images/256x256.png") link(rel="apple-touch-icon" sizes="512x512" href="/images/512x512.png") link(rel="icon" type="image/png" sizes="32x32" href="/images/32x32.png") link(rel="icon" type="image/png" sizes="96x96" href="/images/96x96.png") link(rel="icon" type="image/png" sizes="16x16" href="/images/16x16.png") link(rel = "stylesheet", href = "/css/semantic.min.css") link(rel = "stylesheet", href = "/css/animate.min.css") link(rel = "stylesheet", href = "/css/page.css") ================================================ FILE: app/views/Shared/mainMenu.pug ================================================ #mainMenu_temp( data-bind = "with: mainScript " style = "margin-top: 2em;") .ui.divider .ui.header .content span.shadowText1( data-bind = " text: infoDefine[ $root.languageIndex() ].appsManager.nodeName" style="color: white;" ) span.shadowText1( data-bind = " text: nodeName [ $root.languageIndex() ]" style="color: white;" ) .sub.header( style = "margin-top: 0.5em;") span( data-bind = " text: infoDefine[ $root.languageIndex() ].appsManager.connectAddress " ) span( data-bind = " text: nodeAddress " ) .ui.header .content h2.shadowText1( data-bind = " text: infoDefine[ $root.languageIndex() ].appsManager.serviceList" style="color: white;" ) .ui.divider span.shadowText1( data-bind =" click: function() { $parents[0].updateAppsManu( $parents[0] ) }") i.shadowText1.icon.link.exclamation.triangle.red a( data-bind = "text: messageBoxDefine [ $parents[0].appLoadingErrorIndex() ][ $root.languageIndex() ]" style = "color:red;" href="#") .ui.items.divided( data-bind = " foreach: _mainMenuItem " ) .item a.ui.small.image( data-bind = "css: { 'active dimmer': loading() }, click: function() { $parents[1].appClick ( $index()) } " ) img( data-bind = " attr: { src: imgSrc }" ) .ui.loader( data-bind = "css: { 'loadingGetResponse': loadingGetResponse, 'conetResponse': conetResponse }" ) .content a.header.shadowText1( data-bind = "text: headerText[ $root.languageIndex()], click: function() { $parents[1].appClick ( $index()) }" style="color: white;" ) .meta span( data-bind = " text: meta[ $root.languageIndex() ]" ) .description p( data-bind = " text: description[ $root.languageIndex() ]" style="color: white;") .extra( data-bind = " html: extra [ $root.languageIndex() ]" style="color: white;") ================================================ FILE: app/views/home/Wrt.pug ================================================ extends ../shared/coreLayout.pug block jumbotron1 section.CoContent.content .ui.green.segment.CoGateCards( style="max-width: 50em;") img.ui.centered.medium.image.huge( src="/images/wrt.png") h3.red( data-bind="text: infoDefine[ $root.languageIndex() ].useInfoMacOS.wrtTestAreaTitle" style="position: absolute;top: 11em;margin-left: 10em;") p( style="position: absolute;top: 18em;margin-left: 2em;") span #{ localIP } span( data-bind="text: infoDefine[ $root.languageIndex() ].useInfoMacOS.localIpAddress" style="padding-left: 1em; color: cadetblue;") p( style="position: absolute;top: 19em;margin-left: 2em;padding-top: 0.5em;padding-bottom: 0.5em; color: crimson;") span #{ globalIP } span( data-bind = "text: infoDefine[ $root.languageIndex() ].useInfoMacOS.globalIpAddress" style="padding-left: 1em; color: red;") h3( data-bind="text: infoDefine[ $root.languageIndex() ].useInfoMacOS.wrtTest") iframe.ui.centered.medium.image.huge( src="https://ip.voidsec.com/" style="width: 100%;height: 40em;border: 0px;") ================================================ FILE: app/views/home/coSearchImage.html ================================================ CoSearch ================================================ FILE: app/views/home/customProxy.pug ================================================ extends ../shared/coreLayout.pug block jumbotron1 section ================================================ FILE: app/views/home/index.pug ================================================ extends ../shared/coreLayout.pug block jumbotron include ../shared/CoNETConnectInfo block jumbotron1 .language( style="z-index: 999;top: 1.3em;right: 1em;position: fixed;width: 2em;") .ui.text.shape.languageText( data-bind = " click: selectItem " ) .sides span.ui.header.side.en.languageItem.languageTextCoverColor i.flag.united.kingdom.large //-span.languageItemSpan( data-bind = " text: menu[ 'en' ][0].showName " ) span.ui.header.side.tw.languageItem.languageTextCoverColor i.flag.taiwan.large //-span.languageItemSpan( data-bind = " text: menu[ 'tw' ][0].showName " ) span.ui.header.side.zh.languageItem.languageTextCoverColor i.flag.china.large //-span.languageItemSpan( data-bind = " text: menu[ 'zh' ][0].showName " ) span.ui.header.side.ja.languageItem.languageTextCoverColor i.flag.japan.large //-span.languageItemSpan( data-bind = " text: menu[ 'ja' ][0].showName " ) section#welcome.content .welcome-bg .welcome( style="color: white;") h1( data-bind = " text: infoDefine [ languageIndex() ].cover.firstTitle1, animate:{ animation: ['slideInUp','slideOutUp'], state: languageIndex() + 1, delay: 0 }" ) h1( style="padding-right:1em;padding-left:1em;" data-bind = " text: infoDefine [ languageIndex() ].cover.firstTitle2, animate: { animation: ['slideInUp','slideOutUp'], state: languageIndex() + 1, delay: 70 }") //-.ui.primary.basic.big.button( data-bind="click: openClick, text: infoDefine [ languageIndex() ].cover.start" style="margin-top: 2em;" ) .button(style="position: relative;width: 4em;height: 4em;") a.play-btn(data-bind="click: openClick" href="#") .startupView( style="width:100%; height:100%") video.videoBackground( preload="yes" playsinline autoplay muted loop ) source( src="/images/startup_background.mp4" type="video/mp4") section#CanadaBackground( style = "position: absolute;width: 100%;") include coSearchImage.html section#agreement.content .content.firstNodeContent .ui.header( data-bind = " text: infoDefine[ languageIndex() ].firstNote.title " style = " margin-left: 30px; margin-right: 100px;") .ui.divider .detailSegment .ui.attached.segment span( data-bind = " html: infoDefine[ languageIndex() ].firstNote.firstPart " style = "font-weight: bold;") .detailSegment( data-bind = " foreach: infoDefine[ languageIndex() ].firstNote.detail ") .ui.top.attached.header( data-bind = " visible: header && header.length " ) h4( data-bind = " text: header ") .ui.attached.segment span( data-bind = " html: detail ") .agreementButtom .ui.buttons.nextButtom buttom.ui.button( data-bind = " text: infoDefine[ languageIndex() ].firstNote.disagree, click: function () { sectionAgreement(false); return sectionWelcome(true)} ") .or buttom.ui.positive.button( data-bind = " text: infoDefine[ languageIndex() ].home_index_view.agree, click: agreeClick ") section#iconBar( style = " position: absolute;top: 1.2em;z-index: 999;" ) .content( style="position: relative;") span i.icon.cogs.inverted.large.iconButton( style = "margin-left: 1em;" data-bind = "click: showKeyInfoClick ") i.icon.home.inverted.large.iconButton( style = "margin-left: 1em;margin-right: 1em;" data-bind = "click: homeClick ") a( href = "https://github.com/QTGate/QTGate-Desktop-Client" target="_blank") i.icon.setting.big.loading.red span( data-bind="text: infoDefine[ $root.languageIndex() ].linuxUpdate.step1 + newVersion ()" style="color: white;") section.CoContent.content .ui.cards.loginCards .card.centered.raised( style = " width: 100%;" ) .content .header i.icon.privacy.teal span( data-bind = "text: email " style=" color:#00b5ad!important;") a.activating.element.inline( href="#" data-bind = " attr: { 'data-content': verified ? infoDefine[ $root.languageIndex() ].Home_keyPairInfo_view.emailVerified : infoDefine[ $root.languageIndex() ].Home_keyPairInfo_view.emailNotVerifi }") i.huge.icons( style = " margin-left: 10px; font-size: 2em; margin-top: 5px;" ) i.icon.small.certificate( data-bind = " css: { grey: ! verified, orange: verified }") i.icon.tiny.warning( data-bind = " visible: ! verified " style = " color: white; margin-top: -4px;margin-left: -1px;") i.icon.tiny.checkmark( data-bind = " visible: verified " style = " color: white; margin-top: -4px;margin-left: -1px;") .ui.top.right.attached.label.background-clolr-white a( data-bind = "if: delete_btn_view() && !showConform (), click: function () { showConform ( true )}") i.trash.alternate.outline.icon.large.red .meta i.icon.user span( data-bind = " text: nikeName " ) .description p( data-bind = " text: infoDefine[ $root.languageIndex() ].Home_keyPairInfo_view.creatDate + createDate" ) p span( data-bind = " text: infoDefine[ $root.languageIndex() ].Home_keyPairInfo_view.keyID" ) span( data-bind="text: publicKeyID.substr ( 0, 4 )") span( data-bind="text: publicKeyID.substr ( 4, 4 )" style = "padding-left: 0.5em;" ) span( data-bind="text: publicKeyID.substr ( 8, 4 )" style = "padding-left: 0.5em;" ) span( data-bind="text: publicKeyID.substr ( 12, 4 )" style = "padding-left: 0.5em;" ) .extra.content( data-bind = "if: showDeleteKeyPairNoite(), visible: showDeleteKeyPairNoite()") p( data-bind = " text : infoDefine[ $root.languageIndex() ].Home_keyPairInfo_view.deleteKeyPairHaveLogin " style="color: brown;") .extra.content( data-bind = "if: showConform() && delete_btn_view(), visible: showConform() && delete_btn_view()") p( data-bind = " text : infoDefine[ $root.languageIndex() ].Home_keyPairInfo_view.deleteKeyPairInfo " style="color: brown;") .ui.buttons .ui.button( data-bind = " text: infoDefine[ $root.languageIndex() ].home_index_view.cancel, click: function () { return showConform ( false );}") .or .ui.negative.button( data-bind = " text: infoDefine[ $root.languageIndex() ].Home_keyPairInfo_view.delete, click: deleteKeyPairNext ") .extra.content( data-bind = "visible: !$parents[0].showConform()" ) form.ui.form( data-bind=" submit: keyPair_checkPemPasswordClick") .field.required( data-bind = " css: { error: showPasswordErrorMessage(), disabled: passwordChecking()}") p( data-bind = " text: infoDefine [ $root.languageIndex() ].Home_keyPairInfo_view.locked") .ui.input.huge( data-bind=" css: { action: systemSetup_systemPassword().length > 4 && ! passwordChecking(), 'left loading': passwordChecking()}" ) i.search.icon.right( data-bind = " visible: passwordChecking()" style = " margin: 0 0 0 0!important; width: auto!important; height:auto!important;" ) input( data-bind = "attr: { placeholder: infoDefine[ $root.languageIndex() ].Home_keyPairInfo_view.password1, 'data-content': showPasswordErrorMessage () ? infoDefine[ $root.languageIndex() ].error_message.SystemPasswordError : null }, css: { 'activating element inline': showPasswordErrorMessage() }, textInput: systemSetup_systemPassword, hasFocus: inputFocus", type="password" value="" tabindex = "0" data-variation="very wide") button.ui.icon.button.positive( data-bind = "visible: systemSetup_systemPassword().length > 4 && ! passwordChecking ()" type="submit" ) i.icon.angle.right //- if: $root.showKeyPair //- with: keyPair //- if: keyPair .card.centered.raised( data-bind = "if: showKeyPairForm, visible: showKeyPairForm" style = "width: 100%;padding: 2em;") .keyPairGenerateForm .ui.segment.teal( data-bind = "html: infoDefine [ $root.languageIndex() ].home_index_view.inputEmail" style = "color: rgba(200,150,30,0.9)") form.ui.form( data-bind="submit: form_AdministratorEmail_submit") .field.required( data-bind = "css: { error: EmailAddressError() }" ) .ui.input.focus.left.icon.huge i.icon.spy input( type = "email", z-index = "1", data-bind = "value : SystemAdministratorEmailAddress, attr: { placeholder: infoDefine [ $root.languageIndex() ].home_index_view.emailAddress, 'data-content' : EmailAddressError() ? infoDefine[ $root.languageIndex() ].error_message.EmailAddress[0] : null }, css: { 'activating element inline': EmailAddressError() }" ) .ui.info.message( data-bind = " visible: showInsideFireWallEmail()" ) i.icon.close( data-bind=" click: function () { showInsideFireWallEmail(false);}") span.errorInformationText( data-bind = " text: infoDefine [ $root.languageIndex() ].home_index_view.accountEmailInfo ") .field.required( data-bind = " css: { error: NickNameError ()}") .ui.input.focus.left.icon.huge i.icon.student input( type = "text", z-index = "2", data-bind = " value : SystemAdministratorNickName, attr: { 'data-content' : NickNameError() ? infoDefine[ $root.languageIndex() ].error_message.required : null , placeholder: infoDefine [ $root.languageIndex() ].home_index_view.SystemAdministratorNickName }, css: { 'activating element inline': NickNameError() }" ) .field.required( data-bind = " css: { error: passwordError ()}") .ui.input.focus.left.icon.huge i.icon.privacy input( type = "password" z-index = "3" data-bind = " value: systemSetup_systemPassword, attr: { placeholder: infoDefine[ $root.languageIndex() ].Home_keyPairInfo_view.password, 'data-content' : passwordError() ? infoDefine[ $root.languageIndex() ].error_message.PasswordLengthError : null }, css: { 'activating element inline': passwordError() }" ) button.ui.green.basic.large.button( type = "submit" data-bind = " text: infoDefine [ $root.languageIndex() ].home_index_view.creatKeyPair, click: form_AdministratorEmail_submit ") .card.centered.raised( data-bind = "if: showKeyPairPorcess, visible: showKeyPairPorcess" style = "width: 100%;padding: 2em;") .detail p( data-bind = " html: infoDefine [ $root.languageIndex() ].home_index_view.GenerateKeypair ") .keyPairProcessBar.ui.bottom.teal.attached.progress( style="margin-bottom: 1em;" data-value="1" data-total="100") .bar .card.centered.raised( data-bind = "if: keyPairGenerateFormMessage, visible: keyPairGenerateFormMessage " style = "width: 100%;padding: 2em;") .detail p( data-bind="visible: message_cancel(), text: infoDefine [ $root.languageIndex() ].home_index_view.keyPairCancel ") p( data-bind="visible: message_keyPairGenerateError, text: infoDefine [ $root.languageIndex() ].home_index_view.keyPairGenerateError ") p( data-bind = "visible: message_keyPairGenerateSuccess, text: infoDefine [ $root.languageIndex() ].home_index_view.keyPairGenerateSuccess ") button.ui.negative.basic.button( data-bind= " click: CloseKeyPairGenerateFormMessage, text: infoDefine [ $root.languageIndex() ].error_message.Success") //- if: keyPairGenerateForm //- with: keyPairGenerateForm .card.centered.raised( style = " width: 100%;" ) .content.imapSetupForm( data-bind = "if: showForm ") .ui.segment.teal p( data-bind = "html: infoDefine [ $root.languageIndex() ].imapInformation.infomation ") p( data-bind = "html: infoDefine[ $root.languageIndex() ].imapInformation.tempImapAccount") form.ui.form.fluid .two.fields .field.required( data-bind = " css: { error: emailAddressShowError ()}") .ui.left.icon.input.huge i.icon.outline.mail input( data-bind = " value : emailAddress, css:{ 'activating element inline': emailAddressShowError() }, attr: { tabindex: 1, placeholder: infoDefine [ $root.languageIndex() ].home_index_view.imapEmailAddress, 'data-content' : emailAddressShowError() ? infoDefine[ $root.languageIndex() ].error_message.EmailAddress[ EmailAddressErrorType() ]: null }" type = "text") .field.required .passwdInput.ui.input.huge( data-bind = " css: { 'left icon': !password() || !password().length, 'action': password() && password().length }") i.icon.privacy( data-bind = " visible: !password() || !password().length ") input( data-bind = " textInput: password, attr: { placeholder: infoDefine [ $root.languageIndex() ].imapInformation.emailServerPassword, tabindex: 2 }" type = "password" ) button.ui.icon.button.positive( data-bind = " visible: password() && password().length, click: imapAccountGoCheckClick" ) i.icon.angle.right //- if: showForm .card.centered.raised( style = " width: 100%;" ) .content.checkImapData .ui.segment( data-bind = "css: { yellow: checkProcessing() < -1, red: checkImapError() > -1 }") p( data-bind = " visible: checkImapError() > -1, text: infoDefine [ $root.languageIndex() ].imapInformation.imapCheckError[checkImapError()]") p( data-bind = "visible: checkImapStep() > -1 && checkImapError() === -1, text: infoDefine [ $root.languageIndex() ].imapInformation.imapCheckingStep[checkImapStep()]") Button.ui.icon.button.orange( data-bind = " visible: checkImapError() > -1, click: returnImapSetup, text: infoDefine [ $root.languageIndex() ].imapInformation.title " ) .loaderCoNET( style = "position: relative;") .loaderCoNET-div .loaderCoNET-div .loaderCoNET-div .loaderCoNET-div //- if: showCheckProcess //- if: imapSetup //- with: imapSetup .card.centered.raised( style = " width: 100%;" ) .content .header i.icon.exchange.blue span( data-bind = "text: email " style=" color:#2185d0!important;") .ui.segment .woringText( data-bind = "html: infoDefine [ $root.languageIndex() ].imapInformation.imapAccountConform ( email, account ) " style="padding-bottom: 1em;") .ui.buttons a.ui.button( data-bind = " text: infoDefine[ $root.languageIndex() ].home_index_view.cancel" href="/") .or .ui.negative.button( data-bind = " text: infoDefine[ $root.languageIndex() ].imapInformation.agree, click: imapConform ") .loaderCoNET( style = "position: relative;") .loaderCoNET-div .loaderCoNET-div .loaderCoNET-div .loaderCoNET-div .ui.segment( style = "min-height: 10em;") .infoText( data-bind = "style: { 'color': err() === null ? 'grey' : ( !err() ? 'green' : 'red') }, css: { 'terminalText': ($index() === $parent.infoTextArray().length - 1) && !$parent.showTryAgain() }, text: messageBoxDefine[ text() ] [ $root.languageIndex() ] " style = "color: grey;") .ui.teal.center.aligned.segment( data-bind = " click: sendConnectMail " style = "cursor: pointer;") .text( data-bind = " text: infoDefine[ $root.languageIndex() ].linuxUpdate.tryAgain ") .ui.red.center.aligned.segment( data-bind = " click: tryAgain" style = "cursor: pointer;") .text( data-bind = " text: infoDefine[ $root.languageIndex() ].linuxUpdate.tryAgain ") //- if: showConnectCoNETProcess .card.centered.raised( style = " width: 100%;") .content .ui.segments .ui.segment( data-bind = "css: { yellow: signError() === -1, red: signError() > -1 }" ) span( data-bind = " text: infoDefine [ $root.languageIndex() ].emailConform.info1_1 " style="color:rgba(0,0,0,.5);") b( data-bind = " text: $parents[0].account" style="color:rgba(0,80,80,.8);") span( data-bind = " text: infoDefine [ $root.languageIndex() ].emailConform.info1_2" style="color:rgba(0,0,0,.5);") .ui.segment.errorInformation p( data-bind = " text: infoDefine [ $root.languageIndex() ].error_message.CoNET_requestError[ requestError() ]" style = "color: brown;") .ui.segment .ui.grid.equal.width.right.aligned.container( style="margin-top: 0.1em; margin-bottom: 0.1em;") .row( style = "background-color: #D94235; padding-bottom: 0px;") .column.left.aligned img( src = "/images/512x512.png" style = "margin-left: 1em; height: 50px;") .column .ui.purple.button( style = "position: absolute; right: 2em; top: 0em;" data-bind="css:{ loading: activeing }, text: infoDefine [ $root.languageIndex() ].emailConform.conformButtom, click: checkActiveEmailSubmit, visible: conformButtom ()" ) .ui.inverted.button( data-bind = "css: { 'loading disabled': requestActivEmailrunning()}, visible: showSentActivEmail() < 0 && ! conformButtom(), click: requestActivEmail, text: infoDefine [ $root.languageIndex() ].emailConform.reSendRequest") span(data-bind="text: showSentActivEmail() > -1 ? infoDefine [ $root.languageIndex() ].emailConform.requestReturn[ showSentActivEmail() ]: '', visible: showSentActivEmail() > -1 && !conformButtom()" style="color: cornsilk;") i.icon.exclamation.triangle.circular.red.link( data-bind = "click: clearError " style = "background-color: white!important;") .row( style = "background-color: #D94235; padding-top: .5em;") h2( style = "color: white; margin-left: 2em; padding-top: 0px;" data-bind = "text: infoDefine [ $root.languageIndex() ].emailConform.emailTitle " ) .row( style = "background-color: #FAFAFA; font-weight: bold; padding-bottom: 0px" data-bind="visible: !activeing()") span( data-bind="text: infoDefine [ $root.languageIndex() ].emailConform.emailDetail1" style="margin-left: 20px;color:rgba(0,0,0,.5);") span( data-bind="text: $parents[0].account" style="color:rgba(0,0,0,.5); padding-left: 0.5em;") span( data-bind="text: infoDefine [ $root.languageIndex() ].emailConform.emailDetail1_1" style="color:rgba(0,0,0,.5);") p( data-bind = "text: infoDefine [ $root.languageIndex() ].emailConform.emailDetail2" style="text-align: left; margin-left: 20px; margin-right: 20px; color:rgba(0,0,0,.5);") .row( style = "background-color: #FAFAFA; padding-top: .2em; padding-bottom: 0.2em" data-bind="visible: !activeing()") .ui.form( style="margin: 20px;width: 100%;") .field( data-bind = " css: { error: signError() || conformTextError() }") textarea( data-position="right center" data-bind = " textInput: conformText, attr: { placeholder: infoDefine [ $root.languageIndex() ].emailConform.info2 }" ) a#SendToQTGateTextArea.floating.ui.red.circular.label( data-bind = " text: '!', visible: conformTextError(), attr: { 'data-content': conformTextError () ? messageBoxDefine [ conformTextErrorNumber() ][$root.languageIndex()] : null }, css: { 'activating element1': conformTextError() } ") .row( style = "background-color: #FAFAFA;padding-top: 0px;" data-bind="visible: !activeing()" ) .ui.two.column.grid .stretched.row( style ="padding-top: 0px;") .column.left.aligned(style = "padding-top: 0px;padding-bottom: 0.2em") span( data-bind=" text: infoDefine [ $root.languageIndex() ].emailConform.bottom1_1" style="margin-left: 20px;color:rgba(0,0,0,.5);" ) span( data-bind=" text: infoDefine [ $root.languageIndex() ].emailConform.bottom1_2" style="margin-left: 20px;color:rgba(0,0,0,.5);" ) .column.right.floated .ui.purple.button( style = "position: absolute; right: 2em; top: 0em;" data-bind="text: infoDefine [ $root.languageIndex() ].emailConform.conformButtom, click: checkActiveEmailSubmit, visible: conformButtom ()" ) .row( style = "background-color: #FAFAFA;padding-top: 0px;") //- with: CoNETConnect //- if: CoNETConnect //- AppList //-section.AppList.CoContent.content .CoGateCards( style="max-width: 60em;") h2.ui.header.AppListHeader( data-bind="text: infoDefine[ languageIndex() ].thirdParty.information" style="color: white;") .ui.link.cards .card.AppCardTop( data-bind = "click: function () { click( $root )}, visible: show") .content.cardContentHeader a.ui.orange.right.corner.label.comeSoon( data-bind = "visible: comeSoon, attr: { 'data-content': infoDefine[ $root.languageIndex() ].thirdParty.comesoon }") i.icon.warning.sign .header( data-bind = " text: infoDefine[ $root.languageIndex() ].thirdParty.app[ $index()], style: { color: titleColor }" style="font-size: 1em;") .blurring.dimmable.image .ui.dimmer .content p(data-bind="text: infoDefine[ $root.languageIndex() ].thirdParty.dimmer[$index()]") .ui.AppCardImageArea img.ui.centered.image.AppCardImage( data-bind = "attr: { src: image, style: css }") //-.content //-span.right.floated i.heart.red.like.icon( data-bind="css: { outline: !liked()}") span( data-bind = "text: likeCount()" style="color: #DB2828") //-span.floated i.comment.grey.icon.outline span( data-bind="text: commentCount") section.mainMenu.content.CoContent( style = " margin-top: 5em;") .CoGateCards( style="max-width: 60em;") .welcomeText.ui.header .content h1.shadowText1( data-bind = " text: infoDefine[ $root.languageIndex() ].thirdParty.information" style="color:white;" ) .sub.header( data-bind = " text: infoDefine[ $root.languageIndex() ].appsManager.welcomeTextSub" ) h4.ui.header( data-bind = " text: infoDefine[ $root.languageIndex() ].appsManager.mainLoading" ) .ui.active.inline.loader( data-bind = "css: { 'loadingGetResponse': loadingGetResponse, 'conetResponse': conetResponse }" ) a.ui.red.header( data-bind = "click: mainNemuError, text: messageBoxDefine [ loadingError() ][ $root.languageIndex()]" href="#" ) script#mainMenu( data-bind = "html: mainHtml" type="text/html" ) #mainMenuHtml( data-bind = " template: { name: 'mainMenu' }") include ../shared/mainMenu script#runningAppHtml( data-bind = "html: runningAppHtml" type="text/html" ) section#appHtml( data-bind = " template: { name: 'runningAppHtml' }") section#tempAppHtml( style = " height: 100em;" ) include ../shared/appHtml ================================================ FILE: app/views/shared/coreLayout.pug ================================================ doctype html html include header body#body( data-bind = " css: { 'bodyCoNETBlue': bodyBlue }") block jumbotron block jumbotron1 script. if ( typeof module === 'object') { window.module = module; module = undefined; } script( src='/scripts/jquery.min.js', type="text/javascript" ) script( src='/scripts/socket.io.js', type="text/javascript" ) script( src='/scripts/jcanvas.min.js', type="text/javascript" ) script( src='/scripts/snap.svg.min.js', type="text/javascript" ) script( src='/scripts/semantic.min.js', type="text/javascript" ) script( src='/scripts/jquery.cookie.js', type="text/javascript" ) script( src='/scripts/jszip.min.js', type="text/javascript" ) script( src='/scripts/jimp.min.js', type="text/javascript" ) script( src='/scripts/knockout.js', type="text/javascript" ) script( src='/scripts/knockout.animate.js', type="text/javascript" ) script( src='/scripts/Cleave.js', type="text/javascript" ) script( src='/scripts/openpgp.min.js', type="text/javascript" ) script( src='/scripts/siteShare.js', type="text/javascript" ) script( src='/scripts/connectInformationMessage.js', type="text/javascript" ) script( src='/scripts/keyPairGenerateForm.js', type="text/javascript" ) script( src='/scripts/keyPairPassword.js', type="text/javascript" ) script( src='/scripts/CoNETConnect.js', type="text/javascript" ) script( src='/scripts/imapForm.js', type="text/javascript" ) script( src='/scripts/appsManager.js', type="text/javascript" ) script( src='/scripts/appCosearch.js', type="text/javascript" ) script( src='/scripts/encryptoClass.js', type="text/javascript" ) script( src='/scripts/showHTMLComplete.js', type="text/javascript" ) script( src='/scripts/home.js', type="text/javascript" ) script( src='/scripts/TweenMax.min.js', type="text/javascript" ) block ScriptBlock ================================================ FILE: index.html ================================================ ================================================ FILE: index.js ================================================ "use strict"; /*! * Copyright 2018 CoNET Technology Inc. All Rights Reserved. * * 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. */ Object.defineProperty(exports, "__esModule", { value: true }); const DEBUG = false; const port = 3000; const path_1 = require("path"); const url_1 = require("url"); const { app, BrowserWindow, Tray, Menu, dialog, autoUpdater, desktopCapturer, shell } = require('electron'); // squirrel event handled and app will exit in 1000ms, so don't do anything else const version = app.getVersion(); let localServer1 = null; let tray = null; let doReady = false; const _doUpdate = (tag_name, _port) => { let url = null; if (process.platform === 'darwin') { url = `http://localhost:${_port}/update/mac?ver=${tag_name}`; } else if (process.platform === 'win32') { url = `http://localhost:${_port}/latest/${tag_name}/`; } else { console.log(`process.platform === linux`); return; } autoUpdater.on('update-availabe', () => { console.log('update available'); }); autoUpdater.on('error', err => { console.log('systemError autoUpdater.on error ' + err.message); }); autoUpdater.on('checking-for-update', () => { console.log(`checking-for-update [${url}]`); }); autoUpdater.on('update-not-available', () => { console.log('update-not-available'); }); autoUpdater.on('update-downloaded', e => { console.log("Install?"); autoUpdater.quitAndInstall(); }); autoUpdater.setFeedURL(url); autoUpdater.checkForUpdates(); }; const createLocalBrowser = () => { const localServer = new BrowserWindow({ show: true, webPreferences: { nodeIntegration: true } }); DEBUG ? localServer.webContents.openDevTools() : null; localServer.loadURL(`http://localhost:${port}`); }; const createWindow = () => { if (process.platform === 'win32') { return createLocalBrowser(); } shell.openExternal(`http://localhost:${port}`); }; const data11 = [ { tray: [ { label: '打开', click: createWindow }, { role: 'quit', label: '退出', accelerator: 'Command+Q' } ] }, { tray: [ { label: 'オープン', click: createWindow }, { role: 'quit', label: '退出', accelerator: 'Command+Q' } ] }, { tray: [ { label: 'open', click: createWindow }, { role: 'quit', accelerator: 'Command+Q' } ] }, { tray: [ { label: '打開', click: createWindow }, { role: 'quit', label: '退出', accelerator: 'Command+Q' } ] } ]; const getLocalLanguage = (lang) => { if (/^zh-TW|^zh-HK|^zh-SG/i.test(lang)) return 3; if (/^zh/i.test(lang)) return 0; if (/^ja/i.test(lang)) return 1; return 2; }; let localLanguage = getLocalLanguage(app.getLocale()); const isMacOS = process.platform === 'darwin'; const template = [{ submenu: [ { role: 'undo', visible: isMacOS }, { role: 'redo', visible: isMacOS }, { role: 'selectall', visible: isMacOS }, { role: 'copy', visible: isMacOS }, { role: 'paste', visible: isMacOS }, { role: 'quit', visible: isMacOS } ] }]; const appReady = () => { //const menu = Menu.buildFromTemplate( template ) //Menu.setApplicationMenu ( menu) if (!localServer1) { localServer1 = new BrowserWindow({ show: DEBUG, webPreferences: { nodeIntegration: true } }); localServer1._doUpdate = _doUpdate; DEBUG ? localServer1.webContents.openDevTools() : null; //localServer1.maximize () localServer1.loadURL(url_1.format({ pathname: path_1.join(__dirname, 'index.html'), protocol: 'file:', slashes: true })); setTimeout(() => { createWindow(); }, 2000); /* setTimeout (() => { const checkUpload = new BrowserWindow ({ show: DEBUG }) checkUpload.rendererSidePort = port DEBUG ? checkUpload.webContents.openDevTools() : null checkUpload.loadURL ( format ({ pathname: join ( __dirname, 'app/update.html'), protocol: 'file:', slashes: true })) }, 500 ) */ } else { createWindow(); } if (!tray) { tray = new Tray(path_1.join(__dirname, '16x16.png')); tray.on('click', () => { return createWindow(); }); const contextMenu = Menu.buildFromTemplate(data11[localLanguage].tray); tray.setContextMenu(contextMenu); } }; const initialize = () => { const gotTheLock = app.requestSingleInstanceLock(); if (!gotTheLock) { return app.quit(); } app.on('second-instance', (event, commandLine, workingDirectory) => { createWindow(); }); app.once('ready', () => { if (doReady) { return; } doReady = true; return appReady(); }); app.once('window-all-closed', () => { app.quit(); }); }; initialize(); ================================================ FILE: index.ts ================================================ /*! * Copyright 2018 CoNET Technology Inc. All Rights Reserved. * * 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. */ const DEBUG = false const port = 3000 import { join } from 'path' import { format } from 'url' const { app, BrowserWindow, Tray, Menu, dialog, autoUpdater, desktopCapturer, shell } = require ( 'electron' ) // squirrel event handled and app will exit in 1000ms, so don't do anything else const version = app.getVersion() let localServer1 = null let tray = null let doReady = false const _doUpdate = ( tag_name: string, _port ) => { let url = null if ( process.platform === 'darwin' ) { url = `http://localhost:${ _port }/update/mac?ver=${ tag_name }` } else if ( process.platform === 'win32' ) { url = `http://localhost:${ _port }/latest/${ tag_name }/` } else { console.log (`process.platform === linux`) return } autoUpdater.on ( 'update-availabe', () => { console.log ( 'update available' ) }) autoUpdater.on ( 'error', err => { console.log ( 'systemError autoUpdater.on error ' + err.message ) }) autoUpdater.on('checking-for-update', () => { console.log ( `checking-for-update [${ url }]` ) }) autoUpdater.on( 'update-not-available', () => { console.log ( 'update-not-available' ) }) autoUpdater.on( 'update-downloaded', e => { console.log ( "Install?" ) autoUpdater.quitAndInstall () }) autoUpdater.setFeedURL ( url ) autoUpdater.checkForUpdates () } const createLocalBrowser = () => { const localServer = new BrowserWindow ( { show: true, webPreferences: { nodeIntegration: true } }) DEBUG ? localServer.webContents.openDevTools() : null localServer.loadURL ( `http://localhost:${ port }`) } const createWindow = () => { if ( process.platform === 'win32' ) { return createLocalBrowser () } shell.openExternal (`http://localhost:${ port }`) } const data11 = [ { tray: [ { label: '打开', click: createWindow }, { role: 'quit', label: '退出', accelerator: 'Command+Q' } ] },{ tray: [ { label: 'オープン', click: createWindow }, { role: 'quit', label: '退出', accelerator: 'Command+Q' } ] },{ tray: [ { label: 'open', click: createWindow }, { role: 'quit', accelerator: 'Command+Q' } ] },{ tray: [ { label: '打開', click: createWindow },{ role: 'quit', label: '退出', accelerator: 'Command+Q' } ] } ] const getLocalLanguage = ( lang: string ) => { if ( /^zh-TW|^zh-HK|^zh-SG/i.test ( lang )) return 3 if ( /^zh/i.test ( lang )) return 0 if ( /^ja/i.test ( lang )) return 1 return 2 } let localLanguage = getLocalLanguage ( app.getLocale ()) const isMacOS = process.platform === 'darwin' const template = [{ submenu:[ { role: 'undo', visible: isMacOS }, { role: 'redo', visible: isMacOS }, { role: 'selectall', visible: isMacOS }, { role: 'copy', visible: isMacOS }, { role: 'paste', visible: isMacOS }, { role: 'quit', visible: isMacOS } ] }] const appReady = () => { //const menu = Menu.buildFromTemplate( template ) //Menu.setApplicationMenu ( menu) if ( ! localServer1 ) { localServer1 = new BrowserWindow ( { show: DEBUG, webPreferences: { nodeIntegration: true } }) localServer1._doUpdate = _doUpdate DEBUG ? localServer1.webContents.openDevTools() : null //localServer1.maximize () localServer1.loadURL ( format ({ pathname: join( __dirname, 'index.html'), protocol: 'file:', slashes: true })) setTimeout (() => { createWindow () }, 2000 ) /* setTimeout (() => { const checkUpload = new BrowserWindow ({ show: DEBUG }) checkUpload.rendererSidePort = port DEBUG ? checkUpload.webContents.openDevTools() : null checkUpload.loadURL ( format ({ pathname: join ( __dirname, 'app/update.html'), protocol: 'file:', slashes: true })) }, 500 ) */ } else { createWindow () } if ( !tray ) { tray = new Tray ( join ( __dirname, '16x16.png' )) tray.on( 'click', () => { return createWindow () }) const contextMenu = Menu.buildFromTemplate ( data11 [ localLanguage ].tray ) tray.setContextMenu ( contextMenu ) } } const initialize = () => { const gotTheLock = app.requestSingleInstanceLock() if (!gotTheLock) { return app.quit() } app.on('second-instance', ( event, commandLine, workingDirectory) => { createWindow () }) app.once ( 'ready', () => { if ( doReady ) { return } doReady = true return appReady () }) app.once ( 'window-all-closed', () => { app.quit() }) } initialize() ================================================ FILE: package.json ================================================ { "name": "conet_client", "version": "3.3.0", "license": "MIT", "description": "CoNET platform", "scripts": { "start": "electron .", "pack": "electron-builder --dir", "win": "electron-builder --x64", "win32": "electron-builder --ia32", "linux": "electron-builder --linux", "unix": "", "mac": "electron-builder", "pre": "electron-builder install-app-deps", "release": "electron-builder --win && electron-builder --mac && electron-builder --linux" }, "engines": { "node": ">=50.9" }, "devDependencies": { "@types/asn1js": "0.0.1", "@types/cookie-parser": "^1.4.2", "@types/express": "^4.17.2", "@types/jquery": "^3.3.32", "@types/knockout": "^3.4.66", "@types/node": "13.7.0", "@types/node-uuid": "^0.0.28", "@types/pkijs": "0.0.2", "@types/snapsvg": "0.5.0", "@types/socket.io": "2.1.4", "@types/socket.io-client": "1.4.32", "electron": "8.0.0", "electron-builder-squirrel-windows": "22.3.3" }, "build": { "appId": "com.CoNET.Platform", "win": { "target": [ { "target": "nsis" }, { "target": "squirrel" } ], "icon": "resources/icon.ico" }, "mac": { "category": "public.app-category.utilities", "icon": "resources/qtgate" }, "dmg": { "backgroundColor": "#ffffff", "contents": [ { "x": 110, "y": 220 }, { "x": 420, "y": 220, "type": "link", "path": "/Applications" } ] }, "linux": { "target": [ "deb", "pacman" ] } }, "repository": { "type": "git", "url": "git+https://github.com/QTGate/QTGate-Desktop-Client.git" }, "author": { "name": "CoNET Technology Inc.", "email": "info@CoNETTech.ca" }, "bugs": { "url": "https://github.com/QTGate/QTGate-Desktop-Client/issues" }, "homepage": "https://www.CoNETTech.ca", "dependencies": { "async": "^3.1.1", "cookie-parser": "^1.4.4", "express": "^4.17.1", "jimp": "^0.9.3", "jszip": "^3.2.2", "knockout": "^3.5.1", "mime-types": "^2.1.26", "node-uuid": "^1.4.8", "nodemailer": "^6.4.2", "openpgp": "^4.9.0", "pug": "^2.0.4", "snapsvg": "^0.5.1", "socket.io": "^2.3.0", "socket.io-client": "^2.3.0" } } ================================================ FILE: tsconfig.json ================================================ { "compilerOptions": { "target": "es2020", "module": "commonjs", "allowJs": true }, "include": [ "index.ts", "app/**/*.ts" ] }