as3corelib 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }