var Conf = { appName: 'Verdnatura' ,dsName: 'verdnatura' ,dsPath: 'HKCU\\Software\\ODBC\\ODBC.INI\\verdnatura' ,regPath: 'HKCU\\Software\\Verdnatura\\vn-access' ,remoteUrl: 'https://verdnatura.es/vn-access' ,dbHost: 'db.verdnatura.es' ,defaultModule: 'tpv' ,defaultLocale: 'es' ,dbName: 'vn2008' ,maxCorruptSize: 600 }; var Locale = { es: { "Enter a user name": "Introduce un nombre de usuario" ,"Enter a password": "Introduce una contraseña" ,"Server can't be reached": "No se ha podido conectar con el servidor" ,"Updating": "Actualizando" ,"Bad login": "Usuario o contraseña incorrectos" ,"Application it's already open": "La aplicación ya está abierta" ,"Loading": "Cargando" ,"Error while updating": "Error al actualizar" ,"Microsoft Access 2003 is not installed": "Microsoft Access 2003 no está instalado en el sistema" ,"MDB file not found": "No se encontro el fichero MDB" ,"Cache files have been deleted": "Se han borrado todos los ficheros cacheados" } }; var App = { shell: new ActiveXObject('WScript.Shell'), fso: new ActiveXObject('scripting.filesystemobject'), init: function() { var width = 420; var height = 420; window.resizeTo(width, height); window.moveTo((screen.width - width) / 2, (screen.height - height) / 2); }, onLoad: function() { // Initializes the global variables var split = Verdnatura.commandLine.match(/(?:[^\s"]+|"[^"]*")+/g); if (split.length > 1) this.module = split[1].replace(/^"+|"+$/g, ''); if (!this.module) this.module = Conf.defaultModule; this.appDir = this.getEnv('ProgramFiles') +'\\'+ Conf.appName; this.moduleDir = this.shell.SpecialFolders('AppData') +'\\'+ Conf.appName; this.compressFile = this.getEnv('TEMP') +'\\'+ this.module +'.7z'; this.mdbFile = this.moduleDir +'\\'+ this.module +'.mdb'; this.lockFile = this.moduleDir +'\\'+ this.module +'.ldb'; // Creates the necessary registry entries var configured = this.regRead(Conf.regPath, 'configured'); if (!configured) { var path; // Creates the Access configuration entries path = 'HKCU\\Software\\Microsoft\\Office\\11.0\\Access\\Settings'; this.regWrites(path, 'REG_DWORD', { 'Confirm Document Deletions' : 0, 'Confirm Action Queries' : 0, 'Confirm Record Changes' : 0 }); path = 'HKCU\\Software\\Microsoft\\Office\\11.0\\Access\\Security'; this.regWrite(path, 'Level', 1, 'REG_DWORD'); // Creates the MySQL ODBC connection var driverPath = this.getEnv('ProgramFiles') +'\\MySQL\\Connector ODBC 5.1\\myodbc5.dll'; var params = { 'Driver' : driverPath, 'DESCRIPTION' : Conf.appName, 'SERVER' : Conf.dbHost, 'DATABASE' : Conf.dbName, 'SSLCA' : this.appDir +'\\cacert.pem', 'SSLVERIFY' : 1, 'AUTO_RECONNECT' : 1 }; this.createOdbc( Conf.dsName, 'Mysql ODBC 5.1 Driver', params ); // Marks the application as configured this.regWrite(Conf.regPath, 'configured', 1, 'REG_DWORD'); } // Loads the form data var user = this.regRead(Conf.dsPath, 'UID'); var password = this.regRead(Conf.dsPath, 'PWD'); var remember = this.regRead(Conf.regPath, 'remember'); if (user) this.$('user').value = user; if (remember && password) { this.$('password').value = password; this.$('remember').checked = true; this.onEnterClick(); } else this.resetForm(true); }, resetForm: function(clearPassword) { if (clearPassword) this.$('password').value = ''; this.$('user').focus(); this.$('user').select(); }, createOdbc: function(dsName, driverName, params) { var odbcPath = 'HKCU\\Software\\ODBC\\ODBC.INI\\'; this.regWrites(odbcPath + dsName, 'REG_SZ', params); this.regWrite(odbcPath + 'ODBC Data Sources', dsName, driverName, 'REG_SZ'); }, disableUi: function(disabled, loadMessage) { if (disabled) this.hideMessage(); else loadMessage = ''; this.$('loading-message').innerHTML = loadMessage; this.$('user').disabled = disabled; this.$('password').disabled = disabled; this.$('remember').disabled = disabled; this.$('enter').disabled = disabled; var display = disabled ? 'block' : 'none'; this.$('background').style.display = display; this.$('spinner').style.display = display; }, onCleanCacheClick: function() { setTimeout(function() { App.cleanCache(); }); }, cleanCache: function() { if (this.fso.folderExists(this.moduleDir)) { var folder = this.fso.getFolder(this.moduleDir); var files = new Enumerator(folder.files); for (; !files.atEnd(); files.moveNext()) { var file = files.item(); if (/\.mdb$/.test(file.name) && file.name != 'config.mdb') try { file.Delete(); } catch (e) {} } } this.showMessage(_('Cache files have been deleted'), 'notice'); }, onKeyPress: function(event) { switch (event.keyCode) { case 13: // Enter this.onEnterPress(event); break; case 27: // Esc window.close(); break; } }, onEnterPress: function(event) { var target = event.target || event.srcElement; if (target && target.id == 'user' && this.$('password').value == '') { this.$('password').focus(); return; } this.onEnterClick(); }, onEnterClick: function() { this.disableUi(true, _('Loading')); setTimeout(function() { App.login(); }); }, login: function() { try { var user = this.$('user').value; var password = this.$('password').value; if (!user || user === '') throw new Error(_('Enter a user name')); if (!password || password === '') throw new Error(_('Enter a password')); this.regWrite(Conf.dsPath, 'UID', user, 'REG_SZ'); this.regWrite(Conf.dsPath, 'PWD', password, 'REG_SZ'); var version = this.fetchVersion(); if (version) { this.disableUi(true, _('Updating')); var remoteFile; if (version.code == 'last') { remoteFile = this.module +'.7z?'; remoteFile += version.number ? 'v'+ version.number : new Date().getTime(); } else { remoteFile = '.archive/'+ this.module +'/'+ version.number; } remoteFile = Conf.remoteUrl +'/'+ remoteFile; var request = new ActiveXObject('MSXML2.XMLHTTP'); request.open('GET', remoteFile, true); request.onreadystatechange = function() { App.onRequestReady(request); }; request.send(); } else this.openMdb(); } catch (err) { this.catchError(err); } }, /** * Gets information about the version to download. * * @return {Object} Version information or %null if local is up-to-date */ fetchVersion: function() { // Gets the last version number using the MySQL ODBC connection var mysqlConn = new ActiveXObject('ADODB.Connection'); try { mysqlConn.open(Conf.dsName); } catch (err) { var dbErrors = mysqlConn.errors; if (dbErrors.count > 0) { var newErr; var dbError = dbErrors.item(0); switch (dbError.NativeError) { case 1045: // Access denied clearPassword = true; newErr = new Error(_('Bad login')); newErr.code = 'BadLogin'; break; case 2003: // Can't connect newErr = new Error(_('Server can\'t be reached')); break; default: errorMsg = dbError.description; } dbErrors.clear(); throw newErr; } else throw err; } var sql = "SELECT version FROM versiones WHERE programa = '"+ this.module +"'"; var rs = mysqlConn.execute(sql); var lastVersion = rs.EOF ? null : parseInt(rs.fields(0).value); var version = { code: 'last', number: lastVersion }; rs.close(); mysqlConn.close(); if (this.$('previous-version').checked && lastVersion > 1) version = { code: 'previous', number: lastVersion - 1 }; // Checks if it's already open if (this.fso.fileExists(this.lockFile)) try { this.fso.deleteFile(this.lockFile); return version; } catch (e) { throw new Error(_('Application it\'s already open')); } // Checks if MDB exists if (!this.fso.fileExists(this.mdbFile)) return version; // If it's abnormaly bigger, maybe is corrupted, so force download var file = this.fso.getFile(this.mdbFile); if (file.size > Conf.maxCorruptSize * 1024 * 1024) return version; // Obtains the local version number from the MDB file var localVersion; try { var mdbConn = new ActiveXObject('ADODB.Connection'); mdbConn.open('Provider=Microsoft.Jet.OLEDB.4.0; Data Source='+ this.mdbFile +';'); var oRs = new ActiveXObject('ADODB.Recordset'); oRs.Open('SELECT Version FROM tblVariables', mdbConn); localVersion = oRs.EOF ? -1 : parseInt(oRs('Version')); oRs.close(); mdbConn.close(); } catch (e) {} // Compares the local version with the requested version return !localVersion || localVersion != version.number ? version : null; }, onRequestReady: function(request) { if (request.readyState !== 4) return; try { if (request.status !== 200) throw new Error('HTTP: '+ request.statusText); if (this.fso.fileExists(this.compressFile)) this.fso.deleteFile(this.compressFile); var stream = new ActiveXObject('ADODB.Stream'); stream.open(); stream.Type = 1; //adTypeBinary stream.write(request.responseBody); stream.Position = 0; stream.saveToFile(this.compressFile, 2); stream.close(); if (this.fso.fileExists(this.mdbFile)) this.fso.deleteFile(this.mdbFile); this.run('7za e "'+ this.compressFile +'" -o"'+ this.moduleDir +'"', true); this.fso.deleteFile(this.compressFile); } catch (e) { alert(_('Error while updating') +': '+ e.message); } try { if (!this.fso.fileExists(this.mdbFile)) throw new Error(_('MDB file not found')); this.openMdb(); } catch (e) { this.catchError(e); } }, openMdb: function() { var remember = this.$('remember').checked ? 1 : 0; this.regWrite(Conf.regPath, 'remember', remember, 'REG_DWORD'); var programFiles = this.getEnv('ProgramFiles'); var accessBin = programFiles +'\\Microsoft Office\\OFFICE11\\MSACCESS.EXE'; if (!this.fso.fileExists(accessBin)) throw new Error(_('Microsoft Access 2003 is not installed')); this.shell.exec('"'+ accessBin +'" "'+ this.mdbFile +'"'); window.close(); }, catchError: function(err) { var clearPassword = err.code == 'BadLogin'; if (!this.$('remember').checked || clearPassword) this.regWrite(Conf.dsPath, 'PWD', '', 'REG_SZ'); this.disableUi(false); this.showMessage(err.message, 'error'); this.resetForm(clearPassword); }, /** * Displays a non-intrusive message. * * @param {String} message Message to display * @param {String} className Message type */ showMessage: function(message, className) { setTimeout(function() { App.showMessageAsync(message, className); }); }, showMessageAsync: function(message, className) { if (this.messageTimeout) clearTimeout(this.messageTimeout); var messageDiv = this.$('message'); messageDiv.className = className; messageDiv.innerHTML = message; messageDiv.style.display = 'block'; this.messageTimeout = setTimeout(function() { App.hideMessage(); }, 10000); }, onBodyClick: function() { this.hideMessage(); }, /** * Hides the last displayed non-intrusive message. */ hideMessage: function() { if (this.messageTimeout) { this.$('message').style.display = 'none'; clearTimeout(this.messageTimeout); this.messageTimeout = null; } }, /** * Obtains a DOM element by it's identifier. * * @param {String} id The element id */ $: function(id) { return document.getElementById(id); }, run: function(command, wait) { if (!wait) wait = false; this.shell.run(command, 0, wait); }, getEnv: function(varName) { return this.shell.expandEnvironmentStrings('%'+ varName +'%'); }, regRead: function(path, key) { try { var value = this.shell.regRead(path +'\\'+ key); } catch (e) { var value = null; } return value; }, regWrite: function(path, key, value, type) { this.shell.regWrite(path +'\\'+ key, value, type); }, regWrites: function(path, type, values) { for(var key in values) this.regWrite(path, key, values[key], type); }, onUnload: function() { this.disableUi(false); } }; App.init(); function _(string) { var translation = Locale[Conf.defaultLocale][string]; return translation ? translation : string; }