prevent script tags inside of error popup
[plstackapi.git] / planetstack / core / xoslib / static / js / xoslib / xos-util.js
1 // misc utility functions
2
3 function idInArray(id, arr) {
4     // because sometimes ids are strings and sometimes they're integers
5     for (index in arr) {
6         if (id.toString() == arr[index].toString()) {
7             return true;
8         }
9     }
10     return false;
11 }
12
13 function assert(outcome, description) {
14     if (!outcome) {
15         console.log(description);
16     }
17 }
18
19 function templateFromId(id) {
20     return _.template($(id).html());
21 }
22
23 function firstCharUpper(s) {
24     return s.charAt(0).toUpperCase() + s.slice(1);
25 }
26
27 function toTitleCase(str)
28 {\r
29     return str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});\r
30 }
31
32 function fieldNameToHumanReadable(str)
33 {
34     str = str.replace("_", " ");
35     return toTitleCase(str);
36 }
37
38 // http://stackoverflow.com/questions/2117320/set-maximum-displayed-rows-count-for-html-table
39 function limitTableRows(tableSelector, maxRows) {
40     var table = $(tableSelector)[0] //document.getElementById(tableId);
41     var wrapper = table.parentNode;
42     var rowsInTable = table.rows.length;
43     try {
44         var border = getComputedStyle(table.rows[0].cells[0], '').getPropertyValue('border-top-width');
45         border = border.replace('px', '') * 1;
46     } catch (e) {
47         var border = table.rows[0].cells[0].currentStyle.borderWidth;
48         border = (border.replace('px', '') * 1) / 2;
49     }
50     var height = 0;
51     if (rowsInTable > maxRows) {
52         for (var i = 0; i < maxRows; i++) {
53             height += table.rows[i].clientHeight + border;
54             //console.log("XXX " + height + " " + table.rows[i].clientHeight + " " + border);
55         }
56         wrapper.style.height = height + "px";
57     }
58 }
59
60 function validateField(validatorName, value, obj) {
61     if (validatorName=="notBlank") {
62         if ((value==undefined) || (value=="")) {
63             return "can not be blank";
64         }
65     }
66
67     // if notBlank wasn't set, and the field is blank, then we can return
68     if ((value==undefined) || (value=="")) {
69         return true;
70     }
71
72     switch (validatorName) {
73         case "url":
74             if (! /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value)) {
75                 return "must be a valid url";
76             }
77             break;
78
79         case "portspec":
80             if (! $.trim(value).match(portlist_regexp())) {
81                 return "must be a valid portspec (example: 'tcp 123, udp 456-789')"
82             }
83             break;
84     }
85
86     return true;
87 }
88
89 function array_diff(a1, a2)
90 {\r
91   var a=[], diff=[];\r
92   for(var i=0;i<a1.length;i++)\r
93     a[a1[i]]=true;\r
94   for(var i=0;i<a2.length;i++)\r
95     if(a[a2[i]]) delete a[a2[i]];\r
96     else a[a2[i]]=true;\r
97   for(var k in a)\r
98     diff.push(k);\r
99   return diff;\r
100 }
101
102 function array_subtract(a1, a2)
103 {
104     result=[]
105     for (index in a1) {
106         value = a1[index];
107         if (!$.inArray(value, a2) >= 0) {
108             result.push(value);
109         }
110     }
111     return result;
112 }
113
114 function array_same_elements(arr1, arr2)
115 {
116     // return true if arrays have same elements, even if order is different
117     return ($(arr1).not(arr2).length == 0 && $(arr2).not(arr1).length == 0);
118 }
119
120 function array_pair_lookup(x, names, values)
121 {
122     for (index in values) {
123         if (values[index] == x) {
124             return names[index];
125         }
126     }
127     return "object #" + x;
128 }
129
130 function all_options(selector) {
131     el = $(selector);
132     result = [];
133     _.each(el.find("option"), function(option) {
134         result.push($(option).val());
135     });
136     return result;
137 }
138
139 function make_same_width(containerSelector, itemSelector) {
140     var maxWidth = 0;
141     $(containerSelector).find(itemSelector).each( function(index) { maxWidth = Math.max(maxWidth, $(this).width()); });\r
142     console.log(maxWidth);\r
143     $(containerSelector).find(itemSelector).each( function(index) { $(this).width(maxWidth); });
144 }
145
146 function strip_scripts(s) {
147     var div = document.createElement('div');\r
148     div.innerHTML = s;\r
149     var scripts = div.getElementsByTagName('script');\r
150     var i = scripts.length;\r
151     while (i--) {\r
152       scripts[i].parentNode.removeChild(scripts[i]);\r
153     }\r
154     return div.innerHTML;\r
155   }
156
157 function parse_portlist(ports) {
158     /* Support a list of ports in the format "protocol:port, protocol:port, ..."
159         examples:
160             tcp 123
161             tcp 123:133
162             tcp 123, tcp 124, tcp 125, udp 201, udp 202
163
164         User can put either a "/" or a " " between protocol and ports
165         Port ranges can be specified with "-" or ":"
166
167         This is a straightforward port of the code in core/models/network.py
168     */
169
170     var nats = [];
171     if (ports) {
172         parts = ports.split(",")
173         $.each(parts, function(index, part) {
174             part = $.trim(part);
175             if (part.indexOf("/")>=0) {
176                 parts2 = part.split("/",2);
177                 protocol=parts2[0];
178                 ports=parts2[1];
179             } else if (part.indexOf(" ")>=0) {
180                 parts2 = part.split(" +",2);
181                 protocol=parts2[0];
182                 ports=parts2[1];
183             } else {
184                 throw 'malformed port specifier ' + part + ', format example: "tcp 123, tcp 201:206, udp 333"';
185             }
186
187             protocol = $.trim(protocol);
188             ports = $.trim(ports);
189
190             console.log(ports);
191
192             if (protocol!="tcp" && protocol!="udp") {
193                 throw 'unknown protocol ' + protocol;
194             }
195
196             if (ports.indexOf("-")>=0) {
197                 parts2 = ports.split("-");
198                 first = parseInt($.trim(parts2[0]));
199                 last = parseInt($.trim(parts2[1]));
200                 portStr = first + ":" + last;
201             } else if (ports.indexOf(":")>=0) {
202                 parts2 = ports.split(":");
203                 first = parseInt($.trim(parts2[0]));
204                 last = parseInt($.trim(parts2[1]));
205                 portStr = first + ":" + last;
206             } else {
207                 portStr = parseInt(ports).toString();
208             }
209
210             nats.push( {l4_protocol: protocol, l4_port: portStr} );
211         }); /* end $.each(ports) */
212     }
213     return nats
214 }
215
216 function portlist_regexp() {
217     /* this constructs the big complicated regexp that validates port
218        specifiers. Saved here in long form, in case we need to change it
219        in the future.
220     */
221
222     paren = function(x) { return "(?:" + x + ")"; }
223     whitespace = " *";
224     protocol = paren("tcp|udp");
225     protocolSlash = protocol + paren(whitespace + "|\/");
226     numbers = paren("[0-9]+");
227     range = paren(numbers + paren("-|:") + numbers);
228     numbersOrRange = paren(numbers + "|" + range);
229     protoPorts = paren(protocolSlash + numbersOrRange);
230     protoPortsCommas = paren(paren(protoPorts + "," + whitespace)+"+");
231     multiProtoPorts = paren(protoPortsCommas + protoPorts);
232     portSpec = "^" + paren(protoPorts + "|" + multiProtoPorts) + "$";
233     return RegExp(portSpec);
234 }
235
236 function portlist_selftest() {
237     r = portlist_regexp();
238     assert(! "tcp".match(r), 'should not have matched: "tcp"');
239     assert("tcp 1".match(r), 'should have matched: "tcp 1"');
240     assert("tcp 123".match(r), 'should have matched: "tcp 123"');
241     assert("tcp  123".match(r), 'should have matched: "tcp 123"');
242     assert("tcp 123-456".match(r), 'should have matched: "tcp 123-456"');
243     assert("tcp 123:456".match(r), 'should have matched: "tcp 123:456"');
244     assert(! "tcp 123-".match(r), 'should have matched: "tcp 123-"');
245     assert(! "tcp 123:".match(r), 'should have matched: "tcp 123:"');
246     assert(! "foo 123".match(r), 'should not have matched "foo 123"');
247     assert("udp 123".match(r), 'should have matched: "udp 123"');
248     assert("tcp 123,udp 456".match(r), 'should have matched: "tcp 123,udp 456"');
249     assert("tcp 123, udp 456".match(r), 'should have matched: "tcp 123, udp 456"');
250     assert("tcp 123,  udp 456".match(r), 'should have matched: "tcp 123,  udp 456"');
251     assert("tcp 123-45, udp 456".match(r), 'should have matched: "tcp 123-45, udp 456"');
252     assert("tcp 123-45, udp 456, tcp 11, tcp 22:45, udp 76, udp 47:49, udp 60-61".match(r), 'should have matched: "tcp 123-45, udp 456, tcp 11, tcp 22:45, udp 76, udp 47:49, udp 60-61"');
253     return "done";
254 }
255
256 //portlist_selftest();
257
258