1 /*********************************************************************************
2 * SugarCRM is a customer relationship management program developed by
3 * SugarCRM, Inc. Copyright (C) 2004-2011 SugarCRM Inc.
5 * This program is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU Affero General Public License version 3 as published by the
7 * Free Software Foundation with the addition of the following permission added
8 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
9 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
10 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
17 * You should have received a copy of the GNU Affero General Public License along with
18 * this program; if not, see http://www.gnu.org/licenses or write to the Free
19 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
23 * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
25 * The interactive user interfaces in modified source and object code versions
26 * of this program must display Appropriate Legal Notices, as required under
27 * Section 5 of the GNU Affero General Public License version 3.
29 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
30 * these Appropriate Legal Notices must retain the display of the "Powered by
31 * SugarCRM" logo. If the display of the logo is not reasonably feasible for
32 * technical reasons, the Appropriate Legal Notices must display the words
33 * "Powered by SugarCRM".
34 ********************************************************************************/
36 // inline modules, don't do importmodule!
37 // from file langlite.js
38 langlite = Module("langlite", "0.3.7", function(mod){
40 mod.JSONParser=Class("JSONParser", function(publ, supr){
45 publ.addLib = function(obj, name, exports){
47 this.libs[name] = obj;
49 for(var i=0;i<exports.length;i++){
50 this.libs[name + "." + exports[i]] = obj[exports[i]];
55 publ.objToJson=function(obj){
59 return mod.objToJson(obj);
64 mod.parser = new mod.JSONParser();
67 Turns JSON code into JavaScript objects.
68 @param src The source as a String.
70 mod.jsonToObj=function(src){
71 return mod.parser.jsonToObj(src);
74 var json_types = new Object();
76 json_types['object'] = function(obj){
79 if(typeof obj[attr] != "function"){
80 v.push('"' + attr + '": ' + mod.objToJson(obj[attr]));
83 return "{" + v.join(", ") + "}";
86 json_types['string'] = function(obj){
87 var s = '"' + obj.replace(/(["\\])/g, '\\$1') + '"';
88 s = s.replace(/(\n)/g,"\\n");
92 json_types['number'] = function(obj){
93 return obj.toString();
96 json_types['boolean'] = function(obj){
97 return obj.toString();
100 json_types['date'] = function(obj){
101 var padd=function(s, p){
103 return s.substring(s.length - p.length)
105 var y = padd(obj.getUTCFullYear(), "0000");
106 var m = padd(obj.getUTCMonth() + 1, "00");
107 var d = padd(obj.getUTCDate(), "00");
108 var h = padd(obj.getUTCHours(), "00");
109 var min = padd(obj.getUTCMinutes(), "00");
110 var s = padd(obj.getUTCSeconds(), "00");
112 var isodate = y + m + d + "T" + h + ":" + min + ":" + s
114 return '{"jsonclass":["sys.ISODate", ["' + isodate + '"]]}';
117 json_types['array'] = function(obj){
119 for(var i=0;i<obj.length;i++){
120 v.push(mod.objToJson(obj[i])) ;
122 return "[" + v.join(", ") + "]";
126 mod.objToJson=function(obj){
127 if ( typeof(obj) == 'undefined')
131 if ( typeof(json_types[typeof(obj)]) == 'undefined')
133 alert('class not defined for toJSON():'+typeof(obj));
135 return json_types[typeof(obj)](obj);
141 print(mod.objToJson(['sds', -12377,-1212.1212, 12, '-2312']));
143 print(e.toTraceString());
150 // from file jsonrpclite.js
151 jsonrpclite = Module("jsonrpclite", "0.3.2", function(mod){
153 var lang = langlite // inline module
154 // var lang = importModule("langlite");
156 var tokens = lang.tokens;
158 var ObjectBuffer=Class("ObjectBuffer", function(publ, supr){
159 publ.init=function(){
162 publ.getObjects=function(data){
164 var t = new lang.Tokenizer(this.data);
168 while(! t.finished()){
170 if(n.type != tokens.ERR){
173 }else if(n.value == "}"){
176 var s = this.data.slice(readCnt, n.pos+1);
185 this.data = this.data.slice(readCnt);
190 var nameAllowed=function(name){
191 return name.match(/^[a-zA-Z]\w*$/) != null;
194 var getMethodByName=function(obj, name){
195 try{//to get a method by asking the service
196 obj = obj._getMethodByName(name)
198 var names = name.split(".");
199 for(var i=0;i<names.length;i++){
201 if(nameAllowed(name)){
209 var Response=Class("Response", function(publ, supr){
210 publ.init=function(id, result, error){
212 this.result = result;
215 publ._toJSON=function(){
216 var p = [lang.objToJson(this.id), lang.objToJson(this.result),lang.objToJson(this.error)];
217 return '{"id":' + p[0] + ', "result":' + p[1] + ', "error":' + p[2] + "}";
221 var Request=Class("Request", function(publ, supr){
222 publ.init=function(id, method, params){
224 this.method = method;
225 this.params = params;
228 for(hello in this.params)
230 str += "var:"+hello+":"+this.params[hello]+":\n";
235 publ._toJSON=function(){
236 var p = [lang.objToJson(this.id), lang.objToJson(this.method),lang.objToJson(this.params)];
237 return '{"id":' + p[0] + ', "method":' + p[1] + ', "params":' + p[2] + "}";
241 var Notification=Class("Notification", function(publ, supr){
242 publ.init=function(method, params){
243 this.method = method;
244 this.params = params;
246 publ._toJSON=function(){
247 var p = [lang.objToJson(this.method),lang.objToJson(this.params)];
248 return '{"method":' + p[0] + ', "params":' + p[1] + "}";
252 var ResponseHandler=Class("ResponseHandler", function(publ, supr){
253 publ.init=function(callback){
254 this.callback=callback;
256 publ.handleResponse=function(resp){
257 this.callback(resp.result, resp.error);
261 var RPCLib = Class("RPCLib", function(publ, supr){
265 var BaseConnectionHandler = Class("BaseConnectionHandler", function(publ, supr){
266 publ.init=function(service){
267 this.service = service;
268 this.jsonParser = new lang.JSONParser();
269 this.jsonParser.addLib(new RPCLib(), "rpc", []);
270 this.respHandlers = [];
271 this.objBuffer = new ObjectBuffer();
274 publ.addResponseHandler=function(cb){
276 while(this.respHandlers[""+id] ){
280 this.respHandlers[id] = new ResponseHandler(cb);
284 publ.send = function(data){
287 publ.sendNotify = function(name, args){
288 var n = new Notification(name, args);
289 n = this.jsonParser.objToJson(n);
293 publ.sendRequest = function(name, args, callback){
294 var id = this.addResponseHandler(callback);
295 var r = new Request(id, name, args);
296 r = this.jsonParser.objToJson(r);
300 publ.sendResponse = function(id, result, error){
301 var r = new Response(id, result, error);
302 r = this.jsonParser.objToJson(r);
306 publ.handleRequest = function(req){
307 var name = req.method;
308 var params = req.params;
310 if(this.service[name]){
312 var rslt = this.service[name].apply(this.service,params);
313 this.sendResponse(id, rslt, null)
315 this.sendResponse(id, null, new ApplicationError("" + e))
318 this.sendResponse(id, null, new MethodNotFound());
322 publ.handleNotification = function(notif){
323 if(this.service[notif.method]){
325 this.service[notif.method].apply(this.service, notif.params);
331 publ.handleResponse = function(resp){
333 var h = this.respHandlers[id];
334 h.handleResponse(resp)
335 delete this.respHandlers[id]
338 publ.handleData = function(data){
339 var objs = this.objBuffer.getObjects(data);
340 for(var i=0;i<objs.length;i++){
342 var obj = this.jsonParser.jsonToObj(objs[i]);
344 throw "Not well formed";
346 if(obj.method != null){
348 this.handleRequest(new Request(obj.id, obj.method, obj.params));
350 this.handleNotification(new Notification(obj.method, obj.params));
352 }else if(obj.id != null){
353 this.handleResponse(new Response(obj.id, obj.result, obj.error));
355 throw "Unknown Data";
361 var SocketConnectionHandler = Class("SocketConnectionHandler", BaseConnectionHandler, function(publ, supr){
362 publ.init=function(socket, localService){
363 this.socket = socket;
364 socket.addEventListener("connectionData", this, false);
365 supr(this).init( localService);
368 publ.handleEvent=function(evt){
369 this.handleData(evt.data);
372 publ.send=function(data){
373 this.socket.send(data);
376 publ.close=function(data){
381 var HTTPConnectionHandler = Class("HTTPConnectionHandler", BaseConnectionHandler, function(publ, supr){
384 publ.init=function(url, localService){
385 urllib=importModule("urllib");
387 supr(this).init( localService);
390 publ.handleData = function(data){
392 var obj = JSON.parse(data);
394 throw " Not well formed\n\n" + e + "\n\nResponse from server:\n\n " + data;
399 throw "Unknown Data (No id property found)";
403 publ.sendRequest = function(name, args, callback){
405 if(typeof callback != "function"){//see if it is sync
409 var data = new Request(this.request_id++, name, args);
410 // cn: bug 12274 - defend against CSRF
411 data = JSON.stringify(data); // creates security envelope wrapped JSON object
414 var rsp = urllib.postURL(this.url, data, [["Content-Type", "text/plain"]]);
415 rsp = this.handleData(rsp.responseText);
421 }else{//async connection uses the respHandler to handle the repsonse
423 var request_id = this.request_id;
424 urllib.postURL(this.url, data, [["Content-Type", "text/plain"]], function(rsp){
426 rsp = self.handleData(rsp.responseText);
429 callback(request_id,null,e);
432 callback(request_id,rsp.result, rsp.error);
433 //callback(this.request_id,rsp.result, rsp.error);
434 //callback(rsp.result, rsp.error);
439 publ.sendNotify = function(name, args){
440 var data = new Notification(name, args);
441 data = this.jsonParser.objToJson(data);
442 urllib.postURL(this.url, data, [["Content-Type", "text/plain"]], function(rsp){});
446 var PeerObject=Class("PeerObject", function(publ, supr){
447 publ.init=function(name, conn){
450 for(var i=0;i<arguments.length;i++){
451 args[i] = arguments[i];
454 return conn.sendRequest(name, args, cb);
460 var PeerNotifyObject=Class("PeerNotifyObject", function(publ, supr){
461 publ.init=function(name, conn){
464 for(var i=0;i<arguments.length;i++){
465 args[i] = arguments[i];
467 conn.sendNotify(name, args);
473 var BasePeer = Class("BasePeer", function(publ, supr){
474 publ.init=function(conn, methodNames){
476 this.notify = new PeerObject("notify", conn);
477 this._add(methodNames);
480 var setupPeerMethod=function(root, methodName, conn, MethClass){
481 var names = methodName.split(".");
483 for(var n=0;n<names.length-1;n++){
488 obj[name] = new Object();
492 var name = names[names.length-1];
495 var mth = new MethClass(methodName, conn);
500 publ._add = function(methodNames){
501 for(var i=0;i<methodNames.length;i++){
502 setupPeerMethod(this, methodNames[i], this._conn, PeerObject);
503 setupPeerMethod(this.notify, methodNames[i], this._conn, PeerNotifyObject);
509 mod.ServiceProxy = Class("ServiceProxy", BasePeer, function(publ, supr){
510 publ.init = function(url, methodNames, localService){
512 var n = url.match(/^jsonrpc:\/\/(.*:\d*)$/);
513 if(n!=null){//is it json-rpc over TCP protocoll
516 var socket = createConnection();
518 throw "Can't create a socket connection."
520 socket.connect(hostaddr);
521 supr(this).init( new SocketConnectionHandler(socket, localService), methodNames);
522 }else{//or is it json-rpc over http
523 this.httpConn = new HTTPConnectionHandler(url, localService);
524 supr(this).init( this.httpConn, methodNames);
532 ///////////////////////////////////////////////
534 // superclass for all Sugar* sub-classes
536 ///////////////////////////////////////////////
538 function SugarClass()
540 // if ( arguments.length > 0 )
544 SugarClass.prototype.init = function() {
547 // create inheritance for a class
548 SugarClass.inherit = function(className,parentClassName) {
550 var str = className+".prototype = new "+parentClassName+"();";
551 str += className+".prototype.constructor = "+className+";";
552 str += className+".superclass = "+parentClassName+".prototype;";
561 //Root class of Sugar JS Application:
563 SugarClass.inherit("SugarContainer","SugarClass");
565 function SugarContainer(root_div)
567 GLOBAL_REGISTRY.container = this;
571 SugarContainer.prototype.init = function(root_div) {
572 this.root_div = root_div;
573 SugarContainer.superclass.init.call(this);
576 SugarContainer.prototype.start = function(root_widget) {
578 this.root_widget = new root_widget();
579 this.root_widget.load(this.root_div);
583 jsolait.baseURL = 'include/jsolait/lib';
584 urllib = importModule('urllib');
586 var global_request_registry = new Object();
589 var jsolait_baseURL = 'include/jsolait/lib';
590 var jsonrpc = jsonrpclite; //inline the module
591 //var jsonrpc = importModule("jsonrpclite");
595 //////////////////////////////////////////////////
596 // class: SugarDateTime
597 // date and time utilities
599 //////////////////////////////////////////////////
601 SugarClass.inherit("SugarDateTime","SugarClass");
603 function SugarDateTime()
608 SugarDateTime.prototype.init = function(root_div){
609 this.root_div = root_div;
612 // return the javascript Date object
613 // given the Sugar Meetings date_start/time_start or date_end/time_end
614 SugarDateTime.mysql2jsDateTime = function(mysql_date,mysql_time){
616 //var match = /(\d{4})-(\d{2})-(\d{2})/;
617 var match = new RegExp(date_reg_format);
618 if(((result= match.exec(mysql_date))) == null)
623 var match2 = new RegExp(time_reg_format);
624 // var match2 = /(\d{2}):(\d{2})/;
626 if((result2= match2.exec(mysql_time)) == null)
630 var match3 = /^0(\d)/;
632 if((result3= match3.exec(result2[1])) != null)
634 result2[1] = result3[1];
637 if ( typeof (result2[3]) != 'undefined')
639 if ( result2[3] == 'pm' || result2[3] == 'PM')
641 if (parseInt( result2[1] ) != 12)
643 result2[1] = parseInt( result2[1] ) + 12;
647 else if ( result2[1] == 12 ) {
652 return new Date(result[date_reg_positions['Y']],result[date_reg_positions['m']] - 1,result[date_reg_positions['d']],result2[1],result2[2],0,0);
655 // make it a static func
657 // return the formatted day of the week of the date given a date object
658 SugarDateTime.prototype.getFormattedDate = function(date_obj) {
660 var userDateFormat = GLOBAL_REGISTRY['current_user']['fields']['date_time_format']['date'];
661 var dow = GLOBAL_REGISTRY['calendar_strings']['dom_cal_weekdays_long'][date_obj.getDay()];
662 var month = date_obj.getMonth() + 1;
663 month = GLOBAL_REGISTRY['calendar_strings']['dom_cal_month_long'][month];
668 switch(userDateFormat.charAt(i)) {
670 returnDate += " " + date_obj.getFullYear();
673 returnDate += " " + month;
676 returnDate += " " + date_obj.getDate();
679 // cn: use locale's date separator? probably not.
680 //returnDate += " " + userDateFormat.charAt(i);
686 //return dow+" "+date_obj.getDate()+" "+month+" "+date_obj.getFullYear();
689 SugarDateTime.getFormattedDate = SugarDateTime.prototype.getFormattedDate;
691 // return the formatted day of the week of the date given a date object
692 SugarDateTime.prototype.getFormattedDOW = function(date_obj) {
693 var hour = config.strings.mod_strings.Calendar.dow[date_obj.getDay()];
695 SugarDateTime.getFormattedDOW = SugarDateTime.prototype.getFormattedDOW;
697 // return the formatted hour of the date given a date object
698 SugarDateTime.getAMPM = function(date_obj) {
699 var hour = date_obj.getHour();
706 else if ( hour == 12)
716 SugarDateTime.getFormattedHour = SugarDateTime.prototype.getFormattedHour;
718 //mod.SugarDateTime.getFormattedDate = publ.getFormattedDate;
720 // return the javascript Date object given a vCal UTC string
721 SugarDateTime.prototype.parseUTCDate = function(date_string) {
722 var match = /(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})Z/;
723 if(((result= match.exec(date_string))) != null)
725 var new_date = new Date(Date.UTC(result[1],result[2] - 1,result[3],result[4],result[5],parseInt(result[6])+time_offset));
730 SugarDateTime.parseUTCDate = SugarDateTime.prototype.parseUTCDate;
732 SugarDateTime.prototype.parseAdjustedDate = function(date_string, dst_start, dst_end, gmt_offset_secs) {
734 var match = /(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})Z/;
735 dst_start_parse = match.exec(dst_start);
736 dst_end_parse = match.exec(dst_end);
738 if(dst_start_parse == null || dst_end_parse == null) {
739 var new_date = new Date(result[1],result[2] - 1,result[3],result[4],result[5],parseInt(result[6]));
740 new_date = new Date(new_date.getTime() + gmt_offset_secs * 1000);
742 dst_start_obj = new Date(dst_start_parse[1],dst_start_parse[2] - 1,dst_start_parse[3],dst_start_parse[4],dst_start_parse[5],parseInt(dst_start_parse[6]));
743 dst_end_obj = new Date(dst_end_parse[1],dst_end_parse[2] - 1,dst_end_parse[3],dst_end_parse[4],dst_end_parse[5],parseInt(dst_end_parse[6]));
745 if(((result = match.exec(date_string))) != null)
747 var new_date = new Date(result[1],result[2] - 1,result[3],result[4],result[5],parseInt(result[6]));
748 var event_ts = new_date.getTime();
749 var dst_start_ts = dst_start_obj.getTime();
750 var dst_end_ts = dst_end_obj.getTime();
752 if(((event_ts >= dst_start_ts || event_ts < dst_end_ts) && dst_start_ts > dst_end_ts)
753 || (event_ts >= dst_start_ts && event_ts < dst_end_ts)) {
754 new_date = new Date(new_date.getTime() + 60 * 60 * 1000);
757 new_date = new Date(new_date.getTime() + gmt_offset_secs * 1000);
763 SugarDateTime.parseAdjustedDate = SugarDateTime.prototype.parseAdjustedDate;
765 // create a hash based on a date
766 SugarDateTime.prototype.getUTCHash = function(startdate){
767 var month = ( startdate.getUTCMonth() < 10) ? "0"+startdate.getUTCMonth():""+startdate.getUTCMonth();
768 var day = ( startdate.getUTCDate() < 10) ? "0"+startdate.getUTCDate():""+startdate.getUTCDate();
769 var hours = ( startdate.getUTCHours() < 10) ? "0"+startdate.getUTCHours():""+startdate.getUTCHours();
770 var minutes = ( startdate.getUTCMinutes() < 10) ? "0"+startdate.getUTCMinutes():""+startdate.getUTCMinutes();
771 return startdate.getUTCFullYear()+month+day+hours+minutes;
772 return startdate.getUTCFullYear()+month+day+hours+minutes;
774 SugarDateTime.getUTCHash = SugarDateTime.prototype.getUTCHash;