source: trunk/fl5/src/com/longtailvideo/jwplayer/utils/Strings.as @ 2393

Revision 2393, 7.0 KB checked in by pablo, 9 months ago (diff)
  • Addresses cross-site security issue with links containing base-64 encoded JavaScript (1585)
  • Addresses JavaScript API event flow
Line 
1package com.longtailvideo.jwplayer.utils {
2        import com.adobe.serialization.json.JSONDecoder;
3       
4        /**
5         * This class groups a couple of commonly used string operations.
6         * @author Jeroen Wijering
7         **/
8        public class Strings {
9               
10                /**
11                 * Unescape a string and filter "asfunction" occurences ( can be used for XSS exploits).
12                 *
13                 * @param str   The string to decode.
14                 * @return              The decoded string.
15                 **/
16                public static function decode(str:String):String {
17                        if (str.indexOf('asfunction') == -1) {
18                                return unescape(str);
19                        } else {
20                                return '';
21                        }
22                }
23               
24                /**
25                 * Convert a number to a digital-clock like string.
26                 *
27                 * @param nbr   The number of seconds.
28                 * @return              A MN:SS string.
29                 **/
30                public static function digits(nbr:Number):String {
31                        var min:Number = Math.floor(nbr / 60);
32                        var sec:Number = Math.floor(nbr % 60);
33                        var str:String = Strings.zero(min) + ':' + Strings.zero(sec);
34                        return str;
35                }
36               
37                /**
38                 * Convert a time-representing string to a number.
39                 *
40                 * @param str   The input string. Supported are 00:03:00.1 / 03:00.1 / 180.1s / 3.2m / 3.2h
41                 * @return              The number of seconds.
42                 **/
43                public static function seconds(str:String):Number {
44                        str = str.replace(',', '.');
45                        var arr:Array = str.split(':');
46                        var sec:Number = 0;
47                        if (str.substr(-2) == 'ms') {
48                                sec = Number(str.substr(0, str.length - 2)) / 1000;
49                        } else if (str.substr(-1) == 's') {
50                                        sec = Number(str.substr(0, str.length - 1));
51                        } else if (str.substr(-1) == 'm') {
52                                sec = Number(str.substr(0, str.length - 1)) * 60;
53                        } else if (str.substr(-1) == 'h') {
54                                sec = Number(str.substr(0, str.length - 1)) * 3600;
55                        } else if (arr.length > 1) {
56                                sec = Number(arr[arr.length - 1]);
57                                sec += Number(arr[arr.length - 2]) * 60;
58                                if (arr.length == 3) {
59                                        sec += Number(arr[arr.length - 3]) * 3600;
60                                }
61                        } else {
62                                sec = Number(str);
63                        }
64                        return sec;
65                }
66               
67                /**
68                 * Basic serialization: string representations of booleans and numbers are returned typed;
69                 * strings are returned urldecoded.
70                 *
71                 * @param val   String value to serialize.
72                 * @return              The original value in the correct primitive type.
73                 **/
74                public static function serialize(val:String):Object {
75                        if (val == null) {
76                                return null;
77                        } else if (val == 'true') {
78                                return true;
79                        } else if (val == 'false') {
80                                return false;
81                        } else if (val.indexOf("[[JSON]]") == 0) {
82                                var jsonString:String = val.substring(8, val.length);
83                                try {
84                                        return (new JSONDecoder(jsonString, false)).getValue();
85                                } catch(e:Error) {
86                                        Logger.log("Error parsing JSON string: " + e.message + ".  String: " + jsonString);
87                                }
88                                return jsonString;
89                        } else if (isNaN(Number(val)) || val.length > 5 || val.length == 0) {
90                                return val;
91                        } else {
92                                return Number(val);
93                        }
94                }
95               
96                /**
97                 * Strip HTML tags and linebreaks off a string.
98                 *
99                 * @param str   The string to clean up.
100                 * @return              The clean string.
101                 **/
102                public static function strip(str:String):String {
103                        var tmp:Array = str.split("\n");
104                        str = tmp.join("");
105                        tmp = str.split("\r");
106                        str = tmp.join("");
107                        var idx:Number = str.indexOf("<");
108                        while (idx != -1) {
109                                var end:Number = str.indexOf(">", idx + 1);
110                                end == -1 ? end = str.length - 1 : null;
111                                str = str.substr(0, idx) + " " + str.substr(end + 1, str.length);
112                                idx = str.indexOf("<", idx);
113                        }
114                        return str;
115                }
116               
117                /**
118                 * Add a leading zero to a number.
119                 *
120                 * @param nbr   The number to convert. Can be 0 to 99.
121                 * @ return             A string representation with possible leading 0.
122                 **/
123                public static function zero(nbr:Number):String {
124                        if (nbr < 10) {
125                                return '0' + nbr;
126                        } else {
127                                return '' + nbr;
128                        }
129                }
130                /**
131                 * Finds the extension of a filename or URL
132                 * @param filename      The string on which to search
133                 * @return                      Everything trailing the final '.' character
134                 *
135                 */
136                public static function extension(filename:String):String {
137                        if (filename && filename.lastIndexOf(".") > 0) {
138                                if (filename.lastIndexOf("?") > 0){
139                                        filename = String(filename.split("?")[0]);
140                                }
141                                return filename.substring(filename.lastIndexOf(".")+1, filename.length).toLowerCase();
142                        } else {
143                                return "";
144                        }
145                }
146               
147                /**
148                 * Recursively creates a string representation of an object and its properties.
149                 *
150                 * @param object The object to be converted to a string.
151                 */
152                public static function print_r(object:Object):String {
153                        var result:String = "";
154                        if (typeof(object) == "object") {
155                                result += "{";
156                        }
157                        for (var property:Object in object) {
158                                if (typeof(object[property]) == "object") {
159                                        result += property + ": ";
160                                } else {
161                                        result += property + ": " + object[property];
162                                }
163                                result += print_r(object[property]) +  ", ";
164                        }
165                       
166                        if (result != "{"){
167                                result = result.substr(0, result.length - 2);
168                        }
169                       
170                        if (typeof(object) == "object") {
171                                result += "}";
172                        }
173                       
174                        return result;
175                }
176               
177                /** Remove white space from before and after a string. **/
178                public static function trim(s:String):String {
179                        return s.replace(/^\s+/, '').replace(/\s+$/, '');
180                }
181               
182                /** Get the value of a case-insensitive attribute in an XML node **/
183                public static function xmlAttribute(xml:XML, attribute:String):String {
184                        for each (var attrib:XML in xml.attributes()) {
185                                if (attrib.name().toString().toLowerCase() == attribute.toLowerCase())
186                                        return attrib.toString();
187                        }
188                        return "";
189                }
190               
191                /** Gets an absolute file path based on a relative filepath **/
192                public static function getAbsolutePath(path:String, basepath:String=null):String {
193                        if (basepath == null){
194                                return path;
195                        }
196                        if (isAbsolutePath(path)) {
197                                return path;
198                        }
199                        var protocol:String = basepath.substring(0, basepath.indexOf("://") + 3);
200                        var domain:String = basepath.substring(protocol.length, basepath.indexOf('/', protocol.length + 1));
201                        var patharray:Array;
202                        if (path.indexOf("/") === 0) {
203                                patharray = path.split("/");
204                        } else {
205                                var basepath:String = basepath.split("?")[0];
206                                basepath = basepath.substring(protocol.length + domain.length + 1, basepath.lastIndexOf('/'));
207                                patharray = basepath.split("/").concat(path.split("/"));
208                        }
209                        var result:Array = [];
210                        for (var i:int = 0; i < patharray.length; i++) {
211                                if (!patharray[i] || patharray[i] === undefined || patharray[i] == ".") {
212                                        continue;
213                                } else if (patharray[i] == "..") {
214                                        result.pop();
215                                } else {
216                                        result.push(patharray[i]);
217                                }
218                        }
219                        return protocol + domain + "/" + result.join("/");
220                };
221               
222                public static function isAbsolutePath(path:String):Boolean {
223                        var protocol:int = path.indexOf("://");
224                        var queryparams:int = path.indexOf("?");
225                        return (protocol > 0 && (queryparams < 0 || (queryparams > protocol)));
226                }
227
228                /** Removes potentially harmful string headers from a link **/
229                public static function cleanLink(link:String):String {
230                        // Can't use a regex variable; matching tests will incorrectly return false
231                        while(/(javascript|asfunction|vbscript|feed|data):/gi.test(link)) {
232                                link = link.replace(/(javascript|asfunction|vbscript|feed|data):/gi, "");
233                        }
234                        return link;
235                }
236               
237
238               
239               
240        }
241       
242}
Note: See TracBrowser for help on using the repository browser.