as3corelib 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. data/Gemfile +5 -0
  2. data/Gemfile.lock +28 -0
  3. data/README.textile +79 -0
  4. data/Rakefile +3 -0
  5. data/as3corelib.gemspec +23 -0
  6. data/build/build.properties +48 -0
  7. data/build/build.xml +104 -0
  8. data/examples/JSONExample/JSONExample.mxml +73 -0
  9. data/lib/as3corelib.rb +15 -0
  10. data/src/com/adobe/air/crypto/EncryptionKeyGenerator.as +313 -0
  11. data/src/com/adobe/air/filesystem/FileMonitor.as +245 -0
  12. data/src/com/adobe/air/filesystem/FileUtil.as +63 -0
  13. data/src/com/adobe/air/filesystem/VolumeMonitor.as +184 -0
  14. data/src/com/adobe/air/filesystem/events/FileMonitorEvent.as +61 -0
  15. data/src/com/adobe/air/logging/FileTarget.as +95 -0
  16. data/src/com/adobe/air/net/ResourceCache.as +165 -0
  17. data/src/com/adobe/air/net/events/ResourceCacheEvent.as +70 -0
  18. data/src/com/adobe/crypto/HMAC.as +127 -0
  19. data/src/com/adobe/crypto/MD5.as +281 -0
  20. data/src/com/adobe/crypto/MD5Stream.as +402 -0
  21. data/src/com/adobe/crypto/SHA1.as +289 -0
  22. data/src/com/adobe/crypto/SHA224.as +257 -0
  23. data/src/com/adobe/crypto/SHA256.as +261 -0
  24. data/src/com/adobe/crypto/WSSEUsernameToken.as +114 -0
  25. data/src/com/adobe/errors/IllegalStateError.as +63 -0
  26. data/src/com/adobe/fileformats/vcard/Address.as +47 -0
  27. data/src/com/adobe/fileformats/vcard/Email.as +39 -0
  28. data/src/com/adobe/fileformats/vcard/Phone.as +39 -0
  29. data/src/com/adobe/fileformats/vcard/VCard.as +54 -0
  30. data/src/com/adobe/fileformats/vcard/VCardParser.as +246 -0
  31. data/src/com/adobe/images/BitString.as +39 -0
  32. data/src/com/adobe/images/JPGEncoder.as +648 -0
  33. data/src/com/adobe/images/PNGEncoder.as +141 -0
  34. data/src/com/adobe/net/DynamicURLLoader.as +55 -0
  35. data/src/com/adobe/net/IURIResolver.as +76 -0
  36. data/src/com/adobe/net/MimeTypeMap.as +200 -0
  37. data/src/com/adobe/net/URI.as +2466 -0
  38. data/src/com/adobe/net/URIEncodingBitmap.as +139 -0
  39. data/src/com/adobe/net/proxies/RFC2817Socket.as +198 -0
  40. data/src/com/adobe/protocols/dict/Database.as +66 -0
  41. data/src/com/adobe/protocols/dict/Definition.as +71 -0
  42. data/src/com/adobe/protocols/dict/Dict.as +360 -0
  43. data/src/com/adobe/protocols/dict/DictionaryServer.as +60 -0
  44. data/src/com/adobe/protocols/dict/MatchStrategy.as +66 -0
  45. data/src/com/adobe/protocols/dict/Response.as +71 -0
  46. data/src/com/adobe/protocols/dict/events/ConnectedEvent.as +53 -0
  47. data/src/com/adobe/protocols/dict/events/DatabaseEvent.as +67 -0
  48. data/src/com/adobe/protocols/dict/events/DefinitionEvent.as +70 -0
  49. data/src/com/adobe/protocols/dict/events/DefinitionHeaderEvent.as +69 -0
  50. data/src/com/adobe/protocols/dict/events/DictionaryServerEvent.as +69 -0
  51. data/src/com/adobe/protocols/dict/events/DisconnectedEvent.as +55 -0
  52. data/src/com/adobe/protocols/dict/events/ErrorEvent.as +80 -0
  53. data/src/com/adobe/protocols/dict/events/MatchEvent.as +67 -0
  54. data/src/com/adobe/protocols/dict/events/MatchStrategiesEvent.as +70 -0
  55. data/src/com/adobe/protocols/dict/events/NoMatchEvent.as +54 -0
  56. data/src/com/adobe/protocols/dict/util/CompleteResponseEvent.as +68 -0
  57. data/src/com/adobe/protocols/dict/util/SocketHelper.as +81 -0
  58. data/src/com/adobe/serialization/json/JSON.as +86 -0
  59. data/src/com/adobe/serialization/json/JSONDecoder.as +327 -0
  60. data/src/com/adobe/serialization/json/JSONEncoder.as +312 -0
  61. data/src/com/adobe/serialization/json/JSONParseError.as +87 -0
  62. data/src/com/adobe/serialization/json/JSONToken.as +104 -0
  63. data/src/com/adobe/serialization/json/JSONTokenType.as +69 -0
  64. data/src/com/adobe/serialization/json/JSONTokenizer.as +702 -0
  65. data/src/com/adobe/utils/ArrayUtil.as +187 -0
  66. data/src/com/adobe/utils/DateUtil.as +701 -0
  67. data/src/com/adobe/utils/DictionaryUtil.as +87 -0
  68. data/src/com/adobe/utils/IntUtil.as +99 -0
  69. data/src/com/adobe/utils/NumberFormatter.as +74 -0
  70. data/src/com/adobe/utils/StringUtil.as +239 -0
  71. data/src/com/adobe/utils/XMLUtil.as +168 -0
  72. data/src/com/adobe/webapis/ServiceBase.as +48 -0
  73. data/src/com/adobe/webapis/URLLoaderBase.as +108 -0
  74. data/src/com/adobe/webapis/events/ServiceEvent.as +82 -0
  75. data/tests/src/CoreLibTestRunner-app.xml +135 -0
  76. data/tests/src/CoreLibTestRunner.as +138 -0
  77. data/tests/src/CoreLibTestRunner.mxml +46 -0
  78. data/tests/src/com/adobe/air/crypto/EncryptionKeyGeneratorTest.as +176 -0
  79. data/tests/src/com/adobe/air/filesystem/FileMonitorTest.as +63 -0
  80. data/tests/src/com/adobe/air/filesystem/VolumeMonitorTest.as +57 -0
  81. data/tests/src/com/adobe/air/filesystem/events/FileMonitorEventTest.as +59 -0
  82. data/tests/src/com/adobe/air/net/events/ResourceCacheEventTest.as +72 -0
  83. data/tests/src/com/adobe/crypto/HMACMD5Test.as +134 -0
  84. data/tests/src/com/adobe/crypto/HMACSHA1Test.as +138 -0
  85. data/tests/src/com/adobe/crypto/MD5Test.as +82 -0
  86. data/tests/src/com/adobe/crypto/SHA1Test.as +151 -0
  87. data/tests/src/com/adobe/crypto/SHA224Test.as +104 -0
  88. data/tests/src/com/adobe/crypto/SHA256Test.as +116 -0
  89. data/tests/src/com/adobe/crypto/WSSEUsernameTokenTest.as +87 -0
  90. data/tests/src/com/adobe/images/JPGEncoderTest.as +54 -0
  91. data/tests/src/com/adobe/images/PNGEncoderTest.as +54 -0
  92. data/tests/src/com/adobe/net/URITest.as +589 -0
  93. data/tests/src/com/adobe/protocols/events/ConnectedEventTest.as +59 -0
  94. data/tests/src/com/adobe/protocols/events/DatabaseEventTest.as +62 -0
  95. data/tests/src/com/adobe/protocols/events/DefinitionEventTest.as +61 -0
  96. data/tests/src/com/adobe/protocols/events/DefinitionHeaderEventTest.as +61 -0
  97. data/tests/src/com/adobe/protocols/events/DictionaryServerEventTest.as +61 -0
  98. data/tests/src/com/adobe/protocols/events/DisconnectedEventTest.as +59 -0
  99. data/tests/src/com/adobe/protocols/events/ErrorEventTest.as +63 -0
  100. data/tests/src/com/adobe/protocols/events/MatchEventTest.as +61 -0
  101. data/tests/src/com/adobe/protocols/events/MatchStrategiesEventTest.as +61 -0
  102. data/tests/src/com/adobe/protocols/events/NoMatchEventTest.as +58 -0
  103. data/tests/src/com/adobe/protocols/util/CompletedResponseEventTest.as +60 -0
  104. data/tests/src/com/adobe/serialization/json/JSONTest.as +522 -0
  105. data/tests/src/com/adobe/serialization/json/SimpleClass.as +85 -0
  106. data/tests/src/com/adobe/utils/ArrayUtilTest.as +173 -0
  107. data/tests/src/com/adobe/utils/DateUtilTest.as +436 -0
  108. data/tests/src/com/adobe/utils/DictionaryUtilTest.as +93 -0
  109. data/tests/src/com/adobe/utils/IntUtilTest.as +73 -0
  110. data/tests/src/com/adobe/utils/NumberFormatterTest.as +70 -0
  111. data/tests/src/com/adobe/utils/StringUtilTest.as +304 -0
  112. data/tests/src/com/adobe/utils/XMLUtilTest.as +101 -0
  113. data/tests/src/com/adobe/webapis/events/ServiceEventTest.as +66 -0
  114. metadata +196 -0
