diff --git a/gulliver/js/ext/pmos-common.js b/gulliver/js/ext/pmos-common.js index 311f0323f..59529bfc2 100755 --- a/gulliver/js/ext/pmos-common.js +++ b/gulliver/js/ext/pmos-common.js @@ -28,7 +28,10 @@ PMExtJSCommon = function() { msg: msg, buttons: Ext.MessageBox.YESNO, animEl: 'mb9', - fn: fn != undefined ? fn: function(){}, + fn: function(btn, text){ + if ( btn == 'yes' ) + setTimeout(fn, 0); + }, icon: Ext.MessageBox.QUESTION }); } @@ -132,7 +135,34 @@ PMExtJSCommon = function() { }), loadMask: true }); - } + } + + this.cookie = { + create: function(name, value, days) { + if (days) { + var date = new Date(); + date.setTime(date.getTime()+(days*24*60*60*1000)); + var expires = "; expires="+date.toGMTString(); + }else var expires = ""; + document.cookie = name+"="+value+expires+"; path=/"; + }, + + read: function(name) { + var nameEQ = name + "="; + var ca = document.cookie.split(';'); + for(var i=0;i < ca.length;i++) { + var c = ca[i]; + while (c.charAt(0)==' ') c = c.substring(1,c.length); + if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length); + } + return null; + }, + + erase: function(name) { + Tools.createCookie(name,"",-1); + } + } + } var PMExt = new PMExtJSCommon(); @@ -159,7 +189,7 @@ Ext.msgBoxSlider = function(){ msgCt = Ext.DomHelper.insertFirst(document.body, {id:'msg-div', style:'position:absolute'}, true); } //msgCt.alignTo(document, 'br-br'); - msgCt.alignTo(document, "br-br", [ -20, -20]); + //msgCt.alignTo(document, "br-br", [-20, -20]); var s = String.format.apply(String, Array.prototype.slice.call(arguments, 1)); var m = Ext.DomHelper.append(msgCt, {html:createBox(title, s)}, true); @@ -171,7 +201,57 @@ Ext.msgBoxSlider = function(){ Ext.get('x-box-mc-inner' ).setStyle('background-repeat', 'no-repeat'); Ext.get('x-box-mc-inner' ).setStyle('padding-left', '35px'); m.slideIn('t').pause(3).ghost("t", {remove:true}); + }, + + msgTopCenter : function(type, title, format, time) { + if (typeof remove == 'undefined') + remove : true; + + if (typeof time == 'undefined') + time = 3; + + if( ! msgCt ) { + msgCt = Ext.DomHelper.insertFirst(document.body, {id:'msg-div', style:'position:absolute'}, true); + } + + var s = String.format.apply(String, Array.prototype.slice.call(arguments, 2)); + var m = Ext.DomHelper.append(msgCt, {html:createBox(title, s)}, true); + m.setWidth(400 ); + m.position(null, 5000 ); + m.alignTo(document, 't-t'); + + switch(type) { + case 'alert': + case 'warning': + case 'tmp-warning': + image = '/images/alert.gif'; + break; + case 'error': + case 'tmp-error': + image = '/images/error.png'; + break; + case 'tmp-info': + case 'info': + image = '/images/info.png'; + break; + case 'success': + case 'ok': + image = '/images/select-icon.png'; + break; + default: + image = ''; + } + + if (image != '') { + Ext.get('x-box-mc-inner' ).setStyle('background-image', 'url("'+image+'")'); + } + Ext.get('x-box-mc-inner' ).setStyle('background-position', '5px 10px'); + Ext.get('x-box-mc-inner' ).setStyle('background-repeat', 'no-repeat'); + Ext.get('x-box-mc-inner' ).setStyle('padding-left', '45px'); + + m.slideIn('t').pause(time).ghost("t", {remove:true}); } + }; }(); diff --git a/gulliver/js/ext/ux/portal.js b/gulliver/js/ext/ux/portal.js new file mode 100644 index 000000000..de5035b89 --- /dev/null +++ b/gulliver/js/ext/ux/portal.js @@ -0,0 +1,230 @@ +/*! + * Ext JS Library 3.2.1 + * Copyright(c) 2006-2010 Ext JS, Inc. + * licensing@extjs.com + * http://www.extjs.com/license + */ + +/** Portal.js */ + +Ext.ux.Portal = Ext.extend(Ext.Panel, { + layout : 'column', + autoScroll : true, + cls : 'x-portal', + defaultType : 'portalcolumn', + + initComponent : function(){ + Ext.ux.Portal.superclass.initComponent.call(this); + this.addEvents({ + validatedrop:true, + beforedragover:true, + dragover:true, + beforedrop:true, + drop:true + }); + }, + + initEvents : function(){ + Ext.ux.Portal.superclass.initEvents.call(this); + this.dd = new Ext.ux.Portal.DropZone(this, this.dropConfig); + }, + + beforeDestroy : function() { + if(this.dd){ + this.dd.unreg(); + } + Ext.ux.Portal.superclass.beforeDestroy.call(this); + } +}); + +Ext.reg('portal', Ext.ux.Portal); + +Ext.ux.Portal.DropZone = Ext.extend(Ext.dd.DropTarget, { + + constructor : function(portal, cfg){ + this.portal = portal; + Ext.dd.ScrollManager.register(portal.body); + Ext.ux.Portal.DropZone.superclass.constructor.call(this, portal.bwrap.dom, cfg); + portal.body.ddScrollConfig = this.ddScrollConfig; + }, + + ddScrollConfig : { + vthresh: 50, + hthresh: -1, + animate: true, + increment: 200 + }, + + createEvent : function(dd, e, data, col, c, pos){ + return { + portal: this.portal, + panel: data.panel, + columnIndex: col, + column: c, + position: pos, + data: data, + source: dd, + rawEvent: e, + status: this.dropAllowed + }; + }, + + notifyOver : function(dd, e, data){ + var xy = e.getXY(), portal = this.portal, px = dd.proxy; + + // case column widths + if(!this.grid){ + this.grid = this.getGrid(); + } + + // handle case scroll where scrollbars appear during drag + var cw = portal.body.dom.clientWidth; + if(!this.lastCW){ + this.lastCW = cw; + }else if(this.lastCW != cw){ + this.lastCW = cw; + portal.doLayout(); + this.grid = this.getGrid(); + } + + // determine column + var col = 0, xs = this.grid.columnX, cmatch = false; + for(var len = xs.length; col < len; col++){ + if(xy[0] < (xs[col].x + xs[col].w)){ + cmatch = true; + break; + } + } + // no match, fix last index + if(!cmatch){ + col--; + } + + // find insert position + var p, match = false, pos = 0, + c = portal.items.itemAt(col), + items = c.items.items, overSelf = false; + + for(var len = items.length; pos < len; pos++){ + p = items[pos]; + var h = p.el.getHeight(); + if(h === 0){ + overSelf = true; + } + else if((p.el.getY()+(h/2)) > xy[1]){ + match = true; + break; + } + } + + pos = (match && p ? pos : c.items.getCount()) + (overSelf ? -1 : 0); + var overEvent = this.createEvent(dd, e, data, col, c, pos); + + if(portal.fireEvent('validatedrop', overEvent) !== false && + portal.fireEvent('beforedragover', overEvent) !== false){ + + // make sure proxy width is fluid + px.getProxy().setWidth('auto'); + + if(p){ + px.moveProxy(p.el.dom.parentNode, match ? p.el.dom : null); + }else{ + px.moveProxy(c.el.dom, null); + } + + this.lastPos = {c: c, col: col, p: overSelf || (match && p) ? pos : false}; + this.scrollPos = portal.body.getScroll(); + + portal.fireEvent('dragover', overEvent); + + return overEvent.status; + }else{ + return overEvent.status; + } + + }, + + notifyOut : function(){ + delete this.grid; + }, + + notifyDrop : function(dd, e, data){ + delete this.grid; + if(!this.lastPos){ + return; + } + var c = this.lastPos.c, + col = this.lastPos.col, + pos = this.lastPos.p, + panel = dd.panel, + dropEvent = this.createEvent(dd, e, data, col, c, + pos !== false ? pos : c.items.getCount()); + + if(this.portal.fireEvent('validatedrop', dropEvent) !== false && + this.portal.fireEvent('beforedrop', dropEvent) !== false){ + + dd.proxy.getProxy().remove(); + panel.el.dom.parentNode.removeChild(dd.panel.el.dom); + + if(pos !== false){ + c.insert(pos, panel); + }else{ + c.add(panel); + } + + c.doLayout(); + + this.portal.fireEvent('drop', dropEvent); + + // scroll position is lost on drop, fix it + var st = this.scrollPos.top; + if(st){ + var d = this.portal.body.dom; + setTimeout(function(){ + d.scrollTop = st; + }, 10); + } + + } + delete this.lastPos; + }, + + // internal cache of body and column coords + getGrid : function(){ + var box = this.portal.bwrap.getBox(); + box.columnX = []; + this.portal.items.each(function(c){ + box.columnX.push({x: c.el.getX(), w: c.el.getWidth()}); + }); + return box; + }, + + // unregister the dropzone from ScrollManager + unreg: function() { + Ext.dd.ScrollManager.unregister(this.portal.body); + Ext.ux.Portal.DropZone.superclass.unreg.call(this); + } +}); + +/** PortalColumn.js */ + +Ext.ux.PortalColumn = Ext.extend(Ext.Container, { + layout : 'anchor', + //autoEl : 'div',//already defined by Ext.Component + defaultType : 'portlet', + cls : 'x-portal-column' +}); + +Ext.reg('portalcolumn', Ext.ux.PortalColumn); + +/** Portlet.js */ + +Ext.ux.Portlet = Ext.extend(Ext.Panel, { + anchor : '100%', + frame : true, + collapsible : false, + draggable : true, + cls : 'x-portlet' +}); + +Ext.reg('portlet', Ext.ux.Portlet); diff --git a/gulliver/js/ext/ux/ux.menu.js b/gulliver/js/ext/ux/ux.menu.js new file mode 100644 index 000000000..1be27d143 --- /dev/null +++ b/gulliver/js/ext/ux/ux.menu.js @@ -0,0 +1,13 @@ +/* + * Ext.ux.menu.StoreMenu Addon + * + * @author Marco Wienkoop (wm003/lubber) + * @copyright (c) 2009, Marco Wienkoop (marco.wienkoop@lubber.de) http://www.lubber.de +*/ + +Ext.namespace('Ext.ux.menu');Ext.ux.menu.StoreMenu=function(config){Ext.ux.menu.StoreMenu.superclass.constructor.call(this,config);if(!this.store){this.store=new Ext.data.SimpleStore({fields:['config'],url:this.url,baseParams:this.baseParams});} +this.on('show',this.onMenuLoad,this);this.store.on('beforeload',this.onBeforeLoad,this);this.store.on('load',this.onLoad,this);};Ext.extend(Ext.ux.menu.StoreMenu,Ext.menu.Menu,{loadingText:Ext.LoadMask.prototype.msg||'Loading...',loaded:false,onMenuLoad:function(){if(!this.loaded){this.store.load();}},updateMenuItems:function(loadedState,records){this.removeAll();this.el.sync();if(loadedState){for(var i=0,len=records.length;i'+this.loadingText+'');} +this.loaded=loadedState;},onBeforeLoad:function(store){this.store.baseParams=this.baseParams;this.updateMenuItems(false);},onLoad:function(store,records){this.updateMenuItems(true,records);}}); \ No newline at end of file diff --git a/gulliver/js/ext/ux/virtualkeyboard.js b/gulliver/js/ext/ux/virtualkeyboard.js new file mode 100644 index 000000000..a9ad65da6 --- /dev/null +++ b/gulliver/js/ext/ux/virtualkeyboard.js @@ -0,0 +1,812 @@ +Ext.ns('Ext.ux.plugins'); +Ext.ux.plugins.VirtualKeyboard = Ext.extend ( Ext.util.Observable, { + events: {}, + /** + * Init of plugin + * @param {Ext.Component} field + */ + init: function(field) { + this.addEvents({ + 'expand': true, + 'collapse': true + }); + + if(field.getXType() != 'textfield' && field.getXType() != 'textarea') + return; + + this.component = field; + field.virtualKeyboardPlugin = this; + + field.enableKeyEvents = true; + field.on({ + 'destroy': this.destroy, + 'focus': function(f){ + this.activeTarget = f; + }, + 'keypress': function(field, e){ + if(e.getKey() == e.ESC) + field.collapseKeyboard(); + }, + scope: this + }); + + Ext.apply(field, { + onRender: field.onRender.createSequence(function(ct, position) { + this.wrap = this.el.wrap({cls: "x-form-field-wrap"}); + if(this.fieldLabel && this.keyboardConfig.showIcon) { + var label = this.el.findParent('.x-form-element', 5, true) || this.el.findParent('.x-form-field-wrap', 5, true); + + this.virtualKeyboardIcon = label.createChild({ + cls:(this.keyboardIconCls || 'ux-virtualkeyboard-icon'), + style:'width:16px; height:18px; position:absolute; left:0; top:0; display:block; background:transparent no-repeat scroll 0 2px;' + }); + + this.alignKeyboardIcon = function(){ + var el = this.el; + this.virtualKeyboardIcon.alignTo(el, 'tl-tr', [2, 0]); + } + //Redefine alignErrorIcon to move the errorIcon (if it exist) to the right of helpIcon + if(this.alignErrorIcon) { + this.alignErrorIcon = function() { + this.errorIcon.alignTo(this.virtualKeyboardIcon, 'tl-tr', [2, 0]); + } + } + + this.on('resize', this.alignKeyboardIcon, this); + + this.virtualKeyboardIcon.on('click', function(e){ + if(this.disabled){ + return; + } + this.expandKeyboard(); + this.el.focus(); + }, this); + + } + }), //end of onRender + + initKeyboard: function(){ + var cls = 'x-keyboard-container'; + + this.keyboardContainer = new Ext.Layer({ + shadow: true, + cls: [cls, this.virtualKeyboardClass].join(' '), + constrain: false + }); + + this.keyboardContainer.setWidth(370); + + var config = this.keyboardConfig || {}; + config['showCloseButton'] = true; + config['keyboardTarget'] = this; + + this.keyboard = new Ext.ux.VirtualKeyboard(config); + this.keyboard.render(this.keyboardContainer); + + this.keyboard.getTBar().add('-', new Ext.Button({ + text: this.keyboardConfig.closeButtonText || 'Close', + listeners: { + 'click': this.collapseKeyboard, + scope: this + }, + scope: this + })); + }, + + collapseKeyboardIf : function(e){ + if( !e.within(this.wrap) && !e.within(this.keyboardContainer) && !this.keyboard.selectingLanguage ){ + this.collapseKeyboard(); + } + }, + + expandKeyboard : function(){ + if(this.isKeyboardExpanded() /*|| !this.hasFocus*/){ + return; + } + if(!this.keyboard) + this.initKeyboard(); + this.keyboardContainer.alignTo(this.wrap, this.keyboardAlign || 'tl-bl?'); + this.keyboardContainer.show(); + Ext.getDoc().on('mousewheel', this.collapseKeyboardIf, this); + Ext.getDoc().on('mousedown', this.collapseKeyboardIf, this); + this.virtualKeyboardPlugin.fireEvent('expand', this); + }, + + collapseKeyboard : function(){ + if(!this.isKeyboardExpanded()){ + return; + } + this.keyboardContainer.hide(); + Ext.getDoc().un('mousewheel', this.collapseKeyboardIf, this); + Ext.getDoc().un('mousedown', this.collapseKeyboardIf, this); + this.virtualKeyboardPlugin.fireEvent('collapse', this); + }, + + + isKeyboardExpanded : function(){ + return this.keyboardContainer && this.keyboardContainer.isVisible(); + } + + }); //end of Ext.apply + }, // end of function init + + destroy: function(component){ + if(component){ + if(component.keyboard){ + component.keyboard.keyboard.remove(); + delete component.keyboard; + } + if(component.keyboardContainer){ + component.keyboardContainer.remove(); + delete component.keyboardContainer; + } + } + }, + + expand: function(){ + if(this.activeTarget){ + this.activeTarget.expandKeyboard(); + } + } + +}); // end of extend + +Ext.ns('Ext.ux'); + +/** + * Licensed under GNU LESSER GENERAL PUBLIC LICENSE Version 3 + * + * Inspired from: HTML Virtual Keyboard Interface Script - v1.11 + * http://www.greywyvern.com/code/js/keyboard.html + * Copyright (c) 2008 - GreyWyvern + * Licenced for free distribution under the BSDL + * http://www.opensource.org/licenses/bsd-license.php + + * + * @author Edouard Fattal + * @url http://efattal.fr/extjs/examples/virtualkeyboard + */ + +/** + * @class Ext.ux.VirtualKeyboard + * @extends Ext.Component + */ +Ext.ux.VirtualKeyboard = Ext.extend(Ext.Component, { + /* ***** Create keyboards **************************************** */ + keyboardTarget: null, + languageSelection: false, + numpad: true, + keyCenter: 3, + layoutDDK: {}, + shift: false, + capslock: false, + alternate: false, + dead: false, + deadKeysOn: false, + Languages: { + Arabic: [ // Arabic Keyboard + [["\u0630", "\u0651 "], ["1", "!", "\u00a1", "\u00b9"], ["2", "@", "\u00b2"], ["3", "#", "\u00b3"], ["4", "$", "\u00a4", "\u00a3"], ["5", "%", "\u20ac"], ["6", "^", "\u00bc"], ["7", "&", "\u00bd"], ["8", "*", "\u00be"], ["9", "(", "\u2018"], ["0", ")", "\u2019"], ["-", "_", "\u00a5"], ["=", "+", "\u00d7", "\u00f7"], ["Bksp", "Bksp"]], + [["Tab", "Tab"], ["\u0636", "\u064e"], ["\u0635", "\u064b"], ["\u062b", "\u064f"], ["\u0642", "\u064c"], ["\u0641", "\u0644"], ["\u063a", "\u0625"], ["\u0639", "\u2018"], ["\u0647", "\u00f7"], ["\u062e", "\u00d7"], ["\u062d", "\u061b"], ["\u062c", "\u003c"], ["\u062f", "\u003e"], ["\u005c", "\u007c"]], + [["Caps", "Caps"], ["\u0634", "\u0650"], ["\u0633", "\u064d"], ["\u064a", "\u005d"], ["\u0628", "\u005b"], ["\u0644", "\u0644"], ["\u0627", "\u0623"], ["\u062a", "\u0640"], ["\u0646", "\u060c"], ["\u0645", "\u002f"], ["\u0643", "\u003a"], ["\u0637", "\u0022"], ["Enter", "Enter"]], + [["Shift", "Shift"], ["\u0626", "\u007e"], ["\u0621", "\u0652"], ["\u0624", "\u007d"], ["\u0631", "\u007b"], ["\u0644", "\u0644"], ["\u0649", "\u0622"], ["\u0629", "\u2019"], ["\u0648", "\u002c"], ["\u0632", "\u002e"], ["\u0638", "\u061f"], ["Shift", "Shift"]], + [[" ", " ", " ", " "], ["Alt", "Alt"]] + ], + Belgian: [ // Belgian Standard Keyboard + [["\u00b2", "\u00b3"], ["&", "1", "|"], ["\u00e9", "2", "@"], ['"', "3", "#"], ["'", "4"], ["(", "5"], ["\u00a7", "6", "^"], ["\u00e8", "7"], ["!", "8"], ["\u00e7", "9", "{"], ["\u00e0", "0", "}"], [")", "\u00b0"], ["-", "_"], ["Bksp", "Bksp"]], + [["Tab", "Tab"], ["a", "A"], ["z", "Z"], ["e", "E", "\u20ac"], ["r", "R"], ["t", "T"], ["y", "Y"], ["u", "U"], ["i", "I"], ["o", "O"], ["p", "P"], ["\u005e", "\u00a8", "["], ["$", "*", "]"], ["Enter", "Enter"]], + [["Caps", "Caps"], ["q", "Q"], ["s", "S"], ["d", "D"], ["f", "F"], ["g", "G"], ["h", "H"], ["j", "J"], ["k", "K"], ["l", "L"], ["m", "M"], ["\u00f9", "%", "\u00b4"], ["\u03bc", "\u00a3", "`"]], + [["Shift", "Shift"], ["<", ">", "\\"], ["w", "W"], ["x", "X"], ["c", "C"], ["v", "V"], ["b", "B"], ["n", "N"], [",", "?"], [";", "."], [":", "/"], ["=", "+", "~"], ["Shift", "Shift"]], + [[" ", " ", " ", " "], ["AltGr", "AltGr"]] + ], + /*Burmese: [ // Burmese Keyboard + [["\u1039`", "~"], ["\u1041", "\u100D"], ["\u1042", "\u100E"], ["\u1043", "\u100B"], ["\u1044", "\u1000\u103B\u1015\u103A"], ["\u1045", "%"], ["\u1046", "\u002F"], ["\u1047", "\u101B"], ["\u1048", "\u1002"], ["\u1049", "("], ["\u1040", ")"], ["-", "_"], ["=", "+"], ["Bksp", "Bksp"]], + [["Tab", "Tab"], ["\u1006", "\u1029"], ["\u1010", "\u1040"], ["\u1014", "\u103F"], ["\u1019", "\u1023"], ["\u1021", "\u1024"], ["\u1015", "\u104C"], ["\u1000", "\u1009"], ["\u1004", "\u104D"], ["\u101E", "\u1025"], ["\u1005", "\u100F"], ["\u101F", "\u1027"], ["\u2018", "\u2019"], ["\u104F", "\u100B\u1039\u100C"]], + [["Caps", "Caps"], ["\u200B\u1031", "\u1017"], ["\u200B\u103B", "\u200B\u103E"], ["\u200B\u102D", "\u200B\u102E"], ["\u200B\u103A","\u1004\u103A\u1039\u200B"], ["\u200B\u102B", "\u200B\u103D"], ["\u200B\u1037", "\u200B\u1036"], ["\u200B\u103C", "\u200B\u1032"], ["\u200B\u102F", "\u200B\u102F"], ["\u200B\u1030", "\u200B\u1030"], ["\u200B\u1038", "\u200B\u102B\u103A"], ["\u1012", "\u1013"], ["Enter", "Enter"]], + [["Shift", "Shift"], ["\u1016", "\u1007"], ["\u1011", "\u100C"], ["\u1001", "\u1003"], ["\u101C", "\u1020"], ["\u1018", "\u1026"], ["\u100A", "\u1008"], ["\u200B\u102C", "\u102A"], ["\u101A", "\u101B"], ["\u002E", "\u101B"], ["\u104B", "\u104A"], ["Shift", "Shift"]], + [[" ", " "]] + ],*/ + Dutch: [ // Dutch Standard Keyboard + [["@", "\u00a7", "\u00ac"], ["1", "!", "\u00b9"], ["2", '"', "\u00b2"], ["3", "#", "\u00b3"], ["4", "$", "\u00bc"], ["5", "%", "\u00bd"], ["6", "&", "\u00be"], ["7", "_", "\u00a3"], ["8", "(", "{"], ["9", ")", "}"], ["0", "'"], ["/", "?", "\\"], ["\u00b0", "~", "\u00b8"], ["Bksp", "Bksp"]], + [["Tab", "Tab"], ["q", "Q"], ["w", "W"], ["e", "E", "\u20ac"], ["r", "R", "\u00b6"], ["t", "T"], ["y", "Y"], ["u", "U"], ["i", "I"], ["o", "O"], ["p", "P"], ["\u00a8", "^"], ["*", "|"], ["<", ">"]], + [["Caps", "Caps"], ["a", "A"], ["s", "S", "\u00df"], ["d", "D"], ["f", "F"], ["g", "G"], ["h", "H"], ["j", "J"], ["k", "K"], ["l", "L"], ["+", "\u00b1"], ["\u00b4", "\u0060"], ["Enter", "Enter"]], + [["Shift", "Shift"], ["]", "[", "\u00a6"], ["z", "Z", "\u00ab"], ["x", "X", "\u00bb"], ["c", "C", "\u00a2"], ["v", "V"], ["b", "B"], ["n", "N"], ["m", "M", "\u00b5"], [",", ";"], [".", ":", "\u00b7"], ["-", "="], ["Shift", "Shift"]], + [[" ", " ", " ", " "], ["AltGr", "AltGr"]] + ], + Dvorak: [ // Dvorak Keyboard + [["`", "~"], ["1", "!"], ["2", "@"], ["3", "#"], ["4", "$"], ["5", "%"], ["6", "^"], ["7", "&"], ["8", "*"], ["9", "("], ["0", ")"], ["[", "{"], ["]", "}"], ["Bksp", "Bksp"]], + [["Tab", "Tab"],["'", '"'], [",", "<"], [".", ">"], ["p", "P"], ["y", "Y"], ["f", "F"], ["g", "G"], ["c", "C"], ["r", "R"], ["l", "L"], ["/", "?"], ["=", "+"], ["\\", "|"]], + [["Caps", "Caps"], ["a", "A"], ["o", "O"], ["e", "E"], ["u", "U"], ["i", "I"], ["d", "D"], ["h", "H"], ["t", "T"], ["n", "N"], ["s", "S"], ["-", "_"], ["Enter", "Enter"]], + [["Shift", "Shift"], [";", ":"], ["q", "Q"], ["j", "J"], ["k", "K"], ["x", "X"], ["b", "B"], ["m", "M"], ["w", "W"], ["v", "V"], ["z", "Z"], ["Shift", "Shift"]], + [[" ", " "]] + ], + French: [ // French Standard Keyboard + [["\u00b2", "\u00b3"], ["&", "1"], ["\u00e9", "2", "~"], ['"', "3", "#"], ["'", "4", "{"], ["(", "5", "["], ["-", "6", "|"], ["\u00e8", "7", "\u0060"], ["_", "8", "\\"], ["\u00e7", "9", "\u005e"], ["\u00e0", "0", "\u0040"], [")", "\u00b0", "]"], ["=", "+", "}"], ["Bksp", "Bksp"]], + [["Tab", "Tab"], ["a", "A"], ["z", "Z"], ["e", "E", "\u20ac"], ["r", "R"], ["t", "T"], ["y", "Y"], ["u", "U"], ["i", "I"], ["o", "O"], ["p", "P"], ["^", "\u00a8"], ["$", "\u00a3", "\u00a4"], ["Enter", "Enter"]], + [["Caps", "Caps"], ["q", "Q"], ["s", "S"], ["d", "D"], ["f", "F"], ["g", "G"], ["h", "H"], ["j", "J"], ["k", "K"], ["l", "L"], ["m", "M"], ["\u00f9", "%"], ["*", "\u03bc"]], + [["Shift", "Shift"], ["<", ">"], ["w", "W"], ["x", "X"], ["c", "C"], ["v", "V"], ["b", "B"], ["n", "N"], [",", "?"], [";", "."], [":", "/"], ["!", "\u00a7"], ["Shift", "Shift"]], + [[" ", " ", " ", " "], ["AltGr", "AltGr"]] + ], + German: [ // German Standard Keyboard + [["\u005e", "\u00b0"], ["1", "!"], ["2", '"', "\u00b2"], ["3", "\u00a7", "\u00b3"], ["4", "$"], ["5", "%"], ["6", "&"], ["7", "/", "{"], ["8", "(", "["], ["9", ")", "]"], ["0", "=", "}"], ["\u00df", "?", "\\"], ["\u00b4", "\u0060"], ["Bksp", "Bksp"]], + [["Tab", "Tab"], ["q", "Q", "\u0040"], ["w", "W"], ["e", "E", "\u20ac"], ["r", "R"], ["t", "T"], ["z", "Z"], ["u", "U"], ["i", "I"], ["o", "O"], ["p", "P"], ["\u00fc", "\u00dc"], ["+", "*", "~"], ["Enter", "Enter"]], + [["Caps", "Caps"], ["a", "A"], ["s", "S"], ["d", "D"], ["f", "F"], ["g", "G"], ["h", "H"], ["j", "J"], ["k", "K"], ["l", "L"], ["\u00f6", "\u00d6"], ["\u00e4", "\u00c4"], ["#", "'"]], + [["Shift", "Shift"], ["<", ">", "\u00a6"], ["y", "Y"], ["x", "X"], ["c", "C"], ["v", "V"], ["b", "B"], ["n", "N"], ["m", "M", "\u00b5"], [",", ";"], [".", ":"], ["-", "_"], ["Shift", "Shift"]], + [[" ", " ", " ", " "], ["AltGr", "AltGr"]] + ], + Greek: [ // Greek Standard Keyboard + [["`", "~"], ["1", "!"], ["2", "@", "\u00b2"], ["3", "#", "\u00b3"], ["4", "$", "\u00a3"], ["5", "%", "\u00a7"], ["6", "^", "\u00b6"], ["7", "&"], ["8", "*", "\u00a4"], ["9", "(", "\u00a6"], ["0", ")", "\u00ba"], ["-", "_", "\u00b1"], ["=", "+", "\u00bd"], ["Bksp", "Bksp"]], + [["Tab", "Tab"], [";", ":"], ["\u03c2", "^"], ["\u03b5", "\u0395"], ["\u03c1", "\u03a1"], ["\u03c4", "\u03a4"], ["\u03c5", "\u03a5"], ["\u03b8", "\u0398"], ["\u03b9", "\u0399"], ["\u03bf", "\u039f"], ["\u03c0", "\u03a0"], ["[", "{", "\u201c"], ["]", "}", "\u201d"], ["Enter", "Enter"]], + [["Caps", "Caps"], ["\u03b1", "\u0391"], ["\u03c3", "\u03a3"], ["\u03b4", "\u0394"], ["\u03c6", "\u03a6"], ["\u03b3", "\u0393"], ["\u03b7", "\u0397"], ["\u03be", "\u039e"], ["\u03ba", "\u039a"], ["\u03bb", "\u039b"], ["\u0384", "\u00a8", "\u0385"], ["'", '"'], ["\\", "|", "\u00ac"]], + [["Shift", "Shift"], ["<", ">"], ["\u03b6", "\u0396"], ["\u03c7", "\u03a7"], ["\u03c8", "\u03a8"], ["\u03c9", "\u03a9"], ["\u03b2", "\u0392"], ["\u03bd", "\u039d"], ["\u03bc", "\u039c"], [",", "<"], [".", ">"], ["/", "?"], ["Shift", "Shift"]], + [[" ", " ", " ", " "], ["AltGr", "AltGr"]] + ], + Hebrew: [ // Hebrew Standard Keyboard + [["~", "`"], ["1", "!"], ["2", "@"], ["3", "#"], ["4" , "$", "\u20aa"], ["5" , "%"], ["6", "^"], ["7", "&"], ["8", "*"], ["9", ")"], ["0", "("], ["-", "_"], ["=", "+"], ["\\", "|"], ["Bksp", "Bksp"]], + [["Tab", "Tab"], ["/", "Q"], ["'", "W"], ["\u05e7", "E", "\u20ac"], ["\u05e8", "R"], ["\u05d0", "T"], ["\u05d8", "Y"], ["\u05d5", "U", "\u05f0"], ["\u05df", "I"], ["\u05dd", "O"], ["\u05e4", "P"], ["]", "}"], ["[", "{"]], + [["Caps", "Caps"], ["\u05e9", "A"], ["\u05d3", "S"], ["\u05d2", "D"], ["\u05db", "F"], ["\u05e2", "G"], ["\u05d9", "H", "\u05f2"], ["\u05d7", "J", "\u05f1"], ["\u05dc", "K"], ["\u05da", "L"], ["\u05e3", ":"], ["," , '"'], ["Enter", "Enter"]], + [["Shift", "Shift"], ["\u05d6", "Z"], ["\u05e1", "X"], ["\u05d1", "C"], ["\u05d4", "V"], ["\u05e0", "B"], ["\u05de", "N"], ["\u05e6", "M"], ["\u05ea", ">"], ["\u05e5", "<"], [".", "?"], ["Shift", "Shift"]], + [[" ", " ", " ", " "], ["AltGr", "AltGr"]] + ], + Hungarian: [ // Hungarian Standard Keyboard + [["0", "\u00a7"], ["1", "'", "\u007e"], ["2", '"', "\u02c7"], ["3", "+", "\u02c6"], ["4", "!", "\u02d8"], ["5", "%", "\u00b0"], ["6", "/", "\u02db"], ["7", "=", "\u0060"], ["8", "(", "\u02d9"], ["9", ")", "\u00b4"], ["\u00f6", "\u00d6", "\u02dd"], ["\u00fc", "\u00dc", "\u00a8"], ["\u00f3", "\u00d3", "\u00b8"], ["Bksp", "Bksp"]], + [["Tab", "Tab"], ["q", "Q", "\u005c"], ["w", "W", "\u007c"], ["e", "E", "\u00c4"], ["r", "R"], ["t", "T"], ["z", "Z"], ["u", "U", "\u20ac"], ["i", "I", "\u00cd"], ["o", "O"], ["p", "P"], ["\u0151", "\u0150", "\u00f7"], ["\u00fa", "\u00da", "\u00d7"], ["Enter", "Enter"]], + [["Caps", "Caps"], ["a", "A", "\u00e4"], ["s", "S","\u0111"], ["d", "D","\u0110"], ["f", "F","\u005b"], ["g", "G","\u005d"], ["h", "H"], ["j", "J","\u00ed"], ["k", "K","\u0141"], ["l", "L","\u0142"], ["\u00e9", "\u00c9","\u0024"], ["\u00e1", "\u00c1","\u00df"], ["\u0171", "\u0170","\u00a4"]], + [["Shift", "Shift"], ["\u00ed", "\u00cd","\u003c"], ["y", "Y","\u003e"], ["x", "X","\u0023"], ["c", "C","\u0026"], ["v", "V","\u0040"], ["b", "B","\u007b"], ["n", "N","\u007d"], ["m", "M","\u003c"], [",", "?","\u003b"], [".", ":","\u003e"], ["-", "_","\u002a"], ["Shift", "Shift"]], + [[" ", " ", " ", " "], ["AltGr", "AltGr"]] + ], + Italian: [ // Italian Standard Keyboard + [["\u005c", "\u007c"], ["1", "!"], ["2", '"'], ["3", "\u00a3"], ["4", "$", "\u20ac"], ["5", "%"], ["6", "&"], ["7", "/"], ["8", "("], ["9", ")"], ["0", "="], ["'", "?"], ["\u00ec", "\u005e"], ["Bksp", "Bksp"]], + [["Tab", "Tab"], ["q", "Q"], ["w", "W"], ["e", "E", "\u20ac"], ["r", "R"], ["t", "T"], ["y", "Y"], ["u", "U"], ["i", "I"], ["o", "O"], ["p", "P"], ["\u00e8", "\u00e9", "[", "{"], ["+", "*", "]", "}"], ["Enter", "Enter"]], + [["Caps", "Caps"], ["a", "A"], ["s", "S"], ["d", "D"], ["f", "F"], ["g", "G"], ["h", "H"], ["j", "J"], ["k", "K"], ["l", "L"], ["\u00f2", "\u00e7", "@"], ["\u00e0", "\u00b0", "#"], ["\u00f9", "\u00a7"]], + [["Shift", "Shift"], ["<", ">"], ["z", "Z"], ["x", "X"], ["c", "C"], ["v", "V"], ["b", "B"], ["n", "N"], ["m", "M"], [",", ";"], [".", ":"], ["-", "_"], ["Shift", "Shift"]], + [[" ", " ", " ", " "], ["AltGr", "AltGr"]] + ], + Lithuanian: [ // Lithuanian Standard Keyboard + [["`", "~"], ["\u0105", "\u0104"], ["\u010D", "\u010C"], ["\u0119", "\u0118"], ["\u0117", "\u0116"], ["\u012F", "\u012E"], ["\u0161", "\u0160"], ["\u0173", "\u0172"], ["\u016B", "\u016A"], ["\u201E", "("], ["\u201C", ")"], ["-", "_"], ["\u017E", "\u017D"], ["Bksp", "Bksp"]], + [["Tab", "Tab"], ["q", "Q"], ["w", "W"], ["e", "E"], ["r", "R"], ["t", "T"], ["y", "Y"], ["u", "U"], ["i", "I"], ["o", "O"], ["p", "P"], ["[", "{"], ["]", "}"], ["Enter", "Enter"]], + [["Caps", "Caps"], ["a", "A"], ["s", "S"], ["d", "D"], ["f", "F"], ["g", "G"], ["h", "H"], ["j", "J"], ["k", "K"], ["l", "L"], [";", ":"], ["'", '"'], ["\\", "|"]], + [["Shift", "Shift"], ["\u2013", "\u20AC"], ["z", "Z"], ["x", "X"], ["c", "C"], ["v", "V"], ["b", "B"], ["n", "N"], ["m", "M"], [",", "<"], [".", ">"], ["/", "?"], ["Shift", "Shift"]], + [[" ", " "]] + ], + Norwegian: [ // Norwegian Standard Keyboard + [["|", "\u00a7"], ["1", "!"], ["2", '"', "@"], ["3", "#", "\u00a3"], ["4", "\u00a4", "$"], ["5", "%"], ["6", "&"], ["7", "/", "{"], ["8", "(", "["], ["9", ")", "]"], ["0", "=", "}"], ["+", "?"], ["\\", "`", "\u00b4"], ["Bksp", "Bksp"]], + [["Tab", "Tab"], ["q", "Q"], ["w", "W"], ["e", "E", "\u20ac"], ["r", "R"], ["t", "T"], ["y", "Y"], ["u", "U"], ["i", "I"], ["o", "O"], ["p", "P"], ["\u00e5", "\u00c5"], ["\u00a8", "^", "~"], ["Enter", "Enter"]], + [["Caps", "Caps"], ["a", "A"], ["s", "S"], ["d", "D"], ["f", "F"], ["g", "G"], ["h", "H"], ["j", "J"], ["k", "K"], ["l", "L"], ["\u00f8", "\u00d8"], ["\u00e6", "\u00c6"], ["'", "*"]], + [["Shift", "Shift"], ["<", ">"], ["z", "Z"], ["x", "X"], ["c", "C"], ["v", "V"], ["b", "B"], ["n", "N"], ["m", "M", "\u03bc", "\u039c"], [",", ";"], [".", ":"], ["-", "_"], ["Shift", "Shift"]], + [[" ", " ", " ", " "], ["AltGr", "AltGr"]] + ], + /*Numpad: [ // Number pad + [["$"], ["\u00a3"], ["\u20ac"], ["\u00a5"], ["/"], ["^"], ["Bksp", "Bksp"]], + [["."], ["7"], ["8"], ["9"], ["*"], ["<"], ["("], ["["]], + [["="], ["4"], ["5"], ["6"], ["-"], [">"], [")"], ["]"]], + [["0"], ["1"], ["2"], ["3"], ["+"], ["Enter", "Enter"]], + [[" "]] + ], + "Polish Prog": [ // Polish Programmers Keyboard + [["`", "~"], ["1", "!"], ["2", "@"], ["3", "#"], ["4", "$"], ["5", "%"], ["6", "^"], ["7", "&"], ["8", "*"], ["9", "("], ["0", ")"], ["-", "_"], ["=", "+"], ["Bksp", "Bksp"]], + [["Tab", "Tab"], ["q", "Q"], ["w", "W"], ["e", "E", "\u0119", "\u0118"], ["r", "R"], ["t", "T"], ["y", "Y"], ["u", "U"], ["i", "I"], ["o", "O", "\u00f3", "\u00d3"], ["p", "P"], ["[", "{"], ["]", "}"], ["\\", "|"]], + [["Caps", "Caps"], ["a", "A", "\u0105", "\u0104"], ["s", "S", "\u015b", "\u015a"], ["d", "D"], ["f", "F"], ["g", "G"], ["h", "H"], ["j", "J"], ["k", "K"], ["l", "L", "\u0142", "\u0141"], [";", ":"], ["'", '"'], ["Enter", "Enter"]], + [["Shift", "Shift"], ["z", "Z", "\u017c", "\u017b"], ["x", "X", "\u017a", "\u0179"], ["c", "C", "\u0107", "\u0106"], ["v", "V"], ["b", "B"], ["n", "N", "\u0144", "\u0143"], ["m", "M"], [",", "<"], [".", ">"], ["/", "?"], ["Shift", "Shift"]], + [[" ", " ", " ", " "], ["Alt", "Alt"]] + ],*/ + Portuguese: [ // Portuguese Standard Keyboard + [["`", "\u00ac", "\u00a6"], ["1", "!"], ["2", '"'], ["3", "\u00a3"], ["4", "$", "\u20ac"], ["5", "%"], ["6", "^"], ["7", "&"], ["8", "*"], ["9", "("], ["0", ")"], ["-", "_"], ["=", "+"], ["Bksp", "Bksp"]], + [["Tab", "Tab"], ["q", "Q"], ["w", "W"], ["e", "E", "\u00e9", "\u00c9"], ["r", "R"], ["t", "T"], ["y", "Y"], ["u", "U", "\u00fa", "\u00da"], ["i", "I", "\u00ed", "\u00cd"], ["o", "O", "\u00f3", "\u00d3"], ["p", "P"], ["[", "{"], ["]", "}"], ["Enter", "Enter"]], + [["Caps", "Caps"], ["a", "A", "\u00e1", "\u00c1"], ["s", "S"], ["d", "D"], ["f", "F"], ["g", "G"], ["h", "H"], ["j", "J"], ["k", "K"], ["l", "L"], ["\u00e7", "\u00c7"], [";", ":"], ["'", "@"], ["#", "~"]], + [["Shift", "Shift"], ["\\", "|"], ["z", "Z"], ["x", "X"], ["c", "C"], ["v", "V"], ["b", "B"], ["n", "N"], ["m", "M"], [",", "<"], [".", ">"], ["/", "?"], ["Shift", "Shift"]], + [[" ", " ", " ", " "], ["AltGr", "AltGr"]] + ], + Russian: [ // Russian Standard Keyboard + [["\u0451", "\u0401"], ["1", "!"], ["2", '"'], ["3", "\u2116"], ["4", ";"], ["5", "%"], ["6", ":"], ["7", "?"], ["8", "*"], ["9", "("], ["0", ")"], ["-", "_"], ["=", "+"], ["Bksp", "Bksp"]], + [["Tab", "Tab"], ["\u0439", "\u0419"], ["\u0446", "\u0426"], ["\u0443", "\u0423"], ["\u043A", "\u041A"], ["\u0435", "\u0415"], ["\u043D", "\u041D"], ["\u0433", "\u0413"], ["\u0448", "\u0428"], ["\u0449", "\u0429"], ["\u0437", "\u0417"], ["\u0445", "\u0425"], ["\u044A", "\u042A"], ["Enter", "Enter"]], + [["Caps", "Caps"], ["\u0444", "\u0424"], ["\u044B", "\u042B"], ["\u0432", "\u0412"], ["\u0430", "\u0410"], ["\u043F", "\u041F"], ["\u0440", "\u0420"], ["\u043E", "\u041E"], ["\u043B", "\u041B"], ["\u0434", "\u0414"], ["\u0436", "\u0416"], ["\u044D", "\u042D"], ["\\", "/"]], + [["Shift", "Shift"], ["/", "|"], ["\u044F", "\u042F"], ["\u0447", "\u0427"], ["\u0441", "\u0421"], ["\u043C", "\u041C"], ["\u0438", "\u0418"], ["\u0442", "\u0422"], ["\u044C", "\u042C"], ["\u0431", "\u0411"], ["\u044E", "\u042E"], [".", ","], ["Shift", "Shift"]], + [[" ", " "]] + ], + Slovenian: [ // Slovenian Standard Keyboard + [["\u00a8", "\u00a8", "\u00b8"], ["1", "!", "~"], ["2", '"', "\u02c7"], ["3", "#", "^"], ["4", "$", "\u02d8"], ["5", "%", "\u00b0"], ["6", "&", "\u02db"], ["7", "/", "\u0060"], ["8", "(", "\u00B7"], ["9", ")", "\u00b4"], ["0", "=", "\u2033"], ["'", "?", "\u00a8"], ["+", "*", "\u00b8"], ["Bksp", "Bksp"]], + [["Tab", "Tab"], ["q", "Q", "\\"], ["w", "W","|"], ["e", "E", "\u20ac"], ["r", "R"], ["t", "T"], ["z", "Z"], ["u", "U"], ["i", "I"], ["o", "O"], ["p", "P"], ["\u0161", "\u0160", "\u00f7"], ["\u0111", "\u0110", "\u00d7"], ["Enter", "Enter"]], + [["Caps", "Caps"], ["a", "A"], ["s", "S"], ["d", "D"], ["f", "F", "["], ["g", "G", "]"], ["h", "H"], ["j", "J"], ["k", "K", "\u0142"], ["l", "L", "\u0141"], ["\u010D", "\u010C"], ["\u0107", "\u0106", "\u00df"], ["\u017E", "\u017D", "\u00a4"]], + [["Shift", "Shift"], ["<", ">"], ["y", "Y"], ["x", "X"], ["c", "C"], ["v", "V", "@"], ["b", "B", "{",], ["n", "N", "}"], ["m", "M", "\u00a7"], [",", ";"], [".", ":"], ["-", "_"], ["Shift", "Shift"]], + [[" ", " ", " ", " "], ["AltGr", "AltGr"]] + ], + "Spanish-SP": [ // Spanish (Spain) Standard Keyboard + [["\u00ba", "\u00aa", "\\"], ["1", "!", "|"], ["2", '"', "@"], ["3", "'", "#"], ["4", "$", "~"], ["5", "%", "\u20ac"], ["6", "&","\u00ac"], ["7", "/"], ["8", "("], ["9", ")"], ["0", "="], ["'", "?"], ["\u00a1", "\u00bf"], ["Bksp", "Bksp"]], + [["Tab", "Tab"], ["q", "Q"], ["w", "W"], ["e", "E"], ["r", "R"], ["t", "T"], ["y", "Y"], ["u", "U"], ["i", "I"], ["o", "O"], ["p", "P"], ["\u0060", "^", "["], ["\u002b", "\u002a", "]"], ["Enter", "Enter"]], + [["Caps", "Caps"], ["a", "A"], ["s", "S"], ["d", "D"], ["f", "F"], ["g", "G"], ["h", "H"], ["j", "J"], ["k", "K"], ["l", "L"], ["\u00f1", "\u00d1"], ["\u00b4", "\u00a8", "{"], ["\u00e7", "\u00c7", "}"]], + [["Shift", "Shift"], ["<", ">"], ["z", "Z"], ["x", "X"], ["c", "C"], ["v", "V"], ["b", "B"], ["n", "N"], ["m", "M"], [",", ";"], [".", ":"], ["-", "_"], ["Shift", "Shift"]], + [[" ", " ", " ", " "], ["AltGr", "AltGr"]] + ], + "Turkish-F": [ // Turkish F Keyboard Layout + [['+', "*", "\u00ac"], ["1", "!", "\u00b9", "\u00a1"], ["2", '"', "\u00b2"], ["3", "^", "#", "\u00b3"], ["4", "$", "\u00bc", "\u00a4"], ["5", "%", "\u00bd"], ["6", "&", "\u00be"], ["7", "'", "{"], ["8", "(", '['], ["9", ")", ']'], ["0", "=", "}"], ["/", "?", "\\", "\u00bf"], ["-", "_", "|"], ["Bksp", "Bksp"]], + [["Tab", "Tab"], ["f", "F", "@"], ["g", "G"], ["\u011f", "\u011e"], ["\u0131", "\u0049", "\u00b6", "\u00ae"], ["o", "O"], ["d", "D", "\u00a5"], ["r", "R"], ["n", "N"], ["h", "H", "\u00f8", "\u00d8"], ["p", "P", "\u00a3"], ["q", "Q", "\u00a8"], ["w", "W", "~"], ["Enter", "Enter"]], + [["Caps", "Caps"], ["u", "U", "\u00e6", "\u00c6"], ["i", "\u0130", "\u00df", "\u00a7"], ["e", "E", "\u20ac"], ["a", "A", " ", "\u00aa"], ["\u00fc", "\u00dc"], ["t", "T"], ["k", "K"], ["m", "M"], ["l", "L"], ["y", "Y", "\u00b4"], ["\u015f", "\u015e"], ["x", "X", "`"]], + [["Shift", "Shift"], ["<", ">", "|", "\u00a6"], ["j", "J", "\u00ab", "<"], ["\u00f6", "\u00d6", "\u00bb", ">"], ["v", "V", "\u00a2", "\u00a9"], ["c", "C"], ["\u00e7", "\u00c7"], ["z", "Z"], ["s", "S", "\u00b5", "\u00ba"], ["b", "B", "\u00d7"], [".", ":", "\u00f7"], [",", ";", "-"], ["Shift", "Shift"]], + [[" ", " ", " ", " "], ["AltGr", "AltGr"]] + ], + "Turkish-Q": [ // Turkish Q Keyboard Layout + [['"', "\u00e9", "<"], ["1", "!", ">"], ["2", "'", "\u00a3"], ["3", "^", "#"], ["4", "+", "$"], ["5", "%", "\u00bd"], ["6", "&"], ["7", "/", "{"], ["8", "(", '['], ["9", ")", ']'], ["0", "=", "}"], ["*", "?", "\\"], ["-", "_", "|"], ["Bksp", "Bksp"]], + [["Tab", "Tab"], ["q", "Q", "@"], ["w", "W"], ["e", "E", "\u20ac"], ["r", "R"], ["t", "T"], ["y", "Y"], ["u", "U"], ["\u0131", "\u0049", "\u0069", "\u0130"], ["o", "O"], ["p", "P"], ["\u011f", "\u011e", "\u00a8"], ["\u00fc", "\u00dc", "~"], ["Enter", "Enter"]], + [["Caps", "Caps"], ["a", "A", "\u00e6", "\u00c6"], ["s", "S", "\u00df"], ["d", "D"], ["f", "F"], ["g", "G"], ["h", "H"], ["j", "J"], ["k", "K"], ["l", "L"], ["\u015f", "\u015e", "\u00b4"], ["\u0069", "\u0130"], [",", ";", "`"]], + [["Shift", "Shift"], ["<", ">", "|"], ["z", "Z"], ["x", "X"], ["c", "C"], ["v", "V"], ["b", "B"], ["n", "N"], ["m", "M"], ["\u00f6", "\u00d6"], ["\u00e7", "\u00c7"], [".", ":"], ["Shift", "Shift"]], + [[" ", " ", " ", " "], ["AltGr", "AltGr"]] + ], + UK: [ // UK Standard Keyboard + [["`", "\u00ac", "\u00a6"], ["1", "!"], ["2", '"'], ["3", "\u00a3"], ["4", "$", "\u20ac"], ["5", "%"], ["6", "^"], ["7", "&"], ["8", "*"], ["9", "("], ["0", ")"], ["-", "_"], ["=", "+"], ["Bksp", "Bksp"]], + [["Tab", "Tab"], ["q", "Q"], ["w", "W"], ["e", "E", "\u00e9", "\u00c9"], ["r", "R"], ["t", "T"], ["y", "Y"], ["u", "U", "\u00fa", "\u00da"], ["i", "I", "\u00ed", "\u00cd"], ["o", "O", "\u00f3", "\u00d3"], ["p", "P"], ["[", "{"], ["]", "}"], ["Enter", "Enter"]], + [["Caps", "Caps"], ["a", "A", "\u00e1", "\u00c1"], ["s", "S"], ["d", "D"], ["f", "F"], ["g", "G"], ["h", "H"], ["j", "J"], ["k", "K"], ["l", "L"], [";", ":"], ["'", "@"], ["#", "~"]], + [["Shift", "Shift"], ["\\", "|"], ["z", "Z"], ["x", "X"], ["c", "C"], ["v", "V"], ["b", "B"], ["n", "N"], ["m", "M"], [",", "<"], [".", ">"], ["/", "?"], ["Shift", "Shift"]], + [[" ", " ", " ", " "], ["AltGr", "AltGr"]] + ], + US: [ // US Standard Keyboard + [["`", "~"], ["1", "!"], ["2", "@"], ["3", "#"], ["4", "$"], ["5", "%"], ["6", "^"], ["7", "&"], ["8", "*"], ["9", "("], ["0", ")"], ["-", "_"], ["=", "+"], ["Bksp", "Bksp"]], + [["Tab", "Tab"], ["q", "Q"], ["w", "W"], ["e", "E"], ["r", "R"], ["t", "T"], ["y", "Y"], ["u", "U"], ["i", "I"], ["o", "O"], ["p", "P"], ["[", "{"], ["]", "}"], ["\\", "|"]], + [["Caps", "Caps"], ["a", "A"], ["s", "S"], ["d", "D"], ["f", "F"], ["g", "G"], ["h", "H"], ["j", "J"], ["k", "K"], ["l", "L"], [";", ":"], ["'", '"'], ["Enter", "Enter"]], + [["Shift", "Shift"], ["z", "Z"], ["x", "X"], ["c", "C"], ["v", "V"], ["b", "B"], ["n", "N"], ["m", "M"], [",", "<"], [".", ">"], ["/", "?"], ["Shift", "Shift"]], + [[" ", " "]] + ], + "US Int'l": [ // US International Keyboard + [["`", "~"], ["1", "!", "\u00a1", "\u00b9"], ["2", "@", "\u00b2"], ["3", "#", "\u00b3"], ["4", "$", "\u00a4", "\u00a3"], ["5", "%", "\u20ac"], ["6", "^", "\u00bc"], ["7", "&", "\u00bd"], ["8", "*", "\u00be"], ["9", "(", "\u2018"], ["0", ")", "\u2019"], ["-", "_", "\u00a5"], ["=", "+", "\u00d7", "\u00f7"], ["Bksp", "Bksp"]], + [["Tab", "Tab"], ["q", "Q", "\u00e4", "\u00c4"], ["w", "W", "\u00e5", "\u00c5"], ["e", "E", "\u00e9", "\u00c9"], ["r", "R", "\u00ae"], ["t", "T", "\u00fe", "\u00de"], ["y", "Y", "\u00fc", "\u00dc"], ["u", "U", "\u00fa", "\u00da"], ["i", "I", "\u00ed", "\u00cd"], ["o", "O", "\u00f3", "\u00d3"], ["p", "P", "\u00f6", "\u00d6"], ["[", "{", "\u00ab"], ["]", "}", "\u00bb"], ["\\", "|", "\u00ac", "\u00a6"]], + [["Caps", "Caps"], ["a", "A", "\u00e1", "\u00c1"], ["s", "S", "\u00df", "\u00a7"], ["d", "D", "\u00f0", "\u00d0"], ["f", "F"], ["g", "G"], ["h", "H"], ["j", "J"], ["k", "K"], ["l", "L", "\u00f8", "\u00d8"], [";", ":", "\u00b6", "\u00b0"], ["'", '"', "\u00b4", "\u00a8"], ["Enter", "Enter"]], + [["Shift", "Shift"], ["z", "Z", "\u00e6", "\u00c6"], ["x", "X"], ["c", "C", "\u00a9", "\u00a2"], ["v", "V"], ["b", "B"], ["n", "N", "\u00f1", "\u00d1"], ["m", "M", "\u00b5"], [",", "<", "\u00e7", "\u00c7"], [".", ">"], ["/", "?", "\u00bf"], ["Shift", "Shift"]], + [[" ", " ", " ", " "], ["Alt", "Alt"]] + ] + }, + deadKey: { + '"': [ // Umlaut / Diaeresis / Greek Dialytika + ["a", "\u00e4"], ["e", "\u00eb"], ["i", "\u00ef"], ["o", "\u00f6"], ["u", "\u00fc"], ["y", "\u00ff"], ["\u03b9", "\u03ca"], ["\u03c5", "\u03cb"], + ["A", "\u00c4"], ["E", "\u00cb"], ["I", "\u00cf"], ["O", "\u00d6"], ["U", "\u00dc"], ["Y", "\u0178"], ["\u0399", "\u03aa"], ["\u03a5", "\u03ab"] + ], + '\u00a8': [ // Umlaut / Diaeresis / Greek Dialytika + ["a", "\u00e4"], ["e", "\u00eb"], ["i", "\u00ef"], ["o", "\u00f6"], ["u", "\u00fc"], ["y", "\u00ff"], ["\u03b9", "\u03ca"], ["\u03c5", "\u03cb"], + ["A", "\u00c4"], ["E", "\u00cb"], ["I", "\u00cf"], ["O", "\u00d6"], ["U", "\u00dc"], ["Y", "\u0178"], ["\u0399", "\u03aa"], ["\u03a5", "\u03ab"] + ], + '~': [ // Tilde + ["a", "\u00e3"], ["o", "\u00f5"], ["n", "\u00f1"], + ["A", "\u00c3"], ["O", "\u00d5"], ["N", "\u00d1"] + ], + '^': [ // Circumflex + ["a", "\u00e2"], ["e", "\u00ea"], ["i", "\u00ee"], ["o", "\u00f4"], ["u", "\u00fb"], ["w", "\u0175"], ["y", "\u0177"], + ["A", "\u00c2"], ["E", "\u00ca"], ["I", "\u00ce"], ["O", "\u00d4"], ["U", "\u00db"], ["W", "\u0174"], ["Y", "\u0176"] + ], + '\u02c7': [ // Baltic caron + ["c", "\u010D"], ["s", "\u0161"], ["z", "\u017E"], ["r", "\u0159"], ["d", "\u010f"], ["t", "\u0165"], ["n", "\u0148"], ["l", "\u013e"], ["e", "\u011b"], + ["C", "\u010C"], ["S", "\u0160"], ["Z", "\u017D"], ["R", "\u0158"], ["D", "\u010e"], ["T", "\u0164"], ["N", "\u0147"], ["L", "\u013d"], ["E", "\u011a"] + ], + '\u02d8': [ // Romanian and Turkish breve + ["a", "\u0103"], ["g", "\u011f"], + ["A", "\u0102"], ["G", "\u011e"] + ], + '`': [ // Grave + ["a", "\u00e0"], ["e", "\u00e8"], ["i", "\u00ec"], ["o", "\u00f2"], ["u", "\u00f9"], + ["A", "\u00c0"], ["E", "\u00c8"], ["I", "\u00cc"], ["O", "\u00d2"], ["U", "\u00d9"] + ], + "'": [ // Acute / Greek Tonos + ["a", "\u00e1"], ["e", "\u00e9"], ["i", "\u00ed"], ["o", "\u00f3"], ["u", "\u00fa"], ["\u03b1", "\u03ac"], ["\u03b5", "\u03ad"], ["\u03b7", "\u03ae"], ["\u03b9", "\u03af"], ["\u03bf", "\u03cc"], ["\u03c5", "\u03cd"], ["\u03c9", "\u03ce"], + ["A", "\u00c1"], ["E", "\u00c9"], ["I", "\u00cd"], ["O", "\u00d3"], ["U", "\u00da"], ["\u0391", "\u0386"], ["\u0395", "\u0388"], ["\u0397", "\u0389"], ["\u0399", "\u038a"], ["\u039f", "\u038c"], ["\u03a5", "\u038e"], ["\u03a9", "\u038f"] + ], + '\u00b4':[ // Acute / Greek Tonos + ["a", "\u00e1"], ["e", "\u00e9"], ["i", "\u00ed"], ["o", "\u00f3"], ["u", "\u00fa"], ["\u03b1", "\u03ac"], ["\u03b5", "\u03ad"], ["\u03b7", "\u03ae"], ["\u03b9", "\u03af"], ["\u03bf", "\u03cc"], ["\u03c5", "\u03cd"], ["\u03c9", "\u03ce"], + ["A", "\u00c1"], ["E", "\u00c9"], ["I", "\u00cd"], ["O", "\u00d3"], ["U", "\u00da"], ["\u0391", "\u0386"], ["\u0395", "\u0388"], ["\u0397", "\u0389"], ["\u0399", "\u038a"], ["\u039f", "\u038c"], ["\u03a5", "\u038e"], ["\u03a9", "\u038f"] + ], + '\u0384': [ // Acute / Greek Tonos + ["a", "\u00e1"], ["e", "\u00e9"], ["i", "\u00ed"], ["o", "\u00f3"], ["u", "\u00fa"], ["\u03b1", "\u03ac"], ["\u03b5", "\u03ad"], ["\u03b7", "\u03ae"], ["\u03b9", "\u03af"], ["\u03bf", "\u03cc"], ["\u03c5", "\u03cd"], ["\u03c9", "\u03ce"], + ["A", "\u00c1"], ["E", "\u00c9"], ["I", "\u00cd"], ["O", "\u00d3"], ["U", "\u00da"], ["\u0391", "\u0386"], ["\u0395", "\u0388"], ["\u0397", "\u0389"], ["\u0399", "\u038a"], ["\u039f", "\u038c"], ["\u03a5", "\u038e"], ["\u03a9", "\u038f"] + ], + '\u02dd': [ // Hungarian Double Acute Accent + ["o", "\u0151"], ["u", "\u0171"], + ["O", "\u0150"], ["U", "\u0170"] + ], + '\u0385': [ // Greek Dialytika + Tonos + ["\u03b9", "\u0390"], ["\u03c5", "\u03b0"] + ], + '\u00b0': [ // Ring + ["a", "\u00e5"], + ["A", "\u00c5"] + ], + '\u00ba': [ // Ring + ["a", "\u00e5"], + ["A", "\u00c5"] + ] + }, + + initComponent : function(options){ + Ext.ux.VirtualKeyboard.superclass.initComponent.call(this); + + Ext.apply(this, { + language: this.language || 'US', + deadKeysButtonText: this.deadKeysButtonText || 'Type accented letters', + //deadKeysButtonTip: this.deadKeysButtonTip || 'Dead keys are used to generate accented letters', + autoDestroy: true + }); + + Ext.apply(this, options); + + this.addEvents( + 'keypress' + ); + + /*this.on('beforedestroy', function(){ + this.keyboard.removeAllListeners(); + delete this.keyboard; + }, this);*/ + + }, + + onRender: function(ct, position){ + this.initKeyboard(ct); + Ext.ux.VirtualKeyboard.superclass.onRender.call(this, ct, position); + }, + + initKeyboard : function(ct){ + this.keyboardTarget.el.on('click', this.IESel, this); + this.keyboardTarget.el.on('keyup', this.IESel, this); + this.keyboardTarget.el.on('select', this.IESel, this); + + this.keyboard = ct.createChild({ + tag: 'div', + cls: 'x-keyboard x-panel' + }); + + this.keyboard.setStyle({width: this.width || 370}); + + var layouts = 0; + for (lang in this.Languages) if (typeof this.Languages[lang] == "object") layouts++; + + var dh = Ext.DomHelper; + + var ktbarItems = []; + + if (this.languageSelection) { + + var values = []; + for (ktype in this.Languages) { + if (typeof this.Languages[ktype] == "object") { + values.push([ktype, ktype]); + } + } + + this.languageSelector = new Ext.form.ComboBox({ + store: values, + forceSelection: true, + triggerAction: 'all', + editable: false, + readOnly: true, + height: 15, + width: 100, + value: this.language, + listeners: { + 'select': function(combo, record) { + this.language = record.data.value; + this.buildKeys(); + }, + expand: function(){ + this.selectingLanguage = true; + }, + collapse: function(){ + this.selectingLanguage = false; + }, + scope: this + } + }); + ktbarItems.push(this.languageSelector); + } + else{ + ktbarItems.push(this.language); + } + ktbarItems.push('-', { + text: this.deadKeysButtonText, + iconCls: 'ux-accented-icon', + //tooltip: this.deadKeysButtonTip, + enableToggle: true, + listeners: { + toggle: function(btn, pressed){ + this.deadKeysOn = pressed; + this.keyModify(""); + }, + scope: this + } + }); + + this.ktbar = new Ext.Toolbar({ + renderTo: this.keyboard, + items: ktbarItems + }); + + if (!this.languageSelection){ + Ext.fly(this.ktbar.items.items[0].getEl()).setStyle({fontWeight: 'bold'}); + } + + var wrap = this.keyboard.createChild({ + tag: 'div', + cls: 'x-panel-bwrap' + }); + + var mc = wrap.createChild({ + tag: 'div', + cls: 'x-panel-body' + }); + + this.keysContainer = mc.createChild({ + tag: 'div' + }); + + this.buildKeys(); + }, + + getTBar: function(){ + return this.ktbar; + }, + + buildKeys: function() { + this.shift = this.capslock = this.alternate = this.dead = false; + //this.deadKeysOn = (this.layoutDDK[this.language]) ? false : this.deadCheckbox.checked; + + this.keysContainer.update(''); + + var dh = Ext.DomHelper; + + for (var x = 0, hasdeadKey = false, lyt; lyt = this.Languages[this.language][x++];) { + var table = dh.append(this.keysContainer, { + tag: 'table', + cellSpacing: '1', + cellPadding:'0', + border: '0', + cls: (lyt.length <= this.keyCenter ? 'keyboardInputCenter' : '') + ' keys', + align: (lyt.length <= this.keyCenter ? 'center' : ''), + html: '' + }); + + if(Ext.isIE && table.firstChild){ + table.removeChild(table.firstChild); + + } + var tbody = dh.append(table, {tag: 'tbody'}); + var tr = dh.append(tbody, {tag: 'tr'}); + + for (var y = 0, lkey; lkey = lyt[y++];) { + if (!this.layoutDDK[this.language] && !hasdeadKey){ + for (var z = 0; z < lkey.length; z++){ + if (this.deadKey[lkey[z]]){ + hasdeadKey = true; + break; + } + } + } + + var alive = false; + if (this.deadKeysOn){ + for (key in this.deadKey){ + if (key === lkey[0]){ + alive = true; + } + } + } + //var cls = ['x-btn', 'x-btn-center']; + var cls = []; + if(alive) + cls.push('alive'); + if (lyt.length > this.keyCenter && y == lyt.length) + cls.push('last'); + + var td = dh.append(tr, { + tag: 'td', + cls: cls.join(' '), + html: lkey[0] == " " ? " " : lkey[0] + }); + + if (lkey[0] == " ") + td.id = "spacebar"; + + Ext.fly(td).on('mouseover', function(event, target) { if (!Ext.fly(target).hasClass('dead') && target.firstChild.nodeValue != "\xa0") Ext.fly(target).addClass('hover'); }); + Ext.fly(td).on('mouseout', function(event, target) { if (!Ext.fly(target).hasClass('dead')) Ext.fly(target).removeClass(['hover', 'pressed']); }); + Ext.fly(td).on('mousedown', function(event, target) { if (!Ext.fly(target).hasClass('dead')) Ext.fly(target).addClass('pressed'); }); + Ext.fly(td).on('mouseup', function(event, target) { if (!Ext.fly(target).hasClass('dead') && target.firstChild.nodeValue != "\xa0") Ext.fly(target).removeClass('pressed'); }); + Ext.fly(td). swallowEvent('dblclick', true); + + td.modifier = lkey[1]; + + switch (lkey[1]) { + case "Caps": + case "Shift": + case "Alt": + case "AltGr": + Ext.fly(td).on('click', function(event, target) { + this.keyModify(target.modifier); + }, this, {stopEvent: true}); + break; + case "Tab": + Ext.fly(td).on('click', function(event, target) { + this.keyInsert("\t"); + }, this, {stopEvent: true}); + break; + case "Bksp": + Ext.fly(td).on('click', function() { + this.keyboardTarget.focus(); + var dom = this.keyboardTarget.el.dom; + if (dom.setSelectionRange) { + var srt = dom.selectionStart; + var len = dom.selectionEnd; + if (srt < len) srt++; + this.keyboardTarget.setValue(dom.value.substr(0, srt - 1) + dom.value.substr(len)); + dom.setSelectionRange(srt - 1, srt - 1); + } else if (dom.createTextRange) { + try { this.range.select(); } catch(e) {} + this.range = document.selection.createRange(); + if (!this.range.text.length) + this.range.moveStart('character', -1); + this.range.text = ""; + } else this.keyboardTarget.setValue(dom.value.substr(0, dom.value.length - 1)); + if (this.shift) this.keyModify("Shift"); + if (this.alternate) this.keyModify("AltGr"); + return true; + }, this); + break; + + case "Enter": + //if (self.keyboardTarget.nodeName == "TEXTAREA") { this.keyInsert("\n"); } else self.VKI_close(); + Ext.fly(td).on('click', function(event, target) { + this.keyInsert("\n"); + }, this, {stopEvent: true}); + break; + + default: + Ext.fly(td).on('click', function(event, target) { + var keyValue = target.firstChild.nodeValue; + if(keyValue == "\xa0"){ + keyValue = " "; + } + if (this.deadKeysOn && this.dead) { + if (this.dead != keyValue) { + for (key in this.deadKey) { + if (key == this.dead) { + if (keyValue != " ") { + for (var z = 0, rezzed = false, dk; dk = this.deadKey[key][z++];) { + if (dk[0] == keyValue) { + this.keyInsert(dk[1]); + rezzed = true; + break; + } + } + } else { + this.keyInsert(this.dead); + rezzed = true; + } + break; + } + } + } else rezzed = true; + } + this.dead = false; + + if (!rezzed && keyValue != "\xa0") { + if (this.deadKeysOn) { + for (key in this.deadKey) { + if (key == keyValue) { + this.dead = key; + this.className = "dead"; + if (this.shift) this.keyModify("Shift"); + if (this.alternate) this.keyModify("AltGr"); + break; + } + } + if (!this.dead) this.keyInsert(keyValue); + } else this.keyInsert(keyValue); + } + this.keyModify(""); + }, this, {stopEvent: true}); + delete td; + } + delete tr + for (var z = lkey.length; z < 4; z++) lkey[z] = "\xa0"; + } + delete table; + delete tbody; + } + }, + + keyModify: function(type){ + switch (type) { + case "Alt": + case "AltGr": this.alternate = !this.alternate; break; + case "Caps": this.capslock = !this.capslock; break; + case "Shift": this.shift = !this.shift; break; + } + var vchar = 0; + if (!this.shift != !this.capslock) vchar += 1; + + var tables = this.keyboard.select('table.keys'); + for (var x = 0; x < tables.getCount(); x++) { + var tds = tables.item(x).select('td'); + for (var y = 0; y < tds.getCount(); y++) { + td = tds.item(y); + var dead = alive = isTarget = false; + if(!this.Languages[this.language][x]){ + //alert('stop'); + } + + var lkey = this.Languages[this.language][x][y]; + + switch (lkey[1]) { + case "Alt": + case "AltGr": + if (this.alternate) dead = true; + break; + case "Shift": + if (this.shift) dead = true; + break; + case "Caps": + if (this.capslock) dead = true; + break; + case "Tab": + case "Enter": + case "Bksp": + break; + default: + var char = lkey[vchar + ((this.alternate && lkey.length == 4) ? 2 : 0)]; + if (type) + td.update(char); + if (this.deadKeysOn) { + if (this.dead) { + if (char == this.dead) + dead = true; + for (var z = 0; z < this.deadKey[this.dead].length; z++){ + if (char == this.deadKey[this.dead][z][0]) { + isTarget = true; + break; + } + } + } + for (key in this.deadKey){ + if (key === char) { + alive = true; + break; + } + } + } + } + td.dom.className = (dead) ? "dead" : ((isTarget) ? "target" : ((alive) ? "alive" : "")); + if (y == tds.getCount() - 1 && tds.getCount() > this.keyCenter) td.addClass('last'); + } + } + }, + + keyInsert: function(keyValue){ + this.fireEvent('keyPress', this, keyValue); + + if(this.keyboardTarget){ + this.keyboardTarget.focus(); + var dom = this.keyboardTarget.el.dom; + if (dom.setSelectionRange) { + var srt = dom.selectionStart; + var len = dom.selectionEnd; + dom.value = dom.value.substr(0, srt) + keyValue + dom.value.substr(len); + if (keyValue == "\n" && window.opera) srt++; + dom.setSelectionRange(srt + keyValue.length, srt + keyValue.length); + } else if (dom.createTextRange) { + try { this.range.select(); } catch(e) {} + this.range = document.selection.createRange(); + this.range.text = keyValue; + this.range.collapse(true); + this.range.select(); + } else + this.keyboardTarget.setValue(this.keyboardTarget.getValue() + keyValue); + if (this.shift) this.keyModify("Shift"); + if (this.alternate) this.keyModify("AltGr"); + this.keyboardTarget.focus(); + } + }, + + getXType: function(){ + return 'virtualkeyboard'; + }, + + IESel: function (event, target){ + if (target.createTextRange){ + this.range = document.selection.createRange(); + } + } +}); + +Ext.reg('virtualkeyboard', Ext.ux.VirtualKeyboard); diff --git a/gulliver/system/class.g.php b/gulliver/system/class.g.php index 90c27c023..76c51c0de 100755 --- a/gulliver/system/class.g.php +++ b/gulliver/system/class.g.php @@ -169,7 +169,7 @@ class G * @access public * @return string */ - /*public static*/ function &getVersion( ) + function &getVersion( ) { //majorVersion.minorVersion-SvnRevision return '3.0-1'; @@ -179,7 +179,7 @@ class G * getIpAddress * @return string $ip */ - /*public static*/ function getIpAddress () + function getIpAddress () { if (getenv('HTTP_CLIENT_IP')) { $ip = getenv('HTTP_CLIENT_IP'); @@ -532,7 +532,7 @@ class G /*************** path functions *****************/ - /*public static*/ function mk_dir( $strPath, $rights = 0777) + function mk_dir( $strPath, $rights = 0777) { $folder_path = array($strPath); $oldumask = umask(0); @@ -588,7 +588,7 @@ class G * @param boolean $createPath if true this function will create the path * @return boolean */ - /*public static*/ function verifyPath( $strPath , $createPath = false ) + function verifyPath( $strPath , $createPath = false ) { $folder_path = strstr($strPath, '.') ? dirname($strPath) : $strPath; @@ -910,15 +910,15 @@ class G * @param string $urlLink * @return string */ - function parseURI( $uri ) + function parseURI($uri, $config = array()) { $aRequestUri = explode('/', $uri ); + if ( substr ( $aRequestUri[1], 0, 3 ) == 'sys' ) { define( 'SYS_TEMP', substr ( $aRequestUri[1], 3 ) ); } else { define("ENABLE_ENCRYPT", 'yes' ); - define( 'SYS_TEMP', $aRequestUri[1] ); $plain = '/sys' . SYS_TEMP; @@ -962,8 +962,9 @@ class G unset($toparse); array_shift($URI_VARS); - define("SYS_LANG", array_shift($URI_VARS)); - define("SYS_SKIN", array_shift($URI_VARS)); + + $SYS_LANG = array_shift($URI_VARS); + $SYS_SKIN = array_shift($URI_VARS); $SYS_COLLECTION = array_shift($URI_VARS); $SYS_TARGET = array_shift($URI_VARS); @@ -973,8 +974,26 @@ class G while ( count ( $URI_VARS ) > 0 && $exit == 0) { $SYS_TARGET .= '/' . array_shift($URI_VARS); } - define('SYS_COLLECTION', $SYS_COLLECTION ); - define('SYS_TARGET', $SYS_TARGET ); + + // if ($SYS_TARGET == 'login') { + // if (isset($config['default_lang']) && !empty($config['default_lang'])) { + // $SYS_LANG = $config['default_lang']; + // } + + // if (isset($config['default_skin']) && !empty($config['default_skin'])) { + // $SYS_SKIN = $config['default_skin']; + // } + // } + + /* Fix to prevent use uxs skin outside siplified interface, because that skin is not compatible with others interfaces*/ + if ($SYS_SKIN == 'uxs' && $SYS_COLLECTION !== 'home') { + $SYS_SKIN = 'classic'; + } + + define("SYS_LANG", $SYS_LANG); + define("SYS_SKIN", $SYS_SKIN); + define('SYS_COLLECTION', $SYS_COLLECTION); + define('SYS_TARGET', $SYS_TARGET); if ( $SYS_COLLECTION == 'js2' ) { print "ERROR"; die; @@ -1148,6 +1167,14 @@ $output = $outputHeader.$output; { header('Content-Type: text/javascript'); + if (!G::LoadTranslationObject($locale)) { + header('Cache-Control: no-cache'); + header('Pragma: no-cache'); + return; + } + + global $translation; + //if userAgent (BROWSER) is MSIE we need special headers to avoid MSIE behaivor. $userAgent = strtolower($_SERVER['HTTP_USER_AGENT']); if ( file_exists($filename) ) @@ -1174,11 +1201,7 @@ $output = $outputHeader.$output; } } - $output = ''; - G::LoadTranslationObject($locale); - global $translation; - $output .= JSMin::minify ( 'var TRANSLATIONS = ' . G::json_encode($translation) . ';' ); - return $output; + return JSMin::minify ( 'var TRANSLATIONS = ' . G::json_encode($translation) . ';' ); } /** @@ -1283,8 +1306,7 @@ $output = $outputHeader.$output; $checksum = G::getCheckSum(array( $pathJs . 'ext/wz_jsgraphics.js', $pathJs . 'ext/mootools.js', - $pathJs . 'ext/moocanvas.js', - $pathJs . 'ext/pmos-common.js' + $pathJs . 'ext/moocanvas.js' )); $cf = $cachePath . "ext-draw2d-cache.$checksum.js"; @@ -1300,7 +1322,6 @@ $output = $outputHeader.$output; $output .= JSMin::minify ( file_get_contents ( $pathJs . 'ext/mootools.js' ) ); $output .= JSMin::minify ( file_get_contents ( $pathJs . 'ext/moocanvas.js' ) ); $output .= file_get_contents ($pathJs . 'ext/draw2d.js'); //already minified - $output .= JSMin::minify ( file_get_contents ( $pathJs . 'ext/pmos-common.js' ) ); file_put_contents($cf, $output); //error_log("draw2d.js writting ".$cf); } @@ -1308,6 +1329,7 @@ $output = $outputHeader.$output; case 'ext-all.js' : $cachePath = PATH_C . 'ExtJs' . PATH_SEP; $checksum = G::getCheckSum(array( + $pathJs . 'ext/pmos-common.js', $pathJs . 'ext/ux/miframe.js', $pathJs . 'ext/ux.locationbar/Ext.ux.LocationBar.js', $pathJs . 'ext/ux.statusbar/ext-statusbar.js', @@ -1324,6 +1346,7 @@ $output = $outputHeader.$output; $output .= file_get_contents ( $pathJs . 'ext/ext-all.js' ); //already minified $output .= file_get_contents ( $pathJs . 'ext/ux/ux-all.js' ); //already minified + $output .= JSMin::minify ( file_get_contents ( $pathJs . 'ext/pmos-common.js' ) ); $output .= JSMin::minify ( file_get_contents ( $pathJs . 'ext/ux/miframe.js' ) ); $output .= JSMin::minify ( file_get_contents ( $pathJs . 'ext/ux.locationbar/Ext.ux.LocationBar.js' ) ); $output .= JSMin::minify ( file_get_contents ( $pathJs . 'ext/ux.statusbar/ext-statusbar.js' ) ); @@ -2192,6 +2215,8 @@ $output = $outputHeader.$output; $translation = $foreignTranslations; else $translation = array_merge($defaultTranslations, $foreignTranslations); + + return true; } /** @@ -3274,6 +3299,138 @@ $output = $outputHeader.$output; } return false; } + + /** + * Send a mail using phpmailer + * this method use the global smtp server connection stored on Configuration table + * this information is retrieved by the PMFunction getEmailConfiguration() + * + * @author Erik Amaru Ortiz + * @param string $from address that is sending the email + * @param string $fromName name of sender + * @param mixed $address the possibles values are: + * string + * array('email1', 'some name ') + * array('to'=>array('email1', 'some name '), 'cc'=>array(...), 'bcc'=>array(...)) + * @param string $subject contains the email subject + * @param string $body contains the email body (text plain or html) + * @return mixed boolean or string : if the email was sent successfully returns true, otherwise returns a string within error message + */ + function sendMail($from, $fromName, $address, $subject, $body) + { + // require_once "classes/class.pmFunctions.php"; + G::LoadClass("pmFunctions"); + G::LoadThirdParty('phpmailer', 'class.phpmailer'); + $setup = getEmailConfiguration(); + + if (count($setup) == 0 || !isset($setup['MESS_ENGINE']) || !isset($setup['MESS_SERVER']) + || !isset($setup['MESS_ENABLED']) || !isset($setup['MESS_RAUTH']) || $setup['MESS_SERVER'] == '') { + return G::LoadTranslation('ID_EMAIL_ENGINE_IS_NOT_CONFIGURED'); + } + + if (!$setup['MESS_ENABLED']) { + return G::LoadTranslation('ID_EMAIL_ENGINE_IS_NOT_ENABLED'); + } + + $mail = new PHPMailer(true); + $mail->From = $from != '' && $from ? $from : $setup['MESS_ACCOUNT']; + $mail->FromName = $fromName; + $mail->Subject = $subject; + $mail->Body = $body; + $mail->IsHTML (true); + $mail->IsSMTP(); + $mail->Host = $setup['MESS_SERVER']; + $mail->Port = $setup['MESS_PORT']; + $mail->SMTPAuth = isset($setup['MESS_RAUTH']) && $setup['MESS_RAUTH'] ? true : false; + $mail->Username = $setup['MESS_ACCOUNT']; + $mail->Password = $setup['MESS_PASSWORD']; + $mail->SMTPSecure = $setup['SMTPSecure']; + + $emailAddressList = G::envelopEmailAddresses($address); + + foreach ($emailAddressList['to'] as $emails) { + $mail->AddAddress($emails[0], $emails[1]); + } + foreach ($emailAddressList['cc'] as $emails) { + $mail->AddCC($emails[0], $emails[1]); + } + foreach ($emailAddressList['bcc'] as $emails) { + $mail->AddBCC($emails[0], $emails[1]); + } + + return $mail->Send() ? true : $mail->ErrorInfo; + } + + /** + * Envelope a emails collection from a string or array + * @author Erik Amaru Ortiz + * @param mixed $address the possibles values are: + * string + * array('email1', 'some name ') + * array('to'=>array('email1', 'some name '), 'cc'=>array(...), 'bcc'=>array(...)) + * @return array contains: + * array( + * 'to' => array('email@host.com', 'some name or empty string', array('email@host.com', '..'), ...), + * 'cc' => array('email@host.com', 'some name or empty string', ...), + * 'bcc' => array('email@host.com', 'some name or empty string', ...) + * ) + */ + function envelopEmailAddresses($address) + { + $emailAddressList = array(); + $emailAddressList['to'] = array(); + $emailAddressList['cc'] = array(); + $emailAddressList['bcc'] = array(); + $ereg = '/([\"\w\W\s]*\s*)?(<([\w\-\.]+@[\.-\w]+\.\w{2,3})+>)/'; + + if (!is_array($address)) { + if (preg_match($ereg, $address, $match)) + $emailAddressList['to'][] = array($match[3], $match[1]); + else + $emailAddressList['to'][] = array($address, ''); + } + else { + foreach ($address as $type => $emails) { + if (!is_array($emails)) { + if (preg_match($ereg, $emails, $match)) + $emailAddressList['to'][] = array($match[3], $match[1]); + else + $emailAddressList['to'][] = array($emails, ''); + } + else { + switch ($type) { + case 'cc': + foreach ($emails as $email) { + if (preg_match($ereg, $email, $match)) + $emailAddressList['cc'][] = array($match[3], $match[1]); + else + $emailAddressList['cc'][] = array($email, ''); + } + break; + case 'bcc': + foreach ($emails as $email) { + if (preg_match($ereg, $email, $match)) + $emailAddressList['bcc'][] = array($match[3], $match[1]); + else + $emailAddressList['bcc'][] = array($email, ''); + } + break; + case 'to': + default: + foreach ($emails as $email) { + if (preg_match($ereg, $email, $match)) + $emailAddressList['to'][] = array($match[3], $match[1]); + else + $emailAddressList['to'][] = array($email, ''); + } + break; + } + } + } + } + + return $emailAddressList; + } /** * Get the type of a variable @@ -4705,6 +4862,74 @@ function getDirectorySize($path,$maxmtime=0) $contents = file_put_contents($inifile, sprintf("\n%s = $s\n", $variable, $value)); } } + + function write_php_ini($file, $array) + { + $res = array(); + foreach($array as $key => $val) + { + if(is_array($val)) + { + $res[] = "[$key]"; + foreach($val as $skey => $sval) $res[] = "$skey = ".(is_numeric($sval) ? $sval : '"'.$sval.'"'); + } + else $res[] = "$key = ".(is_numeric($val) ? $val : '"'.$val.'"'); + } + file_put_contents($file, implode("\r\n", $res)); + } + + + /** + * Update a ini file passing a array values, this finction don not remove the original commets + * @author Erik Amaru Ortiz + */ + function update_php_ini($file, $array) + { + $iniLines = array(); + $iniContent = array(); + + if (file_exists($file)) { + $iniContent = file($file); + } + + foreach ($iniContent as $line) { + $line = trim($line); + $lineParts = explode(';', $line); + $setting = parse_ini_string($lineParts[0]); + + if (is_array($setting) && count($setting) > 0) { + list($key, ) = array_keys($setting); + + if (isset($array[$key])) { + $value = $array[$key]; + $line = "$key = ".(is_numeric($value) ? $value : '"'.$value.'"'); + $line .= isset($lineParts[1]) ? ' ;' . $lineParts[1] : ''; + unset($array[$key]); + + $lastComment = array_pop($iniLines); + if (strpos($lastComment, "Setting $key") === false) { + $iniLines[] = $lastComment; + } + + $iniLines[] = ";Setting $key - Updated by System on " . date('D d M, Y H:i:s'); + } + } + $iniLines[] = $line; + } + + // inserting new values + foreach ($array as $key => $value) { + $line = "$key = ".(is_numeric($value) ? $value : '"'.$value.'"'); + $iniLines[] = ''; + $iniLines[] = ";Setting $key - Created by System on " . date('D d M, Y H:i:s'); + $iniLines[] = $line; + } + + $content = implode("\r\n", $iniLines); + + file_put_contents($file, $content); + } + }; /** diff --git a/gulliver/system/class.headPublisher.php b/gulliver/system/class.headPublisher.php index 8a55de51e..4c4295330 100755 --- a/gulliver/system/class.headPublisher.php +++ b/gulliver/system/class.headPublisher.php @@ -57,6 +57,9 @@ class headPublisher { /* variable array, to store the variables generated in PHP, and used in JavaScript */ var $vars = array (); + /* tplVariable array, to store the variables for template power */ + var $tplVariable = array (); + var $leimnudInitString = ' var leimnud = new maborak(); leimnud.make({ zip:true, @@ -280,23 +283,11 @@ class headPublisher { $head = ''; $head .= " \n"; $head .= " \n"; -// $head .= " \n"; -/* - if (isset ( $this->extJsLibrary ) && is_array ( $this->extJsLibrary )) { - foreach ( $this->extJsLibrary as $file ) { - $head .= " \n"; - } - } - */ + + // enabled for particular use + $head .= $this->getExtJsLibraries(); + $head .= " \n"; - - //$head .= " \n"; - //$head .= " \n"; - //$head .= " \n"; - //$head .= " \n"; - //$head .= " \n"; - //$head .= " \n"; - $head .= " \n"; if (! isset ( $this->extJsSkin ) || $this->extJsSkin == '') { @@ -376,6 +367,17 @@ class headPublisher { return $script; } + function getExtJsLibraries() + { + $script = ''; + if (isset ( $this->extJsLibrary ) && is_array ( $this->extJsLibrary )) { + foreach ( $this->extJsLibrary as $file ) { + $script .= " \n"; + } + } + return $script; + } + /** * add a ExtJS extended library * @@ -468,8 +470,13 @@ class headPublisher { $this->extJsScript [] = '/extjs/' . $cacheName; //hook for registered javascripts from plugins - $oPluginRegistry = & PMPluginRegistry::getSingleton(); - $pluginJavascripts = $oPluginRegistry->getRegisteredJavascriptBy($filename); + if ( class_exists( 'PMPluginRegistry' ) ) { + $oPluginRegistry = & PMPluginRegistry::getSingleton(); + $pluginJavascripts = $oPluginRegistry->getRegisteredJavascriptBy($filename); + } + else + $pluginJavascripts = array(); + if (count($pluginJavascripts) > 0) { if ($debug) { foreach ($pluginJavascripts as $pluginJsFile) { @@ -599,6 +606,11 @@ class headPublisher { $template = new TemplatePower ( $sPath . $file . '.html' ); $template->prepare (); + + foreach ($this->getVars() as $k => $v) { + $template->assign($k, $v); + } + $body .= $template->getOutputContent (); } } diff --git a/gulliver/system/class.rbac.php b/gulliver/system/class.rbac.php index 29a25eed0..9f39409ec 100755 --- a/gulliver/system/class.rbac.php +++ b/gulliver/system/class.rbac.php @@ -155,29 +155,20 @@ class RBAC * @param string $sUser the user * @return $this->aUserInfo[ $sSystem ] */ - function loadUserRolePermission( $sSystem, $sUser, $pathData = null, $sid =null ) { - //if we provide a path data and session we will cache the session Info for this user - if ( $pathData != null && $sid != null ) { - $pathData = $pathData . 'session' . PATH_SEP; - $filePath = $pathData . $sid . '.rbac'; - if ( file_exists ( $filePath ) && filesize($filePath) > 0 ) { - $this->aUserInfo = unserialize( file_get_contents ( $filePath ) ); - return; - } - } + function loadUserRolePermission( $sSystem, $sUser ) { + //in previous versions we provided a path data and session we will cache the session Info for this user + //now this is deprecated, and all the aUserInfo is in the memcache + $this->sSystem = $sSystem; $fieldsSystem = $this->systemObj->loadByCode($sSystem); - $fieldsRoles = $this->usersRolesObj->getRolesBySystem ($fieldsSystem['SYS_UID'], $sUser ); + $fieldsRoles = $this->usersRolesObj->getRolesBySystem ($fieldsSystem['SYS_UID'], $sUser ); $fieldsPermissions = $this->usersRolesObj->getAllPermissions ($fieldsRoles['ROL_UID'], $sUser ); + $this->aUserInfo['USER_INFO'] = $this->userObj->load( $sUser); $this->aUserInfo[ $sSystem ]['SYS_UID'] = $fieldsSystem['SYS_UID']; - $this->aUserInfo[ $sSystem ]['ROLE'] = $fieldsRoles; + $this->aUserInfo[ $sSystem ]['ROLE'] = $fieldsRoles; $this->aUserInfo[ $sSystem ]['PERMISSIONS'] = $fieldsPermissions; - - if ( $pathData != null && $sid != null ) { - G::mk_dir ( $pathData ); - file_put_contents( $filePath, serialize ( $this->aUserInfo ) ); - } } + /** * verification the register automatic * @@ -308,6 +299,7 @@ class RBAC return $res; } else { + $this->userObj->reuseUserFields = true; $res = $this->userObj->VerifyLogin($strUser, $strPass); return $res; } diff --git a/workflow/engine/classes/class.processMap.php b/workflow/engine/classes/class.processMap.php index 4058a4e07..b37c09387 100755 --- a/workflow/engine/classes/class.processMap.php +++ b/workflow/engine/classes/class.processMap.php @@ -3133,6 +3133,7 @@ class processMap { */ function listNoProcessesUser($sProcessUID) { G::LoadSystem('rbac'); + $memcache = & PMmemcached::getSingleton(SYS_SYS); $oCriteria = new Criteria('workflow'); $oCriteria->addSelectColumn(ProcessUserPeer::USR_UID); @@ -3156,7 +3157,11 @@ class processMap { $aUIDS = array(); $oRBAC = RBAC::getSingleton (); while ($aRow = $oDataset->getRow()) { - $oRBAC->loadUserRolePermission($oRBAC->sSystem, $aRow ['USR_UID']); + $memKey = 'rbacSession' . session_id(); + if ( ($oRBAC->aUserInfo = $memcache->get($memKey)) === false ) { + $oRBAC->loadUserRolePermission($oRBAC->sSystem, $aRow ['USR_UID']); + $memcache->set( $memKey, $oRBAC->aUserInfo, PMmemcached::EIGHT_HOURS ); + } $aPermissions = $oRBAC->aUserInfo [$oRBAC->sSystem] ['PERMISSIONS']; $bInclude = false; foreach ($aPermissions as $aPermission) { @@ -5730,6 +5735,7 @@ class processMap { */ function listExtNoProcessesUser($sProcessUID) { G::LoadSystem('rbac'); + $memcache = & PMmemcached::getSingleton(SYS_SYS); $oCriteria = new Criteria('workflow'); $oCriteria->addSelectColumn(ProcessUserPeer::USR_UID); @@ -5753,7 +5759,11 @@ class processMap { $aUIDS = array(); $oRBAC = RBAC::getSingleton (); while ($aRow = $oDataset->getRow()) { - $oRBAC->loadUserRolePermission($oRBAC->sSystem, $aRow ['USR_UID']); + $memKey = 'rbacSession' . session_id(); + if ( ($oRBAC->aUserInfo = $memcache->get($memKey)) === false ) { + $oRBAC->loadUserRolePermission($oRBAC->sSystem, $aRow ['USR_UID']); + $memcache->set( $memKey, $oRBAC->aUserInfo, PMmemcached::EIGHT_HOURS ); + } $aPermissions = $oRBAC->aUserInfo [$oRBAC->sSystem] ['PERMISSIONS']; $bInclude = false; foreach ($aPermissions as $aPermission) { diff --git a/workflow/engine/classes/class.system.php b/workflow/engine/classes/class.system.php index 6e568eed0..2f95a1d3b 100755 --- a/workflow/engine/classes/class.system.php +++ b/workflow/engine/classes/class.system.php @@ -922,5 +922,134 @@ class System { return $config; } + + function getSkingList() + { + //Create Skins custom folder if it doesn't exists + if(!is_dir(PATH_CUSTOM_SKINS)){ + G::verifyPath(PATH_CUSTOM_SKINS, true); + } + + //Get Skin Config files + $skinListArray = array(); + $customSkins = glob(PATH_CUSTOM_SKINS . "*/config.xml"); + $configurationFile = G::ExpandPath("skinEngine") . 'base' . PATH_SEP . 'config.xml'; + array_unshift($customSkins, $configurationFile); + + //Read and parse each Configuration File + foreach ($customSkins as $key => $configInformation) { + $folderId = str_replace(G::ExpandPath("skinEngine") . 'base', "", str_replace(PATH_CUSTOM_SKINS, "", str_replace("/config.xml", "", $configInformation))); + + if ($folderId == "") { + $folderId = "classic"; + } + + $xmlConfiguration = file_get_contents($configInformation); + $xmlConfigurationObj = G::xmlParser($xmlConfiguration); + + if (isset($xmlConfigurationObj->result['skinConfiguration'])) { + $skinInformationArray = $skinFilesArray = $xmlConfigurationObj->result['skinConfiguration']['__CONTENT__']['information']['__CONTENT__']; + $res = array(); + $res['SKIN_FOLDER_ID'] = strtolower($folderId); + + foreach ($skinInformationArray as $keyInfo => $infoValue) { + $res['SKIN_' . strtoupper($keyInfo)] = $infoValue['__VALUE__']; + } + + $skinListArray['skins'][] = $res; + } + } + + $skinListArray['currentSkin'] = SYS_SKIN; + + return $skinListArray; + } + + function getAllTimeZones() + { + $timezones = DateTimeZone::listAbbreviations(); + + $cities = array(); + foreach( $timezones as $key => $zones ) + { + foreach( $zones as $id => $zone ) + { + /** + * Only get timezones explicitely not part of "Others". + * @see http://www.php.net/manual/en/timezones.others.php + */ + if ( preg_match( '/^(America|Antartica|Arctic|Asia|Atlantic|Africa|Europe|Indian|Pacific)\//', $zone['timezone_id'] ) + && $zone['timezone_id']) { + $cities[$zone['timezone_id']][] = $key; + } + } + } + + // For each city, have a comma separated list of all possible timezones for that city. + foreach( $cities as $key => $value ) + $cities[$key] = join( ', ', $value); + + // Only keep one city (the first and also most important) for each set of possibilities. + $cities = array_unique( $cities ); + + // Sort by area/city name. + ksort( $cities ); + + return $cities; + } + + public function getSystemConfiguration($iniFile='') + { + $config = array( + 'debug' => 0, + 'debug_sql' => 0, + 'debug_time' => 0, + 'debug_calendar' => 0, + 'wsdl_cache' => 1, + 'memory_limit' => '100M', + 'time_zone' => 'America/La_Paz', + 'memcached' => 0, + 'memcached_server' =>'', + 'default_skin' => 'classic', + 'default_lang' => 'en' + ); + + if (empty($iniFile) || !file_exists($iniFile)) { + return $config; + } + + /* Read the env.ini */ + $ini_contents = parse_ini_file($iniFile, false); + + if ($ini_contents !== false) { + $config = array_merge($config, $ini_contents); + } + //echo '
'; print_r($config); die;
+    return $config;
+  }
+
+  function updateIndexFile($conf)
+  {
+    if (!defined('PATH_TPL')) {
+      throw new Exception('PATH_TPL constant is not defined.');
+    }
+
+    if (!file_exists(PATH_HTML . 'index.html')) {
+      if (!is_writable(PATH_HTML)) {
+        throw new Exception('The public directory is not writable.');
+      }
+    }
+    else {
+      if (!is_writable(PATH_HTML . 'index.html')) {
+        throw new Exception('The public index file is not writable.');
+      }
+    }
+
+    $content = file_get_contents(PATH_TPL . 'index.html.tpl');
+    $content = str_replace('{lang}', $conf['lang'], $content);
+    $content = str_replace('{skin}', $conf['skin'], $content);
+
+    return (@file_put_contents(PATH_HTML . 'index.html', $content) !== false);
+  }
   
 }// end System class
diff --git a/workflow/engine/classes/model/UsersProperties.php b/workflow/engine/classes/model/UsersProperties.php
index 193efbd95..31e782cad 100755
--- a/workflow/engine/classes/model/UsersProperties.php
+++ b/workflow/engine/classes/model/UsersProperties.php
@@ -18,11 +18,14 @@ require_once 'classes/model/om/BaseUsersProperties.php';
  */
 class UsersProperties extends BaseUsersProperties 
 {
-  function UserPropertyExists($sUserUID) 
-  {
+  var $fields = null;
+	
+  function UserPropertyExists($sUserUID) {
     try {
       $oUserProperty = UsersPropertiesPeer::retrieveByPk($sUserUID);
-      if (is_object($oUserProperty) && get_class($oUserProperty) == 'UsersProperties') {
+      if (!is_null($oUserProperty) && is_object($oUserProperty) && get_class($oUserProperty) == 'UsersProperties') {
+        $this->fields = $oUserProperty->toArray(BasePeer::TYPE_FIELDNAME);
+        $this->fromArray($this->fields, BasePeer::TYPE_FIELDNAME);
         return true;
       }
       else {
@@ -124,7 +127,7 @@ class UsersProperties extends BaseUsersProperties
       $this->create($aUserProperty);
     }
     else {
-      $aUserProperty = $this->load($sUserUID);
+      $aUserProperty = $this->fields;
     }
     return $aUserProperty;
   }
@@ -219,6 +222,11 @@ class UsersProperties extends BaseUsersProperties
     }
     //end plugin
 
+    if (substr(SYS_SKIN, 0, 2) === 'ux' && SYS_SKIN != 'uxs') {
+      return '../main';
+    }
+
+
     /**
      * New feature - User Experience Redirector
      * @author Erik Amaru Ortiz 
diff --git a/workflow/engine/config/paths.php b/workflow/engine/config/paths.php
index 9e58954aa..d14d92ece 100755
--- a/workflow/engine/config/paths.php
+++ b/workflow/engine/config/paths.php
@@ -23,56 +23,6 @@
  *
  */
 
-  /* Default configuration values (do not change these, use env.ini) */
-  $default_config = array(
-    'debug' => 0,
-    'debug_sql' => 0,
-    'debug_time' => 0,
-    'debug_calendar' => 0,
-    'wsdl_cache' => 1,
-    'memory_limit' => '100M',
-    'time_zone' => 'America/La_Paz',
-    'memcached' => 0,
-    'memcached_server' => ''
-  );
-
-  /* Read the env.ini */
-  $env_file = realpath(dirname(__FILE__) . "/env.ini");
-  $config = $default_config;
-  if ($env_file !== false && file_exists($env_file)) {
-    $ini_contents = parse_ini_file($env_file, false);
-    if ($ini_contents !== false)
-      $config = array_merge($default_config, $ini_contents);
-  }
-  else {
-    // if the env.ini file doesn't exist, and the current is a developemnt env, then force enable debug
-    if (!file_exists ( PATH_TRUNK . 'workflow/engine/methods/login/version-pmos.php' )) {
-      $config['debug'] = 1;
-    }
-  }
-
-
-//*** Do not change any of these settings directly, use env.ini instead
-  ini_set('display_errors','On');
-
-  ini_set('short_open_tag', 'on');
-  ini_set('asp_tags', 'on');
-  // The register_globals feature has been DEPRECATED as of PHP 5.3.0. default value Off.
-  // ini_set('register_globals', 'off');
-  ini_set('default_charset', "UTF-8");
-  $e_all = defined('E_DEPRECATED') ? E_ALL ^ E_DEPRECATED : E_ALL;
-  ini_set('error_reporting', ($config['debug'] ? $e_all : $e_all ^ E_NOTICE) );
-  ini_set('memory_limit', $config['memory_limit']);
-  ini_set('soap.wsdl_cache_enabled', $config['wsdl_cache']);
-  
-  define ('DEBUG_SQL_LOG', $config['debug_sql'] );
-  define ('DEBUG_TIME_LOG', $config['debug_time'] );
-  define ('DEBUG_CALENDAR_LOG', $config['debug_calendar'] );
-  define ('MEMCACHED_ENABLED',  $config['memcached']);
-  define ('MEMCACHED_SERVER',   $config['memcached_server']);
-  
-  define ('TIME_ZONE', $config['time_zone']);
-
 //***************** System Directories & Paths **************************
 
 //***************** RBAC Paths **************************
@@ -96,6 +46,7 @@
   define( 'PATH_SKIN_ENGINE', PATH_CORE . 'skinEngine'   . PATH_SEP );
   define( 'PATH_METHODS',     PATH_CORE . 'methods'      . PATH_SEP );
   define( 'PATH_XMLFORM',     PATH_CORE . 'xmlform'      . PATH_SEP );
+  define( 'PATH_CONFIG',      PATH_CORE . 'config'       . PATH_SEP );
   define( 'PATH_PLUGINS',     PATH_CORE . 'plugins'      . PATH_SEP  );
   define( 'PATH_HTMLMAIL',    PATH_CORE . 'html_templates' . PATH_SEP );
   define( 'PATH_TPL',         PATH_CORE . 'templates'    . PATH_SEP );
diff --git a/workflow/engine/controllers/admin.php b/workflow/engine/controllers/admin.php
index 76686bdaf..7bd2dbff4 100644
--- a/workflow/engine/controllers/admin.php
+++ b/workflow/engine/controllers/admin.php
@@ -11,6 +11,44 @@ class Admin extends Controller
   
   public $debug = true;
 
+  public function system()
+  {
+    require_once PATH_CONTROLLERS . 'main.php';
+    G::loadClass('system');
+    $skinsList = System::getSkingList();
+    $skins = array();
+    $timeZonesList = System::getAllTimeZones();
+    $timeZonesList = array_keys($timeZonesList);
+    $mainController = new Main();
+    $languagesList = $mainController->getLanguagesList();
+    $sysConf = System::getSystemConfiguration(PATH_CONFIG . 'env.ini');
+
+    foreach ($skinsList['skins'] as $skin) {
+      $skins[] = array($skin['SKIN_FOLDER_ID'], $skin['SKIN_NAME']);
+    }
+    $skins[] = array('uxmodern', 'uxmodern');
+
+    foreach ($timeZonesList as $tz) {
+      $timeZones[] = array($tz, $tz);
+    }
+    
+    
+
+    $this->includeExtJS('admin/system');
+    //G::LoadClass('configuration');
+
+    // $c = new Configurations();
+    // $configPage = $c->getConfiguration('usersList', 'pageSize','',$_SESSION['USER_LOGGED']);
+    // $Config['pageSize'] = isset($configPage['pageSize']) ? $configPage['pageSize'] : 20;
+
+    $this->setJSVar('skinsList', $skins);
+    $this->setJSVar('languagesList', $languagesList);
+    $this->setJSVar('timeZonesList', $timeZones);
+    $this->setJSVar('sysConf', $sysConf);
+    
+    G::RenderPage('publish', 'extJs');
+  }
+
   public function uxList()
   {
     require_once PATH_CONTROLLERS . 'adminProxy.php';
diff --git a/workflow/engine/controllers/adminProxy.php b/workflow/engine/controllers/adminProxy.php
index decf1d804..7ce4a2352 100644
--- a/workflow/engine/controllers/adminProxy.php
+++ b/workflow/engine/controllers/adminProxy.php
@@ -25,6 +25,80 @@
 
 class adminProxy extends HttpProxyController
 {    
+  public function saveSystemConf($httpData)
+  {
+    G::loadClass('system');
+    $envFile = PATH_CONFIG . 'env.ini';
+    $updateRedirector = false;
+    $restart = false;
+
+    if (!file_exists($envFile) ) { // if ini file doesn't exists
+      if (!is_writable(PATH_CONFIG)) {
+        throw new Exception('The enviroment config directory is not writable. 
Please give write permission to directory: /workflow/engine/config'); + } + $content = ";\r\n"; + $content .= "; ProcessMaker System Bootstrap Configuration\r\n"; + $content .= ";\r\n"; + file_put_contents($envFile, $content); + //@chmod($envFile, 0777); + } + else { + if (!is_writable($envFile)) { + throw new Exception('The enviroment ini file file is not writable.
Please give write permission to file: /workflow/engine/config/env.ini'); + } + } + + $sysConf = System::getSystemConfiguration($envFile); + + $updatedConf = array(); + + if ($sysConf['default_lang'] != $httpData->default_lang) { + $updatedConf['default_lang'] = $sysConf['default_lang'] = $httpData->default_lang; + $updateRedirector = true; + } + + if ($sysConf['default_skin'] != $httpData->default_skin) { + $updatedConf['default_skin'] = $sysConf['default_skin'] = $httpData->default_skin; + $updateRedirector = true; + } + + if ($sysConf['time_zone'] != $httpData->time_zone) { + $updatedConf['time_zone'] = $httpData->time_zone; + } + + $httpData->memory_limit .= 'M'; + if ($sysConf['memory_limit'] != $httpData->memory_limit) { + $updatedConf['memory_limit'] = $httpData->memory_limit; + } + + + if ($updateRedirector) { + if (!file_exists(PATH_HTML . 'index.html')) { + if (!is_writable(PATH_HTML)) { + throw new Exception('The public directory is not writable.
Please give write permission to file: /workflow/public_html'); + } + } + else { + if (!is_writable(PATH_HTML . 'index.html')) { + throw new Exception('The public index file is not writable.
Please give write permission to file: /workflow/public_html/index.html'); + } + } + + System::updateIndexFile(array( + 'lang' => $sysConf['default_lang'], + 'skin' => $sysConf['default_skin'] + )); + + $restart = true; + } + + G::update_php_ini($envFile, $updatedConf); + + $this->success = true; + $this->restart = $restart; + $this->message = 'Saved Successfully'; + } + function uxUserUpdate($httpData) { require_once 'classes/model/Users.php'; diff --git a/workflow/engine/controllers/installer.php b/workflow/engine/controllers/installer.php new file mode 100644 index 000000000..966c5ed85 --- /dev/null +++ b/workflow/engine/controllers/installer.php @@ -0,0 +1,1057 @@ + + */ + +class Installer extends Controller { + var $path_config; + var $path_languages; + var $path_plugins; + var $path_xmlforms; + var $path_shared; + var $path_sep; + + var $link; #resource for database connection + + public function __construct() { + $this->path_config = PATH_CORE.'config/'; + $this->path_languages = PATH_CORE.'content/languages/'; + $this->path_plugins = PATH_CORE.'plugins/'; + $this->path_xmlforms = PATH_CORE.'xmlform/'; + $this->path_public = PATH_HOME.'public_html/'; + $this->path_shared = PATH_TRUNK.'shared/'; + $this->path_sep = PATH_SEP; + } + + public function index($httpData) { + $step1_txt = 'If any of these items is not supported (marked as No) then please take actions to correct them.

' . + 'Failure to do so could lead to your ProcessMaker! installation not functioning correctly.

' . + '(*) MSSQL Support is optional.

' . + '(**) OpenSSL is optional.

' . + '(***) LDAP is optional.'; + + $step2_txt = 'These settings are recommended for PHP in order to ensure full compatibility with ProcessMaker. <> ' . + 'However, ProcessMaker still operate if your settings do not quite match the recommended'; + $step3_txt = 'In order for ProcessMaker to function correctly it needs to be able to access or write to certain files or directories.
' . + 'If you see "unwriteable" you need to change the permissions on the file or directory to allow ProcessMaker to write to it.'; + $step4_txt = 'ProcessMaker stores all of its data in a database. This screen gives the installation program the information needed to create this database.

' . + 'If you are installing ProcessMaker on a remote web server, you will need to get this information from your Database Server.
'; + $step5_txt = 'ProcessMaker uses a workspaces to store data. Please select a valid workspace name and credentials to log in it. '; + $step6_txt = 'xxx'; + + $licenseContent = file_get_contents(PATH_TRUNK . 'LICENSE.txt'); + + $this->includeExtJS('installer/CardLayout', false); + $this->includeExtJS('installer/Wizard', false); + $this->includeExtJS('installer/Header', false); + $this->includeExtJS('installer/Card', false); + $this->includeExtJS('installer/main', false); + + $this->setJSVar('licenseTxt', $licenseContent); + $this->setJSVar('step1_txt', $step1_txt); + $this->setJSVar('step2_txt', $step2_txt); + $this->setJSVar('step3_txt', $step3_txt); + $this->setJSVar('step4_txt', $step4_txt); + $this->setJSVar('step5_txt', $step5_txt); + $this->setJSVar('step6_txt', $step6_txt); + + $this->setJSVar('path_config', $this->path_config ); + $this->setJSVar('path_languages', $this->path_languages ); + $this->setJSVar('path_plugins', $this->path_plugins ); + $this->setJSVar('path_xmlforms', $this->path_xmlforms ); + $this->setJSVar('path_public', $this->path_public ); + $this->setJSVar('path_shared', $this->path_shared ); + $this->setJSVar('path_sep', $this->path_sep ); + + $this->setView('installer/main'); + + G::RenderPage('publish', 'extJs'); + } + + public function newSite() { + $textStep1 = 'ProcessMaker stores all of its data in a database. This screen gives the installation program the information needed to create this database.

' . + 'If you are installing ProcessMaker on a remote web server, you will need to get this information from your Database Server.'; + $textStep2 = 'ProcessMaker uses a workspaces to store data. Please select a valid workspace name and credentials to log in it.'; + + $this->includeExtJS('installer/CardLayout', false); + $this->includeExtJS('installer/Wizard', false); + $this->includeExtJS('installer/Header', false); + $this->includeExtJS('installer/Card', false); + $this->includeExtJS('installer/newSite', false); + + $this->setJSVar('textStep1', $textStep1); + $this->setJSVar('textStep2', $textStep2); + + $this->setJSVar('DB_ADAPTER', DB_ADAPTER); + $aux = explode(':', DB_HOST); + $this->setJSVar('DB_HOST', $aux[0]); + $this->setJSVar('DB_PORT', isset($aux[1]) ? $aux[1] : (DB_ADAPTER == 'mssql' ? '1433' : '3306')); + $this->setJSVar('DB_NAME', 'workflow'); + $this->setJSVar('DB_USER', ''); + $this->setJSVar('DB_PASS', ''); + $this->setJSVar('pathConfig', PATH_CORE . 'config' . PATH_SEP); + $this->setJSVar('pathLanguages', PATH_LANGUAGECONT); + $this->setJSVar('pathPlugins', PATH_PLUGINS); + $this->setJSVar('pathXmlforms', PATH_XMLFORM); + $this->setJSVar('pathShared', PATH_DATA); + + $this->setView('installer/newSite'); + + G::RenderPage('publish', 'extJs'); + } + + public function getSystemInfo() { + $this->setResponseType('json'); + + // PHP info and verification + $phpVer = phpversion(); + preg_match('/[0-9\.]+/', $phpVer, $match); + $phpVerNum = (float) $match[0]; + + $info->php->version = phpversion(); + $info->php->result = $phpVerNum > 5.1 ? true : false; + + // MYSQL info and verification + $info->mysql->result = false; + if ( function_exists ( 'mysql_query' ) ) { + $mysqlVer = mysql_get_client_info(); + preg_match('/[0-9\.]+/', $mysqlVer, $match); + $mysqlNum = (float) $match[0]; + $info->mysql->version = 'Client API version ' . $mysqlVer; + $info->mysql->result = $mysqlNum >= 5.0 ? true : false; + } + + // MSSQL info and verification + $info->mssql->result = false; + $info->mssql->version = 'not enabled'; + if ( function_exists ( 'mssql_query' ) ) { + $info->mssql->result = true; + $info->mssql->version = 'enabled'; + } + + // OpenSSL info + $info->openssl->result = false; + $info->openssl->version = 'not enabled'; + if ( function_exists ( 'openssl_open' ) ) { + $info->openssl->result = true; + $info->openssl->version = 'enabled'; + } + + // Curl info + $info->curl->result = false; + $info->curl->version = 'not enabled'; + if ( function_exists ( 'curl_version' ) ) { + $info->curl->result = true; + $version = curl_version(); + $info->curl->version = 'cURL ' . $version['version']; + $info->openssl->version = $version['ssl_version']; + } + + // DOMDocument info + $info->dom->result = false; + $info->dom->version = 'not enabled'; + if ( class_exists ( 'DOMDocument' ) ) { + $info->dom->result = true; + $info->dom->version = 'enabled'; + } + + // GD info + $info->gd->result = false; + $info->gd->version = 'not enabled'; + if ( function_exists ( 'gd_info' ) ) { + $info->gd->result = true; + $gdinfo = gd_info(); + $info->gd->version = $gdinfo['GD Version'] ; + } + + // Multibyte info + $info->multibyte->result = false; + $info->multibyte->version = 'not enabled'; + if ( function_exists ( 'mb_check_encoding' ) ) { + $info->multibyte->result = true; + $info->multibyte->version = 'enabled'; + } + + // soap info + $info->soap->result = false; + $info->soap->version = 'not enabled'; + if ( class_exists ( 'SoapClient' ) ) { + $info->soap->result = true; + $info->soap->version = 'enabled'; + } + + // ldap info + $info->ldap->result = false; + $info->ldap->version = 'not enabled'; + if ( function_exists ( 'ldap_connect' ) ) { + $info->ldap->result = true; + $info->ldap->version = 'enabled'; + } + + // memory limit verification + $memory = (int)ini_get("memory_limit"); + $info->memory->version = $memory . 'M'; + if ( $memory > 80 ) { + $info->memory->result = true; + } + else { + $info->memory->result = false; + } + + return $info; + } + + public function is_dir_writable( $path ) { + return ( is_dir($path) && is_writable($path) ); + } + + public function getPermissionInfo() { + + $this->setResponseType('json'); + + // pathConfig + $info->pathConfig->message = 'unwriteable'; + $info->pathConfig->result = $this->is_dir_writable($_REQUEST['pathConfig']); + if ( $info->pathConfig->result ) $info->pathConfig->message = 'writeable'; + + $info->pathLanguages->message = 'unwriteable'; + $info->pathLanguages->result = $this->is_dir_writable($_REQUEST['pathLanguages']); + if ( $info->pathLanguages->result ) $info->pathLanguages->message = 'writeable'; + + $info->pathPlugins->message = 'unwriteable'; + $info->pathPlugins->result = $this->is_dir_writable($_REQUEST['pathPlugins']); + if ( $info->pathPlugins->result ) $info->pathPlugins->message = 'writeable'; + + $info->pathXmlforms->message = 'unwriteable'; + $info->pathXmlforms->result = $this->is_dir_writable($_REQUEST['pathXmlforms']); + if ( $info->pathXmlforms->result ) $info->pathXmlforms->message = 'writeable'; + + $info->pathPublic->message = 'unwriteable'; + $info->pathPublic->result = $this->is_dir_writable($_REQUEST['pathPublic']); + if ( $info->pathPublic->result ) $info->pathPublic->message = 'writeable'; + + $info->pathShared->message = 'unwriteable'; + $info->pathShared->result = $this->is_dir_writable($_REQUEST['pathShared']); + if ( $info->pathShared->result ) $info->pathShared->message = 'writeable'; + + if (!$info->pathShared->result) { + G::verifyPath($_REQUEST['pathShared'], true); + $info->pathShared->result = $this->is_dir_writable($_REQUEST['pathShared']); + } + + if ($info->pathShared->result) { + $aux = pathinfo($_REQUEST['pathLogFile']); + G::verifyPath($aux['dirname'], true); + if (is_dir($aux['dirname'])) { + if (!file_exists($_REQUEST['pathLogFile'])) { + @file_put_contents($_REQUEST['pathLogFile'], ''); + } + } + } + $info->pathLogFile->message = 'Could not create the installation log'; + $info->pathLogFile->result = file_exists($_REQUEST['pathLogFile']); + if ( $info->pathLogFile->result ) $info->pathLogFile->message = 'Installation log created'; + + return $info; + } + + public function testConnection () { + $this->setResponseType('json'); + if ($_REQUEST['db_engine'] == 'mysql') { + return $this->testMySQLconnection(); + } + else { + return $this->testMSSQLconnection(); + } + } + + /** + log the queries and other information to install.log, + the install.log files should be placed in shared/logs + for that reason we are using the $_REQUEST of pathShared + */ + public function installLog( $text ) { + $serverAddr = $_SERVER['SERVER_ADDR']; + //if this function is called outside the createWorkspace, just returns and do nothing + if ( !isset( $_REQUEST['pathShared']) ) + return; + + //log file is in shared/logs + $pathShared = trim($_REQUEST['pathShared']); + if ( substr($pathShared,-1) != '/' ) $pathShared .= '/'; + $logFile = $pathShared . 'log/install.log'; + + if ( !is_file($logFile) ) { + G::mk_dir(dirname($pathShared)); + $fpt = fopen ( $logFile, 'w' ); + if ( $fpt !== NULL ) { + fwrite( $fpt, sprintf ( "%s %s\n", date('Y:m:d H:i:s'), '----- starting log file ------' )); + fclose( $fpt); + } + else { + throw ( new Exception ( sprintf ( "File '%s' is not writeable. Please check permission before continue", $logFile ) ) ); + return $false; + } + } + + $fpt = fopen ( $logFile, 'a' ); + fwrite( $fpt, sprintf ( "%s %s\n", date('Y:m:d H:i:s'), trim($text) )); + fclose( $fpt); + return true; + } + + /** + function to create a workspace + in fact this function is calling appropiate functions for mysql and mssql + */ + public function createWorkspace() { + $this->setResponseType('json'); + if ($_REQUEST['db_engine'] == 'mysql') { + $info = $this->createMySQLWorkspace(); + } + else { + $info = $this->createMSSQLWorkspace(); + } + $info->url = '/sys' . $_REQUEST['workspace'] . '/en/classic/main/login'; + $this->forceTogenerateTranslationsFiles($info->url); + return $info; + } + + public function forceTogenerateTranslationsFiles($url) { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, (isset($_SERVER['HTTPS']) ? ($_SERVER['HTTPS'] != '' ? 'https://' : 'http://') : 'http://') . $_SERVER['HTTP_HOST'] . '/js/ext/translation.en.js?r=' . rand(1, 10000)); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_FRESH_CONNECT, 1); + curl_setopt($ch, CURLOPT_TIMEOUT, 60); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 20); + curl_exec($ch); + curl_close($ch); + } + + /** + send a query to MySQL and log the query + */ + public function mysqlQuery($sql) { + $this->installLog($sql); + $query = @mysql_query($sql, $this->link); + if (!$query) { + $errorMessage = mysql_error($this->link); + $this->installLog('MySQL error: ' . $errorMessage); + throw new Exception($errorMessage); + return false; + } + @mysql_free_result($query); + return true; + } + + /** + send a query to MSSQL and log the query + */ + public function mssqlQuery( $sql ) { + $this->installLog( $sql ); + $query = @mssql_query($sql, $this->link); + if (!$query) { + $errorMessage = mssql_get_last_message(); + $this->installLog ( 'MSSQL error: ' . $errorMessage ); + throw ( new Exception ( $errorMessage ) ); + return false; + } + @mssql_free_result($query); + return true; + } + + /** + * query_sql_file send many statements to server + * + * @param string $file + * @param string $connection + * @return array $report + */ + public function mysqlFileQuery( $file ) { + if ( !is_file($file) ) { + throw ( new Exception ( sprintf ( "File $file is not a valid sql file", $file ) ) ); + return $false; + } + $this->installLog ( 'Procesing: ' . $file ); + $startTime = microtime(true); + // $content = file_get_contents($file); + // $queries = explode(';', $content); + + // foreach( $queries as $sql) { + // if (trim($sql) != '') { + // $query = @mysql_query($sql, $this->link); + // if (!$query) { + // $errorMessage = mysql_error($this->link); + + // $this->installLog ( sprintf ( 'MySQL error: %s Query: %s ', $errorMessage, $sql ) ); + // throw ( new Exception ( $errorMessage ) ); + // return false; + // } + // } + // } + + //erik: New Update, to support more complex queries + + $lines = file($file); + $previous = NULL; + $errors = ''; + @mysql_query("SET NAMES 'utf8';"); + foreach ($lines as $j => $line) { + $line = trim($line); // Remove comments from the script + + if (strpos($line, "--") === 0) { + $line = substr($line, 0, strpos($line, "--")); + } + + if (empty($line)) { + continue; + } + + if (strpos($line, "#") === 0) { + $line = substr($line, 0, strpos($line, "#")); + } + + if (empty($line)) { + continue; + } + + // Concatenate the previous line, if any, with the current + if ($previous) { + $line = $previous . " " . $line; + } + $previous = NULL; + + // If the current line doesnt end with ; then put this line together + // with the next one, thus supporting multi-line statements. + if (strrpos($line, ";") != strlen($line) - 1) { + $previous = $line; + continue; + } + + $line = substr($line, 0, strrpos($line, ";")); + @mysql_query($line, $this->link); + } + + $endTime = microtime(true); + $this->installLog ( sprintf ('File: %s processed in %3.2f seconds', basename($file) , $endTime - $startTime ) ); + return true; + } + + /** + * query_sql_file send many statements to server + * + * @param string $file + * @param string $connection + * @return array $report + */ + public function mssqlFileQuery( $file ) { + if ( !is_file($file) ) { + throw ( new Exception ( sprintf ( "File $file is not a valid sql file", $file ) ) ); + return $false; + } + $this->installLog ( 'Procesing: ' . $file ); + $startTime = microtime(true); + $content = file_get_contents($file); + $queries = explode(';', $content); + + foreach( $queries as $sql) { + $query = @mssql_query($sql, $this->link); + if (!$query) { + $errorMessage = mssql_get_last_message(); + + $this->installLog ( sprintf ( 'MSSQL error: %s Query: %s ', $errorMessage, $sql ) ); + throw ( new Exception ( $errorMessage ) ); + return false; + } + } + $endTime = microtime(true); + $this->installLog ( sprintf ('File: %s processed in %3.2f seconds', basename($file) , $endTime - $startTime ) ); + return true; + } + + /** + * set Grant Privileges for MySQL + * + * @param string $psUser + * @param string $psPassword + * @param string $psDatabase + * @return void + */ + public function setGrantPrivilegesMySQL($psUser, $psPassword, $psDatabase, $host) { + $host = ($host == 'localhost' || $host == '127.0.0.1' ? 'localhost' : '%'); + $query = sprintf("GRANT ALL PRIVILEGES ON `%s`.* TO %s@'%s' IDENTIFIED BY '%s' WITH GRANT OPTION", $psDatabase, $psUser, $host, $psPassword); + $this->mysqlQuery($query); + } + + /** + * set Grant Privileges for SQLServer + * + * @param string $psUser + * @param string $psPassword + * @param string $psDatabase + * @return void + */ + public function setGrantPrivilegesMSSQL( $psUser, $psPassword, $psDatabase ) { + + $query = sprintf ( "IF EXISTS (SELECT * FROM sys.server_principals WHERE name = N'%s') DROP LOGIN [%s]", $psUser, $psUser ); + $this->mssqlQuery( $query ); + + $query = sprintf ( "CREATE LOGIN [%s] WITH PASSWORD=N'%s', DEFAULT_DATABASE=[%s], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF ", $psUser, $psPassword, $psDatabase ); + $this->mssqlQuery( $query ); + + $query = sprintf ( "USE %s;", $psDatabase ); + $this->mssqlQuery( $query ); + + $query = sprintf ( "IF EXISTS (SELECT * FROM sys.database_principals WHERE name = N'%s') DROP USER [%s]", $psUser, $psUser ); + $this->mssqlQuery( $query ); + + $query = sprintf ( "CREATE USER %s FOR LOGIN %s;", $psUser, $psUser ); + $this->mssqlQuery( $query ); + + $query = sprintf ( "sp_addrolemember 'db_owner', '%s' ", $psUser ); + $this->mssqlQuery( $query ); + + $query = sprintf ( "sp_addrolemember 'db_ddladmin', '%s' ", $psUser ); + $this->mssqlQuery( $query ); + + $query = sprintf ( "sp_addrolemember 'db_accessadmin', '%s' ", $psUser ); + $this->mssqlQuery( $query ); + + $query = sprintf ( "use master " ); + $this->mssqlQuery( $query ); + + return true; + } + + public function createMySQLWorkspace() { + ini_set('max_execution_time', '0'); + $info->result = false; + $info->message = ''; + + $db_hostname = trim($_REQUEST['db_hostname']); + $db_port = trim($_REQUEST['db_port']); + $db_username = trim($_REQUEST['db_username']); + $db_password = trim($_REQUEST['db_password']); + $wf = trim($_REQUEST['wfDatabase']); + $rb = trim($_REQUEST['rbDatabase']); + $rp = trim($_REQUEST['rpDatabase']); + $workspace = trim($_REQUEST['workspace']); + $pathConfig = trim($_REQUEST['pathConfig']); + $pathLanguages = trim($_REQUEST['pathLanguages']); + $pathPlugins = trim($_REQUEST['pathPlugins']); + $pathShared = trim($_REQUEST['pathShared']); + $pathXmlforms = trim($_REQUEST['pathXmlforms']); + $adminPassword = trim($_REQUEST['adminPassword']); + $adminUsername = trim($_REQUEST['adminUsername']); + $deleteDB = ($_REQUEST['deleteDB'] == 'true'); + + if ( substr($pathShared,-1) != '/' ) $pathShared .= '/'; + + $this->installLog ( '-------------------------------------------' ); + $this->installLog ( sprintf ( "Creating workspace '%s' ", $workspace) ); + + try { + $db_host = ($db_port != '' && $db_port != 3306) ? $db_hostname . ':' . $db_port : $db_hostname ; + $this->link = @mysql_connect($db_host, $db_username, $db_password); + $this->installLog (sprintf ( "Connected to server %s:%d using user: '%s' ", $db_hostname, $db_port, $db_username ) ); + + if ($deleteDB) { + $q = sprintf('DROP DATABASE IF EXISTS %s;' , $wf, $wf); + $this->mysqlQuery($q); + + $q = sprintf('DROP DATABASE IF EXISTS %s;' , $rb, $rb); + $this->mysqlQuery($q); + + $q = sprintf('DROP DATABASE IF EXISTS %s;' , $rp, $rp); + $this->mysqlQuery($q); + } + + // CREATE databases wf_workflow, rb_workflow and rp_workflow + $q = sprintf('CREATE DATABASE IF NOT EXISTS %s;' , $wf, $wf); + $this->mysqlQuery($q); + + $q = sprintf('CREATE DATABASE IF NOT EXISTS %s;' , $rb, $rb); + $this->mysqlQuery($q); + + $q = sprintf('CREATE DATABASE IF NOT EXISTS %s;' , $rp, $rp); + $this->mysqlQuery($q); + + // CREATE users and GRANT Privileges + $wfPass = G::generate_password(12); + $rbPass = G::generate_password(12); + $rpPass = G::generate_password(12); + $this->setGrantPrivilegesMySQL($wf, $wfPass, $wf, $db_hostname); + $this->setGrantPrivilegesMySQL($rb, $rbPass, $rb, $db_hostname); + $this->setGrantPrivilegesMySQL($rp, $rpPass, $rp, $db_hostname); + + // Generate the db.php file and folders + $path_site = $pathShared . "/sites/" . $workspace ."/"; + $db_file = $path_site. "db.php"; + @mkdir($path_site, 0777, true); + @mkdir($path_site . "files/", 0777, true); + @mkdir($path_site . "mailTemplates/", 0777, true); + @mkdir($path_site . "public/", 0777, true); + @mkdir($path_site . "reports/", 0777, true); + @mkdir($path_site . "xmlForms", 0777, true); + + $dbText = "installLog("Creating: " . $db_file ); + file_put_contents ( $db_file, $dbText); + + // Generate the databases.php file + $databases_file = $path_site . 'databases.php'; + $dbData = sprintf("\$dbAdapter = '%s';\n", 'mysql'); + $dbData .= sprintf("\$dbHost = '%s';\n", $db_host); + $dbData .= sprintf("\$dbName = '%s';\n", $wf); + $dbData .= sprintf("\$dbUser = '%s';\n", $wf); + $dbData .= sprintf("\$dbPass = '%s';\n", $wfPass); + $dbData .= sprintf("\$dbRbacHost = '%s';\n", $db_host); + $dbData .= sprintf("\$dbRbacName = '%s';\n", $rb); + $dbData .= sprintf("\$dbRbacUser = '%s';\n", $rb); + $dbData .= sprintf("\$dbRbacPass = '%s';\n", $rbPass); + $dbData .= sprintf("\$dbReportHost = '%s';\n", $db_host); + $dbData .= sprintf("\$dbReportName = '%s';\n", $rp); + $dbData .= sprintf("\$dbReportUser = '%s';\n", $rp); + $dbData .= sprintf("\$dbReportPass = '%s';\n", $rpPass); + $databasesText = str_replace('{dbData}', $dbData, @file_get_contents(PATH_HOME . 'engine/templates/installer/databases.tpl')); + + $this->installLog('Creating: ' . $databases_file); + file_put_contents($databases_file, $databasesText); + + + // Execute scripts to create and populates databases + $query = sprintf ( "USE %s;", $rb ); + $this->mysqlQuery( $query ); + + $this->mysqlFileQuery ( PATH_RBAC_HOME . 'engine/data/mysql/schema.sql' ); + $this->mysqlFileQuery ( PATH_RBAC_HOME . 'engine/data/mysql/insert.sql' ); + + $query = sprintf ( "USE %s;", $wf ); + $this->mysqlQuery( $query ); + $this->mysqlFileQuery ( PATH_HOME . 'engine/data/mysql/schema.sql' ); + $this->mysqlFileQuery ( PATH_HOME . 'engine/data/mysql/insert.sql' ); + + // Create the triggers + if (file_exists(PATH_HOME . 'engine/methods/setup/setupSchemas/triggerAppDelegationInsert.sql') && + file_exists(PATH_HOME . 'engine/methods/setup/setupSchemas/triggerAppDelegationUpdate.sql') && + file_exists(PATH_HOME . 'engine/methods/setup/setupSchemas/triggerApplicationUpdate.sql') && + file_exists(PATH_HOME . 'engine/methods/setup/setupSchemas/triggerApplicationDelete.sql')) { + $this->mysqlQuery(@file_get_contents(PATH_HOME . 'engine/methods/setup/setupSchemas/triggerAppDelegationInsert.sql')); + $this->mysqlQuery(@file_get_contents(PATH_HOME . 'engine/methods/setup/setupSchemas/triggerAppDelegationUpdate.sql')); + $this->mysqlQuery(@file_get_contents(PATH_HOME . 'engine/methods/setup/setupSchemas/triggerApplicationUpdate.sql')); + $this->mysqlQuery(@file_get_contents(PATH_HOME . 'engine/methods/setup/setupSchemas/triggerApplicationDelete.sql')); + $this->mysqlQuery("INSERT INTO `CONFIGURATION` ( + `CFG_UID`, + `CFG_VALUE` + ) + VALUES ( + 'APP_CACHE_VIEW_ENGINE', + '" . mysql_real_escape_string(serialize(array('LANG' => 'en', 'STATUS' => 'active'))) . "' + )"); + } + + // Change admin user + $query = sprintf ( "USE %s;", $wf ); + $this->mysqlQuery( $query ); + + $query = sprintf ( "UPDATE USERS SET USR_USERNAME = '%s', USR_PASSWORD = '%s' WHERE USR_UID = '00000000000000000000000000000001' ", $adminUsername, md5($adminPassword) ); + $this->mysqlQuery( $query ); + + $query = sprintf ( "USE %s;", $rb ); + $this->mysqlQuery( $query ); + + $query = sprintf ( "UPDATE USERS SET USR_USERNAME = '%s', USR_PASSWORD = '%s' WHERE USR_UID = '00000000000000000000000000000001' ", $adminUsername, md5($adminPassword) ); + $this->mysqlQuery( $query ); + + // Write the paths_installed.php file (contains all the information configured so far) + if ( !file_exists(FILE_PATHS_INSTALLED) ) { + $sh = md5( filemtime( PATH_GULLIVER . '/class.g.php' ) ); + $h = G::encrypt($db_hostname.$sh.$db_username.$sh.$db_password.'1' , $sh); + $dbText = "installLog("Creating: " . FILE_PATHS_INSTALLED ); + file_put_contents ( FILE_PATHS_INSTALLED, $dbText); + } + + //erik: for new env conf handling + G::loadClass('system'); + $envFile = PATH_CONFIG . 'env.ini'; + + //writting for new installtions to use the new skin 'uxmind' with new Front End ExtJs Based + $updatedConf['default_skin'] = 'uxmodern'; + G::update_php_ini($envFile, $updatedConf); + + // getting configuration from env.ini + $sysConf = System::getSystemConfiguration($envFile); + + // update the main index file + $indexFileUpdated = System::updateIndexFile(array( + 'lang' => 'en', + 'skin' => $updatedConf['default_skin'] + )); + + $this->installLog("Index File updated $indexFileUpdated with lang: {$sysConf['default_lang']}, skin: {$sysConf['default_skin']} " ); + $this->installLog("Install completed Succesfully" ); + + $info->url = '/sys' . $_REQUEST['workspace'] . '/en/uxmodern/main/login'; + $info->uri = '/sys' . $_REQUEST['workspace'] . '/en/uxmodern/main/login'; + $info->result = true; + $info->message = 'Succesfully OK---'; + } + catch (Exception $e) { + $info->result = false; + $info->message = $e->getMessage(); + } + return $info; + } + + public function createMSSQLWorkspace() { + ini_set('max_execution_time', '0'); + $info->result = false; + $info->message = ''; + + $db_hostname = trim($_REQUEST['db_hostname']); + $db_port = trim($_REQUEST['db_port']); + $db_username = trim($_REQUEST['db_username']); + $db_password = trim($_REQUEST['db_password']); + $wf = trim($_REQUEST['wfDatabase']); + $rb = trim($_REQUEST['rbDatabase']); + $rp = trim($_REQUEST['rpDatabase']); + $workspace = trim($_REQUEST['workspace']); + $pathConfig = trim($_REQUEST['pathConfig']); + $pathLanguages = trim($_REQUEST['pathLanguages']); + $pathPlugins = trim($_REQUEST['pathPlugins']); + $pathShared = trim($_REQUEST['pathShared']); + $pathXmlforms = trim($_REQUEST['pathXmlforms']); + $adminPassword = trim($_REQUEST['adminPassword']); + $adminUsername = trim($_REQUEST['adminUsername']); + $deleteDB = ($_REQUEST['deleteDB'] == 'true'); + + if ( substr($pathShared,-1) != '/' ) $pathShared .= '/'; + + $this->installLog ( '-------------------------------------------' ); + $this->installLog ( sprintf ( "Creating workspace '%s' ", $workspace) ); + + try { + $db_host = ($db_port != '' && $db_port != 1433) ? $db_hostname . ':' . $db_port : $db_hostname ; + $this->link = @mssql_connect($db_host, $db_username, $db_password); + $this->installLog (sprintf ( "Connected to server %s:%d using user: '%s' ", $db_hostname, $db_port, $db_username ) ); + + $this->mssqlQuery( 'USE [master]' ); + + // DROP databases wf_workflow, rb_workflow and rp_workflow + if ($deleteDB) { + $q = sprintf ("IF EXISTS (SELECT name FROM sys.databases WHERE name='%s' ) DROP DATABASE %s" , $wf, $wf ); + $this->mssqlQuery( $q); + + $q = sprintf ("IF EXISTS (SELECT name FROM sys.databases WHERE name='%s' ) DROP DATABASE %s" , $rb, $rb ); + $this->mssqlQuery( $q); + + $q = sprintf ("IF EXISTS (SELECT name FROM sys.databases WHERE name='%s' ) DROP DATABASE %s" , $rp, $rp ); + $this->mssqlQuery( $q); + } + + // CREATE databases wf_workflow, rb_workflow and rp_workflow + $q = sprintf ("IF NOT EXISTS (SELECT * FROM sys.databases WHERE name='%s' ) CREATE DATABASE %s" , $wf, $wf ); + $this->mssqlQuery( $q); + + $q = sprintf ("IF NOT EXISTS (SELECT * FROM sys.databases WHERE name='%s' ) CREATE DATABASE %s" , $rb, $rb ); + $this->mssqlQuery( $q); + + $q = sprintf ("IF NOT EXISTS (SELECT * FROM sys.databases WHERE name='%s' ) CREATE DATABASE %s" , $rp, $rp ); + $this->mssqlQuery( $q); + + //CREATE users and GRANT Privileges + $wfPass = G::generate_password(12); + $rbPass = G::generate_password(12); + $rpPass = G::generate_password(12); + $this->setGrantPrivilegesMSSQL($wf, $wfPass, $wf ); + $this->setGrantPrivilegesMSSQL($rb, $rbPass, $rb ); + $this->setGrantPrivilegesMSSQL($rp, $rpPass, $rp ); + + //Generate the db.php file and folders + $path_site = $pathShared . "/sites/" . $workspace ."/"; + $db_file = $path_site. "db.php"; + mkdir($path_site, 0777, true); + @mkdir($path_site . "files/", 0777, true); + @mkdir($path_site . "mailTemplates/", 0777, true); + @mkdir($path_site . "public/", 0777, true); + @mkdir($path_site . "reports/", 0777, true); + @mkdir($path_site . "xmlForms", 0777, true); + + $dbText = "installLog("Creating: " . $db_file ); + file_put_contents ( $db_file, $dbText); + + // Generate the databases.php file + $databases_file = $path_site . 'databases.php'; + $dbData = sprintf("\$dbAdapter = '%s';\n", 'mssql'); + $dbData .= sprintf("\$dbHost = '%s';\n", $db_host); + $dbData .= sprintf("\$dbName = '%s';\n", $wf); + $dbData .= sprintf("\$dbUser = '%s';\n", $wf); + $dbData .= sprintf("\$dbPass = '%s';\n", $wfPass); + $dbData .= sprintf("\$dbRbacHost = '%s';\n", $db_host); + $dbData .= sprintf("\$dbRbacName = '%s';\n", $rb); + $dbData .= sprintf("\$dbRbacUser = '%s';\n", $rb); + $dbData .= sprintf("\$dbRbacPass = '%s';\n", $rbPass); + $dbData .= sprintf("\$dbReportHost = '%s';\n", $db_host); + $dbData .= sprintf("\$dbReportName = '%s';\n", $rp); + $dbData .= sprintf("\$dbReportUser = '%s';\n", $rp); + $dbData .= sprintf("\$dbReportPass = '%s';\n", $rpPass); + $databasesText = str_replace('{dbData}', $dbData, @file_get_contents(PATH_HOME . 'engine/templates/installer/databases.tpl')); + + $this->installLog('Creating: ' . $databases_file); + file_put_contents($databases_file, $databasesText); + + //execute scripts to create and populates databases + $query = sprintf ( "USE %s;", $rb ); + $this->mssqlQuery( $query ); + + $this->mssqlFileQuery ( PATH_RBAC_HOME . 'engine/data/mssql/schema.sql' ); + $this->mssqlFileQuery ( PATH_RBAC_HOME . 'engine/data/mssql/insert.sql' ); + + $query = sprintf ( "USE %s;", $wf ); + $this->mssqlQuery( $query ); + $this->mssqlFileQuery ( PATH_HOME . 'engine/data/mssql/schema.sql' ); + $this->mssqlFileQuery ( PATH_HOME . 'engine/data/mssql/insert.sql' ); + + // Create the triggers + if (file_exists(PATH_HOME . 'engine/plugins/enterprise/data/triggerAppDelegationInsert.sql') && + file_exists(PATH_HOME . 'engine/plugins/enterprise/data/triggerAppDelegationUpdate.sql') && + file_exists(PATH_HOME . 'engine/plugins/enterprise/data/triggerApplicationUpdate.sql') && + file_exists(PATH_HOME . 'engine/plugins/enterprise/data/triggerApplicationDelete.sql')) { + $this->mssqlQuery(@file_get_contents(PATH_HOME . 'engine/plugins/enterprise/data/triggerAppDelegationInsert.sql')); + $this->mssqlQuery(@file_get_contents(PATH_HOME . 'engine/plugins/enterprise/data/triggerAppDelegationUpdate.sql')); + $this->mssqlQuery(@file_get_contents(PATH_HOME . 'engine/plugins/enterprise/data/triggerApplicationUpdate.sql')); + $this->mssqlQuery(@file_get_contents(PATH_HOME . 'engine/plugins/enterprise/data/triggerApplicationDelete.sql')); + $this->mssqlQuery("INSERT INTO CONFIGURATION ( + CFG_UID, + CFG_VALUE + ) + VALUES ( + 'APP_CACHE_VIEW_ENGINE', + '" . addslashes(serialize(array('LANG' => 'en', 'STATUS' => 'active'))) . "' + )"); + } + + //change admin user + $query = sprintf ( "USE %s;", $wf ); + $this->mssqlQuery( $query ); + + $query = sprintf ( "UPDATE USERS SET USR_USERNAME = '%s', USR_PASSWORD = '%s' WHERE USR_UID = '00000000000000000000000000000001' ", $adminUsername, md5($adminPassword) ); + $this->mssqlQuery( $query ); + + $query = sprintf ( "USE %s;", $rb ); + $this->mssqlQuery( $query ); + + $query = sprintf ( "UPDATE USERS SET USR_USERNAME = '%s', USR_PASSWORD = '%s' WHERE USR_UID = '00000000000000000000000000000001' ", $adminUsername, md5($adminPassword) ); + $this->mssqlQuery( $query ); + + // Write the paths_installed.php file (contains all the information configured so far) + if ( !file_exists(FILE_PATHS_INSTALLED) ) { + $sh = md5( filemtime( PATH_GULLIVER . '/class.g.php' ) ); + $h = G::encrypt($db_hostname.$sh.$db_username.$sh.$db_password.'1' , $sh); + $dbText = "installLog("Creating: " . FILE_PATHS_INSTALLED ); + file_put_contents ( FILE_PATHS_INSTALLED, $dbText); + } + $this->installLog("Install completed Succesfully" ); + $info->result = true; + $info->message = 'Succesfully'; + $info->url = '/sys' . $_REQUEST['workspace'] . '/en/classic/main/login'; + } + catch (Exception $e) { + $info->result = false; + $info->message = $e->getMessage(); + } + return $info; + } + + public function getEngines() { + $this->setResponseType('json'); + $engines = array(); + if (function_exists('mysql_query')) { + $engine = new stdclass(); + $engine->id = 'mysql'; + $engine->label = 'MySQL'; + $engines[] = $engine; + } + /** DISABLED TEMPORARELY + if (function_exists('mssql_query')) { + $engine = new stdclass(); + $engine->id = 'mssql'; + $engine->label = 'Microsoft SQL Server'; + $engines[] = $engine; + }*/ + return $engines; + } + + public function checkDatabases() { + $this->setResponseType('json'); + $databasesExists = new stdclass(); + if ($_REQUEST['db_engine'] == 'mysql') { + $link = @mysql_connect($_REQUEST['db_hostname'], $_REQUEST['db_username'], $_REQUEST['db_password']); + $dataset = @mysql_query("show databases like '" . $_REQUEST['wfDatabase'] . "'", $link); + $databasesExists->wfDatabaseExists = (@mysql_num_rows($dataset) > 0); + $dataset = @mysql_query("show databases like '" . $_REQUEST['rbDatabase'] . "'", $link); + $databasesExists->rbDatabaseExists = (@mysql_num_rows($dataset) > 0); + $dataset = @mysql_query("show databases like '" . $_REQUEST['rpDatabase'] . "'", $link); + $databasesExists->rpDatabaseExists = (@mysql_num_rows($dataset) > 0); + } + else { + $link = @mssql_connect($_REQUEST['db_hostname'], $_REQUEST['db_username'], $_REQUEST['db_password']); + $dataset = @mssql_query("select * from sys.databases where name = '" . $_REQUEST['wfDatabase'] . "'", $link); + $databasesExists->wfDatabaseExists = (@mssql_num_rows($dataset) > 0); + $dataset = @mssql_query("select * from sys.databases where name = '" . $_REQUEST['rbDatabase'] . "'", $link); + $databasesExists->rbDatabaseExists = (@mssql_num_rows($dataset) > 0); + $dataset = @mssql_query("select * from sys.databases where name = '" . $_REQUEST['rpDatabase'] . "'", $link); + $databasesExists->rpDatabaseExists = (@mssql_num_rows($dataset) > 0); + } + return $databasesExists; + } + + /** + * Privates functions section, non callable by http request + */ + + private function testMySQLconnection() { + $info->result = false; + $info->message = ''; + if ( !function_exists("mysql_connect") ) { + $info->message = 'php-mysql is Not Installed'; + return $info; + } + $db_hostname = $_REQUEST['db_hostname']; + $db_port = $_REQUEST['db_port']; + $db_username = $_REQUEST['db_username']; + $db_password = $_REQUEST['db_password']; + $fp = @fsockopen($db_hostname, $db_port, $errno, $errstr, 30); + if ( !$fp ) { + $info->message .= "Connection Error: $errstr ($errno)"; + return $info; + } + + $db_host = ($db_port != '' && $db_port != 1433) ? $db_hostname . ':' . $db_port : $db_hostname ; + $link = @mysql_connect($db_host, $db_username, $db_password); + if (!$link) { + $info->message .= "Connection Error: unable to connect to MySQL using provided credentials."; + return $info; + } + $res = @mysql_query("SELECT * FROM `information_schema`.`USER_PRIVILEGES` where (GRANTEE = \"'$db_username'@'$db_hostname'\" OR GRANTEE = \"'$db_username'@'%'\") and PRIVILEGE_TYPE = 'SUPER' ", $link); + $row = @mysql_fetch_array($res); + $hasSuper = is_array($row); + @mysql_free_result($res); + @mysql_close($link); + if (!$hasSuper) { + $info->message .= "Connection Error: User '$db_username' can't create databases and Users
Please provide an user with SUPER privilege."; + return $info; + } + $info->message .= "Succesfully connected to MySQL Server"; + $info->result = true; + return $info; + } + + private function testMSSQLconnection() { + $info->result = false; + $info->message = ''; + if ( !function_exists("mssql_connect") ) { + $info->message = 'php-mssql is Not Installed'; + return $info; + } + + $db_hostname = $_REQUEST['db_hostname']; + $db_port = $_REQUEST['db_port']; + $db_username = $_REQUEST['db_username']; + $db_password = $_REQUEST['db_password']; + + $fp = @fsockopen($db_hostname, $db_port, $errno, $errstr, 30); + if ( !$fp ) { + $info->message .= "Connection Error: $errstr ($errno)"; + return $info; + } + + $db_host = ($db_port != '' && $db_port != 1433) ? $db_hostname . ':' . $db_port : $db_hostname ; + $link = @mssql_connect($db_host, $db_username, $db_password); + if (!$link) { + $info->message .= "Connection Error: unable to connect to MSSQL using provided credentials."; + return $info; + } + + //checking if user has the dbcreator role + $hasDbCreator = false; + $hasSecurityAdmin = false; + $hasSysAdmin = false; + + $res = @mssql_query( "EXEC sp_helpsrvrolemember 'dbcreator' ", $link ); + $row = mssql_fetch_array($res); + while ( is_array( $row ) ) { + if ( $row['MemberName'] == $db_username ) $hasDbCreator = true; + $row = mssql_fetch_array($res); + } + mssql_free_result($res); + + $res = @mssql_query( "EXEC sp_helpsrvrolemember 'sysadmin' ", $link ); + $row = mssql_fetch_array($res); + while ( is_array( $row ) ) { + if ( $row['MemberName'] == $db_username ) $hasSysAdmin = true; + $row = mssql_fetch_array($res); + } + mssql_free_result($res); + + $res = @mssql_query( "EXEC sp_helpsrvrolemember 'SecurityAdmin' ", $link ); + $row = mssql_fetch_array($res); + while ( is_array( $row ) ) { + if ( $row['MemberName'] == $db_username ) $hasSecurityAdmin = true; + $row = mssql_fetch_array($res); + } + mssql_free_result($res); + + if ( ! ( $hasSysAdmin || ( $hasSecurityAdmin && $hasDbCreator) ) ) { + $info->message .= "Connection Error: User '$db_username' can't create databases and Users
Please provide an user with sysadmin role or dbcreator and securityadmin roles."; + return $info; + } + + $info->message .= "Succesfully connected to MSSQL Server"; + $info->result = true; + return $info; + } +} \ No newline at end of file diff --git a/workflow/engine/controllers/main.php b/workflow/engine/controllers/main.php new file mode 100644 index 000000000..a1bbaaa10 --- /dev/null +++ b/workflow/engine/controllers/main.php @@ -0,0 +1,1050 @@ + + */ + +class Main extends Controller +{ + private $memcache; + private $conf; + + public function __construct() + { + G::LoadClass('memcached'); + $this->memcache = & PMmemcached::getSingleton(defined('SYS_SYS') ? SYS_SYS : ''); + + define('ERROR_EXCEPTION' , 1); + define('INFO_EXCEPTION' , 3); + define('WARNING_EXCEPTION', 2); + + //$this->setDebug(true); + } + + function index($httpData) + { + global $RBAC; + $RBAC->requirePermissions('PM_LOGIN'); + + $meta = new stdClass; + $this->includeExtJS('main/index'); + $this->includeExtJSLib('ux/ux.menu'); + $this->setView('main/index'); + + // setting variables for template + $this->setVar('logo_company', $this->getCompanyLogo()); + $this->setVar('userfullname', $this->getUserFullName()); + $this->setVar('user', isset($_SESSION['USR_USERNAME']) ? $_SESSION['USR_USERNAME'] : ''); + $this->setVar('pipe', isset($_SESSION['USR_USERNAME']) ? ' | ' : ''); + $this->setVar('rolename', $this->getUserRole()); + $this->setVar('logout', G::LoadTranslation('ID_LOGOUT')); + $this->setVar('workspace', defined('SYS_SYS')? ucfirst(SYS_SYS): ''); + $this->setVar('user_avatar', 'users/users_ViewPhotoGrid?pUID=' . $_SESSION['USER_LOGGED'].'&h=' . rand()); + $this->setVar('udate', G::getformatedDate(date('Y-m-d'), 'M d, yyyy', SYS_LANG)); + + // setting variables on javascript env. + $this->setJSVar('meta', array('menu'=>$this->getMenu())); + $this->setJSVar('activeTab', $this->getActiveTab()); + $this->setJSVar('urlAddGetParams', $this->getUrlGetParams()); + + $showSystemInfo = $RBAC->userCanAccess('PM_SETUP') == 1; + + $this->setJSVar('showSystemInfo', $showSystemInfo); + + if (($flyNotify = $this->getFlyNotify()) !== false) { + $this->setJSVar('flyNotify', $flyNotify); + } + + G::RenderPage('publish', 'extJs'); + } + + function getSystemInfo() + { + $this->setResponseType('json'); + $infoList = $this->_getSystemInfo(); + $data = array(); + + foreach ($infoList as $row) { + $data[] = array( + 'label' => $row[0], + 'value' => $row[1], + 'section' => $row[2], + ); + } + return $data; + } + + /** + * Login + */ + public function login() + { + require_once 'classes/model/LoginLog.php'; + G::LoadClass('system'); + G::loadClass('configuration'); + $this->conf = new Configurations; + + // getting posibles errors passed by GET method + $this->getInUrlError(); + + if (!isset ($_SESSION ['G_MESSAGE'])) { + $_SESSION['G_MESSAGE'] = ''; + } + if (!isset ($_SESSION ['G_MESSAGE_TYPE'])) { + $_SESSION['G_MESSAGE_TYPE'] = ''; + } + + $msg = $_SESSION['G_MESSAGE']; + $msgType = $_SESSION['G_MESSAGE_TYPE']; + + if (! isset($_SESSION['FAILED_LOGINS'])) { + $_SESSION['FAILED_LOGINS'] = 0; + } + $sFailedLogins = $_SESSION ['FAILED_LOGINS']; + + if ( isset ($_SESSION ['USER_LOGGED']) ) { + //close the session, if the current session_id was used in PM. + $oCriteria = new Criteria ( 'workflow' ); + $oCriteria->add ( LoginLogPeer::LOG_SID, session_id () ); + $oCriteria->add ( LoginLogPeer::USR_UID, isset ( $_SESSION ['USER_LOGGED'] ) ? $_SESSION ['USER_LOGGED'] : '-' ); + $oCriteria->add ( LoginLogPeer::LOG_STATUS, 'ACTIVE' ); + $oCriteria->add ( LoginLogPeer::LOG_END_DATE, NULL, Criteria::ISNULL ); + $oDataset = LoginLogPeer::doSelectRS ( $oCriteria ); + $oDataset->setFetchmode ( ResultSet::FETCHMODE_ASSOC ); + $oDataset->next (); + $aRow = $oDataset->getRow (); + if ($aRow) { + if ($aRow ['LOG_STATUS'] != 'CLOSED' && $aRow ['LOG_END_DATE'] == NULL) { + $weblog = new LoginLog ( ); + $aLog ['LOG_UID'] = $aRow ['LOG_UID']; + $aLog ['LOG_STATUS'] = 'CLOSED'; + $aLog ['LOG_IP'] = $aRow ['LOG_IP']; + $aLog ['LOG_SID'] = session_id (); + $aLog ['LOG_INIT_DATE'] = $aRow ['LOG_INIT_DATE']; + $aLog ['LOG_END_DATE'] = date ( 'Y-m-d H:i:s' ); + $aLog ['LOG_CLIENT_HOSTNAME'] = $aRow ['LOG_CLIENT_HOSTNAME']; + $aLog ['USR_UID'] = $aRow ['USR_UID']; + $weblog->update ( $aLog ); + } + } + //remove memcached session + $this->memcache->delete( 'rbacSession' . session_id() ) ; + } + else { + // Execute SSO trigger + $pluginRegistry =& PMPluginRegistry::getSingleton(); + if (defined('PM_SINGLE_SIGN_ON')) { + if ($pluginRegistry->existsTrigger(PM_SINGLE_SIGN_ON)) { + if ($pluginRegistry->executeTriggers(PM_SINGLE_SIGN_ON, null)) { + // Start new session + @session_destroy(); + session_start(); + session_regenerate_id(); + // Authenticate + $result = $this->authentication(); + if ($result->success) { + // Redirect to landing page for the user + G::header('Location: ' . $result->url); + die(); + } + } + } + } + } + //end log + + //start new session + @session_destroy (); + session_start (); + session_regenerate_id (); + + if (strlen ( $msg ) > 0) { + $_SESSION ['G_MESSAGE'] = $msg; + } + if (strlen ( $msgType ) > 0) { + $_SESSION ['G_MESSAGE_TYPE'] = $msgType; + } + $_SESSION ['FAILED_LOGINS'] = $sFailedLogins; + + $availableLangArray = $this->getLanguagesList(); + + //$G_PUBLISH = new Publisher ( ); + //$G_PUBLISH->AddContent ( 'xmlform', 'xmlform', 'login/login', '', $aFields, SYS_URI . 'login/authentication.php' ); + + G::LoadClass ( 'serverConfiguration' ); + + if ( ($nextBeatDate = $this->memcache->get('nextBeatDate')) === false ) { + //get the serverconf singleton, and check if we can send the heartbeat + $oServerConf = & serverConf::getSingleton (); + + $sflag = $oServerConf->getHeartbeatProperty('HB_OPTION','HEART_BEAT_CONF'); + $sflag = (trim($sflag)!='')?$sflag:'1'; + + //get date of next beat + $nextBeatDate = $oServerConf->getHeartbeatProperty('HB_NEXT_BEAT_DATE','HEART_BEAT_CONF'); + $this->memcache->set( 'nextBeatDate', $nextBeatDate, 1*3600 ); + } + + $sflag = 1; + //TODO analize this & enable to work with this new login + // if flag to send heartbeat is enabled, and it is time to send heartbeat, sent it using asynchronous beat. + // if( ($sflag=="1") && ((strtotime ( "now" ) > $nextBeatDate) || is_null($nextBeatDate) ) ){ + // $oHeadPublisher =& headPublisher::getSingleton(); + // //To do: we need to change to ExtJs + // $oHeadPublisher->addScriptCode( 'var flagHeartBeat = 1; '); + // } + // else + // $oHeadPublisher->addScriptCode( 'var flagHeartBeat = 0; '); + + //check if we show the panel with the getting started info + if ( ($flagGettingStarted = $this->memcache->get('flagGettingStarted')) === false ) { + require_once 'classes/model/Configuration.php'; + $oConfiguration = new Configuration ( ); + $oCriteria = new Criteria ( 'workflow' ); + $oCriteria->add ( ConfigurationPeer::CFG_UID, 'getStarted' ); + $oCriteria->add ( ConfigurationPeer::OBJ_UID, '' ); + $oCriteria->add ( ConfigurationPeer::CFG_VALUE, '1' ); + $oCriteria->add ( ConfigurationPeer::PRO_UID, '' ); + $oCriteria->add ( ConfigurationPeer::USR_UID, '' ); + $oCriteria->add ( ConfigurationPeer::APP_UID, '' ); + $flagGettingStarted = ConfigurationPeer::doCount ( $oCriteria ); + $this->memcache->set( 'flagGettingStarted', $flagGettingStarted, 8*3600 ) ; + } + + // if( $flagGettingStarted == 0 ) { + // $oHeadPublisher->addScriptCode( 'var flagGettingStarted = 1; '); + // } + // else + // $oHeadPublisher->addScriptCode( 'var flagGettingStarted = 0; '); + + G::loadClass('configuration'); + $oConf = new Configurations; + $oConf->loadConfig($obj, 'ENVIRONMENT_SETTINGS',''); + + $flagForgotPassword = isset($oConf->aConfig['login_enableForgotPassword'])? $oConf->aConfig['login_enableForgotPassword']: 'off'; + //$oHeadPublisher->addScriptCode("var flagForgotPassword = '$flagForgotPassword';"); + + $this->includeExtJSLib('ux/virtualkeyboard'); + $this->includeExtJS('main/login'); + $this->setView('main/login'); + + $oConf->loadConfig($obj, 'ENVIRONMENT_SETTINGS',''); + + $forgotPasswd = isset($oConf->aConfig['login_enableForgotPassword'])? $oConf->aConfig['login_enableForgotPassword']: false; + $virtualKeyboad = isset($oConf->aConfig['login_enableVirtualKeyboard'])? $oConf->aConfig['login_enableVirtualKeyboard']: false; + $defaultLanguaje = isset($oConf->aConfig['login_defaultLanguage'])? $oConf->aConfig['login_defaultLanguage']: 'en'; + + + $this->setJSVar('forgotPasswd', $forgotPasswd); + $this->setJSVar('virtualKeyboad', $virtualKeyboad); + + $this->setJSVar('languages', $availableLangArray); + $this->setJSVar('defaultLang', $defaultLanguaje); + + //binding G::SendTemporalMessage() to Ext.msgBoxSlider.msgTopCenter() + if (($flyNotify = $this->getFlyNotify()) !== false) { + $this->setJSVar('flyNotify', $flyNotify); + } + + //binding G::SendTemporalMessage() to Ext.msgBoxSlider.msgTopCenter() + if (isset($_GET['u'])) { + $this->setJSVar('urlRequested', urldecode($_GET['u'])); + } + + $this->setVar('logo_company', $this->getCompanyLogo()); + $this->setVar('pmos_version', System::getVersion()); + + $footerText = 'Copyright © 2003-2011 Colosa, Inc. All rights reserved.'; + $adviseText = 'Supplied free of charge with no support, certification, warranty, + maintenance nor indemnity by Colosa and its Certified Partners. '; + $this->setVar('footer_text', $footerText); + $this->setVar('advise_text', $adviseText); + $loginScript = $this->getHeadPublisher()->getExtJsLibraries(); + $loginScript .= $this->getHeadPublisher()->getExtJsScripts(); + $this->setVar('login_script', $loginScript); + $this->setVar('login_vars', $this->getHeadPublisher()->getExtJsVariablesScript()); + + G::RenderPage('publish', 'plain'); + } + + /** + * SysLogin + */ + public function sysLogin() + { + require_once ("propel/Propel.php"); + require_once ("creole/Creole.php"); + G::LoadClass('system'); + G::LoadThirdParty ( "pake", "pakeColor.class" ); + Propel::init ( PATH_CORE . "config/databases.php" ); + Creole::registerDriver ( 'dbarray', 'creole.contrib.DBArrayConnection' ); + + // getting posibles errors passed by GET method + $this->getInUrlError(); + + $availableWorkspace = $this->getWorkspacesAvailable(); + $availableWorkspaceList = array(); + + foreach ($availableWorkspace as $ws) { + $availableWorkspaceList[] = array($ws, $ws); + } + + $aField ['LOGIN_VERIFY_MSG'] = G::loadTranslation('LOGIN_VERIFY_MSG'); + + //Get Server Configuration + G::LoadClass ( 'serverConfiguration' ); + $oServerConf = & serverConf::getSingleton (); + + $availableLangArray = $this->getLanguagesList(); + + $this->includeExtJSLib('ux/virtualkeyboard'); + $this->includeExtJS('main/sysLogin'); + $this->setView('main/sysLogin'); + + $this->setVar('logo_company', $this->getCompanyLogo()); + $this->setVar('pmos_version', System::getVersion()); + + $footerText = 'Copyright © 2003-2011 Colosa, Inc. All rights reserved.'; + $adviseText = 'Supplied free of charge with no support, certification, warranty, + maintenance nor indemnity by Colosa and its Certified Partners. '; + $this->setVar('footer_text', $footerText); + $this->setVar('advise_text', $adviseText); + + //binding G::SendTemporalMessage() to Ext.msgBoxSlider.msgTopCenter() + if (($flyNotify = $this->getFlyNotify()) !== false) { + $this->setJSVar('flyNotify', $flyNotify); + } + + $this->setJSVar('languages', $availableLangArray); + $this->setJSVar('workspaces', $availableWorkspaceList); + $this->setJSVar('wsPrivate', $oServerConf->getProperty('LOGIN_NO_WS')); + + $this->setJSVar('defaultLang', 'en'); + $this->setJSVar('defaultWS', ''); + + $loginScript = $this->getHeadPublisher()->getExtJsLibraries(); + $loginScript .= $this->getHeadPublisher()->getExtJsScripts(); + $this->setVar('login_script', $loginScript); + $this->setVar('login_vars', $this->getHeadPublisher()->getExtJsVariablesScript()); + + G::RenderPage('publish', 'plain'); + + } + + public function sysLoginVerify() + { + $this->setResponseType('json'); + + try { + if (!defined('SYS_SYS')) { + if (!isset($_POST)) { + throw new Exception('Bad Request!', ERROR_EXCEPTION); + } + + if (!isset($_POST['workspace'])) { + throw new Exception('No workspace specified!', ERROR_EXCEPTION); + } + + session_start(); + $_SESSION['sysLogin'] = $_POST; + + $url = '/sys' . $_POST['workspace'] . '/' . SYS_LANG . '/' . SYS_SKIN . '/main/sysLoginVerify'; + + $result->success = true; + $result->url = $url; + $result->message = G::LoadTranslation('LOGIN_VERIFY_MSG'); + } else { + $_POST = $_SESSION['sysLogin']; + $result = $this->authentication(); + + if ($result->success) { + G::header ( 'location: ' . $result->url); + } else { + G::SendTemporalMessage($result->message, "error", 'string'); + G::header('location: /sys' . $_POST['workspace'] . '/' . SYS_LANG . '/' . SYS_SKIN . '/main/login'); + } + } + } catch ( Exception $e ) { + $result->success = false; + $result->message = $e->getMessage(); + $result->errorCode = $e->getCode(); + } + + return $result; + } + + public function authentication() + { + global $RBAC; + + $this->setResponseType('json'); + + try { + if (!$RBAC->singleSignOn) { + if (!isset($_POST['user']) ) { + throw new Exception(G::LoadTranslation('ID_USER_HAVENT_RIGHTS_SYSTEM')); + } + + $frm = $_POST; + $usr = ''; + $pwd = ''; + $lang = ''; + + if (isset($frm['user'])) { + $usr = strtolower(trim($frm['user'])); + $pwd = $currentPwd = trim($frm['password']); + $lang = trim($frm['lang']) != '' ? $frm['lang'] : SYS_LANG; + } + + $uid = $RBAC->VerifyLogin($usr , $pwd); + + switch ($uid) { + //The user doesn't exist + case -1: + throw new Exception(G::LoadTranslation('ID_USER_NOT_REGISTERED')); + break; + //The password is incorrect + case -2: + throw new Exception(G::LoadTranslation('ID_WRONG_PASS')); + + if(isset($_SESSION['__AUTH_ERROR__'])){ + G::SendMessageText($_SESSION['__AUTH_ERROR__'], "warning"); + unset($_SESSION['__AUTH_ERROR__']); + } + break; + //The user is inactive + case -3: + require_once 'classes/model/Users.php'; + $user = new Users; + $aUser = $user->loadByUsernameInArray($usr); + switch($aUser['USR_STATUS']){ + case 'VACATION': + throw new Exception(G::LoadTranslation('ID_USER_ONVACATION', WARNING_EXCEPTION)); + break; + case 'INACTIVE': + throw new Exception(G::LoadTranslation('ID_USER_INACTIVE', WARNING_EXCEPTION)); + break; + } + break; + //The Due date is finished + case -4: + throw new Exception(G::LoadTranslation('ID_USER_INACTIVE_BY_DATE', WARNING_EXCEPTION)); + break; + case -5: + throw new Exception(G::LoadTranslation('ID_AUTHENTICATION_SOURCE_INVALID', WARNING_EXCEPTION)); + break; + } + + //to avoid empty string in user field. This will avoid a weird message "this row doesn't exist" + if ( !isset($uid) ) { + $uid = -1; + throw new Exception(G::LoadTranslation('ID_USER_NOT_REGISTERED', WARNING_EXCEPTION)); + } + + if ( !isset($uid) || $uid < 0 ) { + if(isset($_SESSION['FAILED_LOGINS'])) + $_SESSION['FAILED_LOGINS']++; + if (!defined('PPP_FAILED_LOGINS')) { + define('PPP_FAILED_LOGINS', 0); + } + if (PPP_FAILED_LOGINS > 0) { + if ($_SESSION['FAILED_LOGINS'] >= PPP_FAILED_LOGINS) { + $oConnection = Propel::getConnection('rbac'); + $oStatement = $oConnection->prepareStatement("SELECT USR_UID FROM USERS WHERE USR_USERNAME = '" . $usr . "'"); + $oDataset = $oStatement->executeQuery(); + if ($oDataset->next()) { + $sUserUID = $oDataset->getString('USR_UID'); + $oConnection = Propel::getConnection('rbac'); + $oStatement = $oConnection->prepareStatement("UPDATE USERS SET USR_STATUS = 0 WHERE USR_UID = '" . $sUserUID . "'"); + $oStatement->executeQuery(); + $oConnection = Propel::getConnection('workflow'); + $oStatement = $oConnection->prepareStatement("UPDATE USERS SET USR_STATUS = 'INACTIVE' WHERE USR_UID = '" . $sUserUID . "'"); + $oStatement->executeQuery(); + unset($_SESSION['FAILED_LOGINS']); + G::SendMessageText(G::LoadTranslation('ID_ACCOUNT') . ' "' . $usr . '" ' . G::LoadTranslation('ID_ACCOUNT_DISABLED_CONTACT_ADMIN'), 'warning'); + } + else { + //Nothing + } + } + } + + //TODO complete this redirection + G::header ("location: login.html"); + die; + } + + //Execute the SSO Script from plugin + $oPluginRegistry =& PMPluginRegistry::getSingleton(); + if ( $oPluginRegistry->existsTrigger ( PM_LOGIN ) ) { + $lSession=""; + $loginInfo = new loginInfo ($usr, $pwd, $lSession ); + $oPluginRegistry->executeTriggers ( PM_LOGIN , $loginInfo ); + } + + $_SESSION['USER_LOGGED'] = $uid; + $_SESSION['USR_USERNAME'] = $usr; + } + else { + $uid = $RBAC->userObj->fields['USR_UID']; + $usr = $RBAC->userObj->fields['USR_USERNAME']; + $_SESSION['USER_LOGGED'] = $uid; + $_SESSION['USR_USERNAME'] = $usr; + } + + if (!isset($_SESSION['WORKSPACE'])) { + $_SESSION['WORKSPACE'] = SYS_SYS; + } + + // Assign the uid of user to userloggedobj + $RBAC->loadUserRolePermission($RBAC->sSystem, $uid); + $res = $RBAC->userCanAccess('PM_LOGIN'); + + if ($res != 1 ) { + if ($res == -2) + throw new Exception(G::LoadTranslation('ID_USER_HAVENT_RIGHTS_SYSTEM', ERROR_EXCEPTION)); + else + throw new Exception(G::LoadTranslation('ID_USER_HAVENT_RIGHTS_PAGE', ERROR_EXCEPTION)); + die; + } + + //using optimization with memcache, the user data will be in memcache 8 hours + $memKey = 'rbacSession' . session_id(); + $this->memcache->set( $memKey, $RBAC->aUserInfo, PMmemcached::EIGHT_HOURS ); + + $_SESSION['USR_FULLNAME'] = $RBAC->aUserInfo['USER_INFO']['USR_FIRSTNAME'] . ' ' . $RBAC->aUserInfo['USER_INFO']['USR_LASTNAME']; + unset($_SESSION['FAILED_LOGINS']); + + //get the default language, language posted in form has preference + if ( isset($frm['USER_LANG']) && $frm['USER_LANG'] != '' ) { + $lang = $frm['USER_LANG']; + } + else { + $lang = (defined('SYS_LANG')) ? SYS_LANG : 'en'; + } + + /**log in table Login**/ + require_once 'classes/model/LoginLog.php'; + $weblog=new LoginLog(); + $aLog['LOG_UID'] = G::generateUniqueID(); + $aLog['LOG_STATUS'] = 'ACTIVE'; + $aLog['LOG_IP'] = $_SERVER['REMOTE_ADDR']; + $aLog['LOG_SID'] = session_id(); + $aLog['LOG_INIT_DATE'] = date('Y-m-d H:i:s'); + $aLog['LOG_CLIENT_HOSTNAME'] = $_SERVER['HTTP_HOST']; + $aLog['USR_UID'] = $_SESSION['USER_LOGGED']; + $aLog['LOG_TYPE'] = (isset($RBAC->aUserInfo['USER_INFO']['USR_AUTH_TYPE']) ? ($RBAC->aUserInfo['USER_INFO']['USR_AUTH_TYPE'] != 'MYSQL' ? $RBAC->aUserInfo['USER_INFO']['USR_AUTH_TYPE'] : 'processmaker') : 'processmaker'); + $aLog['LOG_SSO'] = (int) $RBAC->singleSignOn; + $weblog->create($aLog); + /**end log**/ + + // increment logins in heartbeat + G::LoadClass('serverConfiguration'); + $oServerConf =& serverConf::getSingleton(); + $oServerConf->sucessfulLogin(); + + // disabling this slow process, until revisit this issue + // //************** background processes, here we are putting some back office routines ********** + // $oServerConf->setWsInfo(SYS_SYS,$oServerConf->getWorkspaceInfo(SYS_SYS) ); + // + // + // //**** defining and saving server info, this file has the values of the global array $_SERVER **** + // //this file is useful for command line environment (no Browser), I mean for triggers, crons and other executed over command line + // $_CSERVER = $_SERVER; + // unset($_CSERVER['REQUEST_TIME']); + // unset($_CSERVER['REMOTE_PORT']); + // $cput = serialize($_CSERVER); + // if( !is_file(PATH_DATA_SITE . PATH_SEP . '.server_info') ){ + // file_put_contents(PATH_DATA_SITE . PATH_SEP . '.server_info', $cput); + // } + // else { + // $c = file_get_contents(PATH_DATA_SITE . PATH_SEP . '.server_info'); + // if(md5($c) != md5($cput)){ + // file_put_contents(PATH_DATA_SITE . PATH_SEP . '.server_info', $cput); + // } + // } + // + + + /* Check password using policy - Start */ + require_once 'classes/model/UsersProperties.php'; + $oUserProperty = new UsersProperties(); + if (!$RBAC->singleSignOn) { + $aUserProperty = $oUserProperty->loadOrCreateIfNotExists($_SESSION['USER_LOGGED'], array('USR_PASSWORD_HISTORY' => serialize(array(md5($currentPwd))))); + $aErrors = $oUserProperty->validatePassword($pwd, $aUserProperty['USR_LAST_UPDATE_DATE'], $aUserProperty['USR_LOGGED_NEXT_TIME']); + + if (!empty($aErrors)) { + if (!defined('NO_DISPLAY_USERNAME')) { + define('NO_DISPLAY_USERNAME', 1); + } + $aFields = array(); + $aFields['DESCRIPTION'] = ''; + $aFields['DESCRIPTION'] .= G::LoadTranslation('ID_POLICY_ALERT').':

'; + foreach ($aErrors as $sError) { + switch ($sError) { + case 'ID_PPP_MINIMUM_LENGTH': + $aFields['DESCRIPTION'] .= ' - ' . G::LoadTranslation($sError).': ' . PPP_MINIMUM_LENGTH . '
'; + $aFields[substr($sError, 3)] = PPP_MINIMUM_LENGTH; + break; + case 'ID_PPP_MAXIMUM_LENGTH': + $aFields['DESCRIPTION'] .= ' - ' . G::LoadTranslation($sError).': ' . PPP_MAXIMUM_LENGTH . '
'; + $aFields[substr($sError, 3)] = PPP_MAXIMUM_LENGTH; + break; + case 'ID_PPP_EXPIRATION_IN': + $aFields['DESCRIPTION'] .= ' - ' . G::LoadTranslation($sError).' ' . PPP_EXPIRATION_IN . ' ' . G::LoadTranslation('ID_DAYS') . '
'; + $aFields[substr($sError, 3)] = PPP_EXPIRATION_IN; + break; + default: + $aFields['DESCRIPTION'] .= ' - ' . G::LoadTranslation($sError).'
'; + $aFields[substr($sError, 3)] = 1; + break; + } + } + + //TODO complete this policy section (need update) + $aFields['DESCRIPTION'] .= '
' . G::LoadTranslation('ID_PLEASE_CHANGE_PASSWORD_POLICY') . '

'; + //TODO need migrate to ExtJS + // $G_PUBLISH = new Publisher; + // $G_PUBLISH->AddContent('xmlform', 'xmlform', 'login/changePassword', '', $aFields, 'changePassword'); + // G::RenderPage('publish'); + //die; + } + } + + $sLocation = $oUserProperty->redirectTo($_SESSION['USER_LOGGED'], $lang); + + $result->success = true; + $result->message = 'Logged Successfully'; + + $result->url = $sLocation; + } + catch ( Exception $e ) { + $result->success = false; + $result->message = $e->getMessage(); + $result->errorCode = $e->getCode(); + } + + return $result; + } + + + + public function forgotPassword($httpData) + { + $this->setResponseType('json'); + global $RBAC; + require_once PATH_RBAC."model/RbacUsers.php"; + require_once 'classes/model/Users.php'; + G::LoadClass("system"); + + $rbacUser = new RbacUsers(); + $user = new Users(); + + try { + $userData = $rbacUser->getByUsername($httpData->username); + + if (!$userData) { + $msg = G::LoadTranslation('ID_USER') . ' ' . $httpData->username . ' '. G::LoadTranslation('ID_IS_NOT_REGISTERED'); + throw new Exception($msg); + } + + if (trim($userData['USR_EMAIL']) != trim($httpData->email)) { + $msg = G::LoadTranslation('ID_EMAIL_DOES_NOT_MATCH_FOR_USER') .' '. $httpData->username . ''; + throw new Exception($msg); + } + + $newPass = G::generate_password(); + + $aData['USR_UID'] = $userData['USR_UID']; + $aData['USR_PASSWORD'] = md5($newPass); + + $rbacUser->update($aData); + $user->update($aData); + + $subject = G::loadTranslation('ID_PROCESSMAKER_FORGOT_PASSWORD_SERVICE'); + + $template = new TemplatePower(PATH_TPL . 'main/forgotPassword.tpl'); + $template->prepare(); + $template->assign('server', $_SERVER['SERVER_NAME']); + + $template->assign('serviceMsg', G::loadTranslation('ID_PROCESSMAKER_FORGOT_PASSWORD_SERVICE')); + $template->assign('content', G::loadTranslation('ID_PASSWORD_CHANGED_SUCCESSFULLY')); + $template->assign('passwd', $newPass); + $template->assign('poweredBy', G::loadTranslation('ID_PROCESSMAKER_SLOGAN1')); + $template->assign('versionLabel', G::loadTranslation('ID_VERSION')); + $template->assign('version', System::getVersion()); + $template->assign('visit', G::loadTranslation('ID_VISIT')); + + $template->assign('footer', ''); + $body = $template->getOutputContent(); + + G::sendMail('', 'ProcessMaker Service', $httpData->email, $subject, $body); + + $result->success = true; + $result->message = G::LoadTranslation('ID_NEW_PASSWORD_SENT'); + } catch(Exception $e) { + $result->success = false; + $result->message = $e->getMessage(); + } + return $result; + } + + /** * + * Private Functions * + * **/ + + private function getMenu() + { + global $G_MAIN_MENU; + global $G_SUB_MENU; + global $G_MENU_SELECTED; + global $G_SUB_MENU_SELECTED; + global $G_ID_MENU_SELECTED; + global $G_ID_SUB_MENU_SELECTED; + + $G_MAIN_MENU = 'processmaker'; + $G_SUB_MENU = 'process'; + $G_ID_MENU_SELECTED = 'BPMN'; + + $oMenu = new Menu(); + $menus = $oMenu->generateArrayForTemplate($G_MAIN_MENU, 'SelectedMenu', 'mainMenu', $G_MENU_SELECTED, $G_ID_MENU_SELECTED); + + foreach ($menus as $i => $menu) { + if (strpos($menu['target'], 'cases/main') !== false) + $menus[$i]['target'] = str_replace('cases/main', 'cases/main_init', $menus[$i]['target']); + + if (strpos($menu['target'], 'bpmn/main') !== false) + $menus[$i]['target'] = str_replace('bpmn/main', 'bpmn/mainInit', $menus[$i]['target']); + + if (strpos($menu['target'], 'processes/main') !== false) + $menus[$i]['target'] = str_replace('processes/main', 'processes/mainInit', $menus[$i]['target']); + + if (strpos($menu['target'], 'setup/main') !== false) { + $menus[$i]['target'] = str_replace('setup/main', 'setup/main_init', $menus[$i]['target']); + + // $param = ''; + // if (isset($_GET['i18']) || isset($_GET['i18n'])) { + // $s = strpos($menus[$i]['target'], '?') !== false ? '&' : '?'; + // $menus[$i]['target'] .= $s . 'i18'; + // } + } + + if (strpos($menu['target'], 'dashboard/main') !== false) + $menus[$i]['target'] = str_replace('dashboard/main', 'dashboard', $menus[$i]['target']); + + $menus[$i]['elementclass'] = preg_replace(array('/class=/', '/"/'), array('', ''), $menus[$i]['elementclass']) ; + } + return $menus; + } + + private function getCompanyLogo() + { + $sCompanyLogo = '/images/processmaker2.logo.png'; + //$sCompanyLogo = '/images/logo_processmaker2.gif'; + + if(defined("SYS_SYS")){ + if ( ($aFotoSelect = $this->memcache->get('aFotoSelect')) === false ) { + G::LoadClass( 'replacementLogo' ); + $oLogoR = new replacementLogo(); + $aFotoSelect = $oLogoR->getNameLogo((isset($_SESSION['USER_LOGGED']))?$_SESSION['USER_LOGGED']:''); + $this->memcache->set( 'aFotoSelect', $aFotoSelect, 1*3600 ); + } + + if ( is_array ( $aFotoSelect ) ) { + $sFotoSelect = trim($aFotoSelect['DEFAULT_LOGO_NAME']); + $sWspaceSelect = trim($aFotoSelect['WORKSPACE_LOGO_NAME']); + } + } + + if (class_exists('PMPluginRegistry')) { + $oPluginRegistry = &PMPluginRegistry::getSingleton(); + + if ( isset($sFotoSelect) && $sFotoSelect!='' && !(strcmp($sWspaceSelect,SYS_SYS)) ){ + $sCompanyLogo = $oPluginRegistry->getCompanyLogo($sFotoSelect); + $sCompanyLogo = "/sys".SYS_SYS."/".SYS_LANG."/".SYS_SKIN."/adminProxy/showLogoFile?id=".base64_encode($sCompanyLogo); + } + else { + $sCompanyLogo = $oPluginRegistry->getCompanyLogo($sCompanyLogo); + } + } + + return $sCompanyLogo; + } + + public function getLanguagesList() + { + //translation + $Translations = G::getModel("Translation"); + $translationsTable = $Translations->getTranslationEnvironments(); + + if ( ($languagesList = $this->memcache->get('languagesList')) === false ) { + $languagesList = array (); + + foreach ( $translationsTable as $locale ) { + $LANG_ID = $locale['LOCALE']; + + if( $locale['COUNTRY'] != '.' ) + $LANG_NAME = $locale['LANGUAGE'] . ' (' . (ucwords(strtolower($locale['COUNTRY']))) . ')'; + else + $LANG_NAME = $locale['LANGUAGE']; + + $languagesList [] = array($LANG_ID, $LANG_NAME); + } + $this->memcache->set('languagesList', $languagesList, 1*3600 ); + } + + return $languagesList; + } + + private function getWorkspacesAvailable() { + G::LoadClass ( 'serverConfiguration' ); + $oServerConf = & serverConf::getSingleton (); + $dir = PATH_DB; + $filesArray = array (); + if (file_exists ( $dir )) { + if ($handle = opendir ( $dir )) { + while ( false !== ($file = readdir ( $handle )) ) { + if (($file != ".") && ($file != "..")) { + if (file_exists ( PATH_DB . $file . '/db.php' )) { + if (! $oServerConf->isWSDisabled ( $file )) + $filesArray [] = $file; + } + } + } + closedir ( $handle ); + } + } + sort ( $filesArray, SORT_STRING ); + return $filesArray; + } + + private function getUserRole() + { + global $RBAC; + $rolCode = str_replace('_', ' ', $RBAC->aUserInfo['PROCESSMAKER']['ROLE']['ROL_CODE']); + $rolUid = $RBAC->aUserInfo['PROCESSMAKER']['ROLE']['ROL_UID']; + + $oCriteria1 = new Criteria('workflow'); + $oCriteria1->add(ContentPeer::CON_CATEGORY, 'ROL_NAME'); + $oCriteria1->add(ContentPeer::CON_ID, $rolUid); + $oCriteria1->add(ContentPeer::CON_LANG, SYS_LANG); + $oDataset1 = ContentPeer::doSelectRS($oCriteria1); + $oDataset1->setFetchmode(ResultSet::FETCHMODE_ASSOC); + $oDataset1->next(); + $aRow = $oDataset1->getRow(); + $rolName = $aRow['CON_VALUE']; + + return $rolName ? $rolName : $rolCode; + } + + + /** + * binding G::SendTemporalMessage() to Javascript routine Ext.msgBoxSlider.msgTopCenter() + */ + private function getFlyNotify() + { + if (!isset($_SESSION['G_MESSAGE'])) { + return false; + } + + $flyNotify['title'] = isset($_SESSION['G_MESSAGE_TITLE']) ? $_SESSION['G_MESSAGE_TITLE'] : ''; + $flyNotify['text'] = $_SESSION['G_MESSAGE']; + + unset($_SESSION['G_MESSAGE']); + if (isset($_SESSION['G_MESSAGE_TYPE'])) { + $flyNotify['type'] = $_SESSION['G_MESSAGE_TYPE']; + unset($_SESSION['G_MESSAGE_TYPE']); + } + else { + $flyNotify['type'] = ''; + } + + if ($flyNotify['title'] == '') { + switch($flyNotify['type']) { + case 'alert': case 'warning': case 'tmp-warning': + $flyNotify['title'] = G::loadTranslation('ID_WARNING'); + break; + case 'error': case 'tmp-error': + $flyNotify['title'] = G::loadTranslation('ID_ERROR'); + break; + case 'tmp-info': case 'info': + $flyNotify['title'] = G::loadTranslation('ID_INFO'); + break; + case 'success': case 'ok': + $flyNotify['title'] = G::loadTranslation('ID_SUCCESS'); + break; + } + $flyNotify['title'] = strtoupper($flyNotify['title']); + } + + $flyNotify['time'] = 5; //TODO make dinamic + $this->flyNotify = $flyNotify; + + return $this->flyNotify; + } + + private function setFlyNotify($type, $title, $text, $time = 5) + { + $this->flyNotify = array( + 'type' => $type, + 'title' => $title, + 'text' => $text, + 'time' => $time + ); + + $_SESSION ['G_MESSAGE'] = $text; + $_SESSION ['G_MESSAGE_TYPE'] = $type; + } + + private function getInUrlError() + { + if (isset($_GET['errno'])) { + switch ($_GET['errno']) { + case '1': $trnLabel = 'ID_USER_HAVENT_RIGHTS_PAGE'; break; + case '2': $trnLabel = 'ID_NOT_WORKSPACE'; break; + default : $trnLabel = 'ID_USER_HAVENT_RIGHTS_PAGE'; + } + + $this->setFlyNotify('error', 'ERROR', G::loadTranslation($trnLabel)); + } + } + + private function getActiveTab() + { + $activeTab = ''; + if (isset($_GET['st'])) { + $activeTab = $_GET['st']; + unset($_GET['st']); + if (!is_numeric($activeTab)) { + switch ($activeTab) { + case 'home' : $activeTab = 0; break; + case 'bpmn' : $activeTab = 1; break; + case 'designer': $activeTab = 2; break; + case 'admin' : $activeTab = 3; break; + default: $activeTab = 0; + } + } + else { + $activeTab = $activeTab > -1 && $activeTab < 3 ? (int) $activeTab : ''; + } + } + + return $activeTab; + } + + private function getUrlGetParams() + { + $urlGetParams = ''; + foreach ($_GET as $key => $value) { + $urlGetParams .= $urlGetParams == '' ? $key : "&" . $key; + $urlGetParams .= trim($value) != '' ? '=' . $value : ''; + } + return $urlGetParams; + } + + private function getUserFullName() + { + return isset($_SESSION['USR_FULLNAME']) ? $_SESSION['USR_FULLNAME'] : ''; + } + + private function _getSystemInfo() + { + G::LoadClass("system"); + + if (getenv ( 'HTTP_CLIENT_IP' )) { + $ip = getenv ( 'HTTP_CLIENT_IP' ); + } + else { + if (getenv ( 'HTTP_X_FORWARDED_FOR' )) { + $ip = getenv ( 'HTTP_X_FORWARDED_FOR' ); + } + else { + $ip = getenv ( 'REMOTE_ADDR' ); + } + } + + $redhat = ''; + if (file_exists ( '/etc/redhat-release' )) { + $fnewsize = filesize ( '/etc/redhat-release' ); + $fp = fopen ( '/etc/redhat-release', 'r' ); + $redhat = trim ( fread ( $fp, $fnewsize ) ); + fclose ( $fp ); + } + + $redhat .= " (" . PHP_OS . ")"; + if (defined ( "DB_HOST" )) { + G::LoadClass ( 'net' ); + G::LoadClass ( 'dbConnections' ); + $dbNetView = new NET ( DB_HOST ); + $dbNetView->loginDbServer ( DB_USER, DB_PASS ); + + $dbConns = new dbConnections ( '' ); + $availdb = ''; + foreach ( $dbConns->getDbServicesAvailables () as $key => $val ) { + if ($availdb != '') + $availdb .= ', '; + $availdb .= $val ['name']; + } + + try { + + $sMySQLVersion = $dbNetView->getDbServerVersion ( DB_ADAPTER ); + + } + catch ( Exception $oException ) { + $sMySQLVersion = '?????'; + } + } + + $sysSection = G::loadTranslation('ID_SYSTEM_INFO'); + $pmSection = 'ProcessMaker Information'; + + $properties = array(); + $ee = class_exists('pmLicenseManager') ? " - Enterprise Edition" : ''; + $properties[] = array('ProcessMaker Ver.', System::getVersion() . $ee, $pmSection); + $properties[] = array('Operating System', $redhat, $sysSection); + $properties[] = array('Time Zone', (defined('TIME_ZONE')) ? TIME_ZONE : "Unknown", $sysSection); + $properties[] = array('Web Server', getenv ( 'SERVER_SOFTWARE'), $sysSection); + $properties[] = array('Server Name', getenv ( 'SERVER_NAME'), $pmSection); + $properties[] = array('Server IP Address', $this->lookup ($ip), $sysSection); + $properties[] = array('PHP Version', phpversion(), $sysSection); + + if (defined ( "DB_HOST" )) { + $properties[] = array('Data Base', $dbNetView->dbName(DB_ADAPTER) . ' (Version ' . $sMySQLVersion . ')', $pmSection); + $properties[] = array('Data Base Server', DB_HOST, $pmSection); + $properties[] = array('Data Base Name', DB_NAME, $pmSection); + $properties[] = array('Available DB Engines', $availdb, $sysSection); + } + else { + $properties[] = array('Data Base', "Not defined", $pmSection); + $properties[] = array('Data Base Server', "Not defined", $pmSection); + $properties[] = array('Data Base Name', "Not defined", $pmSection); + $properties[] = array('Available DB Engines', "Not defined", $sysSection); + } + + $properties[] = array('Workspace', defined ( "SYS_SYS" ) ? SYS_SYS : "Not defined", $pmSection); + + + $properties[] = array('Server Protocol', getenv ( 'SERVER_PROTOCOL'), $sysSection); + $properties[] = array('Server Port', getenv ( 'SERVER_PORT'), $sysSection); + //$properties[] = array('Remote Host', getenv ( 'REMOTE_HOST'), $sysSection); + $properties[] = array('Server Addr.', getenv ( 'SERVER_ADDR'), $sysSection); + $properties[] = array('User\'s Browser', getenv ( 'HTTP_USER_AGENT'), $sysSection); + + + return $properties; + } + + private function lookup( $target ) { + global $ntarget; + $msg = $target . ' => '; + //if (eregi ( '[a-zA-Z]', $target )) + if (preg_match( '[a-zA-Z]', $target )) //Made compatible to PHP 5.3 + $ntarget = gethostbyname ( $target ); + else + $ntarget = gethostbyaddr ( $target ); + $msg .= $ntarget; + return ($msg); + } +} \ No newline at end of file diff --git a/workflow/engine/menus/processmaker.php b/workflow/engine/menus/processmaker.php index 2f5648f81..cb7ebf47d 100755 --- a/workflow/engine/menus/processmaker.php +++ b/workflow/engine/menus/processmaker.php @@ -24,40 +24,35 @@ */ -# -# ---= Processmaker main menu=--- -# +/************************************* + * ---= Processmaker main menu=--- + *************************************/ global $G_TMP_MENU; global $RBAC; -if ($RBAC->userCanAccess('PM_DASHBOARD') == 1 ) { - //$G_TMP_MENU->AddIdRawOption('DASHBOARD', 'dashboard/dashboard', G::LoadTranslation('ID_DASHBOARD')); -} - -#CASES MODULE +// HOME MODULE if ($RBAC->userCanAccess('PM_CASES') == 1) { - $G_TMP_MENU->AddIdRawOption('CASES', 'cases/main', G::LoadTranslation('ID_HOME')); + $G_TMP_MENU->AddIdRawOption('CASES', 'cases/main', G::LoadTranslation('ID_HOME'), '', '', '', 'x-pm-home'); } -#PROCESSES MODULE +// DESIGNER MODULE if ($RBAC->userCanAccess('PM_FACTORY') == 1 ) { - $G_TMP_MENU->AddIdRawOption('PROCESSES', 'processes/main', G::LoadTranslation('ID_DESIGNER')); + //$G_TMP_MENU->AddIdRawOption('BPMN', 'bpmn/main', 'BPMN DESIGNER','', '', '', 'x-pm-bpmn'); + $G_TMP_MENU->AddIdRawOption('PROCESSES', 'processes/main', G::LoadTranslation('ID_DESIGNER'), '', '', '', 'x-pm-designer'); } // DASHBOARD MODULE if ($RBAC->userCanAccess('PM_DASHBOARD') == 1) { - $G_TMP_MENU->AddIdRawOption('DASHBOARD', 'dashboard/main', G::LoadTranslation('ID_DASHBOARD')); + $G_TMP_MENU->AddIdRawOption('DASHBOARD', 'dashboard/main', G::LoadTranslation('ID_DASHBOARD'), '', '', '', 'x-pm-dashboard'); } -/*if ($RBAC->userCanAccess('PM_REPORTS') == 1 ) { - $G_TMP_MENU->AddIdRawOption('REPORTS', 'reports/reportsList'); -}*/ - +// ADMIN MODULE if ($RBAC->userCanAccess('PM_SETUP') == 1 || $RBAC->userCanAccess('PM_USERS') == 1) { - $G_TMP_MENU->AddIdRawOption('SETUP', 'setup/main', G::LoadTranslation('ID_SETUP')); + $G_TMP_MENU->AddIdRawOption('SETUP', 'setup/main', G::LoadTranslation('ID_SETUP'), '', '', '', 'x-pm-setup'); } +// PLUGINS MENUS if( file_exists(PATH_CORE . 'menus/plugin.php') ) { require_once(PATH_CORE . 'menus/plugin.php'); } \ No newline at end of file diff --git a/workflow/engine/menus/setup.php b/workflow/engine/menus/setup.php index 6858ab061..55228f116 100755 --- a/workflow/engine/menus/setup.php +++ b/workflow/engine/menus/setup.php @@ -79,6 +79,7 @@ if ($RBAC->userCanAccess('PM_SETUP') == 1 || $RBAC->userCanAccess('PM_USERS') == if ($RBAC->userCanAccess('PM_SETUP_ADVANCE') == 1) { $G_TMP_MENU->AddIdRawOption('AUTHSOURCES', '../authSources/authSources_List', G::LoadTranslation('ID_AUTH_SOURCES'), '', '', 'users'); $G_TMP_MENU->AddIdRawOption('UX', '../admin/uxList', G::LoadTranslation('ID_USER_EXPERIENCE'), '', '', 'users'); + $G_TMP_MENU->AddIdRawOption('SYSTEM', '../admin/system', G::LoadTranslation('ID_SYSTEM'), '', '', 'settings'); } diff --git a/workflow/engine/methods/cases/casesListExtJs.php b/workflow/engine/methods/cases/casesListExtJs.php index 39d5f4069..0a0ef830e 100755 --- a/workflow/engine/methods/cases/casesListExtJs.php +++ b/workflow/engine/methods/cases/casesListExtJs.php @@ -115,7 +115,6 @@ G::LoadClass('configuration'); $c = new Configurations(); - $oHeadPublisher->usingExtJs('ux/GridRowActions'); //$oHeadPublisher->addExtJsScript('cases/caseUtils', true); $oHeadPublisher->addExtJsScript('app/main', true); $oHeadPublisher->addExtJsScript('cases/casesList', false ); //adding a javascript file .js diff --git a/workflow/engine/methods/cases/casesStartPage.php b/workflow/engine/methods/cases/casesStartPage.php index 5dcd078eb..760d016ef 100755 --- a/workflow/engine/methods/cases/casesStartPage.php +++ b/workflow/engine/methods/cases/casesStartPage.php @@ -12,8 +12,6 @@ $oHeadPublisher =& headPublisher::getSingleton(); global $RBAC; switch($page){ case "startCase": - - $oHeadPublisher->usingExtJs('ux.treefilterx/Ext.ux.tree.TreeFilterX'); $oHeadPublisher->addExtJsScript('cases/casesStartCase', true); //adding a javascript file .js $oHeadPublisher->addContent( 'cases/casesStartCase'); //adding a html file .html. @@ -35,9 +33,6 @@ switch($page){ $oHeadPublisher->assign('permitoaddfile' ,$RBAC->userCanAccess('PM_FOLDERS_ADD_FILE') ); $oHeadPublisher->assign('permitoaddfolder',$RBAC->userCanAccess('PM_FOLDERS_ADD_FOLDER')); - $oHeadPublisher->usingExtJs('ux.locationbar/Ext.ux.LocationBar'); - $oHeadPublisher->usingExtJs('ux.statusbar/ext-statusbar'); - $oHeadPublisher->addExtJsScript('cases/casesDocuments', false); //adding a javascript file .js $oHeadPublisher->addContent( 'cases/casesDocuments'); //adding a html file .html. break; diff --git a/workflow/engine/methods/cases/cases_Scheduler_Log.php b/workflow/engine/methods/cases/cases_Scheduler_Log.php index a650e91fc..15a9da6a7 100755 --- a/workflow/engine/methods/cases/cases_Scheduler_Log.php +++ b/workflow/engine/methods/cases/cases_Scheduler_Log.php @@ -33,7 +33,6 @@ $Config['pageSize'] = isset($configPage['pageSize']) ? $configPage['pageSize'] : $oHeadPublisher =& headPublisher::getSingleton(); -//$oHeadPublisher->usingExtJs('ux/Ext.ux.fileUploadField'); $oHeadPublisher->addExtJsScript('cases/casesSchedulerLog', false); //adding a javascript file .js $oHeadPublisher->addContent('cases/casesSchedulerLog'); //adding a html file .html. diff --git a/workflow/engine/methods/cases/main_init.php b/workflow/engine/methods/cases/main_init.php index 97329ce2a..4fcdd7640 100755 --- a/workflow/engine/methods/cases/main_init.php +++ b/workflow/engine/methods/cases/main_init.php @@ -27,12 +27,19 @@ $oHeadPublisher->addExtJsScript('cases/main', false ); //adding a javascript file .js $oHeadPublisher->addContent( 'cases/main'); //adding a html file .html. - G::loadClass('configuration'); - $oConf = new Configurations; - $oConf->loadConfig($x, 'USER_PREFERENCES','','',$_SESSION['USER_LOGGED'],''); + $keyMem = 'USER_PREFERENCES'.$_SESSION['USER_LOGGED']; + $memcache = & PMmemcached::getSingleton(SYS_SYS); + if ( ($arrayConfig = $memcache->get($keyMem)) === false ) { + G::loadClass('configuration'); + $oConf = new Configurations; + $oConf->loadConfig($x, 'USER_PREFERENCES','','',$_SESSION['USER_LOGGED'],''); + $arrayConfig = $oConf->aConfig; + $memcache->set( $keyMem, $arrayConfig, PMmemcached::ONE_HOUR); + } + $confDefaultOption=''; - if( sizeof($oConf->Fields) > 0 && isset($oConf->aConfig['DEFAULT_CASES_MENU']) ){ #this user has a configuration record - $confDefaultOption = $oConf->aConfig['DEFAULT_CASES_MENU']; + if( isset($arrayConfig['DEFAULT_CASES_MENU']) ){ #this user has a configuration record + $confDefaultOption = $arrayConfig['DEFAULT_CASES_MENU']; global $G_TMP_MENU; $oMenu = new Menu(); $oMenu->load('cases'); @@ -45,7 +52,8 @@ } $defaultOption = $defaultOption != '' ? $defaultOption : 'casesListExtJs'; - } else { + } + else { $defaultOption = 'casesListExtJs'; $confDefaultOption = 'CASES_INBOX'; } diff --git a/workflow/engine/methods/cases/open.php b/workflow/engine/methods/cases/open.php index 851317abc..625f4ef8e 100755 --- a/workflow/engine/methods/cases/open.php +++ b/workflow/engine/methods/cases/open.php @@ -54,7 +54,7 @@ $conf = new Configurations; $oHeadPublisher =& headPublisher::getSingleton(); - $oHeadPublisher->usingExtJs('ux/miframe'); + $oHeadPublisher->addExtJsScript('app/main', true); $oHeadPublisher->addExtJsScript('cases/open', true); $oHeadPublisher->assign('FORMATS',$conf->getFormats()); diff --git a/workflow/engine/methods/departments/departments.php b/workflow/engine/methods/departments/departments.php index b6afccc1a..871365bce 100755 --- a/workflow/engine/methods/departments/departments.php +++ b/workflow/engine/methods/departments/departments.php @@ -57,7 +57,6 @@ if (($RBAC_Response=$RBAC->userCanAccess("PM_USERS"))!=1) return $RBAC_Response; $oHeadPublisher =& headPublisher::getSingleton(); -//$oHeadPublisher->usingExtJs('ux/Ext.ux.fileUploadField'); $oHeadPublisher->addExtJsScript('departments/departmentList', false); //adding a javascript file .js $oHeadPublisher->addContent('departments/departmentList'); //adding a html file .html. diff --git a/workflow/engine/methods/groups/groupsMembers.php b/workflow/engine/methods/groups/groupsMembers.php index 0f1e5d84a..fe40d43bc 100755 --- a/workflow/engine/methods/groups/groupsMembers.php +++ b/workflow/engine/methods/groups/groupsMembers.php @@ -57,7 +57,6 @@ $G_PUBLISH = new Publisher; $oHeadPublisher =& headPublisher::getSingleton(); -//$oHeadPublisher->usingExtJs('ux/Ext.ux.fileUploadField'); $oHeadPublisher->addExtJsScript('groups/groupsMembers', false); //adding a javascript file .js $oHeadPublisher->addContent('groups/groupsMembers'); //adding a html file .html. diff --git a/workflow/engine/methods/login/authentication.php b/workflow/engine/methods/login/authentication.php index 65522cdaa..67953a60f 100755 --- a/workflow/engine/methods/login/authentication.php +++ b/workflow/engine/methods/login/authentication.php @@ -124,7 +124,13 @@ try { } else { G::SendTemporalMessage($errLabel, "warning"); - $loginUrl = 'login'; + + if (substr(SYS_SKIN, 0, 2) !== 'ux') { + $loginUrl = 'login'; + } + else { + $loginUrl = '../main/login'; + } } G::header("location: $loginUrl"); diff --git a/workflow/engine/methods/roles/roles_List.php b/workflow/engine/methods/roles/roles_List.php index 798af10ed..6b5c60fea 100755 --- a/workflow/engine/methods/roles/roles_List.php +++ b/workflow/engine/methods/roles/roles_List.php @@ -55,7 +55,6 @@ $Config['pageSize'] = isset($configPage['pageSize']) ? $configPage['pageSize'] : $oHeadPublisher =& headPublisher::getSingleton(); -//$oHeadPublisher->usingExtJs('ux/Ext.ux.fileUploadField'); $oHeadPublisher->addExtJsScript('roles/rolesList', false); //adding a javascript file .js $oHeadPublisher->addContent('roles/rolesList'); //adding a html file .html. $oHeadPublisher->assign('FORMATS',$c->getFormats()); diff --git a/workflow/engine/methods/setup/appCacheViewConf.php b/workflow/engine/methods/setup/appCacheViewConf.php index 6a68d95b7..efb6f0a06 100755 --- a/workflow/engine/methods/setup/appCacheViewConf.php +++ b/workflow/engine/methods/setup/appCacheViewConf.php @@ -4,7 +4,6 @@ $oHeadPublisher =& headPublisher::getSingleton(); //$oHeadPublisher->setExtSkin( 'xtheme-blue'); - //$oHeadPublisher->usingExtJs('ux/Ext.ux.codepress'); $oHeadPublisher->addExtJsScript('setup/appCacheViewConf', false); //adding a javascript file .js $oHeadPublisher->addContent('setup/appCacheViewConf'); //adding a html file .html. diff --git a/workflow/engine/methods/setup/languages.php b/workflow/engine/methods/setup/languages.php index fa8705a84..eb3d2cd4a 100755 --- a/workflow/engine/methods/setup/languages.php +++ b/workflow/engine/methods/setup/languages.php @@ -24,7 +24,6 @@ */ $RBAC->requirePermissions('PM_SETUP_ADVANCE'); -//$oHeadPublisher->usingExtJs('ux/Ext.ux.fileUploadField'); $oHeadPublisher->addExtJsScript('setup/languages', false); //adding a javascript file .js $oHeadPublisher->addContent('setup/languages'); //adding a html file .html. diff --git a/workflow/engine/methods/setup/loginSettings.php b/workflow/engine/methods/setup/loginSettings.php index 0942371ac..72123cfea 100755 --- a/workflow/engine/methods/setup/loginSettings.php +++ b/workflow/engine/methods/setup/loginSettings.php @@ -33,12 +33,14 @@ $oConf->loadConfig($obj, 'ENVIRONMENT_SETTINGS',''); - $defaultOption = isset($oConf->aConfig['login_enableForgotPassword'])? $oConf->aConfig['login_enableForgotPassword']: false; + $forgotPasswd = isset($oConf->aConfig['login_enableForgotPassword'])? $oConf->aConfig['login_enableForgotPassword']: false; + $virtualKeyboad = isset($oConf->aConfig['login_enableVirtualKeyboard'])? $oConf->aConfig['login_enableVirtualKeyboard']: false; $defaultLanguaje = isset($oConf->aConfig['login_defaultLanguage'])? $oConf->aConfig['login_defaultLanguage']: 'en'; - $oHeadPublisher->assign( 'currentLang', $defaultLanguaje); //current language - $oHeadPublisher->assign( 'currentOption', $defaultOption); //current option + $oHeadPublisher->assign('currentLang', $defaultLanguaje); + $oHeadPublisher->assign('forgotPasswd', $forgotPasswd); + $oHeadPublisher->assign('virtualKeyboad',$virtualKeyboad); G::RenderPage('publish', 'extJs'); diff --git a/workflow/engine/methods/setup/loginSettingsAjax.php b/workflow/engine/methods/setup/loginSettingsAjax.php index bea75a980..ed7bd13e2 100755 --- a/workflow/engine/methods/setup/loginSettingsAjax.php +++ b/workflow/engine/methods/setup/loginSettingsAjax.php @@ -1,5 +1,5 @@ loadConfig($obj, 'ENVIRONMENT_SETTINGS',''); - - $conf->aConfig['login_enableForgotPassword'] = isset($_POST['acceptRP']) ? $_POST['acceptRP'] : 'off'; - $conf->aConfig['login_defaultLanguage'] = $_POST['lang']; + + $conf->aConfig['login_enableForgotPassword'] = isset($_REQUEST['forgotPasswd']); + $conf->aConfig['login_enableVirtualKeyboard'] = isset($_REQUEST['virtualKeyboad']); + $conf->aConfig['login_defaultLanguage'] = isset($_REQUEST['lang'])? $_REQUEST['lang'] : 'en'; + $conf->saveConfig('ENVIRONMENT_SETTINGS', ''); - $response->success = true; - if (isset($_POST['acceptRP']) && $_POST['acceptRP']) - $response->enable = true; - else - $response->enable = false; - - echo G::json_encode($response); + //remove from memcache when this value is updated/created + $memcache->delete('flagForgotPassword') ; + $response->success = true; + echo G::json_encode($response); + break; } \ No newline at end of file diff --git a/workflow/engine/methods/setup/skin_Ajax.php b/workflow/engine/methods/setup/skin_Ajax.php index f048ee002..a00e17f75 100755 --- a/workflow/engine/methods/setup/skin_Ajax.php +++ b/workflow/engine/methods/setup/skin_Ajax.php @@ -41,46 +41,10 @@ function updatePageSize() { } function skinList() { - //Create Skins custom folder if it doesn't exists - if(!is_dir(PATH_CUSTOM_SKINS)){ - G::verifyPath(PATH_CUSTOM_SKINS, true); - } + G::loadClass('system'); - //Get Skin Config files - $skinListArray = array(); - $customSkins = glob(PATH_CUSTOM_SKINS . "*/config.xml"); - $configurationFile = G::ExpandPath("skinEngine") . 'base' . PATH_SEP . 'config.xml'; - array_unshift($customSkins, $configurationFile); - - //Read and parse each Configuration File - foreach ($customSkins as $key => $configInformation) { - - $folderId = str_replace(G::ExpandPath("skinEngine") . 'base', "", str_replace(PATH_CUSTOM_SKINS, "", str_replace("/config.xml", "", $configInformation))); - if ($folderId == "") - $folderId = "classic"; - $xmlConfiguration = file_get_contents($configInformation); - $xmlConfigurationObj = G::xmlParser($xmlConfiguration); - if (isset($xmlConfigurationObj->result['skinConfiguration'])) { - $skinInformationArray = $skinFilesArray = $xmlConfigurationObj->result['skinConfiguration']['__CONTENT__']['information']['__CONTENT__']; - - - $menuOption = array(); - - $res = array(); - $res['SKIN_FOLDER_ID'] = strtolower($folderId); - foreach ($skinInformationArray as $keyInfo => $infoValue) { - $res['SKIN_' . strtoupper($keyInfo)] = $infoValue['__VALUE__']; - } - $skinListArray['skins'][] = $res; - $skinMenuArray[] = $menuOption; - } - } - $skinListArray['currentSkin'] = SYS_SKIN; - if ((isset($_REQUEST['type'])) && ($_REQUEST['type'] == "menu")) { - print_r(G::json_encode($skinMenuArray)); - } else { - print_r(G::json_encode($skinListArray)); - } + $skinListArray = System::getSkingList(); + echo G::json_encode($skinListArray); } function newSkin($baseSkin='classic') { diff --git a/workflow/engine/skinEngine/base/css/pmos-xtheme-gray.css b/workflow/engine/skinEngine/base/css/pmos-xtheme-gray.css index 8dfc9bf23..9a0d7e0ed 100755 --- a/workflow/engine/skinEngine/base/css/pmos-xtheme-gray.css +++ b/workflow/engine/skinEngine/base/css/pmos-xtheme-gray.css @@ -834,6 +834,11 @@ antes funcionaba. background-image:url( /images/icons_silk/sprites.png) !important; background-position:0 -8929px !important; } + +.x-headBlock{ + background-color: #EEEEEE; +} + .x-grid-empty{ text-align: center; position: absolute; @@ -928,6 +933,175 @@ antes funcionaba. clear:none; } + +/* default-layout */ + +.x-user-bar { + color:#fff; + font-size:8px; + font-weight: bold; +} + +.x-pm-tabmenu { + color: #000 !important; + padding-left: 32px !important; + padding-right: 15px !important; + padding-top: 5px !important; + padding-bottom: 8px !important; + font: 13px "Lucida Grande",Lucida,Verdana,sans-serif !important; +} + +.x-pm-home { + background-image:url(/images/homeIcon.png) !important; +} + +.x-pm-bpmn { + background-image:url(/images/bpmnIcon.png) !important; +} + +.x-pm-designer { + background-image:url(/images/designerIcon.png) !important; +} + +.x-pm-setup { + background-image:url(/images/setupIcon.png) !important; +} + +.x-pm-profile { + background-image:url(/images/profile-icontab.png) !important; +} + +.x-pm-dashboard { + background-image:url(/images/dashboard.png) !important; +} + +.x-pm-toolbars { + background-color: #F0F0F0; + background-image: url("/images/ext/gray/toolbar/bg.gif"); + border-color: #D0D0D0; +} + +.x-pm-logout-icon { + background-image:url(/images/logout.gif); +} + +.x-pm-headerbar1 { + background-color: #32405a; + background-image: url("/images/header_bg.jpg"); + color: #fff; + padding: 0px; + font: 8pt Tahoma,sans-serif,MiscFixed; + font-size: 12px; +} +.x-pm-headerbar2 { + background-color: #000; + background-image: url("/images/canvastile_bg1.jpg"); + color: #fff; + padding: 5px; + font: 8pt Tahoma,sans-serif,MiscFixed; + font-size: 12px; +} + +.headerRightSection +{ + font: 8pt Tahoma,sans-serif,MiscFixed; + color: #fff; +} + +.headerLeftSection +{ + font: 8pt Tahoma,sans-serif,MiscFixed; + color: #fff; +} + +.headerLeftSideBar a:hover { + color: orange; +} + +.headerLeftSideBar a { + font: bold 8pt Tahoma,sans-serif,MiscFixed; + color: #fff; + text-decoration: none; +} + +.headerRightSideBar a:hover { + color: orange; +} + +a.login { + font: 7pt Tahoma,sans-serif,MiscFixed; + color: #00004e; + text-decoration: none; +} + +a.login:hover { + color: blue; +} + +.headerRightSideBar a { + font: 15px Tahoma,sans-serif,MiscFixed; + color: #fff; + text-decoration: none; + vertical-align: top; +} + +.headerRightSideBar +{ + padding-top: 10px; + padding-bottom: 10px; + padding-left: 0px; + padding-right: 5px; + color: #fff; + + display: table-cell; + vertical-align: top !important; +} +#user-avatar +{ + padding-top: 10px; + padding-bottom: 10px; + padding-left: 0px; + padding-right: 10px; + color: #fff; + display: table-cell; + vertical-align: top !important; +} + +.headerRightSideBar label { + font: 9pt Lucida,Verdana,sans-serif,MiscFixed; + color: #fff; + + display: inline-block; + padding-top: 2px; + padding-bottom: 2px; + padding-left: 3px; + padding-right: 3px; +} +.headerLeftSideBar +{ + padding-top: 0px; + padding-bottom: 17px; + padding-left: 0px; + padding-right: 5px; +} +.companyLogo +{ + padding-top: 0px; + padding-bottom: 0px; + padding-left: 10px; + padding-right: 0px; +} + +.ux-auth-warning { + background:url("../images/ext/default/warning.png") no-repeat center left; + padding: 2px; + padding-left:20px; + font-weight:bold; +} +.ux-auth-header-icon { + background: url("../images/ext/default/locked.png") 0 4px no-repeat !important; +} + /*! * Ext JS Library 3.3.3 * Copyright(c) 2006-2011 Sencha Inc. @@ -1050,6 +1224,141 @@ antes funcionaba. color: #15428B; } +/** Virtual keyboard UX*/ +.ux-virtualkeyboard-icon { + background-image:url(../images/ext/default/keyboard.png) ! important; +} +.ux-accented-icon { + background-image:url(../images/ext/default/accented.png) ! important; +} +.x-keyboard .x-toolbar{ + border-width: 1px; +} +.x-keyboard .x-panel-body{ + padding:5px; +} + +.x-keyboard .x-panel-body tbody tr td { + margin:0px; + padding:0px 6px 3px 6px; +} +.x-keyboard .x-panel-body tbody tr td div { + text-align:center; + position:relative; + height:0px; +} +table.keys { + height:20px; + white-space:nowrap; + width:100%; + border-spacing: 0 2px 2px 0; +} +table.keyboardInputCenter { + width:auto; + margin:0 auto; +} + +#spacebar{width:150px;} + +table.keys tbody tr td { + vertical-align:middle; + text-align: center; + padding:0px 5px; + white-space:pre; + /*font:normal 11px 'Lucida Console',monospace;*/ + font: .69em Arial, sans-serif; + border-top:1px solid #99BBE8; + border-right:1px solid #15428B; + border-bottom:1px solid #15428B; + border-left:1px solid #99BBE8; + background-color:#D0DEF0; + cursor:default; + min-width:0.75em; + -moz-user-select: none; +} +table.keys tbody tr td.last { + width:99%; + margin:10px; +} +table.keys tbody tr td.alive { + background-color:#ccccdd; +} +table.keys tbody tr td.target { + background-color:#ddddcc; +} +table.keys tbody tr td.hover { + border-top:1px solid #99BBE8; + border-right:1px solid #15428B; + border-bottom:1px solid #15428B; + border-left:1px solid #99BBE8; + background-color:#99BBE8; +} +table.keys tbody tr td.pressed, +table.keys tbody tr td.dead { + border-top:1px solid #15428B; + border-right:1px solid #99BBE8; + border-bottom:1px solid #99BBE8; + border-left:1px solid #15428B; + background-color:#99BBE8; +} + +.keyboardInputInitiator { + margin-left:3px; + vertical-align:middle; + cursor:pointer; +} + +/* BPMN Text Rotation */ +.rotateText { + font-family: Arial; + font-size: 10pt; + display: table; + text-align: center; + /* for firefox, safari, chrome, etc. */ + -webkit-transform: rotate(-90deg); + -moz-transform: rotate(-90deg); + -o-transform: rotate(-90deg);/* For Opera*/ + -khtml-transform: rotate(-90deg);/* For Lunix*/ + /* for ie */ + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3); + } + .rotateText p { + display: table-cell; + vertical-align: middle; + } + + .rotateTextIE { + font-family: Arial; + font-size: 10pt; + display: table; + text-align: center; + writing-mode: tb-rl; + filter: flipv fliph; + } + + .normalText{ + font-family: Arial; + font-size: 10pt; + display: table; + text-align: center; + } + + .normalText p{ + display: table-cell; + vertical-align: middle; + } + + .normalTopText{ + font-family: Arial; + font-size: 10pt; + display: table; + text-align: center; + } + + .x-padding-left{ + padding-left: 175px; + } + .x-pm-startcase-btn { background-image:url(/images/start.png) !important; color: #000 !important; @@ -1082,6 +1391,61 @@ antes funcionaba. .x-text-plain { font-weight: bold; } +#oAuth { + background-color: #fff; + text-shadow: #fff 0 1px 0; +} + +#oAuth ul { + position: relative; + display: block; + height: auto; + font-size: 85%; +} + +#oAuth ul li img { + margin-bottom: 1px; +} + +#oAuth ul li { + float: left; + padding: 10px 10px; + margin: 5px; +/* margin: 10px 0 0 25px;*/ + text-align: center; + line-height: 1.25em; + color: #333; + font-family: "Helvetica Neue",sans-serif; + height: 35px; + width: 35px; + overflow: hidden; + border-top: 1px solid transparent; + cursor: pointer; +} + +#oAuth ul li.oAuth-hover { + background-color: #eee; +} + +#oAuth ul li.x-view-selected { + background-color: rgba(100, 100, 100, .15); + -moz-border-radius: 8px; + -webkit-border-radius: 8px; + border-top: 1px solid rgba(0, 0, 0, .15); +} + +#oAuth ul li img { +/* display: block;*/ +} + +#oAuth li strong { + color: #000; + display: block; +} + +#oAuth li span { + color: #999; +} /* Case Notes styles */ @@ -1125,3 +1489,6 @@ td.x-cnotes-label { font: 11px arial,tahoma,helvetica,sans-serif; color: #465070; } +.replace { + display:none; +} \ No newline at end of file diff --git a/workflow/engine/skinEngine/base/layout-submenu.html b/workflow/engine/skinEngine/base/layout-submenu.html index eb3f4c8e5..5cb168d24 100755 --- a/workflow/engine/skinEngine/base/layout-submenu.html +++ b/workflow/engine/skinEngine/base/layout-submenu.html @@ -15,7 +15,20 @@ - + + + {if ($exit_editor==1) } + + {/if} +
diff --git a/workflow/engine/skinEngine/skinEngine.php b/workflow/engine/skinEngine/skinEngine.php index 042b4bde9..71a12000a 100644 --- a/workflow/engine/skinEngine/skinEngine.php +++ b/workflow/engine/skinEngine/skinEngine.php @@ -53,7 +53,7 @@ if (strtolower($G_SKIN_MAIN) != "classic") { if (is_dir($skinsBasePath . $G_SKIN_MAIN)) { // check this skin on core skins path $skinObject = $skinsBasePath . $G_SKIN_MAIN; } - else if (is_dir(PATH_CUSTOM_SKINS . $G_SKIN_MAIN)) { // check this skin on user skins path + else if (defined('PATH_CUSTOM_SKINS') && is_dir(PATH_CUSTOM_SKINS . $G_SKIN_MAIN)) { // check this skin on user skins path $skinObject = PATH_CUSTOM_SKINS . $G_SKIN_MAIN; } else { //Skin doesn't exist @@ -203,6 +203,11 @@ switch (strtolower($G_SKIN)) { $menus = $oMenu->generateArrayForTemplate($G_MAIN_MENU, 'SelectedMenu', 'mainMenu', $G_MENU_SELECTED, $G_ID_MENU_SELECTED); $smarty->assign('menus', $menus); + if (substr(SYS_SKIN, 0, 2) == 'ux') { + $smarty->assign('exit_editor', 1); + $smarty->assign('exit_editor_label', G::loadTranslation('ID_CLOSE_EDITOR')); + } + $oSubMenu = new Menu(); $subMenus = $oSubMenu->generateArrayForTemplate($G_SUB_MENU, 'selectedSubMenu', 'subMenu', $G_SUB_MENU_SELECTED, $G_ID_SUB_MENU_SELECTED); $smarty->assign('subMenus', $subMenus); @@ -273,6 +278,12 @@ switch (strtolower($G_SKIN)) { $smarty->display($layoutFileRaw['basename']); break; //end case 'raw' + + case "plain": + $oHeadPublisher = & headPublisher::getSingleton(); + echo $oHeadPublisher->renderExtJs(); + break; + case 'extjs'://This is a special template but need main skin styles G::LoadClass('serverConfiguration'); diff --git a/workflow/engine/templates/admin/system.js b/workflow/engine/templates/admin/system.js new file mode 100644 index 000000000..7ea23407e --- /dev/null +++ b/workflow/engine/templates/admin/system.js @@ -0,0 +1,185 @@ +Ext.onReady(function(){ + + var cmbSkins = new Ext.form.ComboBox({ + fieldLabel : _('ID_DEFAULT_SKIN'), + hiddenName : 'default_skin', + store : new Ext.data.ArrayStore({ + fields: ['ID', 'NAME'], + data : skinsList + }), + mode : 'local', + emptyText : _('ID_SELECT'), + valueField : 'ID', + displayField : 'NAME', + selectOnFocus : true, + editable : true, + triggerAction: 'all', + allowBlank : false, + forceSelection: true, + listeners:{ + select: function(){ + changeSettings(); + }, + afterrender: function(){ + i = cmbSkins.store.findExact('ID', sysConf.default_skin, 0); + if (i == -1) return; + cmbSkins.setValue(cmbSkins.store.getAt(i).data.ID); + cmbSkins.setRawValue(cmbSkins.store.getAt(i).data.NAME); + } + } + }); + + var cmbLang = new Ext.form.ComboBox({ + fieldLabel : _('ID_DEFAULT_LANG'), + hiddenName : 'default_lang', + store : new Ext.data.ArrayStore({ + fields: ['ID', 'NAME'], + data : languagesList + }), + mode : 'local', + emptyText : _('ID_SELECT'), + valueField : 'ID', + displayField : 'NAME', + selectOnFocus : true, + editable : true, + triggerAction: 'all', + forceSelection: true, + allowBlank : false, + listeners:{ + select: function(){ + changeSettings(); + }, + afterrender: function(){ + i = cmbLang.store.findExact('ID', sysConf.default_lang, 0); + if (i == -1) return; + cmbLang.setValue(cmbLang.store.getAt(i).data.ID); + cmbLang.setRawValue(cmbLang.store.getAt(i).data.NAME); + } + } + }); + + var cmbTimeZone = new Ext.form.ComboBox({ + fieldLabel : _('ID_TIME_ZONE'), + hiddenName : 'time_zone', + store : new Ext.data.ArrayStore({ + fields: ['ID', 'NAME'], + data : timeZonesList + }), + mode : 'local', + emptyText : _('ID_SELECT'), + valueField : 'ID', + displayField : 'NAME', + selectOnFocus : true, + editable : true, + triggerAction: 'all', + forceSelection : true, + allowBlank : false, + listeners:{ + select: function(){ + changeSettings(); + } + } + }); + + cmbTimeZone.setValue(sysConf.time_zone); + + saveButton = new Ext.Action({ + text : _('ID_SAVE_SETTINGS'), + disabled : true, + handler : saveSettings + }); + + xfields = new Ext.form.FieldSet({ + title: _('ID_SYSTEM_SETTINGS'), + items : [ + cmbSkins, + cmbLang, + cmbTimeZone, + { + xtype: 'numberfield', + id : 'memory_limit', + name : 'memory_limit', + fieldLabel: _('ID_MEMORY_LIMIT') + '(MB) ', + allowBlank: false, + value: sysConf.memory_limit, + listeners:{ + change: function(){ + changeSettings(); + } + } + }/*, + { + name: 'forgotPasswd', + xtype: 'checkbox', + checked: false, //forgotPasswd, + fieldLabel: _('ID_ENABLE_FOTGOT_PASSWORD'), + listeners:{ + check:function(){ + changeSettings(); + } + } + }*/ + ], + buttons : [saveButton] + }); + + + var frm = new Ext.FormPanel({ + title: ' ', + id:'frm', + labelWidth: 170, + width:460, + labelAlign:'right', + autoScroll: true, + bodyStyle:'padding:2px', + waitMsgTarget : true, + frame: true, + + defaults: { + allowBlank: false, + msgTarget: 'side', + align:'center' + }, + items:[ xfields ] + + }); + //render to process-panel + frm.render(document.body); + +}); //end onready() + +function saveSettings() +{ + Ext.getCmp('frm').getForm().submit( { + url : '../adminProxy/saveSystemConf', + waitMsg : _('ID_SAVING_PROCESS'), + timeout : 36000, + success : function(obj, resp) { + //nothing to do + response = Ext.decode(resp.response.responseText); + parent.PMExt.notify(_('ID_INFO'),_('ID_SAVED_SUCCESSFULLY')); + + if(response.restart) { + PMExt.confirm(_('ID_CONFIRM'), 'To take effect the changes you need re login.
Redirect now?', function(){ + + if (typeof window.parent.parent != 'undefined') + window.parent.parent.location.href = '/'; + if (typeof window.parent != 'undefined') + window.parent.location.href = '/'; + else + window.location.href = '/'; + }); + } + else + saveButton.disable(); + }, + failure: function(obj, resp) { + PMExt.error( _('ID_ERROR'), resp.result.message); + } + }); +} + +changeSettings = function() +{ + saveButton.enable(); +} diff --git a/workflow/engine/templates/cases/main.js b/workflow/engine/templates/cases/main.js index a7ca8f87e..5d46d840a 100755 --- a/workflow/engine/templates/cases/main.js +++ b/workflow/engine/templates/cases/main.js @@ -21,24 +21,24 @@ var NOTIFIER_FLAG = false; var result; var _action = ''; var _CASE_TITLE; - -new Ext.KeyMap(document, { - key: Ext.EventObject.F5, - fn: function(keycode, e) { - if (! e.ctrlKey) { - if (Ext.isIE) { - e.browserEvent.keyCode = 8; - } - e.stopEvent(); - updateCasesTree(); - } - else - Ext.Msg.alert('Refresh', 'You clicked: CTRL-F5'); - } -}); Ext.onReady(function(){ + new Ext.KeyMap(document, { + key: Ext.EventObject.F5, + fn: function(keycode, e) { + if (! e.ctrlKey) { + if (Ext.isIE) { + e.browserEvent.keyCode = 8; + } + e.stopEvent(); + updateCasesTree(); + } + else + Ext.Msg.alert('Refresh', 'You clicked: CTRL-F5'); + } + }); + Ext.QuickTips.init(); Ext.state.Manager.setProvider(new Ext.state.CookieProvider()); var resetGrid = function() { @@ -158,14 +158,17 @@ Ext.onReady(function(){ }); + //center iframe panel centerPanel = { - region: 'center', // a center region is ALWAYS required for border layout - xtype:'panel', - deferredRender: false, - contentEl:'casesSubFrame' + region : 'center', + xtype : 'iframepanel', + frameConfig:{ + name : 'casesSubFrame', + id : 'casesSubFrame' + }, + deferredRender: false } - /** * Menu Panel */ @@ -326,8 +329,6 @@ Ext.onReady(function(){ /** * Triggers Panel */ - Ext.QuickTips.init(); - var xg = Ext.grid; var reader = new Ext.data.JsonReader( diff --git a/workflow/engine/templates/index.html.tpl b/workflow/engine/templates/index.html.tpl new file mode 100644 index 000000000..239bd9aab --- /dev/null +++ b/workflow/engine/templates/index.html.tpl @@ -0,0 +1,8 @@ + + +Redirector + + + + + \ No newline at end of file diff --git a/workflow/engine/templates/installer/Card.js b/workflow/engine/templates/installer/Card.js new file mode 100644 index 000000000..316e69b58 --- /dev/null +++ b/workflow/engine/templates/installer/Card.js @@ -0,0 +1,147 @@ +Ext.namespace('Ext.ux.Wiz'); + +/** + * Licensed under GNU LESSER GENERAL PUBLIC LICENSE Version 3 + * + * @author Thorsten Suckow-Homberg + * @url http://www.siteartwork.de/wizardcomponent + */ + +/** + * @class Ext.ux.Wiz.Card + * @extends Ext.FormPanel + * + * A specific {@link Ext.FormPanel} that can be used as a card in a + * {@link Ext.ux.Wiz}-component. An instance of this card does only work properly + * if used in a panel that uses a {@see Ext.layout.CardLayout}-layout. + * + * @constructor + * @param {Object} config The config object + */ +Ext.ux.Wiz.Card = Ext.extend(Ext.FormPanel, { + + /** + * @cfg {Boolean} header "True" to create the header element. Defaults to + * "false". See {@link Ext.form.FormPanel#header} + */ + header : false, + + /** + * @cfg {Strting} hideMode Hidemode of this component. Defaults to "offsets". + * See {@link Ext.form.FormPanel#hideMode} + */ + hideMode : 'display', + + initComponent : function() + { + this.addEvents( + /** + * @event beforecardhide + * If you want to add additional checks to your card which cannot be easily done + * using default validators of input-fields (or using the monitorValid-config option), + * add your specific listeners to this event. + * This event gets only fired if the activeItem of the ownerCt-component equals to + * this instance of {@see Ext.ux.Wiz.Card}. This is needed since a card layout usually + * hides it's items right after rendering them, involving the beforehide-event. + * If those checks would be attached to the normal beforehide-event, the card-layout + * would never be able to hide this component after rendering it, depending on the + * listeners return value. + * + * @param {Ext.ux.Wiz.Card} card The card that triggered the event + */ + 'beforecardhide' + ); + + + Ext.ux.Wiz.Card.superclass.initComponent.call(this); + + }, + +// -------- helper + isValid : function() + { + if (this.monitorValid) { + return this.bindHandler(); + } + + return true; + }, + +// -------- overrides + + /** + * Overrides parent implementation since we allow to add any element + * in this component which must not be neccessarily be a form-element. + * So before a call to "isValid()" is about to be made, this implementation + * checks first if the specific item sitting in this component has a method "isValid" - if it + * does not exists, it will be added on the fly. + */ + bindHandler : function() + { + this.form.items.each(function(f){ + if(!f.isValid){ + f.isValid = Ext.emptyFn; + } + }); + + Ext.ux.Wiz.Card.superclass.bindHandler.call(this); + }, + + /** + * Overrides parent implementation. This is needed because in case + * this method uses "monitorValid=true", the method "startMonitoring" must + * not be called, until the "show"-event of this card fires. + */ + initEvents : function() + { + var old = this.monitorValid; + this.monitorValid = false; + Ext.ux.Wiz.Card.superclass.initEvents.call(this); + this.monitorValid = old; + + this.on('beforehide', this.bubbleBeforeHideEvent, this); + + this.on('beforecardhide', this.isValid, this); + this.on('show', this.onCardShow, this); + this.on('hide', this.onCardHide, this); + }, + +// -------- listener + /** + * Checks wether the beforecardhide-event may be triggered. + */ + bubbleBeforeHideEvent : function() + { + var ly = this.ownerCt.layout; + var activeItem = ly.activeItem; + + if (activeItem && activeItem.id === this.id) { + return this.fireEvent('beforecardhide', this); + } + + return true; + }, + + /** + * Stops monitoring the form elements in this component when the + * 'hide'-event gets fired. + */ + onCardHide : function() + { + if (this.monitorValid) { + this.stopMonitoring(); + } + }, + + /** + * Starts monitoring the form elements in this component when the + * 'show'-event gets fired. + */ + onCardShow : function() + { + if (this.monitorValid) { + this.startMonitoring(); + } + } + +}); \ No newline at end of file diff --git a/workflow/engine/templates/installer/CardLayout.js b/workflow/engine/templates/installer/CardLayout.js new file mode 100644 index 000000000..fa762a76a --- /dev/null +++ b/workflow/engine/templates/installer/CardLayout.js @@ -0,0 +1,56 @@ +Ext.namespace('Ext.ux.layout'); + +/** + * Licensed under GNU LESSER GENERAL PUBLIC LICENSE Version 3 + * + * @author Thorsten Suckow-Homberg + * @url http://www.siteartwork.de/cardlayout + */ + +/** + * @class Ext.ux.layout.CardLayout + * @extends Ext.layout.CardLayout + * + * A specific {@link Ext.layout.CardLayout} that only sets the active item + * if the 'beforehide'-method of the card to hide did not return false (in this case, + * components usually won't be hidden). + * The original implementation of {@link Ext.layout.CardLayout} does not take + * the return value of the 'beforehide'-method into account. + * + * @constructor + * @param {Object} config The config object + */ +Ext.ux.layout.CardLayout = Ext.extend(Ext.layout.CardLayout, { + + /** + * Sets the active (visible) item in the layout. + * + * If the currently visible item is still visible after calling the 'hide() + * method on it, this implementation assumes that the 'beforehide'-event returned + * false, thus not the item was not allowed to be hidden. The active item will then + * equal to the item that was active, before this method was called. + * + * @param {String/Number} item The string component id or numeric index of the item to activate + */ + setActiveItem : function(item){ + item = this.container.getComponent(item); + if(this.activeItem != item){ + if(this.activeItem){ + this.activeItem.hide(); + } + // check if the beforehide method allowed to + // hide the current item + if (this.activeItem && !this.activeItem.hidden) { + return; + } + var layout = item.doLayout && (this.layoutOnCardChange || !item.rendered); + this.activeItem = item; + item.show(); + this.layout(); + if(layout){ + item.doLayout(); + } + } + } + +}); \ No newline at end of file diff --git a/workflow/engine/templates/installer/Header.js b/workflow/engine/templates/installer/Header.js new file mode 100644 index 000000000..a086d5968 --- /dev/null +++ b/workflow/engine/templates/installer/Header.js @@ -0,0 +1,175 @@ +Ext.namespace('Ext.ux.Wiz'); + +/** + * Licensed under GNU LESSER GENERAL PUBLIC LICENSE Version 3 + * + * @author Thorsten Suckow-Homberg + * @url http://www.siteartwork.de/wizardcomponent + */ + +/** + * @class Ext.ux.Wiz.Header + * @extends Ext.BoxComponent + * + * A specific {@link Ext.BoxComponent} that can be used to show the current process in an + * {@link Ext.ux.Wiz}. + * + * An instance of this class is usually being created by {@link Ext.ux.Wiz#initPanels} using the + * {@link Ext.ux.Wiz#headerConfig}-object. + * + * @private + * @constructor + * @param {Object} config The config object + */ +Ext.ux.Wiz.Header = Ext.extend(Ext.BoxComponent, { + + /** + * @cfg {Number} height The height of this component. Defaults to "55". + */ + height : 55, + + /** + * @cfg {String} region The Region of this component. Since a {@link Ext.ux.Wiz} + * usually uses a {@link Ext.layout.BorderLayout}, this property defaults to + * "north". If you want to change this property, you should also change the appropriate + * css-classes that are used for this component. + */ + region : 'north', + + /** + * @cfg {String} title The title that gets rendered in the head of the component. This + * should be a text describing the purpose of the wizard. + */ + title : 'Wizard', + + /** + * @cfg {Number} steps The overall number of steps the user has to go through + * to finish the wizard. + */ + steps : 0, + + /** + * @cfg {String} stepText The text in the header indicating the current process in the wizard. + * (defaults to "Step {0} of {1}: {2}"). + * {0} is replaced with the index (+1) of the current card, {1} is replaced by the + * total number of cards in the wizard and {2} is replaced with the title-property of the + * {@link Ext.ux.Wiz.Card} + * @type String + */ + stepText : "Step {0} of {1}: {2}", + + /** + * @cfg {Object} autoEl The element markup used to render this component. + */ + autoEl : { + tag : 'div', + cls : 'ext-ux-wiz-Header', + children : [{ + tag : 'div', + cls : 'ext-ux-wiz-Header-title' + }, { + tag : 'div', + children : [{ + tag : 'div', + cls : 'ext-ux-wiz-Header-step' + }, { + tag : 'div', + cls : 'ext-ux-wiz-Header-stepIndicator-container' + }] + }] + }, + + /** + * @param {Ext.Element} + */ + titleEl : null, + + /** + * @param {Ext.Element} + */ + stepEl : null, + + /** + * @param {Ext.Element} + */ + imageContainer : null, + + /** + * @param {Array} + */ + indicators : null, + + /** + * @param {Ext.Template} + */ + stepTemplate : null, + + /** + * @param {Number} lastActiveStep Stores the index of the last active card that + * was shown- + */ + lastActiveStep : -1, + +// -------- helper + /** + * Gets called by {@link Ext.ux.Wiz#onCardShow()} and updates the header + * with the approppriate information, such as the progress of the wizard + * (i.e. which card is being shown etc.) + * + * @param {Number} currentStep The index of the card currently shown in + * the wizard + * @param {String} title The title-property of the {@link Ext.ux.Wiz.Card} + * + * @private + */ + updateStep : function(currentStep, title) + { + var html = this.stepTemplate.apply({ + 0 : currentStep+1, + 1 : this.steps, + 2 : title + }); + + this.stepEl.update(html); + + if (this.lastActiveStep != -1) { + this.indicators[this.lastActiveStep].removeClass('ext-ux-wiz-Header-stepIndicator-active'); + } + + this.indicators[currentStep].addClass('ext-ux-wiz-Header-stepIndicator-active'); + + this.lastActiveStep = currentStep; + }, + + +// -------- listener + /** + * Overrides parent implementation to render this component properly. + */ + onRender : function(ct, position) + { + Ext.ux.Wiz.Header.superclass.onRender.call(this, ct, position); + + this.indicators = []; + this.stepTemplate = new Ext.Template(this.stepText); + this.stepTemplate.compile(); + + var el = this.el.dom.firstChild; + var ns = el.nextSibling; + + this.titleEl = new Ext.Element(el); + this.stepEl = new Ext.Element(ns.firstChild); + this.imageContainer = new Ext.Element(ns.lastChild); + + this.titleEl.update(this.title); + + var image = null; + for (var i = 0, len = this.steps; i < len; i++) { + image = document.createElement('div'); + image.innerHTML = " "; + image.className = 'ext-ux-wiz-Header-stepIndicator'; + this.indicators[i] = new Ext.Element(image); + this.imageContainer.appendChild(image); + } + } +}); \ No newline at end of file diff --git a/workflow/engine/templates/installer/Wizard.js b/workflow/engine/templates/installer/Wizard.js new file mode 100644 index 000000000..e3fae0631 --- /dev/null +++ b/workflow/engine/templates/installer/Wizard.js @@ -0,0 +1,551 @@ +Ext.namespace('Ext.ux'); + +/** + * Licensed under GNU LESSER GENERAL PUBLIC LICENSE Version 3 + * + * @author Thorsten Suckow-Homberg + * @url http://www.siteartwork.de/wizardcomponent + */ + +/** + * @class Ext.ux.Wiz + * @extends Ext.Window + * + * A specific {@link Ext.Window} that models a wizard component. + * A wizard is basically a dialog that guides a user through various steps + * where he has to fill out form-data. + * A {@link Ext.ux.Wiz}-component consists typically of a {@link Ext.ux.Wiz.Header} + * and window-buttons ({@link Ext.Button}) which are linked to the {@link Ext.ux.Wiz.Card}s + * which themself represent the forms the user has to fill out. + * + * In order to switch between the cards in the wizard, you need the {@link Ext.ux.layout.CardLayout}, + * which will check if an active-item can be hidden, before the requested new item will be set to + * 'active', i.e. shown. This is needed since the wizard may not allow a card to be hidden, if + * the input entered by the user was not valid. You can get this custom layout at + * {@link http://www.siteartwork.de/cardlayout}. + * + * Note: + * When data has been collected and teh "onFinish" listener triggers an AJAX-request, + * you should call the "switchDialogState" method so that the the dialog shows a loadmask. + * Once the requests finishes, call "switchDialogState" again, specially before any call + * to the "close" method of this component, otherwise the "closable" property of this + * instance might prevent a "close" operation for this dialog. + * + * + * @constructor + * @param {Object} config The config object + */ +Ext.ux.Wiz = Ext.extend(Ext.Window, { + + /** + * @cfg {Object} An object containing the messages for the {@link Ext.LoadMask} + * covering the card-panel on request, whereas the property identifies the + * msg-text to show, and the value is the message text itself. Defaults to +

+  {
+      default : 'Saving...'
+  }
+       
+ * + * Depending on the contexts the loadMask has to be shown in (using the method + * showLoadMask of this class), the object can be configure to hold + * various messages. +

+  this.loadMaskConfig = {
+      default    : 'Saving...',
+      validating : 'Please wait, validating input...',
+  };
+  // loadMask will be shown, displaying the message 'Please wait, validating input...'
+  this.showLoadMask(true, 'validating');
+  
+ */ + loadMaskConfig : { + 'default' : 'Saving...' + }, + + /** + * @cfg {Number} height The height of the dialog. Defaults to "400". + */ + height : 400, + + /** + * @cfg {Number} width The width of the dialog. Defaults to "540". + */ + width : 540, + + /** + * @cfg {Boolean} closable Wether the dialog is closable. Defaults to "true". + * This property will be changed by the "switchDialogState"-method, which will + * enable/disable controls based on the passed argument. Thus, this config property + * serves two purposes: Tell the init config to render a "close"-tool, and create a + * "beforeclose"-listener which will either return true or false, indicating if the + * dialog may be closed. + */ + closable : true, + + /** + * @cfg {Boolean} resizable Wether the dialog is resizable. Defaults to "false". + */ + resizable : false, + + /** + * @cfg {Boolean} resizable Wether the dialog is modal. Defaults to "true". + */ + modal : true, + + /** + * @cfg {Array} cards A numeric array with the configured {@link Ext.ux.Wiz.Card}s. + * The index of the cards in the array represent the order in which they get displayed + * in the wizard (i.e. card at index 0 gets displayed in the first step, card at index 1 gets + * displayed in the second step and so on). + */ + cards : null, + + /** + * @cfg {String} previousButtonText The text to render the previous-button with. + * Defaults to "< Back" (< Back) + */ + previousButtonText : '< Previous', + + /** + * @cfg {String} nextButtonText The text to render the next-button with. + * Defaults to "Next >" (Next >) + */ + nextButtonText : 'Next >', + + /** + * @cfg {String} cancelButtonText The text to render the cancel-button with. + * Defaults to "Cancel" + */ + cancelButtonText : 'Cancel', + + /** + * @cfg {String} finishButtonText The text to render the next-button with when the last + * step of the wizard is reached. Defaults to "Finish" + */ + finishButtonText : 'Finish', + + /** + * @cfg {Object} headerConfig A config-object to use with {@link Ext.ux.Wiz.Header}. + * If not present, it defaults to an empty object. + */ + headerConfig : {}, + + /** + * @cfg {Object} cardPanelConfig A config-object to use with {@link Ext.Panel}, which + * represents the card-panel in this dialog. + * If not present, it defaults to an empty object + */ + cardPanelConfig : {}, + + /** + * @param {Ext.Button} The window-button for paging to the previous card. + * @private + */ + previousButton : null, + + /** + * @param {Ext.Button} The window-button for paging to the next card. When the + * last card is reached, the event fired by and the text rendered to this button + * will change. + * @private + */ + nextButton : null, + + /** + * @param {Ext.Button} The window-button for canceling the wizard. The event + * fired by this button will usually close the dialog. + * @private + */ + cancelButton : null, + + /** + * @param {Ex.Panel} The card-panel that holds the various wizard cards + * ({@link Ext.ux.Wiz.Card}). The card-panel itself uses the custom + * {@link Ext.ux.layout.CardLayout}, which needs to be accessible by this class. + * You can get it at {@link http://www.siteartwork.de/cardlayout}. + * @private + */ + cardPanel : null, + + /** + * @param {Number} currentCard The current {@link Ext.ux.Wiz.Card} displayed. + * Defaults to -1. + * @private + */ + currentCard : -1, + + /** + * @param {Ext.ux.Wiz.Header} The header-panel of the wizard. + * @private + */ + headPanel : null, + + /** + * @param {Number} cardCount Helper for storing the number of cards used + * by this wizard. Defaults to 0 (inherits "cards.length" later on). + * @private + */ + cardCount : 0, + + /** + * Inits this component with the specified config-properties and automatically + * creates its components. + */ + initComponent : function() + { + this.initButtons(); + this.initPanels(); + + var title = this.title || this.headerConfig.title; + title = title || ""; + + Ext.apply(this, { + title : title, + layout : 'border', + cardCount : this.cards.length, + buttons : [ + this.previousButton, + this.nextButton, + this.cancelButton + ], + items : [ + this.headPanel, + this.cardPanel + ] + }); + + this.addEvents( + /** + * @event cancel + * Fires after the cancel-button has been clicked. + * @param {Ext.ux.Wiz} this + */ + 'cancel', + /** + * @event finish + * Fires after the last card was reached in the wizard and the + * next/finish-button has been clicked. + * @param {Ext.ux.Wiz} this + * @param {Object} data The collected data of the cards, whereas + * the index is the id of the card and the specific values + * are objects with key/value pairs in the form formElementName : value + */ + 'finish' + ); + + Ext.ux.Wiz.superclass.initComponent.call(this); + }, + + // -------- helper + /** + * Returns the form-data of all cards in this wizard. The first index is the + * id of the card in this wizard, + * and the values are objects containing key/value pairs in the form of + * fieldName : fieldValue. + * + * @return {Array} + */ + getWizardData : function() + { + var formValues = {}; + var cards = this.cards; + for (var i = 0, len = cards.length; i < len; i++) { + if (cards[i].form) { + formValues[cards[i].id] = cards[i].form.getValues(false); + } else { + formValues[cards[i].id] = {}; + } + } + + return formValues; + }, + + /** + * Switches the state of this wizard between disabled/enabled. + * A disabled dialog will have a {@link Ext.LoadMask} covering the card-panel + * to prevent user input, and the buttons will be rendered disabled/enabled. + * If the dialog is closable, the close-tool will be masked, too, and the dialog will not + * be closable by clicking the "close" tool. + * + * @param {Boolean} enabled "false" to prevent user input and mask the elements, + * otherwise true. + * @param {String} type The type of msg for the {@Ext.LoadMask} covering + * the cardPanel, as defined in the cfg property "loadMaskConfig" + */ + switchDialogState : function(enabled, type) + { + this.showLoadMask(!enabled, type); + + this.previousButton.setDisabled(!enabled); + this.nextButton.setDisabled(!enabled); + this.cancelButton.setDisabled(!enabled); + + var ct = this.tools['close']; + + if (ct) { + switch (enabled) { + case true: + this.tools['close'].unmask(); + break; + + default: + this.tools['close'].mask(); + break; + } + } + + this.closable = enabled; + }, + + /** + * Shows the load mask for this wizard. By default, the cardPanel's body + * will be masked. + * + * @param {Boolean} show true to show the load mask, otherwise false. + * @param {String} type The type of message for the {@Ext.LoadMask} covering + * the cardPanel, as defined in the cfg property "loadMaskConfig" + */ + showLoadMask : function(show, type) + { + if (!type) { + type = 'default'; + } + + if (show) { + if (this.loadMask == null) { + this.loadMask = new Ext.LoadMask(this.body); + } + this.loadMask.msg = this.loadMaskConfig[type]; + this.loadMask.show(); + } else { + if (this.loadMask) { + this.loadMask.hide(); + } + } + }, + + + /** + * Inits the listener for the various {@link Ext.ux.Wiz.Card}s used + * by this component. + */ + initEvents : function() + { + Ext.ux.Wiz.superclass.initEvents.call(this); + + this.on('beforeclose', this.onBeforeClose, this); + }, + + /** + * Creates the head- and the card-panel. + * Be sure to have the custom {@link Ext.ux.layout.CardLayout} available + * in order to make the card-panel work as expected by this component + * ({@link http://www.siteartwork.de/cardlayout}). + */ + initPanels : function() + { + var cards = this.cards; + var cardPanelConfig = this.cardPanelConfig; + + Ext.apply(this.headerConfig, { + steps : cards.length + }); + + this.headPanel = new Ext.ux.Wiz.Header(this.headerConfig); + + Ext.apply(cardPanelConfig, { + layout : new Ext.ux.layout.CardLayout(), + items : cards + }); + + Ext.applyIf(cardPanelConfig, { + region : 'center', + border : false, + activeItem : 0 + }); + + var cards = this.cards; + + for (var i = 0, len = cards.length; i < len; i++) { + cards[i].on('show', this.onCardShow, this); + cards[i].on('hide', this.onCardHide, this); + cards[i].on('clientvalidation', this.onClientValidation, this); + } + + this.cardPanel = new Ext.Panel(cardPanelConfig); + }, + + /** + * Creates the instances for the the window buttons. + */ + initButtons : function() + { + this.previousButton = new Ext.Button({ + text : this.previousButtonText, + disabled : true, + minWidth : 75, + handler : this.onPreviousClick, + scope : this + }); + + this.nextButton = new Ext.Button({ + text : this.nextButtonText, + minWidth : 75, + handler : this.onNextClick, + scope : this + }); + + this.cancelButton = new Ext.Button({ + text : this.cancelButtonText, + handler : this.onCancelClick, + scope : this, + minWidth : 75 + }); + }, + +// -------- listeners + + /** + * Listener for the beforeclose event. + * This listener will return true or false based on the "closable" + * property by this component. This property will be changed by the "switchDialogState" + * method, indicating if there is currently any process running that should prevent + * this dialog from being closed. + * + * @param {Ext.Panel} panel The panel being closed + * + * @return {Boolean} + */ + onBeforeClose : function(panel) + { + return this.closable; + }, + + /** + * By default, the card firing this event monitors user input in a frequent + * interval and fires the 'clientvalidation'-event along with it. This listener + * will enable/disable the next/finish-button in accordance with it, based upon + * the parameter isValid. isValid" will be set by the form validation and depends + * on the validators you are using for the different input-elemnts in your form. + * If the card does not contain any forms, this listener will never be called by the + * card itself. + * + * @param {Ext.ux.Wiz.Card} The card that triggered the event. + * @param {Boolean} isValid "true", if the user input was valid, otherwise + * "false" + */ + onClientValidation : function(card, isValid) + { + if (!isValid) { + this.nextButton.setDisabled(true); + } else { + this.nextButton.setDisabled(false); + } + }, + + /** + * This will render the "next" button as disabled since the bindHandler's delay + * of the next card to show might be lagging on slower systems + * + */ + onCardHide : function(card) + { + if (this.cardPanel.layout.activeItem.id === card.id) { + this.nextButton.setDisabled(true); + } + }, + + + /** + * Listener for the "show" event of the card that gets shown in the card-panel. + * Renders the next/previous buttons based on the position of the card in the wizard + * and updates the head-panel accordingly. + * + * @param {Ext.ux.Wiz.Card} The card being shown. + */ + onCardShow : function(card) + { + var parent = card.ownerCt; + + var items = parent.items; + + for (var i = 0, len = items.length; i < len; i++) { + if (items.get(i).id == card.id) { + break; + } + } + + this.currentCard = i; + this.headPanel.updateStep(i, ''+card.title+''); + //erik: fix to set on main title the title of the current cardç + //this.setTitle(card.title); + + if (i == len-1) { + this.nextButton.setText(this.finishButtonText); + } else { + this.nextButton.setText(this.nextButtonText); + } + + /*if (card.isValid()) { + this.nextButton.setDisabled(false); + }*/ + //this.nextButton.setDisabled(card.isValid()); + + if (i == 0) { + this.previousButton.setDisabled(true); + } else { + this.previousButton.setDisabled(false); + } + + }, + + + /** + * Fires the 'cancel'-event. Closes this dialog if the return value of the + * listeners does not equal to "false". + */ + onCancelClick : function() + { + if (this.fireEvent('cancel', this) !== false) { + this.close(); + } + }, + + /** + * Fires the 'finish'-event. Closes this dialog if the return value of the + * listeners does not equal to "false". + */ + onFinish : function() + { + if (this.fireEvent('finish', this, this.getWizardData()) !== false) { + this.close(); + } + }, + + /** + * Listener for the previous-button. + * Switches to the previous displayed {@link Ext.ux.Wiz.Card}. + */ + onPreviousClick : function() + { + if (this.currentCard > 0) { + this.cardPanel.getLayout().setActiveItem(this.currentCard - 1); + } + }, + + /** + * Listener for the next-button. Switches to the next {@link Ext.ux.Wiz.Card} + * if the 'beforehide'-method of it did not return false. The functionality + * for this is implemented in {@link Ext.ux.layout.CardLayout}, which is needed + * as the layout for the card-panel of this component. + */ + onNextClick : function() + { + if (this.currentCard == this.cardCount-1) { + this.onFinish(); + } else { + this.cardPanel.getLayout().setActiveItem(this.currentCard+1); + } + } +}); \ No newline at end of file diff --git a/workflow/engine/templates/installer/databases.tpl b/workflow/engine/templates/installer/databases.tpl new file mode 100644 index 000000000..8e714f09b --- /dev/null +++ b/workflow/engine/templates/installer/databases.tpl @@ -0,0 +1,30 @@ + + .ext-ux-wiz-Header { + background-color:white; + border-bottom:1px solid #99BBE8; + background-image:url(/images/processmaker.logo.jpg); + background-repeat: no-repeat; +} + +.ext-ux-wiz-Header-title { + font-weight: bold; + padding: 4px 0px 0px 4px; +} + +.ext-ux-wiz-Header-step { + color:#767676; + text-align:right; + padding:2px 4px 0px 0px; + font-size:13.5px; +} + +.ext-ux-wiz-Header-stepIndicator-container { + float:right; + margin-right:6px; + margin-top:8px; +} + +.ext-ux-wiz-Header-stepIndicator { + margin-left:28px; + float:left; + background-image:url(/images/ext-ux-wiz-stepIndicator.png); + background-position:6px 0px; + background-repeat:repeat-x; + height:6px; + width:6px; +} + +.ext-ux-wiz-Header-stepIndicator-active { + background-position:0px 0px !important; +} + + \ No newline at end of file diff --git a/workflow/engine/templates/installer/main.js b/workflow/engine/templates/installer/main.js new file mode 100644 index 000000000..130190606 --- /dev/null +++ b/workflow/engine/templates/installer/main.js @@ -0,0 +1,1020 @@ +//var licenseTxt; +var wizard; +var theme; + +Ext.onReady(function(){ + Ext.QuickTips.init(); + var steps = new Array(); + + var storeDatabase = new Ext.data.Store({ + proxy: new Ext.data.HttpProxy({url: 'getEngines', method:'POST'}), + reader: new Ext.data.JsonReader({ + fields: [{name: 'id'},{name: 'label'}] + }), + listeners: {load: function() { + Ext.getCmp('db_engine').setValue(Ext.getCmp('db_engine').store.getAt(0).id); + if (Ext.getCmp('db_engine').store.getAt(0).id == 'mysql') { + Ext.getCmp('db_port').setValue('3306'); + Ext.getCmp('db_username').setValue('root'); + } + else { + Ext.getCmp('db_port').setValue('1433'); + Ext.getCmp('db_username').setValue('sa'); + } + testConnection(); + }} + }); + + var store = new Ext.data.ArrayStore({ + fields: ['id', 'label'], + data : [['en', 'English'],['es', 'Spanish']] + }); + + var cmbLanguages = new Ext.form.ComboBox({ + fieldLabel: 'Language', + store: store, + labelWidth: 200, + displayField:'label', + typeAhead: true, + mode: 'local', + forceSelection: true, + triggerAction: 'all', + emptyText:'Select a language...', + selectOnFocus:true + }); + + // getting the system info + function getSystemInfo() { + wizard.showLoadMask(true); + Ext.Ajax.request({ + url: 'getSystemInfo', + success: function(response){ + var response = Ext.util.JSON.decode(response.responseText); + Ext.getCmp('php').setValue (getFieldOutput(response.php.version, response.php.result)); + Ext.getCmp('mysql').setValue (getFieldOutput(response.mysql.version, response.mysql.result)); + //Ext.getCmp('mssql').setValue (getFieldOutput(response.mssql.version, response.mssql.result)); + Ext.getCmp('curl').setValue (getFieldOutput(response.curl.version, response.curl.result)); + Ext.getCmp('openssl').setValue (getFieldOutput(response.openssl.version, response.openssl.result)); + Ext.getCmp('dom').setValue (getFieldOutput(response.dom.version, response.dom.result)); + Ext.getCmp('gd').setValue (getFieldOutput(response.gd.version, response.gd.result)); + Ext.getCmp('multibyte').setValue (getFieldOutput(response.multibyte.version,response.multibyte.result)); + Ext.getCmp('soap').setValue (getFieldOutput(response.soap.version, response.soap.result)); + Ext.getCmp('ldap').setValue (getFieldOutput(response.ldap.version, response.ldap.result)); + Ext.getCmp('memory').setValue (getFieldOutput(response.memory.version, response.memory.result)); + + dbReq = response.mysql.result || response.mssql.result; + phpReq = response.php.result && response.curl.result && response.dom.result && response.gd.result && response.multibyte.result && response.soap.result && response.memory.result; + wizard.onClientValidation(0, dbReq && phpReq); + wizard.showLoadMask(false); + }, + failure: function(){}, + params: {'clientBrowser': PMExt.getBrowser().name} + }); + } + + // getting the system info + function getPermissionInfo() { + wizard.showLoadMask(true); + Ext.Ajax.request({ + url: 'getPermissionInfo', + success: function(response) { + var okImage = ''; + var badImage = ''; + var response = Ext.util.JSON.decode(response.responseText); + Ext.get('pathConfigSpan').dom.innerHTML = (response.pathConfig.result ? okImage : badImage); + Ext.get('pathLanguagesSpan').dom.innerHTML = (response.pathLanguages.result ? okImage : badImage); + Ext.get('pathPluginsSpan').dom.innerHTML = (response.pathPlugins.result ? okImage : badImage); + Ext.get('pathXmlformsSpan').dom.innerHTML = (response.pathXmlforms.result ? okImage : badImage); + Ext.get('pathPublicSpan').dom.innerHTML = (response.pathPublic.result ? okImage : badImage); + Ext.get('pathSharedSpan').dom.innerHTML = (response.pathShared.result ? okImage : badImage); + Ext.get('pathLogFileSpan').dom.innerHTML = (response.pathLogFile.result ? okImage : badImage); + wizard.onClientValidation(1, response.pathConfig.result && response.pathLanguages.result && response.pathPlugins.result && response.pathXmlforms.result && response.pathShared.result && response.pathLogFile.result); + wizard.showLoadMask(false); + }, + failure: function(){}, + params: { + 'pathConfig': Ext.getCmp('pathConfig').getValue(), + 'pathLanguages': Ext.getCmp('pathLanguages').getValue(), + 'pathPlugins': Ext.getCmp('pathPlugins').getValue(), + 'pathXmlforms': Ext.getCmp('pathXmlforms').getValue(), + 'pathShared': Ext.getCmp('pathShared').getValue(), + 'pathLogFile': Ext.getCmp('pathLogFile').getValue(), + 'pathPublic': Ext.getCmp('pathPublic').getValue() + } + }); + } + + function checkLicenseAgree() { + wizard.onClientValidation(2, Ext.getCmp('agreeCheckbox').getValue()); + } + + + function ckeckDBEnginesValuesLoaded() { + wizard.showLoadMask(true); + if (Ext.getCmp('db_engine').store.getCount() == 0) { + Ext.getCmp('db_engine').store.load(); + } + else { + testConnection(); + } + } + + // test database Connection + function testConnection() { + wizard.showLoadMask(true); + if ((Ext.getCmp('db_engine').getValue() == '') || !Ext.getCmp('db_hostname').isValid() || !Ext.getCmp('db_username').isValid()) { + wizard.onClientValidation(3, false); + wizard.showLoadMask(false); + return false; + } + Ext.Ajax.request({ + url: 'testConnection', + success: function(response){ + var response = Ext.util.JSON.decode(response.responseText); + Ext.getCmp('db_message').setValue(getFieldOutput(response.message, response.result)); + wizard.onClientValidation(3, response.result); + wizard.showLoadMask(false); + }, + failure: function(){}, + params: { + 'db_engine' : Ext.getCmp('db_engine').getValue(), + 'db_hostname': Ext.getCmp('db_hostname').getValue(), + 'db_username': Ext.getCmp('db_username').getValue(), + 'db_password': Ext.getCmp('db_password').getValue(), + 'db_port' : Ext.getCmp('db_port').getValue() + } + }); + } + + function checkWorkspaceConfiguration() { + var canInstall = false; + if (!Ext.getCmp('workspace').isValid()) { + Ext.getCmp('finish_message').setValue(getFieldOutput('Please enter a valid Workspace Name.', false)); + wizard.onClientValidation(4, false); + return; + } + if (!Ext.getCmp('adminUsername').isValid()) { + Ext.getCmp('finish_message').setValue(getFieldOutput('Please enter a valid Admin Username.', false)); + wizard.onClientValidation(4, false); + return; + } + if (Ext.getCmp('adminPassword').getValue() == '') { + Ext.getCmp('finish_message').setValue(getFieldOutput('Please enter the Admin Password.', false)); + wizard.onClientValidation(4, false); + return; + } + if (Ext.getCmp('adminPassword').getValue() != Ext.getCmp('confirmPassword').getValue()) { + Ext.getCmp('finish_message').setValue(getFieldOutput('The password confirmation is incorrect.', false)); + wizard.onClientValidation(4, false); + return; + } + if (!Ext.getCmp('wfDatabase').isValid()) { + Ext.getCmp('finish_message').setValue(getFieldOutput('Please enter the Workflow Database Name.', false)); + wizard.onClientValidation(4, false); + return; + } + if (!Ext.getCmp('rbDatabase').isValid()) { + Ext.getCmp('finish_message').setValue(getFieldOutput('Please enter the Rbac Database Name.', false)); + wizard.onClientValidation(4, false); + return; + } + if (!Ext.getCmp('rpDatabase').isValid()) { + Ext.getCmp('finish_message').setValue(getFieldOutput('Please enter the Report Database Name.', false)); + wizard.onClientValidation(4, false); + return; + } + checkDatabases(); + } + + function checkDatabases() { + wizard.showLoadMask(true); + Ext.Ajax.request({ + url: 'checkDatabases', + success: function(response){ + var existMsg = '(Exists)'; + var noExistsMsg = '(No exists)'; + var response = Ext.util.JSON.decode(response.responseText); + Ext.get('wfDatabaseSpan').dom.innerHTML = (response.wfDatabaseExists ? existMsg : noExistsMsg); + Ext.get('rbDatabaseSpan').dom.innerHTML = (response.rbDatabaseExists ? existMsg : noExistsMsg); + Ext.get('rpDatabaseSpan').dom.innerHTML = (response.rpDatabaseExists ? existMsg : noExistsMsg); + var dbFlag = ((!response.wfDatabaseExists && !response.rbDatabaseExists && !response.rpDatabaseExists) || Ext.getCmp('deleteDB').getValue()); + wizard.onClientValidation(4, dbFlag); + if (dbFlag) { + Ext.getCmp('finish_message').setValue(getFieldOutput('The data is correct.', true)); + } + else { + Ext.getCmp('finish_message').setValue(getFieldOutput('Rename the databases names or workspace name or check the "Delete Databases if exists" to overwrite the exiting databases.', false)); + } + wizard.showLoadMask(false); + }, + failure: function(){}, + params: { + 'db_engine' : Ext.getCmp('db_engine').getValue(), + 'db_hostname': Ext.getCmp('db_hostname').getValue(), + 'db_username': Ext.getCmp('db_username').getValue(), + 'db_password': Ext.getCmp('db_password').getValue(), + 'db_port' : Ext.getCmp('db_port').getValue(), + 'wfDatabase' : Ext.getCmp('wfDatabase').getValue(), + 'rbDatabase' : Ext.getCmp('rbDatabase').getValue(), + 'rpDatabase' : Ext.getCmp('rpDatabase').getValue() + } + }); + } + + + var setIndex = 0; + // first card with welcome message +/* steps[setIndex++] = new Ext.ux.Wiz.Card({ + title : 'Setting language', + labelAlign: 'right', + labelWidth: 200, + items : [ + { + border : false, + bodyStyle : 'background:none;', + html : 'Welcome to the Setup ProcessMaker wizard
'+ + 'Select your language from the list.

' + }, + { + border : false, + bodyStyle : 'background:none;padding-bottom:10px;', + html : 'ProcessMaker! 2.0.x Stable 18-Apr-2011 23:00 GMT:' + }, + cmbLanguages, + { + border : false, + bodyStyle : 'background:none;padding-top:250px;padding-left:420px;', + html : 'Please click the "next"-button and fill out all form values.'+ + '
' + } + ], + listeners: { + show: function(){ + //alert('s'); + //make akax call here + } + } + }); +*/ + // first card with Pre-Installation Check + steps[setIndex++] = new Ext.ux.Wiz.Card({ + title : 'Pre-installation check', + monitorValid : false, + labelAlign: 'left', + labelWidth: 200, + defaults : { + }, + items : [ + { + border : false, + html : 'Pre-installation check', + bodyStyle : 'background:none;padding-top:0px;padding-bottom:5px;font-weight:bold;font-size:1.3em;' + }, + { + xtype:'panel', + layout:'border', + height: 340, + items:[ + { + region: 'west', + width: 250, + bodyStyle : 'padding:10px;font-size:1.2em;', + html: step1_txt + }, + /*{ + region: 'south', + xtype : 'fieldset', + bodyStyle : 'padding:-3px;font-size:1.2em;', + height : 45, + labelAlign: 'right', + items:[ + new Ext.Button({ + text : 'Check Again', + handler : getSystemInfo, + scope : this + }) + ] + },*/ + { + region: 'center', + xtype : 'fieldset', + labelWidth: 200, + items:[ + { + xtype : 'displayfield', + fieldLabel: 'PHP Version >= 5.1', + id : 'php' + }, + { + xtype : 'displayfield', + fieldLabel: 'MySQL Support', + id : 'mysql' + }/*, + { + xtype : 'displayfield', + fieldLabel: 'MSSQL Support (*)', + id : 'mssql' + }*/, + { + xtype : 'displayfield', + fieldLabel: 'cURL Version', + id : 'curl' + }, + { + xtype : 'displayfield', + fieldLabel: 'OpenSSL Version (**)', + id : 'openssl' + }, + { + xtype : 'displayfield', + fieldLabel: 'DOM/XML Support', + id : 'dom' + }, + { + xtype : 'displayfield', + fieldLabel: 'GD Support', + id : 'gd' + }, + { + xtype : 'displayfield', + fieldLabel: 'Multibyte Strings Support', + id : 'multibyte' + }, + { + xtype : 'displayfield', + fieldLabel: 'Soap Support', + id : 'soap' + }, + { + xtype : 'displayfield', + fieldLabel: 'LDAP Support (***)', + id : 'ldap' + }, + { + xtype : 'displayfield', + fieldLabel: 'Memory Limit >= 80M', + id: 'memory', + value: '5.0 or greater' + }, + new Ext.Button({ + text : 'Check Again', + handler : getSystemInfo, + scope : this + }) + ] + } + ] + } + ], + listeners: { + show: getSystemInfo + } + }); + + // second with Pre-Installation Check + /* + steps[setIndex++] = new Ext.ux.Wiz.Card({ + title : 'Recomended Settings', + monitorValid : true, + labelAlign: 'right', + labelWidth: 200, + defaults : { + //labelStyle : 'font-size:11px' + }, + items : [ + { + border : false, + html:'Recomended Settings', + bodyStyle : 'background:none;padding-top:10px;padding-bottom:5px;font-weight:bold;' + }, + { + xtype:'panel', + layout:'border', + height: 120, + items:[ + { + region: 'west', + bodyStyle : 'padding:10px;font-size:1.2em;', + width: 250, + html: step2_txt + }, + { + region: 'center', + xtype : 'fieldset', + defaultType: 'displayfield', + items:[ + { + fieldLabel: 'PHP Version', + value: '5.1.0 or greater' + }, + { + fieldLabel: 'MySql Version', + value: '5.0 or greater' + } + ] + } + ] + } + ] + } ); + */ + + // third card with Directory File Permission + steps[setIndex++] = new Ext.ux.Wiz.Card({ + title:'Directory File Permission', + monitorValid : false, + labelAlign: 'left', + labelWidth: 200, + defaults : { + //labelStyle : 'font-size:11px' + }, + items : [ + { + border : false, + html:'Directory File Permission', + bodyStyle : 'background:none;padding-top:0px;padding-bottom:5px;font-weight:bold;font-size:1.3em;' + }, + { + xtype:'panel', + layout:'border', + height: 300, + items:[ + { + region: 'north', + height: 55, + bodyStyle : 'padding:10px;font-size:1.2em;', + html: step3_txt + }, + { + region: 'center', + xtype : 'fieldset', + alignField : 'left', + bodyStyle : 'padding-left:40px;font-size:12;', + labelWidth: 180, + items:[ + { + xtype: 'textfield', + fieldLabel: ' Config Directory', + id: 'pathConfig', + width: 430, + value: path_config, + disabled: true + }, + { + xtype: 'textfield', + fieldLabel: ' Language Directory', + id: 'pathLanguages', + width: 430, + value: path_languages, + disabled: true + }, + { + xtype: 'textfield', + fieldLabel: ' Plugins Directory', + id: 'pathPlugins', + width: 430, + value: path_plugins, + disabled: true + }, + { + xtype: 'textfield', + fieldLabel: ' Xmlform Directory Directory', + id: 'pathXmlforms', + width: 430, + value: path_xmlforms, + disabled: true + }, + { + xtype: 'textfield', + fieldLabel: ' Public Directory', + id: 'pathPublic', + width: 430, + value: path_public, + disabled: true + }, + { + xtype: 'textfield', + fieldLabel: ' Workflow Data Directory', + id: 'pathShared', + width: 430, + value: path_shared, + enableKeyEvents: true, + listeners: {keyup: function() { + wizard.onClientValidation(2, false); + if (Ext.getCmp('pathShared').getValue().substr(-1, 1) != path_sep) { + Ext.getCmp('pathLogFile').setValue(Ext.getCmp('pathShared').getValue() + path_sep + 'log' + path_sep + 'install.log'); + } + else { + Ext.getCmp('pathLogFile').setValue(Ext.getCmp('pathShared').getValue() + 'log' + path_sep + 'install.log'); + } + }} + }, + { + xtype: 'textfield', + fieldLabel: ' Installation log file', + id: 'pathLogFile', + width: 430, + value: path_shared + 'log' + path_sep + 'install.log', + disabled: true + }, + new Ext.Button({ + text : 'Check Again', + handler : getPermissionInfo, + scope : this + }) + ] + } + ] + } + ], + listeners: { + show: getPermissionInfo + } + + } ); + + // third card with input field email-address + steps[setIndex++] = new Ext.ux.Wiz.Card({ + title:'ProcessMaker Open Source License', + //monitorValid : false, + defaults : { + labelStyle : 'font-size:12px' + }, + items : [ + { + border : false, + html:'ProcessMaker Open Source License', + bodyStyle : 'background:none;padding-top:0px;padding-bottom:5px;font-weight:bold;font-size:1.3em;' + }, + { + xtype:'panel', + layout:'border', + height: 340, + items:[ + { + region: 'center', + xtype : 'fieldset', + items:[ + new Ext.form.TextArea({ + name : 'license', + readOnly : true, + width : 510, + height : 280, + style : 'font-size:13px', + value : licenseTxt + }), + new Ext.form.Checkbox({ + boxLabel : 'I agree', + id : 'agreeCheckbox', + handler: function() { + wizard.onClientValidation(2, this.getValue()); + } + }) + ] + } + ] + } + ], + listeners: { + show: checkLicenseAgree + } + + }); + + // fourth card Database Configuration + steps[setIndex++] = new Ext.ux.Wiz.Card({ + title : 'Database Configuration', + monitorValid : false, + items : [ + { + border : false, + html : 'Database Configuration', + bodyStyle : 'background:none;padding-top:0px;padding-bottom:5px;font-weight:bold;font-size:1.3em;' + }, + { + xtype:'panel', + layout:'border', + height: 360, + items:[ + { + region: 'west', + width: 200, + bodyStyle : 'padding:10px;font-size:1.2em;', + html: step4_txt + }, + { + region: 'center', + xtype : 'panel', + bodyStyle : 'background:none;padding-left:20px;padding-right:20px;padding-top:20px;padding-bottom:20px;font-size:1.2em;', + items:[ + { + xtype:'fieldset', + labelAlign: 'left', + labelWidth: 160, + items:[ + new Ext.form.ComboBox({ + fieldLabel: 'Database Engine', + width : 200, + store : storeDatabase, + displayField : 'label', + valueField : 'id', + mode : 'local', + editable : false, + forceSelection: true, + allowBlank: false, + triggerAction: 'all', + id: 'db_engine', + selectOnFocus : true, + listeners: {select: function() { + if (this.value == 'mysql') { + Ext.getCmp('db_port').setValue('3306'); + Ext.getCmp('db_username').setValue('root'); + } + else { + Ext.getCmp('db_port').setValue('1433'); + Ext.getCmp('db_username').setValue('sa'); + } + wizard.onClientValidation(3, false); + }} + }), + { + xtype : 'textfield', + fieldLabel: 'Host Name', + width : 180, + id: 'db_hostname', + value :'localhost', + allowBlank : false, + validator : function(v){ + var t = /^[0-9\.a-zA-Z_\-]+$/; + return t.test(v); + }, + listeners: {change: function() { + wizard.onClientValidation(3, false); + }} + }, + { + xtype : 'textfield', + fieldLabel: 'Port', + width : 180, + id: 'db_port', + value :'', + allowBlank : false, + validator : function(v){ + var t = /^[0-9]+$/; + return t.test(v); + }, + listeners: {change: function() { + wizard.onClientValidation(3, false); + }} + }, + { + xtype : 'textfield', + fieldLabel: 'Username', + width : 180, + id: 'db_username', + value :'root', + allowBlank : false, + validator : function(v){ + var t = /^[.a-zA-Z_\-]+$/; + return t.test(v); + }, + listeners: {change: function() { + wizard.onClientValidation(3, false); + }} + }, + { + xtype : 'textfield', + fieldLabel: 'Password', + inputType : 'password', + value : '', + width : 180, + id: 'db_password', + allowBlank : true, + listeners: {change: function() { + wizard.onClientValidation(3, false); + }} + }, + { + xtype : 'displayfield', + //fieldLabel: ', + id : 'db_message' + }, + new Ext.Button({ + text : ' Test Connection', + handler : testConnection, + scope : this + }) + ] + }, + ] + } + ] + } + ], + listeners: { + show: ckeckDBEnginesValuesLoaded + } + }); + + + steps[setIndex++] = new Ext.ux.Wiz.Card({ + title : 'Workspace Configuration', + monitorValid : false, + defaults : { + labelStyle : 'font-size:11px' + }, + items : [ + { + border : false, + html : 'Workspace Configuration', + bodyStyle : 'background:none;padding-top:0px;padding-bottom:5px;font-weight:bold;font-size:1.3em;' + }, + { + xtype:'panel', + layout:'border', + height: 360, + items:[ + { + region: 'west', + width: 200, + bodyStyle : 'padding:10px;font-size:1.2em;', + html: step5_txt + }, + { + region: 'center', + xtype : 'panel', + bodyStyle : 'background:none;padding-left:20px;padding-right:20px;padding-top:20px;padding-bottom:20px;font-size:1.2em;', + items:[ + { + xtype:'fieldset', + //labelAlign: 'right', + labelWidth: 210, + items:[ + { + xtype : 'textfield', + fieldLabel: 'Workspace Name', + value :'workflow', + maxLength: 29, + validator : function(v){ + var t = /^[a-zA-Z_0-9]+$/; + return t.test(v); + }, + id : 'workspace', + enableKeyEvents: true, + listeners: {keyup: function() { + wizard.onClientValidation(4, false); + if (!Ext.getCmp('changeDBNames').getValue()) { + Ext.getCmp('wfDatabase').setValue('wf_' + this.getValue()); + Ext.getCmp('rbDatabase').setValue('rb_' + this.getValue()); + Ext.getCmp('rpDatabase').setValue('rp_' + this.getValue()); + } + }} + }, + { + xtype : 'textfield', + fieldLabel: 'Admin Username', + value :'admin', + validator : function(v){ + var t = /^[a-zA-Z_0-9.@-]+$/; + return t.test(v); + }, + id : 'adminUsername', + enableKeyEvents: true, + listeners: {keyup: function() { + wizard.onClientValidation(4, false); + }} + }, + { + xtype : 'textfield', + fieldLabel: 'Admin Password', + inputType : 'password', + id: 'adminPassword', + enableKeyEvents: true, + listeners: {keyup: function() { + wizard.onClientValidation(4, false); + }} + }, + { + xtype : 'textfield', + fieldLabel: 'Confirm Admin Password', + inputType : 'password', + id : 'confirmPassword', + enableKeyEvents: true, + listeners: {keyup: function() { + wizard.onClientValidation(4, false); + }} + } + ] + }, + { + xtype : 'fieldset', + labelAlign: 'left', + labelWidth: 210, + //labelWidth: 200, + //title: 'ProcessMaker Databases', + items:[ + new Ext.form.Checkbox({ + boxLabel: 'Change Database names', + id : 'changeDBNames', + handler: function() { + if (this.getValue()) { + Ext.getCmp('wfDatabase').enable(); + Ext.getCmp('rbDatabase').enable(); + Ext.getCmp('rpDatabase').enable(); + Ext.getCmp('wfDatabase').validate(); + Ext.getCmp('rbDatabase').validate(); + Ext.getCmp('rpDatabase').validate(); + } + else { + Ext.getCmp('wfDatabase').setValue('wf_' + Ext.getCmp('workspace').getValue()); + Ext.getCmp('rbDatabase').setValue('rb_' + Ext.getCmp('workspace').getValue()); + Ext.getCmp('rpDatabase').setValue('rp_' + Ext.getCmp('workspace').getValue()); + Ext.getCmp('wfDatabase').disable(); + Ext.getCmp('rbDatabase').disable(); + Ext.getCmp('rpDatabase').disable(); + } + wizard.onClientValidation(4, false); + } + }), + { + xtype : 'textfield', + fieldLabel: 'Workflow Database Name ', + id : 'wfDatabase', + value :'wf_workflow', + allowBlank : false, + maxLength: 32, + validator : function(v){ + var t = /^[a-zA-Z_0-9]+$/; + return t.test(v); + }, + disabled: true, + enableKeyEvents: true, + listeners: {keyup: function() { + wizard.onClientValidation(4, false); + }} + }, + { + xtype : 'textfield', + fieldLabel: 'Rbac Database Name ', + id : 'rbDatabase', + value :'rb_workflow', + allowBlank : false, + maxLength: 32, + validator : function(v){ + var t = /^[a-zA-Z_0-9]+$/; + return t.test(v); + }, + disabled: true, + enableKeyEvents: true, + listeners: {keyup: function() { + wizard.onClientValidation(4, false); + }} + }, + { + xtype : 'textfield', + fieldLabel: 'Report Database Name ', + id : 'rpDatabase', + value :'rp_workflow', + allowBlank : false, + maxLength: 32, + validator : function(v){ + var t = /^[a-zA-Z_0-9]+$/; + return t.test(v); + }, + disabled: true, + enableKeyEvents: true, + listeners: {keyup: function() { + wizard.onClientValidation(4, false); + }} + }, + new Ext.form.Checkbox({ + boxLabel : "Delete Databases if exists", + id : 'deleteDB', + handler: function() { + wizard.onClientValidation(4, false); + } + }), + { + xtype : 'displayfield', + id : 'finish_message' + }, + new Ext.Button({ + id: 'checkWSConfiguration', + text: ' Check Workspace Configuration', + handler: checkWorkspaceConfiguration, + scope: this + }) + ] + } + ] + } + ] + } + ], + listeners: { + show: function() { + checkWorkspaceConfiguration(); + } + } + }); + + wizard = new Ext.ux.Wiz({ + height: 520, + width : 780, + id : 'wizard', + closable: false, + headerConfig : { + title : ' ' + }, + cardPanelConfig : { + defaults : { + bodyStyle : 'padding:20px 10px 10px 20px;background-color:#F6F6F6;', + border : false + } + }, + cards : steps, + loadMaskConfig: { + default: 'Checking...', + finishing: 'Finishing...' + }, + listeners: { + finish: finishInstallation + } + }); + + // show the wizard + wizard.show(); +}); + + +function finishInstallation() +{ + wizard.showLoadMask(true, 'finishing'); + Ext.Ajax.request({ + url: 'createWorkspace', + success: function(response){ + var response = Ext.util.JSON.decode(response.responseText); + Ext.getCmp('finish_message').setValue(getFieldOutput(response.message, response.result)); + wizard.showLoadMask(false); + if (response.result) { + wizard.onClientValidation(4, false); + + //Ext.msgBoxSlider.msgTopCenter( + PMExt.info( + 'ProcessMaker Installation', + 'ProcessMaker was successfully installed
Workspace "' + Ext.getCmp('workspace').getValue() + '" was installed correctly.', + function(){ + _redirect(response.uri); + } + ); + + //setTimeout("_redirect('"+response.url+"')", 3000); + // Ext.Msg.alert( + // 'ProcessMaker was successfully installed', + // 'Workspace "' + Ext.getCmp('workspace').getValue() + '" was installed correctly now you will be redirected to your new workspace.', + // function() {_redirectwindow.location = response.url;} + // ); + } + }, + failure: function(){wizard.showLoadMask(false);}, + params: { + 'db_engine' : Ext.getCmp('db_engine' ).getValue(), + 'db_hostname' : Ext.getCmp('db_hostname' ).getValue(), + 'db_username' : Ext.getCmp('db_username' ).getValue(), + 'db_password' : Ext.getCmp('db_password' ).getValue(), + 'db_port' : Ext.getCmp('db_port' ).getValue(), + 'pathConfig' : Ext.getCmp('pathConfig' ).getValue(), + 'pathLanguages' : Ext.getCmp('pathLanguages').getValue(), + 'pathPlugins' : Ext.getCmp('pathPlugins' ).getValue(), + 'pathXmlforms' : Ext.getCmp('pathXmlforms' ).getValue(), + 'pathShared' : Ext.getCmp('pathShared' ).getValue(), + 'workspace' : Ext.getCmp('workspace' ).getValue(), + 'adminUsername' : Ext.getCmp('adminUsername').getValue(), + 'adminPassword' : Ext.getCmp('adminPassword').getValue(), + 'wfDatabase' : Ext.getCmp('wfDatabase' ).getValue(), + 'rbDatabase' : Ext.getCmp('rbDatabase' ).getValue(), + 'rpDatabase' : Ext.getCmp('rpDatabase' ).getValue(), + 'deleteDB' : Ext.getCmp('deleteDB' ).getValue() + }, + timeout: 180000 + }); +} + +function _redirect(_uri){ + console.log('redirecting:: '+_uri); + window.location = _uri; +} + +function getFieldOutput(txt, assert) +{ + if(assert == true) { + img = 'dialog-ok-apply.png'; + size = 'width=12 height=12'; + color = 'green'; + } else { + img = 'delete.png'; + size = 'width=15 height=15'; + color = 'red'; + } + return ''+txt + ' '; +} \ No newline at end of file diff --git a/workflow/engine/templates/installer/newSite.html b/workflow/engine/templates/installer/newSite.html new file mode 100644 index 000000000..f4469cd8e --- /dev/null +++ b/workflow/engine/templates/installer/newSite.html @@ -0,0 +1,41 @@ + \ No newline at end of file diff --git a/workflow/engine/templates/installer/newSite.js b/workflow/engine/templates/installer/newSite.js new file mode 100644 index 000000000..4a77459c9 --- /dev/null +++ b/workflow/engine/templates/installer/newSite.js @@ -0,0 +1,535 @@ +Ext.onReady(function(){ + var getFieldOutput = function(txt, assert) { + if(assert == true) { + img = 'dialog-ok-apply.png'; + size = 'width=12 height=12'; + color = 'green'; + } else { + img = 'delete.png'; + size = 'width=15 height=15'; + color = 'red'; + } + return '' + txt + ' '; + }; + + var testConnection = function() { + wizard.showLoadMask(true); + if ((Ext.getCmp('db_engine').getValue() == '') || !Ext.getCmp('db_hostname').isValid() || !Ext.getCmp('db_username').isValid()) { + wizard.onClientValidation(1, false); + wizard.showLoadMask(false); + return false; + } + Ext.Ajax.request({ + url: 'newSite', + success: function(response){ + var response = Ext.util.JSON.decode(response.responseText); + Ext.getCmp('db_message').setValue(getFieldOutput(response.message, response.result)); + wizard.onClientValidation(1, response.result); + wizard.showLoadMask(false); + }, + failure: function(){}, + params: { + 'action': 'testConnection', + 'db_engine': Ext.getCmp('db_engine').getValue(), + 'db_hostname': Ext.getCmp('db_hostname').getValue(), + 'db_port': Ext.getCmp('db_port').getValue(), + 'db_username': Ext.getCmp('db_username').getValue(), + 'db_password': Ext.getCmp('db_password').getValue() + } + }); + }; + + var ckeckDBEnginesValuesLoaded = function() { + wizard.showLoadMask(true); + if (Ext.getCmp('db_engine').store.getCount() == 0) { + Ext.getCmp('db_engine').store.load(); + } + else { + testConnection(); + } + }; + + var checkWorkspaceConfiguration = function() { + var canInstall = false; + if (!Ext.getCmp('workspace').isValid()) { + Ext.getCmp('finish_message').setValue(getFieldOutput('Please enter a valid Workspace Name.', false)); + wizard.onClientValidation(2, false); + return; + } + if (!Ext.getCmp('adminUsername').isValid()) { + Ext.getCmp('finish_message').setValue(getFieldOutput('Please enter a valid Admin Username.', false)); + wizard.onClientValidation(2, false); + return; + } + if (Ext.getCmp('adminPassword').getValue() == '') { + Ext.getCmp('finish_message').setValue(getFieldOutput('Please enter the Admin Password.', false)); + wizard.onClientValidation(2, false); + return; + } + if (Ext.getCmp('adminPassword').getValue() != Ext.getCmp('confirmPassword').getValue()) { + Ext.getCmp('finish_message').setValue(getFieldOutput('The password confirmation is incorrect.', false)); + wizard.onClientValidation(2, false); + return; + } + if (!Ext.getCmp('wfDatabase').isValid()) { + Ext.getCmp('finish_message').setValue(getFieldOutput('Please enter the Workflow Database Name.', false)); + wizard.onClientValidation(2, false); + return; + } + if (!Ext.getCmp('rbDatabase').isValid()) { + Ext.getCmp('finish_message').setValue(getFieldOutput('Please enter the Rbac Database Name.', false)); + wizard.onClientValidation(2, false); + return; + } + if (!Ext.getCmp('rpDatabase').isValid()) { + Ext.getCmp('finish_message').setValue(getFieldOutput('Please enter the Report Database Name.', false)); + wizard.onClientValidation(2, false); + return; + } + checkDatabases(); + }; + + var checkDatabases = function() { + wizard.showLoadMask(true); + Ext.Ajax.request({ + url: 'newSite', + success: function(response){ + var existMsg = '(Exists)'; + var noExistsMsg = '(No exists)'; + var response = Ext.util.JSON.decode(response.responseText); + Ext.get('wfDatabaseSpan').dom.innerHTML = (response.wfDatabaseExists ? existMsg : noExistsMsg); + Ext.get('rbDatabaseSpan').dom.innerHTML = (response.rbDatabaseExists ? existMsg : noExistsMsg); + Ext.get('rpDatabaseSpan').dom.innerHTML = (response.rpDatabaseExists ? existMsg : noExistsMsg); + var dbFlag = ((!response.wfDatabaseExists && !response.rbDatabaseExists && !response.rpDatabaseExists) || Ext.getCmp('deleteDB').getValue()); + wizard.onClientValidation(2, dbFlag); + if (dbFlag) { + Ext.getCmp('finish_message').setValue(getFieldOutput('The data is correct.', true)); + } + else { + Ext.getCmp('finish_message').setValue(getFieldOutput('Rename the databases names or workspace name or check the "Delete Databases if exists" to overwrite the exiting databases.', false)); + } + wizard.showLoadMask(false); + }, + failure: function(){}, + params: { + 'action': 'checkDatabases', + 'db_engine': Ext.getCmp('db_engine').getValue(), + 'db_hostname': Ext.getCmp('db_hostname').getValue(), + 'db_username': Ext.getCmp('db_username').getValue(), + 'db_password': Ext.getCmp('db_password').getValue(), + 'db_port': Ext.getCmp('db_port').getValue(), + 'wfDatabase': Ext.getCmp('wfDatabase').getValue(), + 'rbDatabase': Ext.getCmp('rbDatabase').getValue(), + 'rpDatabase': Ext.getCmp('rpDatabase').getValue() + } + }); + }; + + var steps = []; + var setIndex = 0; + var storeDatabase = new Ext.data.Store({ + proxy: new Ext.data.HttpProxy({url: 'newSite?action=getEngines', method: 'POST'}), + reader: new Ext.data.JsonReader({ + fields: [{name: 'id'},{name: 'label'}] + }), + listeners: {load: function() { + Ext.getCmp('db_engine').setValue(DB_ADAPTER); + testConnection(); + }} + }); + + steps[setIndex++] = new Ext.ux.Wiz.Card({ + title: 'Database Configuration', + monitorValid: false, + items: [ + { + border: false, + html: 'Database Configuration', + bodyStyle: 'background:none;padding-top:0px;padding-bottom:5px;font-weight:bold;font-size:1.3em;' + }, + { + xtype:'panel', + layout:'border', + height: 360, + items: [ + { + region: 'west', + width: 200, + bodyStyle: 'padding:10px;font-size:1.2em;', + html: textStep1 + }, + { + region: 'center', + xtype: 'panel', + bodyStyle: 'background:none;padding-left:20px;padding-right:20px;padding-top:20px;padding-bottom:20px;font-size:1.2em;', + items:[ + { + xtype:'fieldset', + labelAlign: 'left', + labelWidth: 160, + items: [ + new Ext.form.ComboBox({ + fieldLabel: 'Database Engine', + width: 200, + store: storeDatabase, + displayField: 'label', + valueField: 'id', + mode: 'local', + editable: false, + forceSelection: true, + allowBlank: false, + triggerAction: 'all', + id: 'db_engine', + selectOnFocus: true, + listeners: {select: function() { + if (this.value == 'mysql') { + Ext.getCmp('db_port').setValue('3306'); + Ext.getCmp('db_username').setValue('root'); + } + else { + Ext.getCmp('db_port').setValue('1433'); + Ext.getCmp('db_username').setValue('sa'); + } + wizard.onClientValidation(1, false); + }} + }), + { + xtype: 'textfield', + fieldLabel: 'Host Name', + width: 180, + id: 'db_hostname', + value: DB_HOST, + allowBlank: false, + validator: function(v){ + var t = /^[0-9\.a-zA-Z_\-]+$/; + return t.test(v); + }, + listeners: {change: function() { + wizard.onClientValidation(1, false); + }} + }, + { + xtype: 'textfield', + fieldLabel: 'Port', + width: 180, + id: 'db_port', + value: DB_PORT, + allowBlank: false, + validator: function(v){ + var t = /^[0-9]+$/; + return t.test(v); + }, + listeners: {change: function() { + wizard.onClientValidation(1, false); + }} + }, + { + xtype: 'textfield', + fieldLabel: 'Username', + width: 180, + id: 'db_username', + value: DB_USER, + allowBlank: false, + validator: function(v){ + var t = /^[.a-zA-Z_\-]+$/; + return t.test(v); + }, + listeners: {change: function() { + wizard.onClientValidation(1, false); + }} + }, + { + xtype: 'textfield', + fieldLabel: 'Password', + inputType: 'password', + width: 180, + id: 'db_password', + value: DB_PASS, + allowBlank: true, + listeners: {change: function() { + wizard.onClientValidation(1, false); + }} + }, + { + xtype: 'displayfield', + id: 'db_message' + }, + new Ext.Button({ + text: ' Test Connection', + handler: testConnection, + scope: this + }) + ] + }, + ] + } + ] + } + ], + listeners: { + show: ckeckDBEnginesValuesLoaded + } + }); + + steps[setIndex++] = new Ext.ux.Wiz.Card({ + title: 'Workspace Configuration', + monitorValid: false, + defaults: { + labelStyle: 'font-size:11px' + }, + items: [ + { + border: false, + html: 'Workspace Configuration', + bodyStyle: 'background:none;padding-top:0px;padding-bottom:5px;font-weight:bold;font-size:1.3em;' + }, + { + xtype:'panel', + layout:'border', + height: 360, + items:[ + { + region: 'west', + width: 200, + bodyStyle: 'padding:10px;font-size:1.2em;', + html: textStep2 + }, + { + region: 'center', + xtype: 'panel', + bodyStyle: 'background:none;padding-left:20px;padding-right:20px;padding-top:20px;padding-bottom:20px;font-size:1.2em;', + items: [ + { + xtype:'fieldset', + //labelAlign: 'right', + labelWidth: 210, + items:[ + { + xtype: 'textfield', + fieldLabel: 'Workspace Name', + value:'workflow', + maxLength: 29, + validator: function(v){ + var t = /^[a-zA-Z_0-9]+$/; + return t.test(v); + }, + id: 'workspace', + enableKeyEvents: true, + listeners: {keyup: function() { + wizard.onClientValidation(2, false); + if (!Ext.getCmp('changeDBNames').getValue()) { + Ext.getCmp('wfDatabase').setValue('wf_' + this.getValue()); + Ext.getCmp('rbDatabase').setValue('rb_' + this.getValue()); + Ext.getCmp('rpDatabase').setValue('rp_' + this.getValue()); + } + }} + }, + { + xtype: 'textfield', + fieldLabel: 'Admin Username', + value:'admin', + validator: function(v){ + var t = /^[a-zA-Z_0-9.@-]+$/; + return t.test(v); + }, + id: 'adminUsername', + enableKeyEvents: true, + listeners: {keyup: function() { + wizard.onClientValidation(2, false); + }} + }, + { + xtype: 'textfield', + fieldLabel: 'Admin Password', + inputType: 'password', + id: 'adminPassword', + enableKeyEvents: true, + listeners: {keyup: function() { + wizard.onClientValidation(2, false); + }} + }, + { + xtype: 'textfield', + fieldLabel: 'Confirm Admin Password', + inputType: 'password', + id: 'confirmPassword', + enableKeyEvents: true, + listeners: {keyup: function() { + wizard.onClientValidation(2, false); + }} + } + ] + }, + { + xtype: 'fieldset', + labelAlign: 'left', + labelWidth: 210, + //labelWidth: 200, + //title: 'ProcessMaker Databases', + items:[ + new Ext.form.Checkbox({ + boxLabel: 'Change Database names', + id: 'changeDBNames', + handler: function() { + if (this.getValue()) { + Ext.getCmp('wfDatabase').enable(); + Ext.getCmp('rbDatabase').enable(); + Ext.getCmp('rpDatabase').enable(); + Ext.getCmp('wfDatabase').validate(); + Ext.getCmp('rbDatabase').validate(); + Ext.getCmp('rpDatabase').validate(); + } + else { + Ext.getCmp('wfDatabase').setValue('wf_' + Ext.getCmp('workspace').getValue()); + Ext.getCmp('rbDatabase').setValue('rb_' + Ext.getCmp('workspace').getValue()); + Ext.getCmp('rpDatabase').setValue('rp_' + Ext.getCmp('workspace').getValue()); + Ext.getCmp('wfDatabase').disable(); + Ext.getCmp('rbDatabase').disable(); + Ext.getCmp('rpDatabase').disable(); + } + wizard.onClientValidation(2, false); + } + }), + { + xtype: 'textfield', + fieldLabel: 'Workflow Database Name ', + id: 'wfDatabase', + value:'wf_workflow', + allowBlank: false, + maxLength: 32, + validator: function(v){ + var t = /^[a-zA-Z_0-9]+$/; + return t.test(v); + }, + disabled: true, + enableKeyEvents: true, + listeners: {keyup: function() { + wizard.onClientValidation(2, false); + }} + }, + { + xtype: 'textfield', + fieldLabel: 'Rbac Database Name ', + id: 'rbDatabase', + value:'rb_workflow', + allowBlank: false, + maxLength: 32, + validator: function(v){ + var t = /^[a-zA-Z_0-9]+$/; + return t.test(v); + }, + disabled: true, + enableKeyEvents: true, + listeners: {keyup: function() { + wizard.onClientValidation(2, false); + }} + }, + { + xtype: 'textfield', + fieldLabel: 'Report Database Name ', + id: 'rpDatabase', + value:'rp_workflow', + allowBlank: false, + maxLength: 32, + validator: function(v){ + var t = /^[a-zA-Z_0-9]+$/; + return t.test(v); + }, + disabled: true, + enableKeyEvents: true, + listeners: {keyup: function() { + wizard.onClientValidation(2, false); + }} + }, + new Ext.form.Checkbox({ + boxLabel: "Delete Databases if exists", + id: 'deleteDB', + handler: function() { + wizard.onClientValidation(2, false); + } + }), + { + xtype: 'displayfield', + id: 'finish_message' + }, + new Ext.Button({ + id: 'checkWSConfiguration', + text: ' Check Workspace Configuration', + handler: checkWorkspaceConfiguration, + scope: this + }) + ] + } + ] + } + ] + } + ], + listeners: { + show: function() { + checkWorkspaceConfiguration(); + } + } + }); + + var wizard = new Ext.ux.Wiz({ + height: 520, + width: 780, + id: 'wizard', + closable: false, + headerConfig: { + title: ' ' + }, + cardPanelConfig: { + defaults: { + bodyStyle: 'padding:20px 10px 10px 20px;background-color:#F6F6F6;', + border: false + } + }, + cards: steps, + loadMaskConfig: { + default: 'Checking...', + finishing: 'Finishing...' + }, + listeners: { + finish: function(){ + wizard.showLoadMask(true, 'finishing'); + Ext.Ajax.request({ + url: 'newSite', + success: function(response){ + var response = Ext.util.JSON.decode(response.responseText); + Ext.getCmp('finish_message').setValue(getFieldOutput(response.message, response.result)); + wizard.showLoadMask(false); + if (response.result) { + Ext.Msg.alert('ProcessMaker was successfully installed', 'Workspace "' + Ext.getCmp('workspace').getValue() + '" was installed correctly now you will be redirected to your new workspace.', function() {window.location = response.url;}); + } + }, + failure: function(){wizard.showLoadMask(false);}, + params: { + 'action': 'createWorkspace', + 'db_engine': Ext.getCmp('db_engine').getValue(), + 'db_hostname': Ext.getCmp('db_hostname').getValue(), + 'db_username': Ext.getCmp('db_username').getValue(), + 'db_password': Ext.getCmp('db_password').getValue(), + 'db_port': Ext.getCmp('db_port').getValue(), + 'pathConfig': pathConfig, + 'pathLanguages': pathLanguages, + 'pathPlugins': pathPlugins, + 'pathXmlforms': pathXmlforms, + 'pathShared': pathShared, + 'workspace': Ext.getCmp('workspace').getValue(), + 'adminUsername': Ext.getCmp('adminUsername').getValue(), + 'adminPassword': Ext.getCmp('adminPassword').getValue(), + 'wfDatabase': Ext.getCmp('wfDatabase').getValue(), + 'rbDatabase': Ext.getCmp('rbDatabase').getValue(), + 'rpDatabase': Ext.getCmp('rpDatabase').getValue(), + 'deleteDB': Ext.getCmp('deleteDB').getValue() + }, + timeout: 180000 + }); + } + } + }); + + wizard.show(); +}); \ No newline at end of file diff --git a/workflow/engine/templates/main/forgotPassword.tpl b/workflow/engine/templates/main/forgotPassword.tpl new file mode 100644 index 000000000..da21504d6 --- /dev/null +++ b/workflow/engine/templates/main/forgotPassword.tpl @@ -0,0 +1,26 @@ + + + + + + + + + + + + +
+ +
+

{serviceMsg}

+ {content} {passwd} +
+
+
+ {poweredBy} {versionLabel} {version} +
+ {visit} http://www.processmaker.com +
+
\ No newline at end of file diff --git a/workflow/engine/templates/main/index.html b/workflow/engine/templates/main/index.html new file mode 100644 index 000000000..eb8c31270 --- /dev/null +++ b/workflow/engine/templates/main/index.html @@ -0,0 +1,30 @@ +
+ + + + + + + + +
+ + + + + + + +
+ +
+ {userfullname} 
+ {rolename}  +
+
+ +
+
+
+
+
\ No newline at end of file diff --git a/workflow/engine/templates/main/index.js b/workflow/engine/templates/main/index.js new file mode 100644 index 000000000..8468d5f17 --- /dev/null +++ b/workflow/engine/templates/main/index.js @@ -0,0 +1,244 @@ +/** + * Main Controller for processMaker v2.x + * @date Jul 17, 2011 + * @author Erik Amaru Ortiz + */ + +var Main = function() { + return { + /** properties */ + panels : new Array(), + configuration: {}, + viewport : null, + systemInfoWindow : null, + + /** init method */ + init : function() { + + Ext.QuickTips.init(); + Ext.form.Field.prototype.msgTarget = 'side'; + + this.configureComponents(); + this.buildComponents(); + + this.viewport = new Ext.Viewport({ + layout: 'border', + items: [this.panels] + }); + + Ext.getCmp('eastPanel').hide(); + Ext.getCmp('westPanel').hide(); + Ext.getCmp('southPanel').hide(); + + Ext.getCmp('centerPanel').ownerCt.doLayout(); + + if (typeof flyNotify != 'undefined') { + Ext.msgBoxSlider.msgTopCenter(flyNotify.type, flyNotify.title, flyNotify.text, flyNotify.time); + } + } + } +}(); + +Main.configureComponents = function() +{ + this.configuration.eastPanel = { + id:'eastPanel', + region: 'east', + width: 200, + height: 500, + minSize: 175, + maxSize: 400, + split: true, + collapsible: true, + items: [] + }; + + this.configuration.centerPanel = { + id:'centerPanel', + region: 'center', + layout: 'fit', + width: 200, + margins: '0 0 0 0' // top right botom left + }; + + this.configuration.centerPanel.items = new Array(); + this.configuration.centerPanel.items.push({ + xtype:"tabpanel", + id: 'mainTabPanel', + defaultType:"iframepanel", + activeTab: activeTab != '' ? activeTab : 0 + }); + + this.configuration.westPanel = { + id:'westPanel', + title: '', + region: 'west', + width: 200, + split: true, + collapsible: true, + items: [] + }; + + this.configuration.northPanel = { + id:'northPanel', + region: 'north', + height: 40, + applyTo: 'panel-header', + margins: '0 0 0 0', // top right botom left + items: [] + }; + + this.configuration.southPanel = { + id:'southPanel', + region: 'south', + height: 68, + margins: '0 0 0 0', // top right botom left + items: [] + }; + + this.configuration.userMenu = {} + this.configuration.userMenu.items = new Array(); + this.configuration.userMenu.items.push({ + text : _("ID_VIEW_EDIT_PROFILE"), + icon: '/images/profile-picture.png', + handler: function() { + Main._addTab('profile', 'Profile', 'users/usersInit'); + } + }); + + /*this.configuration.userMenu.items.push({ + id:'skinMenu', + text : _("ID_SKINS"), + icon: '/images/icon-pmskins.png' + });*/ + + if (showSystemInfo) { + this.configuration.userMenu.items.push({ + text : _('ID_SYSTEM_INFO'), + icon: '/images/sys-info-icon.png', + handler: systemInfo + }); + } + + this.configuration.userMenu.items.push({ + text : _('ID_LOGOUT'), + icon: '/images/logout.gif', + handler: function() { + location.href = 'main/login'; + } + }); +}; + +Main.buildComponents = function() +{ + var centerTabPanelItems = new Array(); + for (var i=0; i + + + + + + + + + +

+ + + + + + + + + + + + + + + + + + +{login_script} +{login_vars} + + \ No newline at end of file diff --git a/workflow/engine/templates/main/login.js b/workflow/engine/templates/main/login.js new file mode 100644 index 000000000..5a8a81331 --- /dev/null +++ b/workflow/engine/templates/main/login.js @@ -0,0 +1,480 @@ +/* + * ProcessMaker Login + * Created on date Jul 15, 2011 + * + * @author Erik Amaru Ortiz + */ + +var loadMask = function(){ + return { + init: function() { + var loading = Ext.get('loading'); + var mask = Ext.get('loading-mask'); + mask.setOpacity(0.8); + mask.shift({ + xy: loading.getXY(), + width: loading.getWidth(), + height: loading.getHeight(), + remove: true, + duration: 1, + opacity: 0.3, + easing: 'bounceOut', + callback: function(){ + loading.fadeOut({ + duration: 0.2, + remove: true + }); + document.getElementById('loginLogo').style.display = 'block'; + } + }); + }}; +}(); + +Ext.onReady(loadMask.init, loadMask, true); + +var Login = function() { + return { + /** Properties */ + form : null, + window : null, + enableVirtualKeyboard : false, + enableForgotPassword : false, + fieldsWidth : 200, + + /** Init method */ + init : function() { + new Ext.KeyMap(document, { + key: [10, 13], + fn: function(keycode, e) { + Login.submit(); + } + }); + + Ext.QuickTips.init(); + Ext.form.Field.prototype.msgTarget = 'side'; + + this.enableVirtualKeyboard = virtualKeyboad; + this.enableForgotPassword = forgotPasswd; + + this.initComponents(); + + this.window.show(); + Ext.getCmp('userTxt').focus(true, 1000); + + if (typeof errMsg != 'undefined') { + Ext.msgBoxSlider.msgTopCenter('alert', 'ERROR', errMsg, 10); + } + + if (typeof flyNotify != 'undefined') { + Ext.msgBoxSlider.msgTopCenter(flyNotify.type, flyNotify.title, flyNotify.text, flyNotify.time); + } + } + } +}(); + +Login.initComponents = function() +{ + var userTxt = { + id : 'userTxt', + name : 'form[USR_USERNAME]', + fieldLabel: _('ID_USER'), + allowBlank: false + } + + var usernameTxt = { + id : 'usernameTxt', + name : 'username', + fieldLabel: _('ID_USER'), + allowBlank: false + } + + var emailTxt = { + id : 'emailTxt', + name : 'email', + fieldLabel: _('ID_EMAIL'), + allowBlank: false + } + + var passwordTxt = { + fieldLabel: _('ID_PASSWORD'), + name : 'form[USR_PASSWORD]', + inputType : 'password', + allowBlank: false, + + validationEvent : this.enableVirtualKeyboard == true ? 'blur' : 'keyup', + enableKeyEvents : true, + width: this.fieldsWidth, //this.enableVirtualKeyboard == true ? 183 : this.fieldsWidth, + keyboardConfig: { + showIcon: true, + languageSelection: true + }, + plugins: this.enableVirtualKeyboard == true ? new Ext.ux.plugins.VirtualKeyboard() : null, + + listeners: { + render: function() { + this.capsWarningTooltip = new Ext.ToolTip({ + target: this.id, + anchor: 'top', + width: 305, + html: '
'+_('ID_CAPS_LOCK_IS_ON')+'

' + + '
'+_('ID_CAPS_LOCK_ALERT1')+'

' + + '
'+_('ID_CAPS_LOCK_ALERT2')+'
' + }); + this.capsWarningTooltip.disable(); + this.capsWarningTooltip.on('enable', function() { + this.disable(); + }); + }, + + keypress: { + fn: function(field, e) { + if(this.forceVirtualKeyboard) { + field.plugins.expand(); + e.stopEvent(); + } + else { + var charCode = e.getCharCode(); + if((e.shiftKey && charCode >= 97 && charCode <= 122) || + (!e.shiftKey && charCode >= 65 && charCode <= 90)) { + + field.capsWarningTooltip.show(); + } + else { + if(field.capsWarningTooltip.hidden == false) { + field.capsWarningTooltip.hide(); + } + } + } + }, + scope: this + }, + blur: function(field) { + if(this.capsWarningTooltip.hidden == false) { + this.capsWarningTooltip.hide(); + } + } + } + + /*, + listeners : { + specialkey: function(f,e){ + if (e.getKey() == e.ENTER) { + Login.submit(); + } + } + }*/ + } + + var forgotPasswordLink = { + xtype: 'box', + autoEl: { + html: '' + } + }; + var forgotPasswordBox = { + xtype: 'box', + autoEl: 'div', + height: 4 + } + + var languagesCmb = new Ext.form.ComboBox({ + id : 'language', + fieldLabel : _('ID_LAN_LANGUAGE'), + name : 'form[USER_LANG]', + displayField: 'name', + typeAhead : true, + mode : 'local', + emptyText : _('ID_SELECT'), + allowBlank : false, + valueField : 'id', + editable : true, + selectOnFocus : true, + forceSelection: true, + triggerAction : 'all', + store : new Ext.data.ArrayStore({ + fields: ['id', 'name'], + data : languages + }), + listeners : { + afterrender : function(){ + var store = languagesCmb.getStore(); + var i = store.findExact('id', defaultLang, 0); + if (i > -1){ + Ext.getCmp('language').setValue(store.getAt(i).data.id); + Ext.getCmp('language').setRawValue(store.getAt(i).data.name); + } + } + } + }); + + + var formConfig = { + id : 'login-form', + labelWidth: 80, + labelAlign: 'right', + bodyStyle : "padding: 10px;", + url : "authentication", + closeAction: 'hide', + frame : true, + width : 230, + padding : 10, + defaultType : 'textfield', + monitorValid: true, + defaults : { + width : this.fieldsWidth + }, + buttons: [{ + id: 'submit-btn', + text: _('LOGIN'), + formBind: true, + handler: Login.submit + }] + }; + + formConfig.items = new Array(); + + if (this.enableForgotPassword) { + formConfig.items.push(forgotPasswordLink); + } + formConfig.items.push(userTxt); + formConfig.items.push(passwordTxt); + formConfig.items.push(languagesCmb); + + + this.form = new Ext.FormPanel(formConfig); + + this.forgotPasswordForm = new Ext.FormPanel({ + id : 'fp-form', + labelWidth: 80, + labelAlign: 'right', + bodyStyle : "padding: 10px;", + url : "forgotPassword", + closeAction: 'hide', + frame : true, + width : 230, + padding : 10, + defaultType : 'textfield', + monitorValid: true, + defaults : { + width : this.fieldsWidth + }, + items: [ + usernameTxt, + emailTxt + ], + buttons: [{ + id: 'send-btn', + text: _('ID_SEND'), + formBind: true, + handler: Login.sendFpRequest + }, { + id: 'cancel-btn', + text: _('ID_CANCEL'), + handler: Login.restore + }] + }); + + this.forgotPasswordForm = new Ext.FormPanel({ + id : 'fp-form', + labelWidth: 80, + labelAlign: 'right', + bodyStyle : "padding: 10px;", + url : "forgotPassword", + closeAction: 'hide', + frame : true, + width : 230, + padding : 10, + defaultType : 'textfield', + monitorValid: true, + defaults : { + width : this.fieldsWidth + }, + items: [ + usernameTxt, + emailTxt + ], + buttons: [{ + id: 'send-btn', + text: _('ID_SEND'), + formBind: true, + handler: Login.sendFpRequest + }, { + id: 'cancel-btn', + text: _('ID_CANCEL'), + handler: Login.restore + }] + }); + + this.window = new Ext.Window({ + layout: 'fit', + title: _('LOGIN'), + width: 380, + height: 194, //180, + iconCls: 'ux-auth-header-icon', + closable: false, + resizable: false, + plain: true, + draggable: false, + items: [this.form], + bbar: new Ext.ux.StatusBar({ + defaultText: '', + id: 'login-statusbar', + statusAlign: 'right', // the magic config + items: [] + }) + }); + + this.fpWindow = new Ext.Window({ + layout: 'fit', + title: _('ID_FORGOT_PASSWORD'), + width: 380, + height: 150, //180, + //iconCls: 'ux-auth-header-icon', + closable: false, + resizable: false, + plain: true, + draggable: false, + items: [this.forgotPasswordForm], + bbar: new Ext.ux.StatusBar({ + defaultText: '', + id: 'login-statusbar2', + statusAlign: 'right' + }) + }); + + //Ext.getCmp('login-form').hide(); +} + +Login.forgotPassword = function() +{ + this.window.hide(); + this.fpWindow.show(); +} +Login.restore = function() +{ + Login.window.show(); + Login.fpWindow.hide(); +} + + +Login.sendFpRequest = function() +{ + Ext.getCmp('login-statusbar2').showBusy(); + + if (!Login.forgotPasswordForm.getForm().isValid()) { + Ext.getCmp('login-statusbar2').setStatus({ + text: _('ID_VALIDATION_ERRORS'), + iconCls: 'x-status-error', + clear: true + }); + return; + } + + Login.forgotPasswordForm.getForm().submit({ + method: 'POST', + waitTitle: '', + waitMsg: 'Sending Request...', + success: function(form, action) + { + serverResponse = Ext.util.JSON.decode(action.response.responseText); + Ext.getCmp('login-statusbar2').setStatus({ + text: _('ID_SUCCESS'), + iconCls: 'x-status-valid', + clear: true // auto-clear after a set interval + }); + Ext.msgBoxSlider.msgTopCenter('info', _('ID_INFO'), serverResponse.message, 10); + setTimeout('Login.restore()', 4000); + }, + failure: function(form, action) + { + + if (action.failureType == 'server') { + serverResponse = Ext.util.JSON.decode(action.response.responseText); + Ext.getCmp('login-statusbar2').setStatus({ + text: serverResponse.message, + iconCls: 'x-status-error', + clear: true // auto-clear after a set interval + }); + Login.submiting = false; + //Ext.msgBoxSlider.msgTopCenter('alert', 'LOGIN ERROR', serverResponse.message, 10); + } + else { + Ext.Msg.alert('ERROR', _('ID_SERVER_PROBLEM') + ' ' + action.response.responseText); + } + //Login.form.getForm().reset(); + } + }); + +} + + +Login.submiting = false; +Login.submit = function() +{ + if (Login.submiting) { + return false; + } + + Login.submiting = true; + + document.forms[0].action = '../login/authentication'; + document.forms[0].submit(); + return; + + + Ext.getCmp('login-statusbar').showBusy(); + + if (!Login.form.getForm().isValid()) { + Ext.getCmp('login-statusbar').setStatus({ + text: _('ID_VALIDATION_ERRORS'), + iconCls: 'x-status-error', + clear: true + }); + return; + } + + Login.form.getForm().submit({ + method: 'POST', + //waitTitle: '', + //waitMsg: 'Verifying User...', + success: function(form, action) + { + serverResponse = Ext.util.JSON.decode(action.response.responseText); + Ext.getCmp('login-statusbar').setStatus({ + text: serverResponse.message, + iconCls: 'x-status-valid', + clear: true // auto-clear after a set interval + }); + + if (typeof urlRequested != 'undefined') { + window.location = urlRequested; + } + else { + window.location = serverResponse.url; + } + }, + failure: function(form, action) + { + + if (action.failureType == 'server') { + serverResponse = Ext.util.JSON.decode(action.response.responseText); + Ext.getCmp('login-statusbar').setStatus({ + text: serverResponse.message, + iconCls: 'x-status-error', + clear: true // auto-clear after a set interval + }); + Login.submiting = false; + //Ext.msgBoxSlider.msgTopCenter('alert', 'LOGIN ERROR', serverResponse.message, 10); + } + else { + Ext.Msg.alert('ERROR', _('ID_SERVER_PROBLEM') + ' ' + action.response.responseText); + } + //Login.form.getForm().reset(); + } + }); +} + +Ext.onReady(Login.init, Login, true); + diff --git a/workflow/engine/templates/main/sysLogin.html b/workflow/engine/templates/main/sysLogin.html new file mode 100644 index 000000000..d17590cb6 --- /dev/null +++ b/workflow/engine/templates/main/sysLogin.html @@ -0,0 +1,97 @@ + + + + + + + + + + +

+ + + + + + + + + + + + + + + + + + +{login_script} +{login_vars} + + \ No newline at end of file diff --git a/workflow/engine/templates/main/sysLogin.js b/workflow/engine/templates/main/sysLogin.js new file mode 100644 index 000000000..82725c692 --- /dev/null +++ b/workflow/engine/templates/main/sysLogin.js @@ -0,0 +1,323 @@ +/* + * ProcessMaker Login + * Created on date Jul 15, 2011 + * + * @author Erik Amaru Ortiz + */ + +var loadMask = function(){ + return { + init: function() { + var loading = Ext.get('loading'); + var mask = Ext.get('loading-mask'); + mask.setOpacity(0.8); + mask.shift({ + xy: loading.getXY(), + width: loading.getWidth(), + height: loading.getHeight(), + remove: true, + duration: 1, + opacity: 0.3, + easing: 'bounceOut', + callback: function(){ + loading.fadeOut({ + duration: 0.2, + remove: true + }); + document.getElementById('loginLogo').style.display = 'block'; + } + }); + }}; +}(); + +Ext.onReady(loadMask.init, loadMask, true); + +var Login = function() { + return { + /** Properties */ + form : null, + window : null, + enableVirtualKeyboard : true, + fieldsWidth : 200, + + /** Init method */ + init : function() { + new Ext.KeyMap(document, { + key: [10, 13], + fn: function(keycode, e) { + Login.submit(); + } + }); + + Ext.QuickTips.init(); + Ext.form.Field.prototype.msgTarget = 'side'; + + this.initComponents(); + + Ext.getCmp('workspace').setValue(PMExt.cookie.read('x-pm-ws')); + + this.window.show(); + Ext.getCmp('userTxt').focus(true, 1000); + + if (typeof flyNotify != 'undefined') { + Ext.msgBoxSlider.msgTopCenter(flyNotify.type, flyNotify.title, flyNotify.text, flyNotify.time); + } + } + } +}(); + +Login.initComponents = function() +{ + var userTxt = { + id : 'userTxt', + name : 'form[USR_USERNAME]', + fieldLabel: _('ID_USER'), + allowBlank: false + } + + var passwordTxt = { + fieldLabel: _('ID_PASSWORD'), + name : 'form[USR_PASSWORD]', + inputType : 'password', + allowBlank: false, + + validationEvent : this.enableVirtualKeyboard == true ? 'blur' : 'keyup', + enableKeyEvents : true, + width: this.fieldsWidth, //this.enableVirtualKeyboard == true ? 183 : this.fieldsWidth, + keyboardConfig: { + showIcon: true, + languageSelection: true + }, + plugins: this.enableVirtualKeyboard == true ? new Ext.ux.plugins.VirtualKeyboard() : null, + + listeners: { + render: function() { + this.capsWarningTooltip = new Ext.ToolTip({ + target: this.id, + anchor: 'top', + width: 305, + html: '
'+_('ID_CAPS_LOCK_IS_ON')+'

' + + '
'+_('ID_CAPS_LOCK_ALERT1')+'

' + + '
'+_('ID_CAPS_LOCK_ALERT2')+'
' + }); + this.capsWarningTooltip.disable(); + this.capsWarningTooltip.on('enable', function() { + this.disable(); + }); + }, + + keypress: { + fn: function(field, e) { + if(this.forceVirtualKeyboard) { + field.plugins.expand(); + e.stopEvent(); + } + else { + var charCode = e.getCharCode(); + if((e.shiftKey && charCode >= 97 && charCode <= 122) || + (!e.shiftKey && charCode >= 65 && charCode <= 90)) { + + field.capsWarningTooltip.show(); + } + else { + if(field.capsWarningTooltip.hidden == false) { + field.capsWarningTooltip.hide(); + } + } + } + }, + scope: this + }, + blur: function(field) { + if(this.capsWarningTooltip.hidden == false) { + this.capsWarningTooltip.hide(); + } + } + } + } + + var workspaceField; + + if (wsPrivate) { + workspaceField = { + id: 'workspace', + name: 'form[USER_ENV]', + fieldLabel: _('ID_WORKSPACE'), + allowBlank: false + } + } else { + workspaceField = new Ext.form.ComboBox({ + id: 'workspace', + fieldLabel: _('ID_WORKSPACE'), + name : 'form[USER_ENV]', + store: new Ext.data.ArrayStore({ + fields: ['id', 'name'], + data : workspaces + }), + displayField:'name', + typeAhead : true, + mode : 'local', + forceSelection: true, + triggerAction: 'all', + emptyText : _('ID_SELECT_WORKSPACE'), + allowBlank : false, + selectOnFocus: true, + valueField : 'id', + editable : true, + listeners: { + afterrender: function(){ + var store = workspaceField.getStore(); + var i = store.findExact('id', defaultWS, 0); + if (i > -1){ + Ext.getCmp('workspace').setValue(store.getAt(i).data.id); + Ext.getCmp('workspace').setRawValue(store.getAt(i).data.name); + } + } + } + }); + } + + var languagesCmb = new Ext.form.ComboBox({ + id : 'language', + fieldLabel : _('ID_LAN_LANGUAGE'), + name : 'form[USER_LANG]', + displayField: 'name', + typeAhead : true, + mode : 'local', + emptyText : _('ID_SELECT'), + allowBlank : false, + valueField : 'id', + editable : true, + selectOnFocus : true, + forceSelection: true, + triggerAction : 'all', + store : new Ext.data.ArrayStore({ + fields: ['id', 'name'], + data : languages + }), + listeners : { + afterrender : function(){ + var store = languagesCmb.getStore(); + var i = store.findExact('id', defaultLang, 0); + if (i > -1){ + Ext.getCmp('language').setValue(store.getAt(i).data.id); + Ext.getCmp('language').setRawValue(store.getAt(i).data.name); + } + } + } + }); + + this.form = new Ext.FormPanel({ + id : 'login-form', + name : 'login_form', + labelWidth: 80, + labelAlign: 'right', + url : "../main/sysLoginVerify", + frame : true, + width : 230, + padding : 10, + defaultType : 'textfield', + monitorValid: true, + defaults : { + width:200 + }, + items: [ + userTxt, + passwordTxt, + workspaceField, + languagesCmb + ], + buttons: [{ + text: _('LOGIN'), + formBind: true, + handler: Login.submit + }] + }); + + this.window = new Ext.Window({ + layout: 'fit', + width: 380, + height: 210, + title : _('LOGIN'), + iconCls: 'ux-auth-header-icon', + closable: false, + resizable: false, + plain: true, + draggable: false, + items: [this.form], + bbar: new Ext.ux.StatusBar({ + defaultText: '', + id: 'login-statusbar', + statusAlign: 'right', // the magic config + items: [] + }) + }); + +} + +Login.submiting = false; + +Login.submit = function() +{ + if (Login.submiting) { + return false; + } + + Ext.getCmp('login-statusbar').showBusy(); + + if (!Login.form.getForm().isValid()) { + Ext.getCmp('login-statusbar').setStatus({ + text: _('ID_VALIDATION_ERRORS'), + iconCls: 'x-status-error', + clear: true + }); + return; + } + + Login.submiting = true; + + document.forms[0].action = '../login/sysLoginVerify'; + document.forms[0].submit(); + return; + + + Login.form.getForm().submit({ + method: 'POST', + //waitTitle: '', + //waitMsg: 'Verifying User...', + success: function(form, action) + { + // persistene on cookie + PMExt.cookie.create('x-pm-ws', Ext.getCmp('workspace').getValue(), 30); + + + serverResponse = Ext.util.JSON.decode(action.response.responseText); + Ext.getCmp('login-statusbar').setStatus({ + text: serverResponse.message, + iconCls: 'x-status-valid', + clear: true // auto-clear after a set interval + }); + window.location = serverResponse.url; + }, + failure: function(form, action) + { + Login.submiting = false; + if (action.failureType == 'server') { + serverResponse = Ext.util.JSON.decode(action.response.responseText); + Ext.getCmp('login-statusbar').setStatus({ + text: serverResponse.message, + iconCls: 'x-status-error', + clear: true // auto-clear after a set interval + }); + //Ext.msgBoxSlider.msgTopCenter('alert', 'LOGIN ERROR', serverResponse.message, 10); + } + else { + Ext.Msg.alert('ERROR', _('ID_SERVER_PROBLEM') + ' ' + action.response.responseText); + } + //Login.form.getForm().reset(); + } + }); +} + +Ext.onReady(Login.init, Login, true); + diff --git a/workflow/engine/templates/main/systemInfo.js b/workflow/engine/templates/main/systemInfo.js new file mode 100644 index 000000000..e13e8671e --- /dev/null +++ b/workflow/engine/templates/main/systemInfo.js @@ -0,0 +1,36 @@ +Ext.onReady(function(){ + + var store = new Ext.data.ArrayStore({ + fields: ['name', 'value'], + idIndex: 0 + }); + var propsGrid = new Ext.grid.GridPanel({ + store : store, + columns : [{ + id : 'name', + header : '', + width : 150, + sortable : false, + dataIndex : 'name', + renderer: function(v){return ''+v+''}, + align: 'right' + }, + { + header : '', + width : 350, + sortable : false, + dataIndex : 'value' + }], + stripeRows : true, + autoHeight : true, + width : 480, + columnLines: true, + enableColumnHide: false, + enableColumnResize: false, + enableHdMenu: false + }); + + store.loadData(properties); + propsGrid.render(document.body); + +}); \ No newline at end of file diff --git a/workflow/engine/templates/setup/loginSettings.js b/workflow/engine/templates/setup/loginSettings.js index 3a627c120..403c10d91 100755 --- a/workflow/engine/templates/setup/loginSettings.js +++ b/workflow/engine/templates/setup/loginSettings.js @@ -1,7 +1,7 @@ Ext.onReady(function(){ var cmbLanguages = new Ext.form.ComboBox({ - fieldLabel : TRANSLATIONS.ID_CACHE_LANGUAGE, // 'Language' + fieldLabel : _('ID_DEFAULT_LANGUAGE'), hiddenName : 'lang', store : new Ext.data.Store( { proxy : new Ext.data.HttpProxy( { @@ -21,7 +21,9 @@ Ext.onReady(function(){ editable : false, allowBlank : false, listeners:{ - select: function(){ChangeSettings('1');} + select: function(){ + changeSettings(); + } } }); @@ -33,31 +35,42 @@ Ext.onReady(function(){ handler : saveSettings }); - loginFields = new Ext.form.FieldSet({ + loginFields = new Ext.form.FieldSet({ title: _('ID_LOGIN_SETTINGS'), items : [ - cmbLanguages, - { + cmbLanguages, + { + name: 'forgotPasswd', xtype: 'checkbox', - checked: currentOption, - name: 'acceptRP', + checked: forgotPasswd, fieldLabel: _('ID_ENABLE_FOTGOT_PASSWORD'), - id: 'ch_ii', listeners:{ - check:function(){ChangeSettings('2');} + check:function(){ + changeSettings(); + } + } + }, + { + name: 'virtualKeyboad', + xtype: 'checkbox', + checked: virtualKeyboad, + fieldLabel: _('ID_ENABLE_VIRTUAL_KEYBOARD'), + listeners:{ + check:function(){ + changeSettings(); + } } - } ], - buttons : [saveButton] + buttons : [saveButton] }); - var frm = new Ext.FormPanel( { + var frm = new Ext.FormPanel({ title: ' ', id:'frm', labelWidth: 150, - width:400, + width:460, labelAlign:'right', autoScroll: true, bodyStyle:'padding:2px', @@ -74,9 +87,11 @@ Ext.onReady(function(){ }); //render to process-panel frm.render(document.body); -}); -function saveSettings() { +}); //end onready() + +function saveSettings() +{ Ext.getCmp('frm').getForm().submit( { url : 'loginSettingsAjax?request=saveSettings', waitMsg : _('ID_SAVING_PROCESS'), @@ -84,10 +99,7 @@ function saveSettings() { success : function(obj, resp) { //nothing to do response = Ext.decode(resp.response.responseText); - if (response.enable) - parent.PMExt.notify(_('ID_LOGIN_SETTINGS'),_('ID_ENABLE_FORGOT_PASSWORD')); - else - parent.PMExt.notify(_('ID_LOGIN_SETTINGS'),_('ID_DISABLE_FORGOT_PASSWORD')); + parent.PMExt.notify(_('ID_INFO'),_('ID_SAVED_SUCCESSFULLY')); saveButton.disable(); }, failure: function(obj, resp) { @@ -96,6 +108,7 @@ function saveSettings() { }); } -ChangeSettings = function(iType){ +changeSettings = function() +{ saveButton.enable(); } diff --git a/workflow/engine/templates/setup/main.js b/workflow/engine/templates/setup/main.js index 90b4c2d55..4cb7c6635 100755 --- a/workflow/engine/templates/setup/main.js +++ b/workflow/engine/templates/setup/main.js @@ -118,8 +118,13 @@ var main = function(){ items: items }), { - region: 'center', // a center region is ALWAYS required for border - contentEl: 'setup-frame' + region: 'center', + xtype : 'iframepanel', + frameConfig:{ + name : 'setup-frame', + id : 'setup-frame' + }, + deferredRender: false } ] }); diff --git a/workflow/public_html/images/canvastile_bg1.jpg b/workflow/public_html/images/canvastile_bg1.jpg new file mode 100644 index 000000000..290685e78 Binary files /dev/null and b/workflow/public_html/images/canvastile_bg1.jpg differ diff --git a/workflow/public_html/images/canvastile_bg2.jpg b/workflow/public_html/images/canvastile_bg2.jpg new file mode 100644 index 000000000..0ab19e7e2 Binary files /dev/null and b/workflow/public_html/images/canvastile_bg2.jpg differ diff --git a/workflow/public_html/images/close.png b/workflow/public_html/images/close.png new file mode 100644 index 000000000..5a1226f2b Binary files /dev/null and b/workflow/public_html/images/close.png differ diff --git a/workflow/public_html/images/dashboard.png b/workflow/public_html/images/dashboard.png new file mode 100644 index 000000000..1a35ff7a7 Binary files /dev/null and b/workflow/public_html/images/dashboard.png differ diff --git a/workflow/public_html/images/designerIcon.png b/workflow/public_html/images/designerIcon.png new file mode 100644 index 000000000..5962ca7ad Binary files /dev/null and b/workflow/public_html/images/designerIcon.png differ diff --git a/workflow/public_html/images/error.png b/workflow/public_html/images/error.png new file mode 100644 index 000000000..0f657fba4 Binary files /dev/null and b/workflow/public_html/images/error.png differ diff --git a/workflow/public_html/images/ext-ux-wiz-stepIndicator.png b/workflow/public_html/images/ext-ux-wiz-stepIndicator.png new file mode 100644 index 000000000..5137e93e5 Binary files /dev/null and b/workflow/public_html/images/ext-ux-wiz-stepIndicator.png differ diff --git a/workflow/public_html/images/header_bg.jpg b/workflow/public_html/images/header_bg.jpg new file mode 100644 index 000000000..ec7eee1f2 Binary files /dev/null and b/workflow/public_html/images/header_bg.jpg differ diff --git a/workflow/public_html/images/homeIcon.png b/workflow/public_html/images/homeIcon.png new file mode 100644 index 000000000..63504b3e4 Binary files /dev/null and b/workflow/public_html/images/homeIcon.png differ diff --git a/workflow/public_html/images/icon-logout.png b/workflow/public_html/images/icon-logout.png new file mode 100644 index 000000000..5dbec9f55 Binary files /dev/null and b/workflow/public_html/images/icon-logout.png differ diff --git a/workflow/public_html/images/icon-user-arrow.png b/workflow/public_html/images/icon-user-arrow.png new file mode 100644 index 000000000..738e9b426 Binary files /dev/null and b/workflow/public_html/images/icon-user-arrow.png differ diff --git a/workflow/public_html/images/icon-user-sep.png b/workflow/public_html/images/icon-user-sep.png new file mode 100644 index 000000000..ee9be202f Binary files /dev/null and b/workflow/public_html/images/icon-user-sep.png differ diff --git a/workflow/public_html/images/icon-user.png b/workflow/public_html/images/icon-user.png new file mode 100644 index 000000000..8af87d088 Binary files /dev/null and b/workflow/public_html/images/icon-user.png differ diff --git a/workflow/public_html/images/info.png b/workflow/public_html/images/info.png new file mode 100644 index 000000000..1eff76437 Binary files /dev/null and b/workflow/public_html/images/info.png differ diff --git a/workflow/public_html/images/login-loader.gif b/workflow/public_html/images/login-loader.gif new file mode 100644 index 000000000..f9bc34d66 Binary files /dev/null and b/workflow/public_html/images/login-loader.gif differ diff --git a/workflow/public_html/images/logo_processmaker2.gif b/workflow/public_html/images/logo_processmaker2.gif new file mode 100644 index 000000000..93bc6ab07 Binary files /dev/null and b/workflow/public_html/images/logo_processmaker2.gif differ diff --git a/workflow/public_html/images/logo_processmaker2.xcf b/workflow/public_html/images/logo_processmaker2.xcf new file mode 100644 index 000000000..ec567c768 Binary files /dev/null and b/workflow/public_html/images/logo_processmaker2.xcf differ diff --git a/workflow/public_html/images/logout.gif b/workflow/public_html/images/logout.gif new file mode 100644 index 000000000..59588a45a Binary files /dev/null and b/workflow/public_html/images/logout.gif differ diff --git a/workflow/public_html/images/processmaker.logo.png b/workflow/public_html/images/processmaker.logo.png new file mode 100644 index 000000000..808819cdc Binary files /dev/null and b/workflow/public_html/images/processmaker.logo.png differ diff --git a/workflow/public_html/images/processmaker2.logo.png b/workflow/public_html/images/processmaker2.logo.png new file mode 100644 index 000000000..22102fdfb Binary files /dev/null and b/workflow/public_html/images/processmaker2.logo.png differ diff --git a/workflow/public_html/images/processmaker2.logo2.png b/workflow/public_html/images/processmaker2.logo2.png new file mode 100644 index 000000000..10c382021 Binary files /dev/null and b/workflow/public_html/images/processmaker2.logo2.png differ diff --git a/workflow/public_html/images/profile-icontab.png b/workflow/public_html/images/profile-icontab.png new file mode 100644 index 000000000..63f57b9af Binary files /dev/null and b/workflow/public_html/images/profile-icontab.png differ diff --git a/workflow/public_html/images/profile-picture.png b/workflow/public_html/images/profile-picture.png new file mode 100644 index 000000000..0e08d7dc2 Binary files /dev/null and b/workflow/public_html/images/profile-picture.png differ diff --git a/workflow/public_html/images/profile.gif b/workflow/public_html/images/profile.gif new file mode 100644 index 000000000..64df9df21 Binary files /dev/null and b/workflow/public_html/images/profile.gif differ diff --git a/workflow/public_html/images/setup-gears.gif b/workflow/public_html/images/setup-gears.gif new file mode 100644 index 000000000..f253ec1ca Binary files /dev/null and b/workflow/public_html/images/setup-gears.gif differ diff --git a/workflow/public_html/images/setupIcon.png b/workflow/public_html/images/setupIcon.png new file mode 100644 index 000000000..e05d78695 Binary files /dev/null and b/workflow/public_html/images/setupIcon.png differ diff --git a/workflow/public_html/images/start.png b/workflow/public_html/images/start.png new file mode 100644 index 000000000..b542706d5 Binary files /dev/null and b/workflow/public_html/images/start.png differ diff --git a/workflow/public_html/images/sys-info-icon.png b/workflow/public_html/images/sys-info-icon.png new file mode 100644 index 000000000..ebb09b845 Binary files /dev/null and b/workflow/public_html/images/sys-info-icon.png differ diff --git a/workflow/public_html/images/x-icon-user.png b/workflow/public_html/images/x-icon-user.png new file mode 100644 index 000000000..a6fb7b166 Binary files /dev/null and b/workflow/public_html/images/x-icon-user.png differ diff --git a/workflow/public_html/index.html b/workflow/public_html/index.html index d1a08e840..057cd02f8 100755 --- a/workflow/public_html/index.html +++ b/workflow/public_html/index.html @@ -3,6 +3,6 @@ Redirector - + \ No newline at end of file diff --git a/workflow/public_html/sysGeneric.php b/workflow/public_html/sysGeneric.php index 3ea6b5493..2a8a288ad 100755 --- a/workflow/public_html/sysGeneric.php +++ b/workflow/public_html/sysGeneric.php @@ -58,6 +58,56 @@ define('PATH_TRUNK', $pathTrunk ); define('PATH_OUTTRUNK', $pathOutTrunk ); +//////////////////////////// start, from paths.php + + /* Default configuration values (do not change these, use env.ini) */ + // $default_config = array( + // 'debug' => 0, + // 'debug_sql' => 0, + // 'debug_time' => 0, + // 'debug_calendar' => 0, + // 'wsdl_cache' => 1, + // 'memory_limit' => '100M', + // 'time_zone' => 'America/La_Paz', + // 'memcached' => 0, + // 'memcached_server' => '' + // ); + + // /* Read the env.ini */ + // $env_file = realpath($pathhome . PATH_SEP . 'engine' . PATH_SEP . 'config' . PATH_SEP . 'env.ini'); + // $config = $default_config; + + // if ($env_file !== false && file_exists($env_file)) { + // $ini_contents = parse_ini_file($env_file, false); + // if ($ini_contents !== false) + // $config = array_merge($default_config, $ini_contents); + // } + //var_dump($pathhome . 'engine' . PATH_SEP . 'classes' . PATH_SEP . 'class.system.php'); die; + require_once $pathhome . 'engine' . PATH_SEP . 'classes' . PATH_SEP . 'class.system.php'; + $config = System::getSystemConfiguration($pathhome . 'engine' . PATH_SEP . 'config' . PATH_SEP . 'env.ini'); + +//*** Do not change any of these settings directly, use env.ini instead + ini_set('display_errors','On'); + + ini_set('short_open_tag', 'on'); + ini_set('asp_tags', 'on'); + // The register_globals feature has been DEPRECATED as of PHP 5.3.0. default value Off. + // ini_set('register_globals', 'off'); + ini_set('default_charset', "UTF-8"); + $e_all = defined('E_DEPRECATED') ? E_ALL ^ E_DEPRECATED : E_ALL; + ini_set('error_reporting', ($config['debug'] ? $e_all : $e_all ^ E_NOTICE) ); + ini_set('memory_limit', $config['memory_limit']); + ini_set('soap.wsdl_cache_enabled', $config['wsdl_cache']); + + define ('DEBUG_SQL_LOG', $config['debug_sql'] ); + define ('DEBUG_TIME_LOG', $config['debug_time'] ); + define ('DEBUG_CALENDAR_LOG', $config['debug_calendar'] ); + define ('MEMCACHED_ENABLED', $config['memcached']); + define ('MEMCACHED_SERVER', $config['memcached_server']); + + define ('TIME_ZONE', $config['time_zone']); +//////////////////////////// end, from paths.php + //************* Including these files we get the PM paths and definitions (that should be just one file *********** require_once ( $pathhome . PATH_SEP . 'engine' . PATH_SEP . 'config' . PATH_SEP . 'paths.php' ); @@ -104,6 +154,13 @@ $oHeadPublisher->addMaborakFile( PATH_CORE . 'js' . PATH_SEP . 'appFolder/core/appFolderList.js', true ); $oHeadPublisher->addMaborakFile( PATH_THIRDPARTY . 'htmlarea/editor.js', true ); + //erik: if it is a installation instance + if(!defined('PATH_C')) { + $tmpDir = G::getSysTemDir(); + define('PATH_C', $tmpDir . ((substr($tmpDir, -1) == PATH_SEP)? '': PATH_SEP)); + define('PATH_LANGUAGECONT', PATH_HOME . 'engine/content/languages/' ); + } + //************ defining Virtual URLs ****************/ $virtualURITable = array(); $virtualURITable['/plugin/(*)'] = 'plugin'; @@ -214,7 +271,7 @@ die; break; case 'errorFile': - header ("location: /errors/error404.php"); + header ("location: /errors/error404.php?url=" . urlencode($_SERVER['REQUEST_URI'])); if ( DEBUG_TIME_LOG ) logTimeByPage(); //log this page die; break; @@ -228,7 +285,8 @@ //************** the request correspond to valid php page, now parse the URI ************** - G::parseURI ( getenv( "REQUEST_URI" ) ); + G::parseURI(getenv("REQUEST_URI" ), $config); + $oHeadPublisher->addMaborakFile( PATH_GULLIVER_HOME . 'js' . PATH_SEP . "widgets/jscalendar/lang/calendar-" . SYS_LANG . ".js"); define( 'SYS_URI' , '/sys' . SYS_TEMP . '/' . SYS_LANG . '/' . SYS_SKIN . '/' ); @@ -265,16 +323,32 @@ //************** Installer, redirect to install if we don't have a valid shared data folder ***************/ if ( !defined('PATH_DATA') || !file_exists(PATH_DATA)) { - if ( (SYS_TARGET==='installServer')) { - $phpFile = G::ExpandPath('methods') ."install/installServer.php"; - require_once($phpFile); - die(); + + /*new installer, extjs based*/ + + define('PATH_DATA', PATH_C); + require_once ( PATH_CONTROLLERS . 'installer.php' ); + $controller = 'Installer'; + + //if the method name is empty set default to index method + if (strpos(SYS_TARGET, '/') !== false) + list($controller, $controllerAction) = explode('/', SYS_TARGET); + else + $controllerAction = SYS_TARGET; + + $controllerAction = ($controllerAction != '' && $controllerAction != 'login')? $controllerAction: 'index'; + + //create the installer controller and call its method + if( is_callable(Array('Installer', $controllerAction)) ) { + $installer = new $controller(); + $installer->setHttpRequestData($_REQUEST); + $installer->call($controllerAction); } else { - $phpFile = G::ExpandPath('methods') ."install/install.php"; - require_once($phpFile); - die(); + $_SESSION['phpFileNotFound'] = $_SERVER['REQUEST_URI']; + header ("location: /errors/error404.php?url=" . urlencode($_SERVER['REQUEST_URI'])); } + die; } // ************* Load Language Translation ***************** @@ -303,15 +377,13 @@ set_include_path(get_include_path() . PATH_SEPARATOR . PATH_WORKSPACE); } else { - $aMessage['MESSAGE'] = G::LoadTranslation ('ID_NOT_WORKSPACE'); - $G_PUBLISH = new Publisher; - $G_PUBLISH->AddContent('xmlform', 'xmlform', 'login/showMessage', '', $aMessage ); - G::RenderPage( 'publish' ); + G::SendTemporalMessage ('ID_NOT_WORKSPACE', "error"); + G::header('location: /sys/' . SYS_LANG . '/' . SYS_SKIN . '/main/sysLogin?errno=2'); die; } } else { //when we are in global pages, outside any valid workspace - if ((SYS_TARGET==='sysLoginVerify') || (SYS_TARGET==='sysLogin') || (SYS_TARGET==='newSite')) { + if (SYS_TARGET==='newSite') { $phpFile = G::ExpandPath('methods') . SYS_COLLECTION . "/" . SYS_TARGET.'.php'; require_once($phpFile); die(); @@ -321,7 +393,22 @@ require_once( PATH_METHODS . "login/dbInfo.php" ) ; } else{ - require_once( PATH_METHODS . "login/sysLogin.php" ) ; + + if (substr(SYS_SKIN, 0, 2) === 'ux' && SYS_TARGET != 'sysLoginVerify') { // new ux sysLogin - extjs based form + require_once PATH_CONTROLLERS . 'main.php'; + $controllerClass = 'Main'; + $controllerAction = SYS_TARGET == 'sysLoginVerify' ? SYS_TARGET : 'sysLogin'; + //if the method exists + if( is_callable(Array($controllerClass, $controllerAction)) ) { + $controller = new $controllerClass(); + $controller->setHttpRequestData($_REQUEST); + $controller->call($controllerAction); + } + } + else { // classic sysLogin interface + require_once( PATH_METHODS . "login/sysLogin.php" ) ; + die(); + } } if ( DEBUG_TIME_LOG ) logTimeByPage(); //log this page die(); @@ -486,7 +573,7 @@ if ( ! $isControllerCall && ! file_exists( $phpFile ) ) { $_SESSION['phpFileNotFound'] = $_SERVER['REQUEST_URI']; print $phpFile; - header ("location: /errors/error404.php"); + header ("location: /errors/error404.php?url=" . urlencode($_SERVER['REQUEST_URI'])); die; } } @@ -494,8 +581,9 @@ //redirect to login, if user changed the workspace in the URL if( ! $avoidChangedWorkspaceValidation && isset( $_SESSION['WORKSPACE'] ) && $_SESSION['WORKSPACE'] != SYS_SYS) { $_SESSION['WORKSPACE'] = SYS_SYS; + G::SendTemporalMessage ('ID_USER_HAVENT_RIGHTS_SYSTEM', "error"); - header ( 'Location: /sys' . SYS_SYS . '/' . SYS_LANG . '/' . SYS_SKIN . '/login/login' ); + header ( 'Location: /sys' . SYS_SYS . '/' . SYS_LANG . '/' . SYS_SKIN . '/main/login' ); die; } @@ -516,7 +604,12 @@ if((isset( $_SESSION['USER_LOGGED'] ))&&(!(isset($_GET['sid'])))) { $RBAC->initRBAC(); - $RBAC->loadUserRolePermission( $RBAC->sSystem, $_SESSION['USER_LOGGED'] , PATH_DATA, session_id()); + //using optimization with memcache, the user data will be in memcache 8 hours, or until session id goes invalid + $memKey = 'rbacSession' . session_id(); + if ( ($RBAC->aUserInfo = $memcache->get($memKey)) === false ) { + $RBAC->loadUserRolePermission( $RBAC->sSystem, $_SESSION['USER_LOGGED'] ); + $memcache->set( $memKey, $RBAC->aUserInfo, PMmemcached::EIGHT_HOURS ); + } } else { // this is the blank list to allow execute scripts with no login (without session started) @@ -539,6 +632,7 @@ $noLoginFolders[] = 'services'; $noLoginFolders[] = 'tracker'; + $noLoginFolders[] = 'installer'; //This sentence is used when you lost the Session if ( !in_array(SYS_TARGET, $noLoginFiles) && !in_array(SYS_COLLECTION, $noLoginFolders) && $bWE != true && $collectionPlugin != 'services') { @@ -556,6 +650,8 @@ $bRedirect = false; $RBAC->initRBAC(); $RBAC->loadUserRolePermission( $RBAC->sSystem, $_SESSION['USER_LOGGED'] ); + $memKey = 'rbacSession' . session_id(); + $memcache->set( $memKey, $RBAC->aUserInfo, PMmemcached::EIGHT_HOURS ); } } if ($bRedirect) { @@ -564,14 +660,19 @@ $loginUrl = 'home/login'; } else { - $loginUrl = 'login/login'; + $loginUrl = 'main/login'; } if (empty($_POST)) { header('location: ' . SYS_URI . $loginUrl . '?u=' . urlencode($_SERVER['REQUEST_URI'])); } else { - header('location: ' . SYS_URI . $loginUrl); + if ( $isControllerCall ) { + header("HTTP/1.0 302 session lost in controller"); + } + else { + header('location: ' . SYS_URI . $loginUrl); + } } die(); }