@@ -0,0 +1,313 @@
1
+ /*
2
+ Copyright (c) 2009, Adobe Systems Incorporated
3
+ All rights reserved.
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are
7
+ met:
8
+
9
+ * Redistributions of source code must retain the above copyright notice,
10
+ this list of conditions and the following disclaimer.
11
+
12
+ * Redistributions in binary form must reproduce the above copyright
13
+ notice, this list of conditions and the following disclaimer in the
14
+ documentation and/or other materials provided with the distribution.
15
+
16
+ * Neither the name of Adobe Systems Incorporated nor the names of its
17
+ contributors may be used to endorse or promote products derived from
18
+ this software without specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
21
+ IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23
+ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
+ */
32
+
33
+ package com.adobe.air.crypto
34
+ {
35
+ import com.adobe.crypto.SHA256;
36
+
37
+ import flash.data.EncryptedLocalStore;
38
+ import flash.utils.ByteArray;
39
+
40
+ /**
41
+ * The EncryptionKeyGenerator class generates an encryption key value, such as you would use
42
+ * to encrypt files or data. For example, the encryption key is suitable to use as
43
+ * an encryption key for an encrypted AIR local SQL (SQLite) database.
44
+ *
45
+ * <p>This class uses techniques and algorithms that are designed for maximum
46
+ * data privacy and security. Use this class to generate an encryption key if your
47
+ * application requires data to be encrypted on a per-user level (in other words,
48
+ * if only one user of the application should be able to access his or her data).
49
+ * In some situations you may also want to use per-user encryption for data even
50
+ * if the application design specifies that other users can access the data. For more
51
+ * information, see
52
+ * "<a href="http://help.adobe.com/en_US/AIR/1.5/devappsflex/WS34990ABF-C893-47ec-B813-9C9D9587A398.html">Considerations for using encryption with a database</a>"
53
+ * in the guide
54
+ * "<a href="http://help.adobe.com/en_US/AIR/1.5/devappsflex/">Developing Adobe AIR Applications with Flex</a>."</p>
55
+ *
56
+ * <p>The generated encryption key is based on a password that you provide. For any given
57
+ * password, in the same AIR application
58
+ * running in the same user account on the same machine, the encryption key result is
59
+ * the same.</p>
60
+ *
61
+ * <p>To generate an encryption key from a password, use the <code>getEncryptionKey()</code>
62
+ * method. To confirm that a password is a "strong" password before calling the
63
+ * <code>getEncryptionKey()</code> method, use the <code>validateStrongPassword()</code>
64
+ * method.</p>
65
+ *
66
+ * <p>In addition, the EncryptionKeyGenerator includes a utility constant,
67
+ * <code>ENCRYPTED_DB_PASSWORD_ERROR_ID</code>. This constant matches the error ID of
68
+ * the SQLError error that occurs when code that is attempting to open an encrypted database
69
+ * provides the wrong encryption key.</p>
70
+ *
71
+ * <p>This class is designed to create an encryption key suitable for providing the highest
72
+ * level of data privacy and security. In order to achieve that level of security, a few
73
+ * security principles must be followed:</p>
74
+ *
75
+ * <ul>
76
+ * <li>Your application should never store the user-entered password</li>
77
+ * <li>Your application should never store the encryption key returned by the
78
+ * <code>getEncryptionKey()</code> method.</li>
79
+ * <li>Instead, each time the user runs the application and attempts to access the database,
80
+ * your application code should call the <code>getEncryptionKey()</code> method to
81
+ * regenerate the encryption key.</li>
82
+ * </ul>
83
+ *
84
+ * <p>For more information about data security, and an explanation of the security techniques
85
+ * used in the EncryptionKeyGenerator class, see
86
+ * "<a href="http://help.adobe.com/en_US/AIR/1.5/devappsflex/WS61068DCE-9499-4d40-82B8-B71CC35D832C.html">Example: Generating and using an encryption key</a>"
87
+ * in the guide
88
+ * "<a href="http://help.adobe.com/en_US/AIR/1.5/devappsflex/">Developing Adobe AIR Applications with Flex</a>."</p>
89
+ */
90
+ public class EncryptionKeyGenerator
91
+ {
92
+ // ------- Constants -------
93
+ /**
94
+ * This constant matches the error ID (3138) of the SQLError error that occurs when
95
+ * code that is attempting to open an encrypted database provides the wrong
96
+ * encryption key.
97
+ */
98
+ public static const ENCRYPTED_DB_PASSWORD_ERROR_ID:uint = 3138;
99
+
100
+ private static const STRONG_PASSWORD_PATTERN:RegExp = /(?=^.{8,32}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$/;
101
+ private static const SALT_ELS_KEY:String = "com.adobe.air.crypto::EncryptedDBSalt$$$";
102
+
103
+
104
+ // ------- Constructor -------
105
+
106
+ /**
107
+ * Creates a new EncryptionKeyGenerator instance.
108
+ */
109
+ public function EncryptionKeyGenerator() {}
110
+
111
+
112
+ // ------- Public methods -------
113
+
114
+ /**
115
+ * Checks a password and returns a value indicating whether the password is a "strong"
116
+ * password. The criteria for a strong password are:
117
+ *
118
+ * <ul>
119
+ * <li>Minimum 8 characters</li>
120
+ * <li>Maxmium 32 characters</li>
121
+ * <li>Contains at least one lowercase letter</li>
122
+ * <li>Contains at least one uppercase letter</li>
123
+ * <li>Contains at least one number or symbol character</li>
124
+ * </ul>
125
+ *
126
+ * @param password The password to check
127
+ *
128
+ * @return A value indicating whether the password is a strong password (<code>true</code>)
129
+ * or not (<code>false</code>).
130
+ */
131
+ public function validateStrongPassword(password:String):Boolean
132
+ {
133
+ if (password == null || password.length <= 0)
134
+ {
135
+ return false;
136
+ }
137
+
138
+ return STRONG_PASSWORD_PATTERN.test(password);
139
+ }
140
+
141
+
142
+ /**
143
+ * Uses a password to generate a 16-byte encryption key. The return value is suitable
144
+ * to use as an encryption key for an encrypted AIR local SQL (SQLite) database.
145
+ *
146
+ * <p>For any given
147
+ * password, calling the <code>getEncryptionKey()</code> method from the same AIR application
148
+ * running in the same user account on the same machine, the encryption key result is
149
+ * the same.
150
+ *
151
+ * <p>This method is designed to create an encryption key suitable for providing the highest
152
+ * level of data privacy and security. In order to achieve that level of security, your
153
+ * application must follow several security principles:</p>
154
+ *
155
+ * <ul>
156
+ * <li>Your application can never store the user-entered password</li>
157
+ * <li>Your application can never store the encryption key returned by the
158
+ * <code>getEncryptionKey()</code> method.</li>
159
+ * <li>Instead, each time the user runs the application and attempts to access the database,
160
+ * call the <code>getEncryptionKey()</code> method to regenerate the encryption key.</li>
161
+ * </ul>
162
+ *
163
+ * <p>For more information about data security, and an explanation of the security techniques
164
+ * used in the EncryptionKeyGenerator class, see
165
+ * "<a href="http://help.adobe.com/en_US/AIR/1.5/devappsflex/WS61068DCE-9499-4d40-82B8-B71CC35D832C.html">Example: Generating and using an encryption key</a>"
166
+ * in the guide
167
+ * "<a href="http://help.adobe.com/en_US/AIR/1.5/devappsflex/">Developing Adobe AIR Applications with Flex</a>."</p>
168
+ *
169
+ * @param password The password to use to generate the encryption key.
170
+ * @param overrideSaltELSKey The EncryptionKeyGenerator creates and stores a random value
171
+ * (known as a <i>salt</i>) as part of the process of
172
+ * generating the encryption key. The first time an application
173
+ * calls the <code>getEncryptionKey()</code> method, the salt
174
+ * value is created and stored in the AIR application's encrypted
175
+ * local store (ELS). From then on, the salt value is loaded from the
176
+ * ELS.
177
+ * <p>If you wish to provide a custom String ELS key for storing
178
+ * the salt value, specify a value for the <code>overrideSaltELSKey</code>
179
+ * parameter. If the parameter is <code>null</code> (the default)
180
+ * a default key name is used.</p>
181
+ *
182
+ * @return The generated encryption key, a 16-byte ByteArray object.
183
+ *
184
+ * @throws ArgumentError If the specified password is not a "strong" password according to the
185
+ * criteria explained in the <code>validateStrongPassword()</code>
186
+ * method description
187
+ *
188
+ * @throws ArgumentError If a non-<code>null</code> value is specified for the <code>overrideSaltELSKey</code>
189
+ * parameter, and the value is an empty String (<code>""</code>)
190
+ */
191
+ public function getEncryptionKey(password:String, overrideSaltELSKey:String=null):ByteArray
192
+ {
193
+ if (!validateStrongPassword(password))
194
+ {
195
+ throw new ArgumentError("The password must be a strong password. It must be 8-32 characters long. It must contain at least one uppercase letter, at least one lowercase letter, and at least one number or symbol.");
196
+ }
197
+
198
+ if (overrideSaltELSKey != null && overrideSaltELSKey.length <= 0)
199
+ {
200
+ throw new ArgumentError("If an overrideSaltELSKey parameter value is specified, it can't be an empty String.");
201
+ }
202
+
203
+ var concatenatedPassword:String = concatenatePassword(password);
204
+
205
+ var saltKey:String;
206
+ if (overrideSaltELSKey == null)
207
+ {
208
+ saltKey = SALT_ELS_KEY;
209
+ }
210
+ else
211
+ {
212
+ saltKey = overrideSaltELSKey;
213
+ }
214
+
215
+ var salt:ByteArray = EncryptedLocalStore.getItem(saltKey);
216
+ if (salt == null)
217
+ {
218
+ salt = makeSalt();
219
+ EncryptedLocalStore.setItem(saltKey, salt);
220
+ }
221
+
222
+ var unhashedKey:ByteArray = xorBytes(concatenatedPassword, salt);
223
+
224
+ var hashedKey:String = SHA256.hashBytes(unhashedKey);
225
+
226
+ var encryptionKey:ByteArray = generateEncryptionKey(hashedKey);
227
+
228
+ return encryptionKey;
229
+ }
230
+
231
+
232
+ // ------- Creating encryption key -------
233
+
234
+ private function concatenatePassword(pwd:String):String
235
+ {
236
+ var len:int = pwd.length;
237
+ var targetLength:int = 32;
238
+
239
+ if (len == targetLength)
240
+ {
241
+ return pwd;
242
+ }
243
+
244
+ var repetitions:int = Math.floor(targetLength / len);
245
+ var excess:int = targetLength % len;
246
+
247
+ var result:String = "";
248
+
249
+ for (var i:uint = 0; i < repetitions; i++)
250
+ {
251
+ result += pwd;
252
+ }
253
+
254
+ result += pwd.substr(0, excess);
255
+
256
+ return result;
257
+ }
258
+
259
+
260
+ private function makeSalt():ByteArray
261
+ {
262
+ var result:ByteArray = new ByteArray;
263
+
264
+ for (var i:uint = 0; i < 8; i++)
265
+ {
266
+ result.writeUnsignedInt(Math.round(Math.random() * uint.MAX_VALUE));
267
+ }
268
+
269
+ return result;
270
+ }
271
+
272
+
273
+ private function xorBytes(passwordString:String, salt:ByteArray):ByteArray
274
+ {
275
+ var result:ByteArray = new ByteArray();
276
+
277
+ for (var i:uint = 0; i < 32; i += 4)
278
+ {
279
+ // Extract 4 bytes from the password string and convert to a uint
280
+ var o1:uint = passwordString.charCodeAt(i) << 24;
281
+ o1 += passwordString.charCodeAt(i + 1) << 16;
282
+ o1 += passwordString.charCodeAt(i + 2) << 8;
283
+ o1 += passwordString.charCodeAt(i + 3);
284
+
285
+ salt.position = i;
286
+ var o2:uint = salt.readUnsignedInt();
287
+
288
+ var xor:uint = o1 ^ o2;
289
+ result.writeUnsignedInt(xor);
290
+ }
291
+
292
+ return result;
293
+ }
294
+
295
+
296
+ private function generateEncryptionKey(hash:String):ByteArray
297
+ {
298
+ var result:ByteArray = new ByteArray();
299
+
300
+ // select a range of 128 bits (32 hex characters) from the hash
301
+ // In this case, we'll use the bits starting from position 17
302
+ for (var i:uint = 0; i < 32; i += 2)
303
+ {
304
+ var position:uint = i + 17;
305
+ var hex:String = hash.substr(position, 2);
306
+ var byte:int = parseInt(hex, 16);
307
+ result.writeByte(byte);
308
+ }
309
+
310
+ return result;
311
+ }
312
+ }
313
+ }
@@ -0,0 +1,245 @@
1
+ /*
2
+ Copyright (c) 2009, Adobe Systems Incorporated
3
+ All rights reserved.
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are
7
+ met:
8
+
9
+ * Redistributions of source code must retain the above copyright notice,
10
+ this list of conditions and the following disclaimer.
11
+
12
+ * Redistributions in binary form must reproduce the above copyright
13
+ notice, this list of conditions and the following disclaimer in the
14
+ documentation and/or other materials provided with the distribution.
15
+
16
+ * Neither the name of Adobe Systems Incorporated nor the names of its
17
+ contributors may be used to endorse or promote products derived from
18
+ this software without specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
21
+ IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23
+ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
+ */
32
+
33
+ package com.adobe.air.filesystem
34
+ {
35
+ import flash.filesystem.File;
36
+ import flash.utils.Timer;
37
+ import flash.events.TimerEvent;
38
+ import flash.events.Event;
39
+ import flash.events.EventDispatcher;
40
+ import com.adobe.air.filesystem.events.FileMonitorEvent;
41
+
42
+ /*
43
+ Todo:
44
+
45
+ -Cmonitor changes in multiple attributes
46
+ -add support for monitoring multiple files
47
+ */
48
+
49
+ /**
50
+ * Dispatched when the modified date of the file being modified changes.
51
+ *
52
+ * @eventType com.adobe.air.filesystem.events.FileMonitor.CHANGE
53
+ */
54
+ [Event(name="CHANGE", type="com.adobe.air.filesystem.events.FileMonitor")]
55
+
56
+ /**
57
+ * Dispatched when the file being monitored is moved or deleted. The file
58
+ * will be unwatched.
59
+ *
60
+ * @eventType com.adobe.air.filesystem.events.FileMonitor.MOVE
61
+ */
62
+ [Event(name="MOVE", type="com.adobe.air.filesystem.events.FileMonitor")]
63
+
64
+ /**
65
+ * Dispatched when the file being monitored is created.
66
+ *
67
+ * @eventType com.adobe.air.filesystem.events.FileMonitor.CREATE
68
+ */
69
+ [Event(name="CREATE", type="com.adobe.air.filesystem.events.FileMonitor")]
70
+
71
+ /**
72
+ * Class that monitors files for changes.
73
+ */
74
+ public class FileMonitor extends EventDispatcher
75
+ {
76
+ private var _file:File;
77
+ private var timer:Timer;
78
+ public static const DEFAULT_MONITOR_INTERVAL:Number = 1000;
79
+ private var _interval:Number;
80
+ private var fileExists:Boolean = false;
81
+
82
+ private var lastModifiedTime:Number;
83
+
84
+ /**
85
+ * Constructor
86
+ *
87
+ * @parameter file The File that will be monitored for changes.
88
+ *
89
+ * @param interval How often in milliseconds the file is polled for
90
+ * change events. Default value is 1000, minimum value is 1000
91
+ */
92
+ public function FileMonitor(file:File = null, interval:Number = -1)
93
+ {
94
+ this.file = file;
95
+
96
+ if(interval != -1)
97
+ {
98
+ if(interval < 1000)
99
+ {
100
+ _interval = 1000;
101
+ }
102
+ else
103
+ {
104
+ _interval = interval;
105
+ }
106
+ }
107
+ else
108
+ {
109
+ _interval = DEFAULT_MONITOR_INTERVAL;
110
+ }
111
+ }
112
+
113
+ /**
114
+ * File being monitored for changes.
115
+ *
116
+ * Setting the property will result in unwatch() being called.
117
+ */
118
+ public function get file():File
119
+ {
120
+ return _file;
121
+ }
122
+
123
+ public function set file(file:File):void
124
+ {
125
+ if(timer && timer.running)
126
+ {
127
+ unwatch();
128
+ }
129
+
130
+ _file = file;
131
+
132
+ if(!_file)
133
+ {
134
+ fileExists = false;
135
+ return;
136
+ }
137
+
138
+ //note : this will throw an error if new File() is passed in.
139
+ fileExists = _file.exists;
140
+ if(fileExists)
141
+ {
142
+ lastModifiedTime = _file.modificationDate.getTime();
143
+ }
144
+
145
+ }
146
+
147
+ /**
148
+ * How often the system is polled for Volume change events.
149
+ */
150
+ public function get interval():Number
151
+ {
152
+ return _interval;
153
+ }
154
+
155
+ /**
156
+ * Begins monitoring the specified file for changes.
157
+ *
158
+ * Broadcasts Event.CHANGE event when the file's modification date has changed.
159
+ */
160
+ public function watch():void
161
+ {
162
+ if(!file)
163
+ {
164
+ //should we throw an error?
165
+ return;
166
+ }
167
+
168
+ if(timer && timer.running)
169
+ {
170
+ return;
171
+ }
172
+
173
+ //check and see if timer is active. if it is, return
174
+ if(!timer)
175
+ {
176
+ timer = new Timer(_interval);
177
+ timer.addEventListener(TimerEvent.TIMER, onTimerEvent, false, 0, true);
178
+ }
179
+
180
+ timer.start();
181
+ }
182
+
183
+ /**
184
+ * Stops watching the specified file for changes.
185
+ */
186
+ public function unwatch():void
187
+ {
188
+ if(!timer)
189
+ {
190
+ return;
191
+ }
192
+
193
+ timer.stop();
194
+ timer.removeEventListener(TimerEvent.TIMER, onTimerEvent);
195
+ }
196
+
197
+ private function onTimerEvent(e:TimerEvent):void
198
+ {
199
+ var outEvent:FileMonitorEvent;
200
+
201
+ if(fileExists != _file.exists)
202
+ {
203
+ if(_file.exists)
204
+ {
205
+ //file was created
206
+ outEvent = new FileMonitorEvent(FileMonitorEvent.CREATE);
207
+ lastModifiedTime = _file.modificationDate.getTime();
208
+ }
209
+ else
210
+ {
211
+ //file was moved / deleted
212
+ outEvent = new FileMonitorEvent(FileMonitorEvent.MOVE);
213
+ unwatch();
214
+ }
215
+ fileExists = _file.exists;
216
+ }
217
+ else
218
+ {
219
+ if(!_file.exists)
220
+ {
221
+ return;
222
+ }
223
+
224
+ var modifiedTime:Number = _file.modificationDate.getTime();
225
+
226
+ if(modifiedTime == lastModifiedTime)
227
+ {
228
+ return;
229
+ }
230
+
231
+ lastModifiedTime = modifiedTime;
232
+
233
+ //file modified
234
+ outEvent = new FileMonitorEvent(FileMonitorEvent.CHANGE);
235
+ }
236
+
237
+ if(outEvent)
238
+ {
239
+ outEvent.file = _file;
240
+ dispatchEvent(outEvent);
241
+ }
242
+
243
+ }
244
+ }
245
+ }
@@ -0,0 +1,63 @@
1
+ /*
2
+ Copyright (c) 2009, Adobe Systems Incorporated
3
+ All rights reserved.
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are
7
+ met:
8
+
9
+ * Redistributions of source code must retain the above copyright notice,
10
+ this list of conditions and the following disclaimer.
11
+
12
+ * Redistributions in binary form must reproduce the above copyright
13
+ notice, this list of conditions and the following disclaimer in the
14
+ documentation and/or other materials provided with the distribution.
15
+
16
+ * Neither the name of Adobe Systems Incorporated nor the names of its
17
+ contributors may be used to endorse or promote products derived from
18
+ this software without specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
21
+ IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23
+ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
+ */
32
+
33
+ package com.adobe.air.filesystem
34
+ {
35
+ import flash.system.Capabilities;
36
+ import flash.filesystem.File;
37
+
38
+
39
+ public class FileUtil
40
+ {
41
+ /**
42
+ * @return An Array of Files representing the root directories of the
43
+ * operating system.
44
+ */
45
+ public static function getRootDirectories():Array
46
+ {
47
+ var v:Array = File.getRootDirectories();
48
+ var os:String = Capabilities.os;
49
+
50
+ if(os.indexOf("Mac") > -1)
51
+ {
52
+ v = File(v[0]).resolvePath("Volumes").getDirectoryListing();
53
+ }
54
+ else if(os.indexOf("Linux") > -1)
55
+ {
56
+ //todo: need to impliment Linux
57
+ }
58
+
59
+ return v;
60
+ }
61
+
62
+ }
63
+ }