johnson 2.0.0.pre1 → 2.0.0.pre2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (311) hide show
  1. data/CHANGELOG.rdoc +12 -0
  2. data/Manifest.txt +4 -285
  3. data/Rakefile +13 -20
  4. data/ext/tracemonkey/global.cc +4 -1
  5. data/ext/tracemonkey/js.cc +30 -33
  6. data/ext/tracemonkey/runtime.cc +96 -6
  7. data/ext/tracemonkey/split_global.cc +0 -5
  8. data/ext/tracemonkey/tracemonkey.h +2 -2
  9. data/lib/johnson.rb +2 -2
  10. data/lib/johnson/runtime.rb +25 -15
  11. data/lib/johnson/tracemonkey/runtime.rb +6 -3
  12. data/vendor/tracemonkey/config/system-headers +1 -3
  13. data/vendor/tracemonkey/jscntxt.h +5 -2
  14. data/vendor/tracemonkey/jsdbgapi.cpp +9 -1
  15. data/vendor/tracemonkey/jsdbgapi.h +4 -0
  16. data/vendor/tracemonkey/tests/ecma/NativeObjects/browser.js +0 -0
  17. data/vendor/tracemonkey/tests/ecma/NativeObjects/jstests.list +0 -0
  18. data/vendor/tracemonkey/tests/ecma_3_1/Object/jstests.list +1 -1
  19. data/vendor/tracemonkey/tests/js1_3/misc/browser.js +0 -0
  20. data/vendor/tracemonkey/tests/js1_3/misc/jstests.list +0 -0
  21. data/vendor/tracemonkey/tests/js1_5/Regress/jstests.list +4 -4
  22. data/vendor/tracemonkey/tests/js1_5/Scope/jstests.list +1 -1
  23. data/vendor/tracemonkey/tests/js1_5/decompilation/jstests.list +2 -2
  24. data/vendor/tracemonkey/tests/js1_7/decompilation/jstests.list +1 -1
  25. data/vendor/tracemonkey/tests/shell.js +2 -1
  26. metadata +51 -309
  27. data/ext/spidermonkey/context.c +0 -116
  28. data/ext/spidermonkey/context.h +0 -19
  29. data/ext/spidermonkey/conversions.c +0 -361
  30. data/ext/spidermonkey/conversions.h +0 -31
  31. data/ext/spidermonkey/debugger.c +0 -234
  32. data/ext/spidermonkey/debugger.h +0 -10
  33. data/ext/spidermonkey/extconf.rb +0 -32
  34. data/ext/spidermonkey/extensions.c +0 -37
  35. data/ext/spidermonkey/extensions.h +0 -12
  36. data/ext/spidermonkey/global.c +0 -40
  37. data/ext/spidermonkey/global.h +0 -11
  38. data/ext/spidermonkey/idhash.c +0 -16
  39. data/ext/spidermonkey/idhash.h +0 -8
  40. data/ext/spidermonkey/immutable_node.c +0 -1153
  41. data/ext/spidermonkey/immutable_node.c.erb +0 -523
  42. data/ext/spidermonkey/immutable_node.h +0 -22
  43. data/ext/spidermonkey/jroot.h +0 -197
  44. data/ext/spidermonkey/js_land_proxy.c +0 -620
  45. data/ext/spidermonkey/js_land_proxy.h +0 -20
  46. data/ext/spidermonkey/ruby_land_proxy.c +0 -618
  47. data/ext/spidermonkey/ruby_land_proxy.h +0 -38
  48. data/ext/spidermonkey/runtime.c +0 -396
  49. data/ext/spidermonkey/runtime.h +0 -27
  50. data/ext/spidermonkey/spidermonkey.c +0 -22
  51. data/ext/spidermonkey/spidermonkey.h +0 -29
  52. data/lib/johnson/spidermonkey.rb +0 -12
  53. data/lib/johnson/spidermonkey/context.rb +0 -10
  54. data/lib/johnson/spidermonkey/debugger.rb +0 -67
  55. data/lib/johnson/spidermonkey/immutable_node.rb +0 -282
  56. data/lib/johnson/spidermonkey/js_land_proxy.rb +0 -64
  57. data/lib/johnson/spidermonkey/mutable_tree_visitor.rb +0 -242
  58. data/lib/johnson/spidermonkey/ruby_land_proxy.rb +0 -17
  59. data/lib/johnson/spidermonkey/runtime.rb +0 -74
  60. data/test/johnson/spidermonkey/context_test.rb +0 -21
  61. data/test/johnson/spidermonkey/immutable_node_test.rb +0 -34
  62. data/test/johnson/spidermonkey/js_land_proxy_test.rb +0 -273
  63. data/test/johnson/spidermonkey/ruby_land_proxy_test.rb +0 -274
  64. data/test/johnson/spidermonkey/runtime_test.rb +0 -41
  65. data/vendor/spidermonkey/.cvsignore +0 -9
  66. data/vendor/spidermonkey/Makefile.in +0 -449
  67. data/vendor/spidermonkey/Makefile.ref +0 -365
  68. data/vendor/spidermonkey/README.html +0 -820
  69. data/vendor/spidermonkey/SpiderMonkey.rsp +0 -12
  70. data/vendor/spidermonkey/Y.js +0 -19
  71. data/vendor/spidermonkey/build.mk +0 -43
  72. data/vendor/spidermonkey/config.mk +0 -192
  73. data/vendor/spidermonkey/config/AIX4.1.mk +0 -65
  74. data/vendor/spidermonkey/config/AIX4.2.mk +0 -64
  75. data/vendor/spidermonkey/config/AIX4.3.mk +0 -65
  76. data/vendor/spidermonkey/config/Darwin.mk +0 -83
  77. data/vendor/spidermonkey/config/Darwin1.3.mk +0 -81
  78. data/vendor/spidermonkey/config/Darwin1.4.mk +0 -41
  79. data/vendor/spidermonkey/config/Darwin5.2.mk +0 -81
  80. data/vendor/spidermonkey/config/Darwin5.3.mk +0 -81
  81. data/vendor/spidermonkey/config/HP-UXB.10.10.mk +0 -77
  82. data/vendor/spidermonkey/config/HP-UXB.10.20.mk +0 -77
  83. data/vendor/spidermonkey/config/HP-UXB.11.00.mk +0 -80
  84. data/vendor/spidermonkey/config/IRIX.mk +0 -87
  85. data/vendor/spidermonkey/config/IRIX5.3.mk +0 -44
  86. data/vendor/spidermonkey/config/IRIX6.1.mk +0 -44
  87. data/vendor/spidermonkey/config/IRIX6.2.mk +0 -44
  88. data/vendor/spidermonkey/config/IRIX6.3.mk +0 -44
  89. data/vendor/spidermonkey/config/IRIX6.5.mk +0 -44
  90. data/vendor/spidermonkey/config/Linux_All.mk +0 -103
  91. data/vendor/spidermonkey/config/Mac_OS10.0.mk +0 -82
  92. data/vendor/spidermonkey/config/OSF1V4.0.mk +0 -72
  93. data/vendor/spidermonkey/config/OSF1V5.0.mk +0 -69
  94. data/vendor/spidermonkey/config/SunOS4.1.4.mk +0 -101
  95. data/vendor/spidermonkey/config/SunOS5.10.mk +0 -50
  96. data/vendor/spidermonkey/config/SunOS5.3.mk +0 -91
  97. data/vendor/spidermonkey/config/SunOS5.4.mk +0 -92
  98. data/vendor/spidermonkey/config/SunOS5.5.1.mk +0 -44
  99. data/vendor/spidermonkey/config/SunOS5.5.mk +0 -87
  100. data/vendor/spidermonkey/config/SunOS5.6.mk +0 -89
  101. data/vendor/spidermonkey/config/SunOS5.7.mk +0 -44
  102. data/vendor/spidermonkey/config/SunOS5.8.mk +0 -44
  103. data/vendor/spidermonkey/config/SunOS5.9.mk +0 -44
  104. data/vendor/spidermonkey/config/WINNT4.0.mk +0 -117
  105. data/vendor/spidermonkey/config/WINNT5.0.mk +0 -117
  106. data/vendor/spidermonkey/config/WINNT5.1.mk +0 -117
  107. data/vendor/spidermonkey/config/WINNT5.2.mk +0 -117
  108. data/vendor/spidermonkey/config/WINNT6.0.mk +0 -117
  109. data/vendor/spidermonkey/config/dgux.mk +0 -64
  110. data/vendor/spidermonkey/editline/Makefile.ref +0 -144
  111. data/vendor/spidermonkey/editline/README +0 -83
  112. data/vendor/spidermonkey/editline/editline.3 +0 -175
  113. data/vendor/spidermonkey/editline/editline.c +0 -1369
  114. data/vendor/spidermonkey/editline/editline.h +0 -135
  115. data/vendor/spidermonkey/editline/sysunix.c +0 -182
  116. data/vendor/spidermonkey/editline/unix.h +0 -82
  117. data/vendor/spidermonkey/fdlibm/.cvsignore +0 -7
  118. data/vendor/spidermonkey/fdlibm/Makefile.in +0 -127
  119. data/vendor/spidermonkey/fdlibm/Makefile.ref +0 -192
  120. data/vendor/spidermonkey/fdlibm/e_acos.c +0 -147
  121. data/vendor/spidermonkey/fdlibm/e_acosh.c +0 -105
  122. data/vendor/spidermonkey/fdlibm/e_asin.c +0 -156
  123. data/vendor/spidermonkey/fdlibm/e_atan2.c +0 -165
  124. data/vendor/spidermonkey/fdlibm/e_atanh.c +0 -110
  125. data/vendor/spidermonkey/fdlibm/e_cosh.c +0 -133
  126. data/vendor/spidermonkey/fdlibm/e_exp.c +0 -202
  127. data/vendor/spidermonkey/fdlibm/e_fmod.c +0 -184
  128. data/vendor/spidermonkey/fdlibm/e_gamma.c +0 -71
  129. data/vendor/spidermonkey/fdlibm/e_gamma_r.c +0 -70
  130. data/vendor/spidermonkey/fdlibm/e_hypot.c +0 -173
  131. data/vendor/spidermonkey/fdlibm/e_j0.c +0 -524
  132. data/vendor/spidermonkey/fdlibm/e_j1.c +0 -523
  133. data/vendor/spidermonkey/fdlibm/e_jn.c +0 -315
  134. data/vendor/spidermonkey/fdlibm/e_lgamma.c +0 -71
  135. data/vendor/spidermonkey/fdlibm/e_lgamma_r.c +0 -347
  136. data/vendor/spidermonkey/fdlibm/e_log.c +0 -184
  137. data/vendor/spidermonkey/fdlibm/e_log10.c +0 -134
  138. data/vendor/spidermonkey/fdlibm/e_pow.c +0 -386
  139. data/vendor/spidermonkey/fdlibm/e_rem_pio2.c +0 -222
  140. data/vendor/spidermonkey/fdlibm/e_remainder.c +0 -120
  141. data/vendor/spidermonkey/fdlibm/e_scalb.c +0 -89
  142. data/vendor/spidermonkey/fdlibm/e_sinh.c +0 -122
  143. data/vendor/spidermonkey/fdlibm/e_sqrt.c +0 -497
  144. data/vendor/spidermonkey/fdlibm/fdlibm.h +0 -273
  145. data/vendor/spidermonkey/fdlibm/fdlibm.mak +0 -1453
  146. data/vendor/spidermonkey/fdlibm/fdlibm.mdp +0 -0
  147. data/vendor/spidermonkey/fdlibm/k_cos.c +0 -135
  148. data/vendor/spidermonkey/fdlibm/k_rem_pio2.c +0 -354
  149. data/vendor/spidermonkey/fdlibm/k_sin.c +0 -114
  150. data/vendor/spidermonkey/fdlibm/k_standard.c +0 -785
  151. data/vendor/spidermonkey/fdlibm/k_tan.c +0 -170
  152. data/vendor/spidermonkey/fdlibm/s_asinh.c +0 -101
  153. data/vendor/spidermonkey/fdlibm/s_atan.c +0 -175
  154. data/vendor/spidermonkey/fdlibm/s_cbrt.c +0 -133
  155. data/vendor/spidermonkey/fdlibm/s_ceil.c +0 -120
  156. data/vendor/spidermonkey/fdlibm/s_copysign.c +0 -72
  157. data/vendor/spidermonkey/fdlibm/s_cos.c +0 -118
  158. data/vendor/spidermonkey/fdlibm/s_erf.c +0 -356
  159. data/vendor/spidermonkey/fdlibm/s_expm1.c +0 -267
  160. data/vendor/spidermonkey/fdlibm/s_fabs.c +0 -70
  161. data/vendor/spidermonkey/fdlibm/s_finite.c +0 -71
  162. data/vendor/spidermonkey/fdlibm/s_floor.c +0 -121
  163. data/vendor/spidermonkey/fdlibm/s_frexp.c +0 -99
  164. data/vendor/spidermonkey/fdlibm/s_ilogb.c +0 -85
  165. data/vendor/spidermonkey/fdlibm/s_isnan.c +0 -74
  166. data/vendor/spidermonkey/fdlibm/s_ldexp.c +0 -66
  167. data/vendor/spidermonkey/fdlibm/s_lib_version.c +0 -73
  168. data/vendor/spidermonkey/fdlibm/s_log1p.c +0 -211
  169. data/vendor/spidermonkey/fdlibm/s_logb.c +0 -79
  170. data/vendor/spidermonkey/fdlibm/s_matherr.c +0 -64
  171. data/vendor/spidermonkey/fdlibm/s_modf.c +0 -132
  172. data/vendor/spidermonkey/fdlibm/s_nextafter.c +0 -124
  173. data/vendor/spidermonkey/fdlibm/s_rint.c +0 -131
  174. data/vendor/spidermonkey/fdlibm/s_scalbn.c +0 -107
  175. data/vendor/spidermonkey/fdlibm/s_signgam.c +0 -40
  176. data/vendor/spidermonkey/fdlibm/s_significand.c +0 -68
  177. data/vendor/spidermonkey/fdlibm/s_sin.c +0 -118
  178. data/vendor/spidermonkey/fdlibm/s_tan.c +0 -112
  179. data/vendor/spidermonkey/fdlibm/s_tanh.c +0 -122
  180. data/vendor/spidermonkey/fdlibm/w_acos.c +0 -78
  181. data/vendor/spidermonkey/fdlibm/w_acosh.c +0 -78
  182. data/vendor/spidermonkey/fdlibm/w_asin.c +0 -80
  183. data/vendor/spidermonkey/fdlibm/w_atan2.c +0 -79
  184. data/vendor/spidermonkey/fdlibm/w_atanh.c +0 -81
  185. data/vendor/spidermonkey/fdlibm/w_cosh.c +0 -77
  186. data/vendor/spidermonkey/fdlibm/w_exp.c +0 -88
  187. data/vendor/spidermonkey/fdlibm/w_fmod.c +0 -78
  188. data/vendor/spidermonkey/fdlibm/w_gamma.c +0 -85
  189. data/vendor/spidermonkey/fdlibm/w_gamma_r.c +0 -81
  190. data/vendor/spidermonkey/fdlibm/w_hypot.c +0 -78
  191. data/vendor/spidermonkey/fdlibm/w_j0.c +0 -105
  192. data/vendor/spidermonkey/fdlibm/w_j1.c +0 -106
  193. data/vendor/spidermonkey/fdlibm/w_jn.c +0 -128
  194. data/vendor/spidermonkey/fdlibm/w_lgamma.c +0 -85
  195. data/vendor/spidermonkey/fdlibm/w_lgamma_r.c +0 -81
  196. data/vendor/spidermonkey/fdlibm/w_log.c +0 -78
  197. data/vendor/spidermonkey/fdlibm/w_log10.c +0 -81
  198. data/vendor/spidermonkey/fdlibm/w_pow.c +0 -99
  199. data/vendor/spidermonkey/fdlibm/w_remainder.c +0 -77
  200. data/vendor/spidermonkey/fdlibm/w_scalb.c +0 -95
  201. data/vendor/spidermonkey/fdlibm/w_sinh.c +0 -77
  202. data/vendor/spidermonkey/fdlibm/w_sqrt.c +0 -77
  203. data/vendor/spidermonkey/javascript-trace.d +0 -73
  204. data/vendor/spidermonkey/js.c +0 -3951
  205. data/vendor/spidermonkey/js.mdp +0 -0
  206. data/vendor/spidermonkey/js.msg +0 -308
  207. data/vendor/spidermonkey/js.pkg +0 -2
  208. data/vendor/spidermonkey/js3240.rc +0 -79
  209. data/vendor/spidermonkey/jsOS240.def +0 -654
  210. data/vendor/spidermonkey/jsapi.c +0 -5836
  211. data/vendor/spidermonkey/jsapi.h +0 -2624
  212. data/vendor/spidermonkey/jsarena.c +0 -450
  213. data/vendor/spidermonkey/jsarena.h +0 -318
  214. data/vendor/spidermonkey/jsarray.c +0 -2996
  215. data/vendor/spidermonkey/jsarray.h +0 -127
  216. data/vendor/spidermonkey/jsatom.c +0 -1045
  217. data/vendor/spidermonkey/jsatom.h +0 -442
  218. data/vendor/spidermonkey/jsbit.h +0 -253
  219. data/vendor/spidermonkey/jsbool.c +0 -176
  220. data/vendor/spidermonkey/jsbool.h +0 -73
  221. data/vendor/spidermonkey/jsclist.h +0 -139
  222. data/vendor/spidermonkey/jscntxt.c +0 -1348
  223. data/vendor/spidermonkey/jscntxt.h +0 -1120
  224. data/vendor/spidermonkey/jscompat.h +0 -57
  225. data/vendor/spidermonkey/jsconfig.h +0 -248
  226. data/vendor/spidermonkey/jsconfig.mk +0 -181
  227. data/vendor/spidermonkey/jscpucfg.c +0 -396
  228. data/vendor/spidermonkey/jscpucfg.h +0 -212
  229. data/vendor/spidermonkey/jsdate.c +0 -2390
  230. data/vendor/spidermonkey/jsdate.h +0 -124
  231. data/vendor/spidermonkey/jsdbgapi.c +0 -1802
  232. data/vendor/spidermonkey/jsdbgapi.h +0 -464
  233. data/vendor/spidermonkey/jsdhash.c +0 -868
  234. data/vendor/spidermonkey/jsdhash.h +0 -592
  235. data/vendor/spidermonkey/jsdtoa.c +0 -3167
  236. data/vendor/spidermonkey/jsdtoa.h +0 -130
  237. data/vendor/spidermonkey/jsdtracef.c +0 -317
  238. data/vendor/spidermonkey/jsdtracef.h +0 -77
  239. data/vendor/spidermonkey/jsemit.c +0 -6909
  240. data/vendor/spidermonkey/jsemit.h +0 -741
  241. data/vendor/spidermonkey/jsexn.c +0 -1371
  242. data/vendor/spidermonkey/jsexn.h +0 -96
  243. data/vendor/spidermonkey/jsfile.c +0 -2736
  244. data/vendor/spidermonkey/jsfile.h +0 -56
  245. data/vendor/spidermonkey/jsfile.msg +0 -90
  246. data/vendor/spidermonkey/jsfun.c +0 -2634
  247. data/vendor/spidermonkey/jsfun.h +0 -254
  248. data/vendor/spidermonkey/jsgc.c +0 -3562
  249. data/vendor/spidermonkey/jsgc.h +0 -403
  250. data/vendor/spidermonkey/jshash.c +0 -476
  251. data/vendor/spidermonkey/jshash.h +0 -151
  252. data/vendor/spidermonkey/jsify.pl +0 -485
  253. data/vendor/spidermonkey/jsinterp.c +0 -7007
  254. data/vendor/spidermonkey/jsinterp.h +0 -525
  255. data/vendor/spidermonkey/jsinvoke.c +0 -43
  256. data/vendor/spidermonkey/jsiter.c +0 -1067
  257. data/vendor/spidermonkey/jsiter.h +0 -122
  258. data/vendor/spidermonkey/jskeyword.tbl +0 -124
  259. data/vendor/spidermonkey/jskwgen.c +0 -460
  260. data/vendor/spidermonkey/jslibmath.h +0 -266
  261. data/vendor/spidermonkey/jslock.c +0 -1309
  262. data/vendor/spidermonkey/jslock.h +0 -313
  263. data/vendor/spidermonkey/jslocko.asm +0 -60
  264. data/vendor/spidermonkey/jslog2.c +0 -94
  265. data/vendor/spidermonkey/jslong.c +0 -264
  266. data/vendor/spidermonkey/jslong.h +0 -412
  267. data/vendor/spidermonkey/jsmath.c +0 -567
  268. data/vendor/spidermonkey/jsmath.h +0 -57
  269. data/vendor/spidermonkey/jsnum.c +0 -1239
  270. data/vendor/spidermonkey/jsnum.h +0 -283
  271. data/vendor/spidermonkey/jsobj.c +0 -5282
  272. data/vendor/spidermonkey/jsobj.h +0 -709
  273. data/vendor/spidermonkey/jsopcode.c +0 -5245
  274. data/vendor/spidermonkey/jsopcode.h +0 -394
  275. data/vendor/spidermonkey/jsopcode.tbl +0 -523
  276. data/vendor/spidermonkey/jsotypes.h +0 -202
  277. data/vendor/spidermonkey/jsparse.c +0 -6704
  278. data/vendor/spidermonkey/jsparse.h +0 -511
  279. data/vendor/spidermonkey/jsprf.c +0 -1264
  280. data/vendor/spidermonkey/jsprf.h +0 -150
  281. data/vendor/spidermonkey/jsproto.tbl +0 -128
  282. data/vendor/spidermonkey/jsprvtd.h +0 -267
  283. data/vendor/spidermonkey/jspubtd.h +0 -744
  284. data/vendor/spidermonkey/jsregexp.c +0 -4364
  285. data/vendor/spidermonkey/jsregexp.h +0 -183
  286. data/vendor/spidermonkey/jsreops.tbl +0 -145
  287. data/vendor/spidermonkey/jsscan.c +0 -2012
  288. data/vendor/spidermonkey/jsscan.h +0 -387
  289. data/vendor/spidermonkey/jsscope.c +0 -1957
  290. data/vendor/spidermonkey/jsscope.h +0 -418
  291. data/vendor/spidermonkey/jsscript.c +0 -1832
  292. data/vendor/spidermonkey/jsscript.h +0 -287
  293. data/vendor/spidermonkey/jsshell.msg +0 -50
  294. data/vendor/spidermonkey/jsstddef.h +0 -83
  295. data/vendor/spidermonkey/jsstr.c +0 -5005
  296. data/vendor/spidermonkey/jsstr.h +0 -641
  297. data/vendor/spidermonkey/jstypes.h +0 -475
  298. data/vendor/spidermonkey/jsutil.c +0 -345
  299. data/vendor/spidermonkey/jsutil.h +0 -157
  300. data/vendor/spidermonkey/jsxdrapi.c +0 -800
  301. data/vendor/spidermonkey/jsxdrapi.h +0 -218
  302. data/vendor/spidermonkey/jsxml.c +0 -8476
  303. data/vendor/spidermonkey/jsxml.h +0 -349
  304. data/vendor/spidermonkey/lock_SunOS.s +0 -119
  305. data/vendor/spidermonkey/perfect.js +0 -39
  306. data/vendor/spidermonkey/plify_jsdhash.sed +0 -36
  307. data/vendor/spidermonkey/prmjtime.c +0 -846
  308. data/vendor/spidermonkey/prmjtime.h +0 -103
  309. data/vendor/spidermonkey/resource.h +0 -15
  310. data/vendor/spidermonkey/rules.mk +0 -197
  311. data/vendor/spidermonkey/win32.order +0 -384
@@ -1,96 +0,0 @@
1
- /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2
- *
3
- * ***** BEGIN LICENSE BLOCK *****
4
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5
- *
6
- * The contents of this file are subject to the Mozilla Public License Version
7
- * 1.1 (the "License"); you may not use this file except in compliance with
8
- * the License. You may obtain a copy of the License at
9
- * http://www.mozilla.org/MPL/
10
- *
11
- * Software distributed under the License is distributed on an "AS IS" basis,
12
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13
- * for the specific language governing rights and limitations under the
14
- * License.
15
- *
16
- * The Original Code is Mozilla Communicator client code, released
17
- * March 31, 1998.
18
- *
19
- * The Initial Developer of the Original Code is
20
- * Netscape Communications Corporation.
21
- * Portions created by the Initial Developer are Copyright (C) 1998
22
- * the Initial Developer. All Rights Reserved.
23
- *
24
- * Contributor(s):
25
- *
26
- * Alternatively, the contents of this file may be used under the terms of
27
- * either of the GNU General Public License Version 2 or later (the "GPL"),
28
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29
- * in which case the provisions of the GPL or the LGPL are applicable instead
30
- * of those above. If you wish to allow use of your version of this file only
31
- * under the terms of either the GPL or the LGPL, and not to allow others to
32
- * use your version of this file under the terms of the MPL, indicate your
33
- * decision by deleting the provisions above and replace them with the notice
34
- * and other provisions required by the GPL or the LGPL. If you do not delete
35
- * the provisions above, a recipient may use your version of this file under
36
- * the terms of any one of the MPL, the GPL or the LGPL.
37
- *
38
- * ***** END LICENSE BLOCK ***** */
39
-
40
- /*
41
- * JS runtime exception classes.
42
- */
43
-
44
- #ifndef jsexn_h___
45
- #define jsexn_h___
46
-
47
- JS_BEGIN_EXTERN_C
48
-
49
- extern JSClass js_ErrorClass;
50
-
51
- /*
52
- * Initialize the exception constructor/prototype hierarchy.
53
- */
54
- extern JSObject *
55
- js_InitExceptionClasses(JSContext *cx, JSObject *obj);
56
-
57
- /*
58
- * Given a JSErrorReport, check to see if there is an exception associated with
59
- * the error number. If there is, then create an appropriate exception object,
60
- * set it as the pending exception, and set the JSREPORT_EXCEPTION flag on the
61
- * error report. Exception-aware host error reporters should probably ignore
62
- * error reports so flagged. Returns JS_TRUE if an associated exception is
63
- * found and set, JS_FALSE otherwise..
64
- */
65
- extern JSBool
66
- js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp);
67
-
68
- /*
69
- * Called if a JS API call to js_Execute or js_InternalCall fails; calls the
70
- * error reporter with the error report associated with any uncaught exception
71
- * that has been raised. Returns true if there was an exception pending, and
72
- * the error reporter was actually called.
73
- *
74
- * The JSErrorReport * that the error reporter is called with is currently
75
- * associated with a JavaScript object, and is not guaranteed to persist after
76
- * the object is collected. Any persistent uses of the JSErrorReport contents
77
- * should make their own copy.
78
- *
79
- * The flags field of the JSErrorReport will have the JSREPORT_EXCEPTION flag
80
- * set; embeddings that want to silently propagate JavaScript exceptions to
81
- * other contexts may want to use an error reporter that ignores errors with
82
- * this flag.
83
- */
84
- extern JSBool
85
- js_ReportUncaughtException(JSContext *cx);
86
-
87
- extern JSErrorReport *
88
- js_ErrorFromException(JSContext *cx, jsval exn);
89
-
90
- extern const JSErrorFormatString *
91
- js_GetLocalizedErrorMessage(JSContext* cx, void *userRef, const char *locale,
92
- const uintN errorNumber);
93
-
94
- JS_END_EXTERN_C
95
-
96
- #endif /* jsexn_h___ */
@@ -1,2736 +0,0 @@
1
- /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2
- * vim: set ts=8 sw=4 et tw=78:
3
- *
4
- * ***** BEGIN LICENSE BLOCK *****
5
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6
- *
7
- * The contents of this file are subject to the Mozilla Public License Version
8
- * 1.1 (the "License"); you may not use this file except in compliance with
9
- * the License. You may obtain a copy of the License at
10
- * http://www.mozilla.org/MPL/
11
- *
12
- * Software distributed under the License is distributed on an "AS IS" basis,
13
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14
- * for the specific language governing rights and limitations under the
15
- * License.
16
- *
17
- * The Original Code is Mozilla Communicator client code, released
18
- * March 31, 1998.
19
- *
20
- * The Initial Developer of the Original Code is
21
- * Netscape Communications Corporation.
22
- * Portions created by the Initial Developer are Copyright (C) 1998
23
- * the Initial Developer. All Rights Reserved.
24
- *
25
- * Contributor(s):
26
- *
27
- * Alternatively, the contents of this file may be used under the terms of
28
- * either of the GNU General Public License Version 2 or later (the "GPL"),
29
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30
- * in which case the provisions of the GPL or the LGPL are applicable instead
31
- * of those above. If you wish to allow use of your version of this file only
32
- * under the terms of either the GPL or the LGPL, and not to allow others to
33
- * use your version of this file under the terms of the MPL, indicate your
34
- * decision by deleting the provisions above and replace them with the notice
35
- * and other provisions required by the GPL or the LGPL. If you do not delete
36
- * the provisions above, a recipient may use your version of this file under
37
- * the terms of any one of the MPL, the GPL or the LGPL.
38
- *
39
- * ***** END LICENSE BLOCK ***** */
40
-
41
- /*
42
- * JS File object
43
- */
44
- #if JS_HAS_FILE_OBJECT
45
-
46
- #include "jsstddef.h"
47
- #include "jsfile.h"
48
-
49
- /* ----------------- Platform-specific includes and defines ----------------- */
50
- #if defined(XP_WIN) || defined(XP_OS2)
51
- # include <direct.h>
52
- # include <io.h>
53
- # include <sys/types.h>
54
- # include <sys/stat.h>
55
- # define FILESEPARATOR '\\'
56
- # define FILESEPARATOR2 '/'
57
- # define CURRENT_DIR "c:\\"
58
- # define POPEN _popen
59
- # define PCLOSE _pclose
60
- #elif defined(XP_UNIX) || defined(XP_BEOS)
61
- # include <strings.h>
62
- # include <stdio.h>
63
- # include <stdlib.h>
64
- # include <unistd.h>
65
- # define FILESEPARATOR '/'
66
- # define FILESEPARATOR2 '\0'
67
- # define CURRENT_DIR "/"
68
- # define POPEN popen
69
- # define PCLOSE pclose
70
- #endif
71
-
72
- /* --------------- Platform-independent includes and defines ---------------- */
73
- #include "jsapi.h"
74
- #include "jsatom.h"
75
- #include "jscntxt.h"
76
- #include "jsdate.h"
77
- #include "jsdbgapi.h"
78
- #include "jsemit.h"
79
- #include "jsfun.h"
80
- #include "jslock.h"
81
- #include "jsobj.h"
82
- #include "jsparse.h"
83
- #include "jsscan.h"
84
- #include "jsscope.h"
85
- #include "jsscript.h"
86
- #include "jsstr.h"
87
- #include "jsutil.h" /* Added by JSIFY */
88
- #include <string.h>
89
-
90
- /* NSPR dependencies */
91
- #include "prio.h"
92
- #include "prerror.h"
93
-
94
- #define SPECIAL_FILE_STRING "Special File"
95
- #define CURRENTDIR_PROPERTY "currentDir"
96
- #define SEPARATOR_PROPERTY "separator"
97
- #define FILE_CONSTRUCTOR "File"
98
- #define PIPE_SYMBOL '|'
99
-
100
- #define ASCII 0
101
- #define UTF8 1
102
- #define UCS2 2
103
-
104
- #define asciistring "text"
105
- #define utfstring "binary"
106
- #define unicodestring "unicode"
107
-
108
- #define MAX_PATH_LENGTH 1024
109
- #define MODE_SIZE 256
110
- #define NUMBER_SIZE 32
111
- #define MAX_LINE_LENGTH 256
112
- #define URL_PREFIX "file://"
113
-
114
- #define STDINPUT_NAME "Standard input stream"
115
- #define STDOUTPUT_NAME "Standard output stream"
116
- #define STDERROR_NAME "Standard error stream"
117
-
118
- #define RESOLVE_PATH js_canonicalPath /* js_absolutePath */
119
-
120
- /* Error handling */
121
- typedef enum JSFileErrNum {
122
- #define MSG_DEF(name, number, count, exception, format) \
123
- name = number,
124
- #include "jsfile.msg"
125
- #undef MSG_DEF
126
- JSFileErr_Limit
127
- #undef MSGDEF
128
- } JSFileErrNum;
129
-
130
- #define JSFILE_HAS_DFLT_MSG_STRINGS 1
131
-
132
- JSErrorFormatString JSFile_ErrorFormatString[JSFileErr_Limit] = {
133
- #if JSFILE_HAS_DFLT_MSG_STRINGS
134
- #define MSG_DEF(name, number, count, exception, format) \
135
- { format, count },
136
- #else
137
- #define MSG_DEF(name, number, count, exception, format) \
138
- { NULL, count },
139
- #endif
140
- #include "jsfile.msg"
141
- #undef MSG_DEF
142
- };
143
-
144
- const JSErrorFormatString *
145
- JSFile_GetErrorMessage(void *userRef, const char *locale,
146
- const uintN errorNumber)
147
- {
148
- if ((errorNumber > 0) && (errorNumber < JSFileErr_Limit))
149
- return &JSFile_ErrorFormatString[errorNumber];
150
- else
151
- return NULL;
152
- }
153
-
154
- #define JSFILE_CHECK_NATIVE(op) \
155
- if (file->isNative) { \
156
- JS_ReportWarning(cx, "Cannot call or access \"%s\" on native file %s",\
157
- op, file->path); \
158
- goto out; \
159
- }
160
-
161
- #define JSFILE_CHECK_WRITE \
162
- if (!file->isOpen) { \
163
- JS_ReportWarning(cx, \
164
- "File %s is closed, will open it for writing, proceeding", \
165
- file->path); \
166
- js_FileOpen(cx, obj, file, "write,append,create"); \
167
- } \
168
- if (!js_canWrite(cx, file)) { \
169
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, \
170
- JSFILEMSG_CANNOT_WRITE, file->path); \
171
- goto out; \
172
- }
173
-
174
- #define JSFILE_CHECK_READ \
175
- if (!file->isOpen) { \
176
- JS_ReportWarning(cx, \
177
- "File %s is closed, will open it for reading, proceeding", \
178
- file->path); \
179
- js_FileOpen(cx, obj, file, "read"); \
180
- } \
181
- if (!js_canRead(cx, file)) { \
182
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, \
183
- JSFILEMSG_CANNOT_READ, file->path); \
184
- goto out; \
185
- }
186
-
187
- #define JSFILE_CHECK_OPEN(op) \
188
- if (!file->isOpen) { \
189
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, \
190
- JSFILEMSG_FILE_MUST_BE_OPEN, op); \
191
- goto out; \
192
- }
193
-
194
- #define JSFILE_CHECK_CLOSED(op) \
195
- if (file->isOpen) { \
196
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, \
197
- JSFILEMSG_FILE_MUST_BE_CLOSED, op); \
198
- goto out; \
199
- }
200
-
201
- #define JSFILE_CHECK_ONE_ARG(op) \
202
- if (argc != 1) { \
203
- char str[NUMBER_SIZE]; \
204
- sprintf(str, "%d", argc); \
205
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, \
206
- JSFILEMSG_EXPECTS_ONE_ARG_ERROR, op, str); \
207
- goto out; \
208
- }
209
-
210
-
211
- /*
212
- Security mechanism, should define a callback for this.
213
- The parameters are as follows:
214
- SECURITY_CHECK(JSContext *cx, JSPrincipals *ps, char *op_name, JSFile *file)
215
- XXX Should this be a real function returning a JSBool result (and getting
216
- some typesafety help from the compiler?).
217
- */
218
- #define SECURITY_CHECK(cx, ps, op, file) \
219
- /* Define a callback here... */
220
-
221
-
222
- /* Structure representing the file internally */
223
- typedef struct JSFile {
224
- char *path; /* the path to the file. */
225
- JSBool isOpen;
226
- int32 mode; /* mode used to open the file: read, write, append, create, etc.. */
227
- int32 type; /* Asciiz, utf, unicode */
228
- char byteBuffer[3]; /* bytes read in advance by js_FileRead ( UTF8 encoding ) */
229
- jsint nbBytesInBuf; /* number of bytes stored in the buffer above */
230
- jschar charBuffer; /* character read in advance by readln ( mac files only ) */
231
- JSBool charBufferUsed; /* flag indicating if the buffer above is being used */
232
- JSBool hasRandomAccess;/* can the file be randomly accessed? false for stdin, and
233
- UTF-encoded files. */
234
- JSBool hasAutoflush; /* should we force a flush for each line break? */
235
- JSBool isNative; /* if the file is using OS-specific file FILE type */
236
- /* We can actually put the following two in a union since they should never be used at the same time */
237
- PRFileDesc *handle; /* the handle for the file, if open. */
238
- FILE *nativehandle; /* native handle, for stuff NSPR doesn't do. */
239
- JSBool isPipe; /* if the file is really an OS pipe */
240
- } JSFile;
241
-
242
- /* a few forward declarations... */
243
- JS_PUBLIC_API(JSObject*) js_NewFileObject(JSContext *cx, char *filename);
244
- static JSBool file_open(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
245
- static JSBool file_close(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
246
-
247
- /* New filename manipulation procesures */
248
- /* assumes we don't have leading/trailing spaces */
249
- static JSBool
250
- js_filenameHasAPipe(const char *filename)
251
- {
252
- if (!filename)
253
- return JS_FALSE;
254
-
255
- return filename[0] == PIPE_SYMBOL ||
256
- filename[strlen(filename) - 1] == PIPE_SYMBOL;
257
- }
258
-
259
- static JSBool
260
- js_isAbsolute(const char *name)
261
- {
262
- #if defined(XP_WIN) || defined(XP_OS2)
263
- return *name && name[1] == ':';
264
- #else
265
- return (name[0]
266
- # if defined(XP_UNIX) || defined(XP_BEOS)
267
- ==
268
- # else
269
- !=
270
- # endif
271
- FILESEPARATOR);
272
- #endif
273
- }
274
-
275
- /*
276
- * Concatenates base and name to produce a valid filename.
277
- * Returned string must be freed.
278
- */
279
- static char*
280
- js_combinePath(JSContext *cx, const char *base, const char *name)
281
- {
282
- int len = strlen(base);
283
- char* result = JS_malloc(cx, len + strlen(name) + 2);
284
-
285
- if (!result)
286
- return NULL;
287
-
288
- strcpy(result, base);
289
-
290
- if (base[len - 1] != FILESEPARATOR && base[len - 1] != FILESEPARATOR2) {
291
- result[len] = FILESEPARATOR;
292
- result[len + 1] = '\0';
293
- }
294
- strcat(result, name);
295
- return result;
296
- }
297
-
298
- /* Extract the last component from a path name. Returned string must be freed */
299
- static char *
300
- js_fileBaseName(JSContext *cx, const char *pathname)
301
- {
302
- jsint index, aux;
303
- char *result;
304
-
305
- index = strlen(pathname)-1;
306
-
307
- /* Chop off trailing seperators. */
308
- while (index > 0 && (pathname[index]==FILESEPARATOR ||
309
- pathname[index]==FILESEPARATOR2)) {
310
- --index;
311
- }
312
-
313
- aux = index;
314
-
315
- /* Now find the next separator. */
316
- while (index >= 0 && pathname[index] != FILESEPARATOR &&
317
- pathname[index] != FILESEPARATOR2) {
318
- --index;
319
- }
320
-
321
- /* Allocate and copy. */
322
- result = JS_malloc(cx, aux - index + 1);
323
- if (!result)
324
- return NULL;
325
- strncpy(result, pathname + index + 1, aux - index);
326
- result[aux - index] = '\0';
327
- return result;
328
- }
329
-
330
- /*
331
- * Returns everything but the last component from a path name.
332
- * Returned string must be freed.
333
- */
334
- static char *
335
- js_fileDirectoryName(JSContext *cx, const char *pathname)
336
- {
337
- char *result;
338
- const char *cp, *end;
339
- size_t pathsize;
340
-
341
- end = pathname + strlen(pathname);
342
- cp = end - 1;
343
-
344
- /* If this is already a directory, chop off the trailing /s. */
345
- while (cp >= pathname) {
346
- if (*cp != FILESEPARATOR && *cp != FILESEPARATOR2)
347
- break;
348
- --cp;
349
- }
350
-
351
- if (cp < pathname && end != pathname) {
352
- /* There were just /s, return the root. */
353
- result = JS_malloc(cx, 1 + 1); /* The separator + trailing NUL. */
354
- result[0] = FILESEPARATOR;
355
- result[1] = '\0';
356
- return result;
357
- }
358
-
359
- /* Now chop off the last portion. */
360
- while (cp >= pathname) {
361
- if (*cp == FILESEPARATOR || *cp == FILESEPARATOR2)
362
- break;
363
- --cp;
364
- }
365
-
366
- /* Check if this is a leaf. */
367
- if (cp < pathname) {
368
- /* It is, return "pathname/". */
369
- if (end[-1] == FILESEPARATOR || end[-1] == FILESEPARATOR2) {
370
- /* Already has its terminating /. */
371
- return JS_strdup(cx, pathname);
372
- }
373
-
374
- pathsize = end - pathname + 1;
375
- result = JS_malloc(cx, pathsize + 1);
376
- if (!result)
377
- return NULL;
378
-
379
- strcpy(result, pathname);
380
- result[pathsize - 1] = FILESEPARATOR;
381
- result[pathsize] = '\0';
382
-
383
- return result;
384
- }
385
-
386
- /* Return everything up to and including the seperator. */
387
- pathsize = cp - pathname + 1;
388
- result = JS_malloc(cx, pathsize + 1);
389
- if (!result)
390
- return NULL;
391
-
392
- strncpy(result, pathname, pathsize);
393
- result[pathsize] = '\0';
394
-
395
- return result;
396
- }
397
-
398
- static char *
399
- js_absolutePath(JSContext *cx, const char * path)
400
- {
401
- JSObject *obj;
402
- JSString *str;
403
- jsval prop;
404
-
405
- if (js_isAbsolute(path)) {
406
- return JS_strdup(cx, path);
407
- } else {
408
- obj = JS_GetGlobalObject(cx);
409
- if (!JS_GetProperty(cx, obj, FILE_CONSTRUCTOR, &prop)) {
410
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
411
- JSFILEMSG_FILE_CONSTRUCTOR_UNDEFINED_ERROR);
412
- return JS_strdup(cx, path);
413
- }
414
-
415
- obj = JSVAL_TO_OBJECT(prop);
416
- if (!JS_GetProperty(cx, obj, CURRENTDIR_PROPERTY, &prop)) {
417
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
418
- JSFILEMSG_FILE_CURRENTDIR_UNDEFINED_ERROR);
419
- return JS_strdup(cx, path);
420
- }
421
-
422
- str = JS_ValueToString(cx, prop);
423
- if (!str)
424
- return JS_strdup(cx, path);
425
-
426
- /* should we have an array of curr dirs indexed by drive for windows? */
427
- return js_combinePath(cx, JS_GetStringBytes(str), path);
428
- }
429
- }
430
-
431
- /* Side effect: will remove spaces in the beginning/end of the filename */
432
- static char *
433
- js_canonicalPath(JSContext *cx, char *oldpath)
434
- {
435
- char *tmp;
436
- char *path = oldpath;
437
- char *base, *dir, *current, *result;
438
- jsint c;
439
- jsint back = 0;
440
- unsigned int i = 0, j = strlen(path)-1;
441
-
442
- /* This is probably optional */
443
- /* Remove possible spaces in the beginning and end */
444
- while (i < j && path[i] == ' ')
445
- i++;
446
- while (j >= 0 && path[j] == ' ')
447
- j--;
448
-
449
- tmp = JS_malloc(cx, j-i+2);
450
- if (!tmp)
451
- return NULL;
452
-
453
- strncpy(tmp, path + i, j - i + 1);
454
- tmp[j - i + 1] = '\0';
455
-
456
- path = tmp;
457
-
458
- /* Pipe support. */
459
- if (js_filenameHasAPipe(path))
460
- return path;
461
-
462
- /* file:// support. */
463
- if (!strncmp(path, URL_PREFIX, strlen(URL_PREFIX))) {
464
- tmp = js_canonicalPath(cx, path + strlen(URL_PREFIX));
465
- JS_free(cx, path);
466
- return tmp;
467
- }
468
-
469
- if (!js_isAbsolute(path)) {
470
- tmp = js_absolutePath(cx, path);
471
- if (!tmp)
472
- return NULL;
473
- JS_free(cx, path);
474
- path = tmp;
475
- }
476
-
477
- result = JS_strdup(cx, "");
478
-
479
- current = path;
480
-
481
- base = js_fileBaseName(cx, current);
482
- dir = js_fileDirectoryName(cx, current);
483
-
484
- while (strcmp(dir, current)) {
485
- if (!strcmp(base, "..")) {
486
- back++;
487
- } else {
488
- if (back > 0) {
489
- back--;
490
- } else {
491
- tmp = result;
492
- result = JS_malloc(cx, strlen(base) + 1 + strlen(tmp) + 1);
493
- if (!result)
494
- goto out;
495
-
496
- strcpy(result, base);
497
- c = strlen(result);
498
- if (*tmp) {
499
- result[c] = FILESEPARATOR;
500
- result[c + 1] = '\0';
501
- strcat(result, tmp);
502
- }
503
- JS_free(cx, tmp);
504
- }
505
- }
506
- JS_free(cx, current);
507
- JS_free(cx, base);
508
- current = dir;
509
- base = js_fileBaseName(cx, current);
510
- dir = js_fileDirectoryName(cx, current);
511
- }
512
-
513
- tmp = result;
514
- result = JS_malloc(cx, strlen(dir)+1+strlen(tmp)+1);
515
- if (!result)
516
- goto out;
517
-
518
- strcpy(result, dir);
519
- c = strlen(result);
520
- if (tmp[0]!='\0') {
521
- if ((result[c-1]!=FILESEPARATOR)&&(result[c-1]!=FILESEPARATOR2)) {
522
- result[c] = FILESEPARATOR;
523
- result[c+1] = '\0';
524
- }
525
- strcat(result, tmp);
526
- }
527
-
528
- out:
529
- if (tmp)
530
- JS_free(cx, tmp);
531
- if (dir)
532
- JS_free(cx, dir);
533
- if (base)
534
- JS_free(cx, base);
535
- if (current)
536
- JS_free(cx, current);
537
-
538
- return result;
539
- }
540
-
541
- /* -------------------------- Text conversion ------------------------------- */
542
- /* The following is ripped from libi18n/unicvt.c and include files.. */
543
-
544
- /*
545
- * UTF8 defines and macros
546
- */
547
- #define ONE_OCTET_BASE 0x00 /* 0xxxxxxx */
548
- #define ONE_OCTET_MASK 0x7F /* x1111111 */
549
- #define CONTINUING_OCTET_BASE 0x80 /* 10xxxxxx */
550
- #define CONTINUING_OCTET_MASK 0x3F /* 00111111 */
551
- #define TWO_OCTET_BASE 0xC0 /* 110xxxxx */
552
- #define TWO_OCTET_MASK 0x1F /* 00011111 */
553
- #define THREE_OCTET_BASE 0xE0 /* 1110xxxx */
554
- #define THREE_OCTET_MASK 0x0F /* 00001111 */
555
- #define FOUR_OCTET_BASE 0xF0 /* 11110xxx */
556
- #define FOUR_OCTET_MASK 0x07 /* 00000111 */
557
- #define FIVE_OCTET_BASE 0xF8 /* 111110xx */
558
- #define FIVE_OCTET_MASK 0x03 /* 00000011 */
559
- #define SIX_OCTET_BASE 0xFC /* 1111110x */
560
- #define SIX_OCTET_MASK 0x01 /* 00000001 */
561
-
562
- #define IS_UTF8_1ST_OF_1(x) (( (x)&~ONE_OCTET_MASK ) == ONE_OCTET_BASE)
563
- #define IS_UTF8_1ST_OF_2(x) (( (x)&~TWO_OCTET_MASK ) == TWO_OCTET_BASE)
564
- #define IS_UTF8_1ST_OF_3(x) (( (x)&~THREE_OCTET_MASK) == THREE_OCTET_BASE)
565
- #define IS_UTF8_1ST_OF_4(x) (( (x)&~FOUR_OCTET_MASK ) == FOUR_OCTET_BASE)
566
- #define IS_UTF8_1ST_OF_5(x) (( (x)&~FIVE_OCTET_MASK ) == FIVE_OCTET_BASE)
567
- #define IS_UTF8_1ST_OF_6(x) (( (x)&~SIX_OCTET_MASK ) == SIX_OCTET_BASE)
568
- #define IS_UTF8_2ND_THRU_6TH(x) \
569
- (( (x)&~CONTINUING_OCTET_MASK ) == CONTINUING_OCTET_BASE)
570
- #define IS_UTF8_1ST_OF_UCS2(x) \
571
- IS_UTF8_1ST_OF_1(x) \
572
- || IS_UTF8_1ST_OF_2(x) \
573
- || IS_UTF8_1ST_OF_3(x)
574
-
575
-
576
- #define MAX_UCS2 0xFFFF
577
- #define DEFAULT_CHAR 0x003F /* Default char is "?" */
578
- #define BYTE_MASK 0xBF
579
- #define BYTE_MARK 0x80
580
-
581
-
582
- /* Function: one_ucs2_to_utf8_char
583
- *
584
- * Function takes one UCS-2 char and writes it to a UTF-8 buffer.
585
- * We need a UTF-8 buffer because we don't know before this
586
- * function how many bytes of utf-8 data will be written. It also
587
- * takes a pointer to the end of the UTF-8 buffer so that we don't
588
- * overwrite data. This function returns the number of UTF-8 bytes
589
- * of data written, or -1 if the buffer would have been overrun.
590
- */
591
-
592
- #define LINE_SEPARATOR 0x2028
593
- #define PARAGRAPH_SEPARATOR 0x2029
594
- static int16 one_ucs2_to_utf8_char(unsigned char *tobufp,
595
- unsigned char *tobufendp,
596
- uint16 onechar)
597
- {
598
- int16 numUTF8bytes = 0;
599
-
600
- if (onechar == LINE_SEPARATOR || onechar == PARAGRAPH_SEPARATOR) {
601
- strcpy((char*)tobufp, "\n");
602
- return strlen((char*)tobufp);
603
- }
604
-
605
- if (onechar < 0x80) {
606
- numUTF8bytes = 1;
607
- } else if (onechar < 0x800) {
608
- numUTF8bytes = 2;
609
- } else {
610
- /* 0x800 >= onechar <= MAX_UCS2 */
611
- numUTF8bytes = 3;
612
- }
613
-
614
- tobufp += numUTF8bytes;
615
-
616
- /* return error if we don't have space for the whole character */
617
- if (tobufp > tobufendp) {
618
- return(-1);
619
- }
620
-
621
- switch(numUTF8bytes) {
622
- case 3: *--tobufp = (onechar | BYTE_MARK) & BYTE_MASK; onechar >>=6;
623
- *--tobufp = (onechar | BYTE_MARK) & BYTE_MASK; onechar >>=6;
624
- *--tobufp = onechar | THREE_OCTET_BASE;
625
- break;
626
-
627
- case 2: *--tobufp = (onechar | BYTE_MARK) & BYTE_MASK; onechar >>=6;
628
- *--tobufp = onechar | TWO_OCTET_BASE;
629
- break;
630
-
631
- case 1: *--tobufp = (unsigned char)onechar;
632
- break;
633
- }
634
-
635
- return numUTF8bytes;
636
- }
637
-
638
- /*
639
- * utf8_to_ucs2_char
640
- *
641
- * Convert a utf8 multibyte character to ucs2
642
- *
643
- * inputs: pointer to utf8 character(s)
644
- * length of utf8 buffer ("read" length limit)
645
- * pointer to return ucs2 character
646
- *
647
- * outputs: number of bytes in the utf8 character
648
- * -1 if not a valid utf8 character sequence
649
- * -2 if the buffer is too short
650
- */
651
- static int16
652
- utf8_to_ucs2_char(const unsigned char *utf8p, int16 buflen, uint16 *ucs2p)
653
- {
654
- uint16 lead, cont1, cont2;
655
-
656
- /*
657
- * Check for minimum buffer length
658
- */
659
- if ((buflen < 1) || (utf8p == NULL)) {
660
- return -2;
661
- }
662
- lead = (uint16) (*utf8p);
663
-
664
- /*
665
- * Check for a one octet sequence
666
- */
667
- if (IS_UTF8_1ST_OF_1(lead)) {
668
- *ucs2p = lead & ONE_OCTET_MASK;
669
- return 1;
670
- }
671
-
672
- /*
673
- * Check for a two octet sequence
674
- */
675
- if (IS_UTF8_1ST_OF_2(*utf8p)) {
676
- if (buflen < 2)
677
- return -2;
678
- cont1 = (uint16) *(utf8p+1);
679
- if (!IS_UTF8_2ND_THRU_6TH(cont1))
680
- return -1;
681
- *ucs2p = (lead & TWO_OCTET_MASK) << 6;
682
- *ucs2p |= cont1 & CONTINUING_OCTET_MASK;
683
- return 2;
684
- }
685
-
686
- /*
687
- * Check for a three octet sequence
688
- */
689
- else if (IS_UTF8_1ST_OF_3(lead)) {
690
- if (buflen < 3)
691
- return -2;
692
- cont1 = (uint16) *(utf8p+1);
693
- cont2 = (uint16) *(utf8p+2);
694
- if ( (!IS_UTF8_2ND_THRU_6TH(cont1))
695
- || (!IS_UTF8_2ND_THRU_6TH(cont2)))
696
- return -1;
697
- *ucs2p = (lead & THREE_OCTET_MASK) << 12;
698
- *ucs2p |= (cont1 & CONTINUING_OCTET_MASK) << 6;
699
- *ucs2p |= cont2 & CONTINUING_OCTET_MASK;
700
- return 3;
701
- }
702
- else { /* not a valid utf8/ucs2 character */
703
- return -1;
704
- }
705
- }
706
-
707
- /* ----------------------------- Helper functions --------------------------- */
708
- /* Ripped off from lm_win.c .. */
709
- /* where is strcasecmp?.. for now, it's case sensitive..
710
- *
711
- * strcasecmp is in strings.h, but on windows it's called _stricmp...
712
- * will need to #ifdef this
713
- */
714
-
715
- static int32
716
- js_FileHasOption(JSContext *cx, const char *oldoptions, const char *name)
717
- {
718
- char *comma, *equal, *current;
719
- char *options = JS_strdup(cx, oldoptions);
720
- int32 found = 0;
721
-
722
- current = options;
723
- for (;;) {
724
- comma = strchr(current, ',');
725
- if (comma) *comma = '\0';
726
- equal = strchr(current, '=');
727
- if (equal) *equal = '\0';
728
- if (strcmp(current, name) == 0) {
729
- if (!equal || strcmp(equal + 1, "yes") == 0)
730
- found = 1;
731
- else
732
- found = atoi(equal + 1);
733
- }
734
- if (equal) *equal = '=';
735
- if (comma) *comma = ',';
736
- if (found || !comma)
737
- break;
738
- current = comma + 1;
739
- }
740
- JS_free(cx, options);
741
- return found;
742
- }
743
-
744
- /* empty the buffer */
745
- static void
746
- js_ResetBuffers(JSFile * file)
747
- {
748
- file->charBufferUsed = JS_FALSE;
749
- file->nbBytesInBuf = 0;
750
- }
751
-
752
- /* Reset file attributes */
753
- static void
754
- js_ResetAttributes(JSFile * file)
755
- {
756
- file->mode = file->type = 0;
757
- file->isOpen = JS_FALSE;
758
- file->handle = NULL;
759
- file->nativehandle = NULL;
760
- file->hasRandomAccess = JS_TRUE; /* Innocent until proven guilty. */
761
- file->hasAutoflush = JS_FALSE;
762
- file->isNative = JS_FALSE;
763
- file->isPipe = JS_FALSE;
764
-
765
- js_ResetBuffers(file);
766
- }
767
-
768
- static JSBool
769
- js_FileOpen(JSContext *cx, JSObject *obj, JSFile *file, char *mode){
770
- JSString *type, *mask;
771
- jsval v[2];
772
- jsval rval;
773
-
774
- type = JS_InternString(cx, asciistring);
775
- mask = JS_NewStringCopyZ(cx, mode);
776
- v[0] = STRING_TO_JSVAL(mask);
777
- v[1] = STRING_TO_JSVAL(type);
778
-
779
- if (!file_open(cx, obj, 2, v, &rval))
780
- return JS_FALSE;
781
- return JS_TRUE;
782
- }
783
-
784
- /* Buffered version of PR_Read. Used by js_FileRead */
785
- static int32
786
- js_BufferedRead(JSFile *f, unsigned char *buf, int32 len)
787
- {
788
- int32 count = 0;
789
-
790
- while (f->nbBytesInBuf>0&&len>0) {
791
- buf[0] = f->byteBuffer[0];
792
- f->byteBuffer[0] = f->byteBuffer[1];
793
- f->byteBuffer[1] = f->byteBuffer[2];
794
- f->nbBytesInBuf--;
795
- len--;
796
- buf+=1;
797
- count++;
798
- }
799
-
800
- if (len > 0) {
801
- count += (!f->isNative)
802
- ? PR_Read(f->handle, buf, len)
803
- : fread(buf, 1, len, f->nativehandle);
804
- }
805
- return count;
806
- }
807
-
808
- static int32
809
- js_FileRead(JSContext *cx, JSFile *file, jschar *buf, int32 len, int32 mode)
810
- {
811
- unsigned char *aux;
812
- int32 count = 0, i;
813
- jsint remainder;
814
- unsigned char utfbuf[3];
815
-
816
- if (file->charBufferUsed) {
817
- buf[0] = file->charBuffer;
818
- buf++;
819
- len--;
820
- file->charBufferUsed = JS_FALSE;
821
- }
822
-
823
- switch (mode) {
824
- case ASCII:
825
- aux = (unsigned char*)JS_malloc(cx, len);
826
- if (!aux)
827
- return 0;
828
-
829
- count = js_BufferedRead(file, aux, len);
830
- if (count == -1) {
831
- JS_free(cx, aux);
832
- return 0;
833
- }
834
-
835
- for (i = 0; i < len; i++)
836
- buf[i] = (jschar)aux[i];
837
-
838
- JS_free(cx, aux);
839
- break;
840
-
841
- case UTF8:
842
- remainder = 0;
843
- for (count = 0;count<len;count++) {
844
- i = js_BufferedRead(file, utfbuf+remainder, 3-remainder);
845
- if (i<=0) {
846
- return count;
847
- }
848
- i = utf8_to_ucs2_char(utfbuf, (int16)i, &buf[count] );
849
- if (i<0) {
850
- return count;
851
- } else {
852
- if (i==1) {
853
- utfbuf[0] = utfbuf[1];
854
- utfbuf[1] = utfbuf[2];
855
- remainder = 2;
856
- } else if (i==2) {
857
- utfbuf[0] = utfbuf[2];
858
- remainder = 1;
859
- } else if (i==3) {
860
- remainder = 0;
861
- }
862
- }
863
- }
864
- while (remainder>0) {
865
- file->byteBuffer[file->nbBytesInBuf] = utfbuf[0];
866
- file->nbBytesInBuf++;
867
- utfbuf[0] = utfbuf[1];
868
- utfbuf[1] = utfbuf[2];
869
- remainder--;
870
- }
871
- break;
872
-
873
- case UCS2:
874
- count = js_BufferedRead(file, (unsigned char *)buf, len * 2) >> 1;
875
- if (count == -1)
876
- return 0;
877
-
878
- break;
879
-
880
- default:
881
- /* Not reached. */
882
- JS_ASSERT(0);
883
- }
884
-
885
- if(count == -1) {
886
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
887
- JSFILEMSG_OP_FAILED, "read", file->path);
888
- }
889
-
890
- return count;
891
- }
892
-
893
- static int32
894
- js_FileSeek(JSContext *cx, JSFile *file, int32 len, int32 mode)
895
- {
896
- int32 count = 0, i;
897
- jsint remainder;
898
- unsigned char utfbuf[3];
899
- jschar tmp;
900
-
901
- switch (mode) {
902
- case ASCII:
903
- count = PR_Seek(file->handle, len, PR_SEEK_CUR);
904
- break;
905
-
906
- case UTF8:
907
- remainder = 0;
908
- for (count = 0;count<len;count++) {
909
- i = js_BufferedRead(file, utfbuf+remainder, 3-remainder);
910
- if (i<=0) {
911
- return 0;
912
- }
913
- i = utf8_to_ucs2_char(utfbuf, (int16)i, &tmp );
914
- if (i<0) {
915
- return 0;
916
- } else {
917
- if (i==1) {
918
- utfbuf[0] = utfbuf[1];
919
- utfbuf[1] = utfbuf[2];
920
- remainder = 2;
921
- } else if (i==2) {
922
- utfbuf[0] = utfbuf[2];
923
- remainder = 1;
924
- } else if (i==3) {
925
- remainder = 0;
926
- }
927
- }
928
- }
929
- while (remainder>0) {
930
- file->byteBuffer[file->nbBytesInBuf] = utfbuf[0];
931
- file->nbBytesInBuf++;
932
- utfbuf[0] = utfbuf[1];
933
- utfbuf[1] = utfbuf[2];
934
- remainder--;
935
- }
936
- break;
937
-
938
- case UCS2:
939
- count = PR_Seek(file->handle, len*2, PR_SEEK_CUR)/2;
940
- break;
941
-
942
- default:
943
- /* Not reached. */
944
- JS_ASSERT(0);
945
- }
946
-
947
- if(count == -1) {
948
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
949
- JSFILEMSG_OP_FAILED, "seek", file->path);
950
- }
951
-
952
- return count;
953
- }
954
-
955
- static int32
956
- js_FileWrite(JSContext *cx, JSFile *file, jschar *buf, int32 len, int32 mode)
957
- {
958
- unsigned char *aux;
959
- int32 count = 0, i, j;
960
- unsigned char *utfbuf;
961
-
962
- switch (mode) {
963
- case ASCII:
964
- aux = (unsigned char*)JS_malloc(cx, len);
965
- if (!aux)
966
- return 0;
967
-
968
- for (i = 0; i<len; i++)
969
- aux[i] = buf[i] % 256;
970
-
971
- count = (!file->isNative)
972
- ? PR_Write(file->handle, aux, len)
973
- : fwrite(aux, 1, len, file->nativehandle);
974
-
975
- if (count==-1) {
976
- JS_free(cx, aux);
977
- return 0;
978
- }
979
-
980
- JS_free(cx, aux);
981
- break;
982
-
983
- case UTF8:
984
- utfbuf = (unsigned char*)JS_malloc(cx, len*3);
985
- if (!utfbuf) return 0;
986
- i = 0;
987
- for (count = 0;count<len;count++) {
988
- j = one_ucs2_to_utf8_char(utfbuf+i, utfbuf+len*3, buf[count]);
989
- if (j==-1) {
990
- JS_free(cx, utfbuf);
991
- return 0;
992
- }
993
- i+=j;
994
- }
995
- j = (!file->isNative)
996
- ? PR_Write(file->handle, utfbuf, i)
997
- : fwrite(utfbuf, 1, i, file->nativehandle);
998
-
999
- if (j<i) {
1000
- JS_free(cx, utfbuf);
1001
- return 0;
1002
- }
1003
- JS_free(cx, utfbuf);
1004
- break;
1005
-
1006
- case UCS2:
1007
- count = (!file->isNative)
1008
- ? PR_Write(file->handle, buf, len*2) >> 1
1009
- : fwrite(buf, 1, len*2, file->nativehandle) >> 1;
1010
-
1011
- if (count == -1)
1012
- return 0;
1013
- break;
1014
-
1015
- default:
1016
- /* Not reached. */
1017
- JS_ASSERT(0);
1018
- }
1019
-
1020
- if(count == -1) {
1021
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
1022
- JSFILEMSG_OP_FAILED, "write", file->path);
1023
- }
1024
-
1025
- return count;
1026
- }
1027
-
1028
- /* ----------------------------- Property checkers -------------------------- */
1029
- static JSBool
1030
- js_exists(JSContext *cx, JSFile *file)
1031
- {
1032
- if (file->isNative) {
1033
- /* It doesn't make sense for a pipe of stdstream. */
1034
- return JS_FALSE;
1035
- }
1036
-
1037
- return PR_Access(file->path, PR_ACCESS_EXISTS) == PR_SUCCESS;
1038
- }
1039
-
1040
- static JSBool
1041
- js_canRead(JSContext *cx, JSFile *file)
1042
- {
1043
- if (!file->isNative) {
1044
- if (file->isOpen && !(file->mode & PR_RDONLY))
1045
- return JS_FALSE;
1046
- return PR_Access(file->path, PR_ACCESS_READ_OK) == PR_SUCCESS;
1047
- }
1048
-
1049
- if (file->isPipe) {
1050
- /* Is this pipe open for reading? */
1051
- return file->path[0] == PIPE_SYMBOL;
1052
- }
1053
-
1054
- return !strcmp(file->path, STDINPUT_NAME);
1055
- }
1056
-
1057
- static JSBool
1058
- js_canWrite(JSContext *cx, JSFile *file)
1059
- {
1060
- if (!file->isNative) {
1061
- if (file->isOpen && !(file->mode & PR_WRONLY))
1062
- return JS_FALSE;
1063
- return PR_Access(file->path, PR_ACCESS_WRITE_OK) == PR_SUCCESS;
1064
- }
1065
-
1066
- if(file->isPipe) {
1067
- /* Is this pipe open for writing? */
1068
- return file->path[strlen(file->path)-1] == PIPE_SYMBOL;
1069
- }
1070
-
1071
- return !strcmp(file->path, STDOUTPUT_NAME) ||
1072
- !strcmp(file->path, STDERROR_NAME);
1073
- }
1074
-
1075
- static JSBool
1076
- js_isFile(JSContext *cx, JSFile *file)
1077
- {
1078
- if (!file->isNative) {
1079
- PRFileInfo info;
1080
-
1081
- if (file->isOpen
1082
- ? PR_GetOpenFileInfo(file->handle, &info)
1083
- : PR_GetFileInfo(file->path, &info) != PR_SUCCESS) {
1084
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
1085
- JSFILEMSG_CANNOT_ACCESS_FILE_STATUS, file->path);
1086
- return JS_FALSE;
1087
- }
1088
-
1089
- return info.type == PR_FILE_FILE;
1090
- }
1091
-
1092
- /* This doesn't make sense for a pipe of stdstream. */
1093
- return JS_FALSE;
1094
- }
1095
-
1096
- static JSBool
1097
- js_isDirectory(JSContext *cx, JSFile *file)
1098
- {
1099
- if(!file->isNative){
1100
- PRFileInfo info;
1101
-
1102
- /* Hack needed to get get_property to work. */
1103
- if (!js_exists(cx, file))
1104
- return JS_FALSE;
1105
-
1106
- if (file->isOpen
1107
- ? PR_GetOpenFileInfo(file->handle, &info)
1108
- : PR_GetFileInfo(file->path, &info) != PR_SUCCESS) {
1109
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
1110
- JSFILEMSG_CANNOT_ACCESS_FILE_STATUS, file->path);
1111
- return JS_FALSE;
1112
- }
1113
-
1114
- return info.type == PR_FILE_DIRECTORY;
1115
- }
1116
-
1117
- /* This doesn't make sense for a pipe of stdstream. */
1118
- return JS_FALSE;
1119
- }
1120
-
1121
- static jsval
1122
- js_size(JSContext *cx, JSFile *file)
1123
- {
1124
- PRFileInfo info;
1125
-
1126
- JSFILE_CHECK_NATIVE("size");
1127
-
1128
- if (file->isOpen
1129
- ? PR_GetOpenFileInfo(file->handle, &info)
1130
- : PR_GetFileInfo(file->path, &info) != PR_SUCCESS) {
1131
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
1132
- JSFILEMSG_CANNOT_ACCESS_FILE_STATUS, file->path);
1133
- return JSVAL_VOID;
1134
- }
1135
-
1136
- return INT_TO_JSVAL(info.size);
1137
-
1138
- out:
1139
- return JSVAL_VOID;
1140
- }
1141
-
1142
- /*
1143
- * Return the parent object
1144
- */
1145
- static JSBool
1146
- js_parent(JSContext *cx, JSFile *file, jsval *resultp)
1147
- {
1148
- char *str;
1149
-
1150
- /* Since we only care about pipes and native files, return NULL. */
1151
- if (file->isNative) {
1152
- *resultp = JSVAL_VOID;
1153
- return JS_TRUE;
1154
- }
1155
-
1156
- str = js_fileDirectoryName(cx, file->path);
1157
- if (!str)
1158
- return JS_FALSE;
1159
-
1160
- /* If the directory is equal to the original path, we're at the root. */
1161
- if (!strcmp(file->path, str)) {
1162
- *resultp = JSVAL_NULL;
1163
- } else {
1164
- JSObject *obj = js_NewFileObject(cx, str);
1165
- if (!obj) {
1166
- JS_free(cx, str);
1167
- return JS_FALSE;
1168
- }
1169
- *resultp = OBJECT_TO_JSVAL(obj);
1170
- }
1171
-
1172
- JS_free(cx, str);
1173
- return JS_TRUE;
1174
- }
1175
-
1176
- static JSBool
1177
- js_name(JSContext *cx, JSFile *file, jsval *vp)
1178
- {
1179
- char *name;
1180
- JSString *str;
1181
-
1182
- if (file->isPipe) {
1183
- *vp = JSVAL_VOID;
1184
- return JS_TRUE;
1185
- }
1186
-
1187
- name = js_fileBaseName(cx, file->path);
1188
- if (!name)
1189
- return JS_FALSE;
1190
-
1191
- str = JS_NewString(cx, name, strlen(name));
1192
- if (!str) {
1193
- JS_free(cx, name);
1194
- return JS_FALSE;
1195
- }
1196
-
1197
- *vp = STRING_TO_JSVAL(str);
1198
- return JS_TRUE;
1199
- }
1200
-
1201
- /* ------------------------------ File object methods ---------------------------- */
1202
- static JSBool
1203
- file_open(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1204
- {
1205
- JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
1206
- JSString *strmode, *strtype;
1207
- char *ctype, *mode;
1208
- int32 mask, type;
1209
- int len;
1210
-
1211
- mode = NULL;
1212
-
1213
- SECURITY_CHECK(cx, NULL, "open", file);
1214
-
1215
- /* A native file that is already open */
1216
- if(file->isOpen && file->isNative) {
1217
- JS_ReportWarning(cx, "Native file %s is already open, proceeding",
1218
- file->path);
1219
- goto good;
1220
- }
1221
-
1222
- /* Close before proceeding */
1223
- if (file->isOpen) {
1224
- JS_ReportWarning(cx, "File %s is already open, we will close it and "
1225
- "reopen, proceeding", file->path);
1226
- if(!file_close(cx, obj, 0, NULL, rval))
1227
- goto out;
1228
- }
1229
-
1230
- if (js_isDirectory(cx, file)) {
1231
- JS_ReportWarning(cx, "%s seems to be a directory, there is no point in "
1232
- "trying to open it, proceeding", file->path);
1233
- goto good;
1234
- }
1235
-
1236
- /* Path must be defined at this point */
1237
- len = strlen(file->path);
1238
-
1239
- /* Mode */
1240
- if (argc >= 1) {
1241
- strmode = JS_ValueToString(cx, argv[0]);
1242
- if (!strmode) {
1243
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
1244
- JSFILEMSG_FIRST_ARGUMENT_OPEN_NOT_STRING_ERROR,
1245
- argv[0]);
1246
- goto out;
1247
- }
1248
- mode = JS_strdup(cx, JS_GetStringBytes(strmode));
1249
- } else {
1250
- if(file->path[0]==PIPE_SYMBOL) {
1251
- /* pipe default mode */
1252
- mode = JS_strdup(cx, "read");
1253
- } else if(file->path[len-1]==PIPE_SYMBOL) {
1254
- /* pipe default mode */
1255
- mode = JS_strdup(cx, "write");
1256
- } else {
1257
- /* non-destructive, permissive defaults. */
1258
- mode = JS_strdup(cx, "readWrite,append,create");
1259
- }
1260
- }
1261
-
1262
- /* Process the mode */
1263
- mask = 0;
1264
- /* TODO: this is pretty ugly, we walk thru the string too many times */
1265
- mask |= js_FileHasOption(cx, mode, "read") ? PR_RDONLY : 0;
1266
- mask |= js_FileHasOption(cx, mode, "write") ? PR_WRONLY : 0;
1267
- mask |= js_FileHasOption(cx, mode, "readWrite")? PR_RDWR : 0;
1268
- mask |= js_FileHasOption(cx, mode, "append") ? PR_APPEND : 0;
1269
- mask |= js_FileHasOption(cx, mode, "create") ? PR_CREATE_FILE : 0;
1270
- mask |= js_FileHasOption(cx, mode, "replace") ? PR_TRUNCATE : 0;
1271
-
1272
- if (mask & PR_RDWR)
1273
- mask |= (PR_RDONLY | PR_WRONLY);
1274
- if ((mask & PR_RDONLY) && (mask & PR_WRONLY))
1275
- mask |= PR_RDWR;
1276
-
1277
- file->hasAutoflush |= js_FileHasOption(cx, mode, "autoflush");
1278
-
1279
- /* Type */
1280
- if (argc > 1) {
1281
- strtype = JS_ValueToString(cx, argv[1]);
1282
- if (!strtype) {
1283
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
1284
- JSFILEMSG_SECOND_ARGUMENT_OPEN_NOT_STRING_ERROR,
1285
- argv[1]);
1286
- goto out;
1287
- }
1288
- ctype = JS_GetStringBytes(strtype);
1289
-
1290
- if(!strcmp(ctype, utfstring)) {
1291
- type = UTF8;
1292
- } else if (!strcmp(ctype, unicodestring)) {
1293
- type = UCS2;
1294
- } else {
1295
- if (strcmp(ctype, asciistring)) {
1296
- JS_ReportWarning(cx, "File type %s is not supported, using "
1297
- "'text' instead, proceeding", ctype);
1298
- }
1299
- type = ASCII;
1300
- }
1301
- } else {
1302
- type = ASCII;
1303
- }
1304
-
1305
- /* Save the relevant fields */
1306
- file->type = type;
1307
- file->mode = mask;
1308
- file->nativehandle = NULL;
1309
- file->hasRandomAccess = (type != UTF8);
1310
-
1311
- /*
1312
- * Deal with pipes here. We can't use NSPR for pipes, so we have to use
1313
- * POPEN.
1314
- */
1315
- if (file->path[0]==PIPE_SYMBOL || file->path[len-1]==PIPE_SYMBOL) {
1316
- if (file->path[0] == PIPE_SYMBOL && file->path[len-1] == PIPE_SYMBOL) {
1317
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
1318
- JSFILEMSG_BIDIRECTIONAL_PIPE_NOT_SUPPORTED);
1319
- goto out;
1320
- } else {
1321
- int i = 0;
1322
- char pipemode[3];
1323
- SECURITY_CHECK(cx, NULL, "pipe_open", file);
1324
-
1325
- if(file->path[0] == PIPE_SYMBOL){
1326
- if(mask & (PR_WRONLY | PR_APPEND | PR_CREATE_FILE | PR_TRUNCATE)){
1327
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
1328
- JSFILEMSG_OPEN_MODE_NOT_SUPPORTED_WITH_PIPES,
1329
- mode, file->path);
1330
- goto out;
1331
- }
1332
- /* open(SPOOLER, "| cat -v | lpr -h 2>/dev/null") -- pipe for writing */
1333
- pipemode[i++] = 'r';
1334
- #ifndef XP_UNIX
1335
- pipemode[i++] = file->type==UTF8 ? 'b' : 't';
1336
- #endif
1337
- pipemode[i++] = '\0';
1338
- file->nativehandle = POPEN(&file->path[1], pipemode);
1339
- } else if(file->path[len-1] == PIPE_SYMBOL) {
1340
- char *command = JS_malloc(cx, len);
1341
-
1342
- strncpy(command, file->path, len-1);
1343
- command[len-1] = '\0';
1344
- /* open(STATUS, "netstat -an 2>&1 |") */
1345
- pipemode[i++] = 'w';
1346
- #ifndef XP_UNIX
1347
- pipemode[i++] = file->type==UTF8 ? 'b' : 't';
1348
- #endif
1349
- pipemode[i++] = '\0';
1350
- file->nativehandle = POPEN(command, pipemode);
1351
- JS_free(cx, command);
1352
- }
1353
- /* set the flags */
1354
- file->isNative = JS_TRUE;
1355
- file->isPipe = JS_TRUE;
1356
- file->hasRandomAccess = JS_FALSE;
1357
- }
1358
- } else {
1359
- /* TODO: what about the permissions?? Java ignores the problem... */
1360
- file->handle = PR_Open(file->path, mask, 0644);
1361
- }
1362
-
1363
- js_ResetBuffers(file);
1364
- JS_free(cx, mode);
1365
- mode = NULL;
1366
-
1367
- /* Set the open flag and return result */
1368
- if (file->handle == NULL && file->nativehandle == NULL) {
1369
- file->isOpen = JS_FALSE;
1370
-
1371
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
1372
- JSFILEMSG_OP_FAILED, "open", file->path);
1373
- goto out;
1374
- }
1375
-
1376
- good:
1377
- file->isOpen = JS_TRUE;
1378
- *rval = JSVAL_TRUE;
1379
- return JS_TRUE;
1380
-
1381
- out:
1382
- if(mode)
1383
- JS_free(cx, mode);
1384
- return JS_FALSE;
1385
- }
1386
-
1387
- static JSBool
1388
- file_close(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1389
- {
1390
- JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
1391
-
1392
- SECURITY_CHECK(cx, NULL, "close", file);
1393
-
1394
- if(!file->isOpen){
1395
- JS_ReportWarning(cx, "File %s is not open, can't close it, proceeding",
1396
- file->path);
1397
- goto out;
1398
- }
1399
-
1400
- if(!file->isPipe){
1401
- if(file->isNative){
1402
- JS_ReportWarning(cx, "Unable to close a native file, proceeding", file->path);
1403
- goto out;
1404
- }else{
1405
- if(file->handle && PR_Close(file->handle)){
1406
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
1407
- JSFILEMSG_OP_FAILED, "close", file->path);
1408
-
1409
- goto out;
1410
- }
1411
- }
1412
- }else{
1413
- if(PCLOSE(file->nativehandle)==-1){
1414
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
1415
- JSFILEMSG_OP_FAILED, "pclose", file->path);
1416
- goto out;
1417
- }
1418
- }
1419
-
1420
- js_ResetAttributes(file);
1421
- *rval = JSVAL_TRUE;
1422
- return JS_TRUE;
1423
-
1424
- out:
1425
- return JS_FALSE;
1426
- }
1427
-
1428
-
1429
- static JSBool
1430
- file_remove(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1431
- {
1432
- JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
1433
-
1434
- SECURITY_CHECK(cx, NULL, "remove", file);
1435
- JSFILE_CHECK_NATIVE("remove");
1436
- JSFILE_CHECK_CLOSED("remove");
1437
-
1438
- if ((js_isDirectory(cx, file) ?
1439
- PR_RmDir(file->path) : PR_Delete(file->path))==PR_SUCCESS) {
1440
- js_ResetAttributes(file);
1441
- *rval = JSVAL_TRUE;
1442
- return JS_TRUE;
1443
- } else {
1444
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
1445
- JSFILEMSG_OP_FAILED, "remove", file->path);
1446
- goto out;
1447
- }
1448
- out:
1449
- *rval = JSVAL_FALSE;
1450
- return JS_FALSE;
1451
- }
1452
-
1453
- /* Raw PR-based function. No text processing. Just raw data copying. */
1454
- static JSBool
1455
- file_copyTo(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1456
- {
1457
- JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
1458
- char *dest = NULL;
1459
- PRFileDesc *handle = NULL;
1460
- char *buffer;
1461
- jsval count, size;
1462
- JSBool fileInitiallyOpen=JS_FALSE;
1463
-
1464
- SECURITY_CHECK(cx, NULL, "copyTo", file); /* may need a second argument!*/
1465
- JSFILE_CHECK_ONE_ARG("copyTo");
1466
- JSFILE_CHECK_NATIVE("copyTo");
1467
- /* remeber the state */
1468
- fileInitiallyOpen = file->isOpen;
1469
- JSFILE_CHECK_READ;
1470
-
1471
- dest = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
1472
-
1473
- /* make sure we are not reading a file open for writing */
1474
- if (file->isOpen && !js_canRead(cx, file)) {
1475
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
1476
- JSFILEMSG_CANNOT_COPY_FILE_OPEN_FOR_WRITING_ERROR, file->path);
1477
- goto out;
1478
- }
1479
-
1480
- if (file->handle==NULL){
1481
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
1482
- JSFILEMSG_OP_FAILED, "open", file->path);
1483
- goto out;
1484
- }
1485
-
1486
- handle = PR_Open(dest, PR_WRONLY|PR_CREATE_FILE|PR_TRUNCATE, 0644);
1487
-
1488
- if(!handle){
1489
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
1490
- JSFILEMSG_OP_FAILED, "open", dest);
1491
- goto out;
1492
- }
1493
-
1494
- if ((size=js_size(cx, file))==JSVAL_VOID) {
1495
- goto out;
1496
- }
1497
-
1498
- buffer = JS_malloc(cx, size);
1499
-
1500
- count = INT_TO_JSVAL(PR_Read(file->handle, buffer, size));
1501
-
1502
- /* reading panic */
1503
- if (count!=size) {
1504
- JS_free(cx, buffer);
1505
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
1506
- JSFILEMSG_COPY_READ_ERROR, file->path);
1507
- goto out;
1508
- }
1509
-
1510
- count = INT_TO_JSVAL(PR_Write(handle, buffer, JSVAL_TO_INT(size)));
1511
-
1512
- /* writing panic */
1513
- if (count!=size) {
1514
- JS_free(cx, buffer);
1515
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
1516
- JSFILEMSG_COPY_WRITE_ERROR, file->path);
1517
- goto out;
1518
- }
1519
-
1520
- JS_free(cx, buffer);
1521
-
1522
- if(!fileInitiallyOpen){
1523
- if(!file_close(cx, obj, 0, NULL, rval)) goto out;
1524
- }
1525
-
1526
- if(PR_Close(handle)!=PR_SUCCESS){
1527
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
1528
- JSFILEMSG_OP_FAILED, "close", dest);
1529
- goto out;
1530
- }
1531
-
1532
- *rval = JSVAL_TRUE;
1533
- return JS_TRUE;
1534
- out:
1535
- if(file->isOpen && !fileInitiallyOpen){
1536
- if(PR_Close(file->handle)!=PR_SUCCESS){
1537
- JS_ReportWarning(cx, "Can't close %s, proceeding", file->path);
1538
- }
1539
- }
1540
-
1541
- if(handle && PR_Close(handle)!=PR_SUCCESS){
1542
- JS_ReportWarning(cx, "Can't close %s, proceeding", dest);
1543
- }
1544
-
1545
- *rval = JSVAL_FALSE;
1546
- return JS_FALSE;
1547
- }
1548
-
1549
- static JSBool
1550
- file_renameTo(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1551
- {
1552
- JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
1553
- char *dest;
1554
-
1555
- SECURITY_CHECK(cx, NULL, "renameTo", file); /* may need a second argument!*/
1556
- JSFILE_CHECK_ONE_ARG("renameTo");
1557
- JSFILE_CHECK_NATIVE("renameTo");
1558
- JSFILE_CHECK_CLOSED("renameTo");
1559
-
1560
- dest = RESOLVE_PATH(cx, JS_GetStringBytes(JS_ValueToString(cx, argv[0])));
1561
-
1562
- if (PR_Rename(file->path, dest)==PR_SUCCESS){
1563
- /* copy the new filename */
1564
- JS_free(cx, file->path);
1565
- file->path = dest;
1566
- *rval = JSVAL_TRUE;
1567
- return JS_TRUE;
1568
- }else{
1569
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
1570
- JSFILEMSG_RENAME_FAILED, file->path, dest);
1571
- goto out;
1572
- }
1573
- out:
1574
- *rval = JSVAL_FALSE;
1575
- return JS_FALSE;
1576
- }
1577
-
1578
- static JSBool
1579
- file_flush(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1580
- {
1581
- JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
1582
-
1583
- SECURITY_CHECK(cx, NULL, "flush", file);
1584
- JSFILE_CHECK_NATIVE("flush");
1585
- JSFILE_CHECK_OPEN("flush");
1586
-
1587
- if (PR_Sync(file->handle)==PR_SUCCESS){
1588
- *rval = JSVAL_TRUE;
1589
- return JS_TRUE;
1590
- }else{
1591
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
1592
- JSFILEMSG_OP_FAILED, "flush", file->path);
1593
- goto out;
1594
- }
1595
- out:
1596
- *rval = JSVAL_FALSE;
1597
- return JS_FALSE;
1598
- }
1599
-
1600
- static JSBool
1601
- file_write(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1602
- {
1603
- JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
1604
- JSString *str;
1605
- int32 count;
1606
- uintN i;
1607
-
1608
- SECURITY_CHECK(cx, NULL, "write", file);
1609
- JSFILE_CHECK_WRITE;
1610
-
1611
- for (i = 0; i<argc; i++) {
1612
- str = JS_ValueToString(cx, argv[i]);
1613
- count = js_FileWrite(cx, file, JS_GetStringChars(str),
1614
- JS_GetStringLength(str), file->type);
1615
- if (count==-1){
1616
- *rval = JSVAL_FALSE;
1617
- return JS_FALSE;
1618
- }
1619
- }
1620
-
1621
- *rval = JSVAL_TRUE;
1622
- return JS_TRUE;
1623
- out:
1624
- *rval = JSVAL_FALSE;
1625
- return JS_FALSE;
1626
- }
1627
-
1628
- static JSBool
1629
- file_writeln(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1630
- {
1631
- JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
1632
- JSString *str;
1633
-
1634
- SECURITY_CHECK(cx, NULL, "writeln", file);
1635
- JSFILE_CHECK_WRITE;
1636
-
1637
- /* don't report an error here */
1638
- if(!file_write(cx, obj, argc, argv, rval)) return JS_FALSE;
1639
- /* don't do security here -- we passed the check in file_write */
1640
- str = JS_NewStringCopyZ(cx, "\n");
1641
-
1642
- if (js_FileWrite(cx, file, JS_GetStringChars(str), JS_GetStringLength(str),
1643
- file->type)==-1){
1644
- *rval = JSVAL_FALSE;
1645
- return JS_FALSE;
1646
- }
1647
-
1648
- /* eol causes flush if hasAutoflush is turned on */
1649
- if (file->hasAutoflush)
1650
- file_flush(cx, obj, 0, NULL, rval);
1651
-
1652
- *rval = JSVAL_TRUE;
1653
- return JS_TRUE;
1654
- out:
1655
- *rval = JSVAL_FALSE;
1656
- return JS_FALSE;
1657
- }
1658
-
1659
- static JSBool
1660
- file_writeAll(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1661
- {
1662
- JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
1663
- jsuint i;
1664
- jsuint limit;
1665
- JSObject *array;
1666
- JSObject *elem;
1667
- jsval elemval;
1668
-
1669
- SECURITY_CHECK(cx, NULL, "writeAll", file);
1670
- JSFILE_CHECK_ONE_ARG("writeAll");
1671
- JSFILE_CHECK_WRITE;
1672
-
1673
- if (!JS_IsArrayObject(cx, JSVAL_TO_OBJECT(argv[0]))) {
1674
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
1675
- JSFILEMSG_FIRST_ARGUMENT_WRITEALL_NOT_ARRAY_ERROR);
1676
- goto out;
1677
- }
1678
-
1679
- array = JSVAL_TO_OBJECT(argv[0]);
1680
-
1681
- JS_GetArrayLength(cx, array, &limit);
1682
-
1683
- for (i = 0; i<limit; i++) {
1684
- if (!JS_GetElement(cx, array, i, &elemval)) return JS_FALSE;
1685
- elem = JSVAL_TO_OBJECT(elemval);
1686
- file_writeln(cx, obj, 1, &elemval, rval);
1687
- }
1688
-
1689
- *rval = JSVAL_TRUE;
1690
- return JS_TRUE;
1691
- out:
1692
- *rval = JSVAL_FALSE;
1693
- return JS_FALSE;
1694
- }
1695
-
1696
- static JSBool
1697
- file_read(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1698
- {
1699
- JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
1700
- JSString *str;
1701
- int32 want, count;
1702
- jschar *buf;
1703
-
1704
- SECURITY_CHECK(cx, NULL, "read", file);
1705
- JSFILE_CHECK_ONE_ARG("read");
1706
- JSFILE_CHECK_READ;
1707
-
1708
- if (!JS_ValueToInt32(cx, argv[0], &want)){
1709
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
1710
- JSFILEMSG_FIRST_ARGUMENT_MUST_BE_A_NUMBER, "read", argv[0]);
1711
- goto out;
1712
- }
1713
-
1714
- /* want = (want>262144)?262144:want; * arbitrary size limitation */
1715
-
1716
- buf = JS_malloc(cx, want*sizeof buf[0]);
1717
- if (!buf) goto out;
1718
-
1719
- count = js_FileRead(cx, file, buf, want, file->type);
1720
- if (count>0) {
1721
- str = JS_NewUCStringCopyN(cx, buf, count);
1722
- *rval = STRING_TO_JSVAL(str);
1723
- JS_free(cx, buf);
1724
- return JS_TRUE;
1725
- } else {
1726
- JS_free(cx, buf);
1727
- goto out;
1728
- }
1729
- out:
1730
- *rval = JSVAL_FALSE;
1731
- return JS_FALSE;
1732
- }
1733
-
1734
- static JSBool
1735
- file_readln(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1736
- {
1737
- JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
1738
- JSString *str;
1739
- jschar *buf = NULL, *tmp;
1740
- int32 offset, read;
1741
- intN room;
1742
- jschar data, data2;
1743
-
1744
- SECURITY_CHECK(cx, NULL, "readln", file);
1745
- JSFILE_CHECK_READ;
1746
-
1747
- buf = JS_malloc(cx, MAX_LINE_LENGTH * sizeof data);
1748
- if (!buf)
1749
- return JS_FALSE;
1750
-
1751
- room = MAX_LINE_LENGTH - 1;
1752
- offset = 0;
1753
-
1754
- for (;;) {
1755
- read = js_FileRead(cx, file, &data, 1, file->type);
1756
- if (read < 0)
1757
- goto out;
1758
- if (read == 0)
1759
- goto eof;
1760
-
1761
- switch (data) {
1762
- case '\r':
1763
- read = js_FileRead(cx, file, &data2, 1, file->type);
1764
- if (read < 0)
1765
- goto out;
1766
-
1767
- if (read == 1 && data2 != '\n') {
1768
- /* We read one char too far. Buffer it. */
1769
- file->charBuffer = data2;
1770
- file->charBufferUsed = JS_TRUE;
1771
- }
1772
-
1773
- /* Fall through. */
1774
- case '\n':
1775
- goto done;
1776
-
1777
- default:
1778
- if (--room < 0) {
1779
- tmp = JS_realloc(cx, buf,
1780
- (offset + MAX_LINE_LENGTH) * sizeof data);
1781
- if (!tmp)
1782
- goto out;
1783
-
1784
- room = MAX_LINE_LENGTH - 1;
1785
- buf = tmp;
1786
- }
1787
-
1788
- buf[offset++] = data;
1789
- break;
1790
- }
1791
- }
1792
-
1793
- eof:
1794
- if (offset == 0) {
1795
- *rval = JSVAL_NULL;
1796
- return JS_TRUE;
1797
- }
1798
-
1799
- done:
1800
- buf[offset] = 0;
1801
- tmp = JS_realloc(cx, buf, (offset + 1) * sizeof data);
1802
- if (!tmp)
1803
- goto out;
1804
-
1805
- str = JS_NewUCString(cx, tmp, offset);
1806
- if (!str)
1807
- goto out;
1808
-
1809
- *rval = STRING_TO_JSVAL(str);
1810
- return JS_TRUE;
1811
-
1812
- out:
1813
- if (buf)
1814
- JS_free(cx, buf);
1815
-
1816
- return JS_FALSE;
1817
- }
1818
-
1819
- static JSBool
1820
- file_readAll(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1821
- {
1822
- JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
1823
- JSObject *array;
1824
- jsint len;
1825
- jsval line;
1826
- JSBool lineok = JS_FALSE;
1827
-
1828
- SECURITY_CHECK(cx, NULL, "readAll", file);
1829
- JSFILE_CHECK_READ;
1830
-
1831
- array = JS_NewArrayObject(cx, 0, NULL);
1832
- if (!array)
1833
- return JS_FALSE;
1834
- *rval = OBJECT_TO_JSVAL(array);
1835
-
1836
- len = 0;
1837
-
1838
- lineok = file_readln(cx, obj, 0, NULL, &line);
1839
- while (lineok && !JSVAL_IS_NULL(line)) {
1840
- JS_SetElement(cx, array, len++, &line);
1841
- lineok = file_readln(cx, obj, 0, NULL, &line);
1842
- }
1843
-
1844
- out:
1845
- return lineok;
1846
- }
1847
-
1848
- static JSBool
1849
- file_seek(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1850
- {
1851
- JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
1852
- int32 toskip;
1853
- int32 pos;
1854
-
1855
- SECURITY_CHECK(cx, NULL, "seek", file);
1856
- JSFILE_CHECK_ONE_ARG("seek");
1857
- JSFILE_CHECK_NATIVE("seek");
1858
- JSFILE_CHECK_READ;
1859
-
1860
- if (!JS_ValueToInt32(cx, argv[0], &toskip)){
1861
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
1862
- JSFILEMSG_FIRST_ARGUMENT_MUST_BE_A_NUMBER, "seek", argv[0]);
1863
- goto out;
1864
- }
1865
-
1866
- if(!file->hasRandomAccess){
1867
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
1868
- JSFILEMSG_NO_RANDOM_ACCESS, file->path);
1869
- goto out;
1870
- }
1871
-
1872
- if(js_isDirectory(cx, file)){
1873
- JS_ReportWarning(cx,"Seek on directories is not supported, proceeding");
1874
- goto out;
1875
- }
1876
-
1877
- pos = js_FileSeek(cx, file, toskip, file->type);
1878
-
1879
- if (pos!=-1) {
1880
- *rval = INT_TO_JSVAL(pos);
1881
- return JS_TRUE;
1882
- }
1883
- out:
1884
- *rval = JSVAL_VOID;
1885
- return JS_FALSE;
1886
- }
1887
-
1888
- static JSBool
1889
- file_list(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1890
- {
1891
- PRDir *dir;
1892
- PRDirEntry *entry;
1893
- JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
1894
- JSObject *array;
1895
- JSObject *eachFile;
1896
- jsint len;
1897
- jsval v;
1898
- JSRegExp *re = NULL;
1899
- JSFunction *func = NULL;
1900
- JSString *str;
1901
- jsval args[1];
1902
- char *filePath;
1903
-
1904
- SECURITY_CHECK(cx, NULL, "list", file);
1905
- JSFILE_CHECK_NATIVE("list");
1906
-
1907
- if (argc==1) {
1908
- if (JSVAL_IS_REGEXP(cx, argv[0])) {
1909
- re = JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
1910
- }else
1911
- if (VALUE_IS_FUNCTION(cx, argv[0])) {
1912
- func = JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
1913
- }else{
1914
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
1915
- JSFILEMSG_FIRST_ARGUMENT_MUST_BE_A_FUNCTION_OR_REGEX, argv[0]);
1916
- goto out;
1917
- }
1918
- }
1919
-
1920
- if (!js_isDirectory(cx, file)) {
1921
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
1922
- JSFILEMSG_CANNOT_DO_LIST_ON_A_FILE, file->path);
1923
- goto out;
1924
- }
1925
-
1926
- dir = PR_OpenDir(file->path);
1927
- if(!dir){
1928
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
1929
- JSFILEMSG_OP_FAILED, "open", file->path);
1930
- goto out;
1931
- }
1932
-
1933
- /* create JSArray here... */
1934
- array = JS_NewArrayObject(cx, 0, NULL);
1935
- len = 0;
1936
-
1937
- while ((entry = PR_ReadDir(dir, PR_SKIP_BOTH))!=NULL) {
1938
- /* first, check if we have a regexp */
1939
- if (re!=NULL) {
1940
- size_t index = 0;
1941
-
1942
- str = JS_NewStringCopyZ(cx, entry->name);
1943
- if(!js_ExecuteRegExp(cx, re, str, &index, JS_TRUE, &v)){
1944
- /* don't report anything here */
1945
- goto out;
1946
- }
1947
- /* not matched! */
1948
- if (JSVAL_IS_NULL(v)) {
1949
- continue;
1950
- }
1951
- }else
1952
- if (func!=NULL) {
1953
- str = JS_NewStringCopyZ(cx, entry->name);
1954
- args[0] = STRING_TO_JSVAL(str);
1955
- if(!JS_CallFunction(cx, obj, func, 1, args, &v)){
1956
- goto out;
1957
- }
1958
-
1959
- if (v==JSVAL_FALSE) {
1960
- continue;
1961
- }
1962
- }
1963
-
1964
- filePath = js_combinePath(cx, file->path, (char*)entry->name);
1965
-
1966
- eachFile = js_NewFileObject(cx, filePath);
1967
- JS_free(cx, filePath);
1968
- if (!eachFile){
1969
- JS_ReportWarning(cx, "File %s cannot be retrieved", filePath);
1970
- continue;
1971
- }
1972
- v = OBJECT_TO_JSVAL(eachFile);
1973
- JS_SetElement(cx, array, len, &v);
1974
- JS_SetProperty(cx, array, entry->name, &v);
1975
- len++;
1976
- }
1977
-
1978
- if(PR_CloseDir(dir)!=PR_SUCCESS){
1979
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
1980
- JSFILEMSG_OP_FAILED, "close", file->path);
1981
- goto out;
1982
- }
1983
- *rval = OBJECT_TO_JSVAL(array);
1984
- return JS_TRUE;
1985
- out:
1986
- *rval = JSVAL_NULL;
1987
- return JS_FALSE;
1988
- }
1989
-
1990
- static JSBool
1991
- file_mkdir(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1992
- {
1993
- JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
1994
-
1995
- SECURITY_CHECK(cx, NULL, "mkdir", file);
1996
- JSFILE_CHECK_ONE_ARG("mkdir");
1997
- JSFILE_CHECK_NATIVE("mkdir");
1998
-
1999
- /* if the current file is not a directory, find out the directory name */
2000
- if (!js_isDirectory(cx, file)) {
2001
- char *dir = js_fileDirectoryName(cx, file->path);
2002
- JSObject *dirObj = js_NewFileObject(cx, dir);
2003
-
2004
- JS_free(cx, dir);
2005
-
2006
- /* call file_mkdir with the right set of parameters if needed */
2007
- if (file_mkdir(cx, dirObj, argc, argv, rval))
2008
- return JS_TRUE;
2009
- else
2010
- goto out;
2011
- }else{
2012
- char *dirName = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
2013
- char *fullName;
2014
-
2015
- fullName = js_combinePath(cx, file->path, dirName);
2016
- if (PR_MkDir(fullName, 0755)==PR_SUCCESS){
2017
- *rval = JSVAL_TRUE;
2018
- JS_free(cx, fullName);
2019
- return JS_TRUE;
2020
- }else{
2021
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
2022
- JSFILEMSG_OP_FAILED, "mkdir", fullName);
2023
- JS_free(cx, fullName);
2024
- goto out;
2025
- }
2026
- }
2027
- out:
2028
- *rval = JSVAL_FALSE;
2029
- return JS_FALSE;
2030
- }
2031
-
2032
- static JSBool
2033
- file_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval*rval)
2034
- {
2035
- JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
2036
- JSString *str;
2037
-
2038
- str = JS_NewStringCopyZ(cx, file->path);
2039
- if (!str)
2040
- return JS_FALSE;
2041
- *rval = STRING_TO_JSVAL(str);
2042
- return JS_TRUE;
2043
- }
2044
-
2045
- static JSBool
2046
- file_toURL(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2047
- {
2048
- JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
2049
- char url[MAX_PATH_LENGTH];
2050
- jschar *urlChars;
2051
- size_t len;
2052
- JSString *str;
2053
-
2054
- JSFILE_CHECK_NATIVE("toURL");
2055
-
2056
- sprintf(url, "file://%s", file->path);
2057
-
2058
- len = strlen(url);
2059
- urlChars = js_InflateString(cx, url, &len);
2060
- if (!urlChars)
2061
- return JS_FALSE;
2062
- str = js_NewString(cx, urlChars, len);
2063
- if (!str) {
2064
- JS_free(cx, urlChars);
2065
- return JS_FALSE;
2066
- }
2067
- *rval = STRING_TO_JSVAL(str);
2068
-
2069
- /* TODO: js_escape in jsstr.h may go away at some point */
2070
- return js_str_escape(cx, obj, 0, rval, rval);
2071
-
2072
- out:
2073
- *rval = JSVAL_VOID;
2074
- return JS_FALSE;
2075
- }
2076
-
2077
-
2078
- static void
2079
- file_finalize(JSContext *cx, JSObject *obj)
2080
- {
2081
- JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
2082
-
2083
- if(file) {
2084
- /* Close the file before exiting. */
2085
- if(file->isOpen && !file->isNative) {
2086
- jsval vp;
2087
- file_close(cx, obj, 0, NULL, &vp);
2088
- }
2089
-
2090
- if (file->path)
2091
- JS_free(cx, file->path);
2092
-
2093
- JS_free(cx, file);
2094
- }
2095
- }
2096
-
2097
- /*
2098
- Allocates memory for the file object, sets fields to defaults.
2099
- */
2100
- static JSFile*
2101
- file_init(JSContext *cx, JSObject *obj, char *bytes)
2102
- {
2103
- JSFile *file;
2104
-
2105
- file = JS_malloc(cx, sizeof *file);
2106
- if (!file)
2107
- return NULL;
2108
- memset(file, 0 , sizeof *file);
2109
-
2110
- js_ResetAttributes(file);
2111
-
2112
- file->path = RESOLVE_PATH(cx, bytes);
2113
-
2114
- if (!JS_SetPrivate(cx, obj, file)) {
2115
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
2116
- JSFILEMSG_CANNOT_SET_PRIVATE_FILE, file->path);
2117
- JS_free(cx, file);
2118
- return NULL;
2119
- }
2120
-
2121
- return file;
2122
- }
2123
-
2124
- /* Returns a JSObject. This function is globally visible */
2125
- JS_PUBLIC_API(JSObject*)
2126
- js_NewFileObject(JSContext *cx, char *filename)
2127
- {
2128
- JSObject *obj;
2129
- JSFile *file;
2130
-
2131
- obj = JS_NewObject(cx, &js_FileClass, NULL, NULL);
2132
- if (!obj){
2133
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
2134
- JSFILEMSG_OBJECT_CREATION_FAILED, "js_NewFileObject");
2135
- return NULL;
2136
- }
2137
- file = file_init(cx, obj, filename);
2138
- if(!file) return NULL;
2139
- return obj;
2140
- }
2141
-
2142
- /* Internal function, used for cases which NSPR file support doesn't cover */
2143
- JSObject*
2144
- js_NewFileObjectFromFILE(JSContext *cx, FILE *nativehandle, char *filename,
2145
- int32 mode, JSBool open, JSBool randomAccess)
2146
- {
2147
- JSObject *obj;
2148
- JSFile *file;
2149
-
2150
- obj = JS_NewObject(cx, &js_FileClass, NULL, NULL);
2151
- if (!obj){
2152
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
2153
- JSFILEMSG_OBJECT_CREATION_FAILED, "js_NewFileObjectFromFILE");
2154
- return NULL;
2155
- }
2156
- file = file_init(cx, obj, filename);
2157
- if(!file) return NULL;
2158
-
2159
- file->nativehandle = nativehandle;
2160
-
2161
- /* free result of RESOLVE_PATH from file_init. */
2162
- JS_ASSERT(file->path != NULL);
2163
- JS_free(cx, file->path);
2164
-
2165
- file->path = strdup(filename);
2166
- file->isOpen = open;
2167
- file->mode = mode;
2168
- file->hasRandomAccess = randomAccess;
2169
- file->isNative = JS_TRUE;
2170
- return obj;
2171
- }
2172
-
2173
- /*
2174
- Real file constructor that is called from JavaScript.
2175
- Basically, does error processing and calls file_init.
2176
- */
2177
- static JSBool
2178
- file_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
2179
- jsval *rval)
2180
- {
2181
- JSString *str;
2182
- JSFile *file;
2183
-
2184
- if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) {
2185
- /* Replace obj with a new File object. */
2186
- obj = JS_NewObject(cx, &js_FileClass, NULL, NULL);
2187
- if (!obj)
2188
- return JS_FALSE;
2189
- *rval = OBJECT_TO_JSVAL(obj);
2190
- }
2191
-
2192
- str = (argc == 0)
2193
- ? JS_InternString(cx, "")
2194
- : JS_ValueToString(cx, argv[0]);
2195
-
2196
- if (!str) {
2197
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
2198
- JSFILEMSG_FIRST_ARGUMENT_CONSTRUCTOR_NOT_STRING_ERROR,
2199
- argv[0]);
2200
- return JS_FALSE;
2201
- }
2202
-
2203
- file = file_init(cx, obj, JS_GetStringBytes(str));
2204
- if (!file)
2205
- return JS_FALSE;
2206
-
2207
- SECURITY_CHECK(cx, NULL, "constructor", file);
2208
-
2209
- return JS_TRUE;
2210
- }
2211
-
2212
- /* -------------------- File methods and properties ------------------------- */
2213
- static JSFunctionSpec file_functions[] = {
2214
- { "open", file_open, 0},
2215
- { "close", file_close, 0},
2216
- { "remove", file_remove, 0},
2217
- { "copyTo", file_copyTo, 0},
2218
- { "renameTo", file_renameTo, 0},
2219
- { "flush", file_flush, 0},
2220
- { "seek", file_seek, 0},
2221
- { "read", file_read, 0},
2222
- { "readln", file_readln, 0},
2223
- { "readAll", file_readAll, 0},
2224
- { "write", file_write, 0},
2225
- { "writeln", file_writeln, 0},
2226
- { "writeAll", file_writeAll, 0},
2227
- { "list", file_list, 0},
2228
- { "mkdir", file_mkdir, 0},
2229
- { "toString", file_toString, 0},
2230
- { "toURL", file_toURL, 0},
2231
- {0}
2232
- };
2233
-
2234
- enum file_tinyid {
2235
- FILE_LENGTH = -2,
2236
- FILE_PARENT = -3,
2237
- FILE_PATH = -4,
2238
- FILE_NAME = -5,
2239
- FILE_ISDIR = -6,
2240
- FILE_ISFILE = -7,
2241
- FILE_EXISTS = -8,
2242
- FILE_CANREAD = -9,
2243
- FILE_CANWRITE = -10,
2244
- FILE_OPEN = -11,
2245
- FILE_TYPE = -12,
2246
- FILE_MODE = -13,
2247
- FILE_CREATED = -14,
2248
- FILE_MODIFIED = -15,
2249
- FILE_SIZE = -16,
2250
- FILE_RANDOMACCESS = -17,
2251
- FILE_POSITION = -18,
2252
- FILE_APPEND = -19,
2253
- FILE_REPLACE = -20,
2254
- FILE_AUTOFLUSH = -21,
2255
- FILE_ISNATIVE = -22,
2256
- };
2257
-
2258
- static JSPropertySpec file_props[] = {
2259
- {"length", FILE_LENGTH, JSPROP_ENUMERATE | JSPROP_READONLY },
2260
- {"parent", FILE_PARENT, JSPROP_ENUMERATE | JSPROP_READONLY },
2261
- {"path", FILE_PATH, JSPROP_ENUMERATE | JSPROP_READONLY },
2262
- {"name", FILE_NAME, JSPROP_ENUMERATE | JSPROP_READONLY },
2263
- {"isDirectory", FILE_ISDIR, JSPROP_ENUMERATE | JSPROP_READONLY },
2264
- {"isFile", FILE_ISFILE, JSPROP_ENUMERATE | JSPROP_READONLY },
2265
- {"exists", FILE_EXISTS, JSPROP_ENUMERATE | JSPROP_READONLY },
2266
- {"canRead", FILE_CANREAD, JSPROP_ENUMERATE | JSPROP_READONLY },
2267
- {"canWrite", FILE_CANWRITE, JSPROP_ENUMERATE | JSPROP_READONLY },
2268
- {"canAppend", FILE_APPEND, JSPROP_ENUMERATE | JSPROP_READONLY },
2269
- {"canReplace", FILE_REPLACE, JSPROP_ENUMERATE | JSPROP_READONLY },
2270
- {"isOpen", FILE_OPEN, JSPROP_ENUMERATE | JSPROP_READONLY },
2271
- {"type", FILE_TYPE, JSPROP_ENUMERATE | JSPROP_READONLY },
2272
- {"mode", FILE_MODE, JSPROP_ENUMERATE | JSPROP_READONLY },
2273
- {"creationTime", FILE_CREATED, JSPROP_ENUMERATE | JSPROP_READONLY },
2274
- {"lastModified", FILE_MODIFIED, JSPROP_ENUMERATE | JSPROP_READONLY },
2275
- {"size", FILE_SIZE, JSPROP_ENUMERATE | JSPROP_READONLY },
2276
- {"hasRandomAccess", FILE_RANDOMACCESS, JSPROP_ENUMERATE | JSPROP_READONLY },
2277
- {"hasAutoFlush", FILE_AUTOFLUSH, JSPROP_ENUMERATE | JSPROP_READONLY },
2278
- {"position", FILE_POSITION, JSPROP_ENUMERATE },
2279
- {"isNative", FILE_ISNATIVE, JSPROP_ENUMERATE | JSPROP_READONLY },
2280
- {0}
2281
- };
2282
-
2283
- /* ------------------------- Property getter/setter ------------------------- */
2284
- static JSBool
2285
- file_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
2286
- {
2287
- JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
2288
- char *bytes;
2289
- JSString *str;
2290
- jsint tiny;
2291
- PRFileInfo info;
2292
- JSBool flag;
2293
- PRExplodedTime expandedTime;
2294
-
2295
- tiny = JSVAL_TO_INT(id);
2296
- if (!file)
2297
- return JS_TRUE;
2298
-
2299
- switch (tiny) {
2300
- case FILE_PARENT:
2301
- SECURITY_CHECK(cx, NULL, "parent", file);
2302
- if (!js_parent(cx, file, vp))
2303
- return JS_FALSE;
2304
- break;
2305
- case FILE_PATH:
2306
- str = JS_NewStringCopyZ(cx, file->path);
2307
- if (!str)
2308
- return JS_FALSE;
2309
- *vp = STRING_TO_JSVAL(str);
2310
- break;
2311
- case FILE_NAME:
2312
- if (!js_name(cx, file, vp))
2313
- return JS_FALSE;
2314
- break;
2315
- case FILE_ISDIR:
2316
- SECURITY_CHECK(cx, NULL, "isDirectory", file);
2317
- *vp = BOOLEAN_TO_JSVAL(js_isDirectory(cx, file));
2318
- break;
2319
- case FILE_ISFILE:
2320
- SECURITY_CHECK(cx, NULL, "isFile", file);
2321
- *vp = BOOLEAN_TO_JSVAL(js_isFile(cx, file));
2322
- break;
2323
- case FILE_EXISTS:
2324
- SECURITY_CHECK(cx, NULL, "exists", file);
2325
- *vp = BOOLEAN_TO_JSVAL(js_exists(cx, file));
2326
- break;
2327
- case FILE_ISNATIVE:
2328
- SECURITY_CHECK(cx, NULL, "isNative", file);
2329
- *vp = BOOLEAN_TO_JSVAL(file->isNative);
2330
- break;
2331
- case FILE_CANREAD:
2332
- SECURITY_CHECK(cx, NULL, "canRead", file);
2333
- *vp = BOOLEAN_TO_JSVAL(js_canRead(cx, file));
2334
- break;
2335
- case FILE_CANWRITE:
2336
- SECURITY_CHECK(cx, NULL, "canWrite", file);
2337
- *vp = BOOLEAN_TO_JSVAL(js_canWrite(cx, file));
2338
- break;
2339
- case FILE_OPEN:
2340
- SECURITY_CHECK(cx, NULL, "isOpen", file);
2341
- *vp = BOOLEAN_TO_JSVAL(file->isOpen);
2342
- break;
2343
- case FILE_APPEND :
2344
- SECURITY_CHECK(cx, NULL, "canAppend", file);
2345
- JSFILE_CHECK_OPEN("canAppend");
2346
- *vp = BOOLEAN_TO_JSVAL(!file->isNative &&
2347
- (file->mode&PR_APPEND)==PR_APPEND);
2348
- break;
2349
- case FILE_REPLACE :
2350
- SECURITY_CHECK(cx, NULL, "canReplace", file);
2351
- JSFILE_CHECK_OPEN("canReplace");
2352
- *vp = BOOLEAN_TO_JSVAL(!file->isNative &&
2353
- (file->mode&PR_TRUNCATE)==PR_TRUNCATE);
2354
- break;
2355
- case FILE_AUTOFLUSH :
2356
- SECURITY_CHECK(cx, NULL, "hasAutoFlush", file);
2357
- JSFILE_CHECK_OPEN("hasAutoFlush");
2358
- *vp = BOOLEAN_TO_JSVAL(!file->isNative && file->hasAutoflush);
2359
- break;
2360
- case FILE_TYPE:
2361
- SECURITY_CHECK(cx, NULL, "type", file);
2362
- JSFILE_CHECK_OPEN("type");
2363
- if(js_isDirectory(cx, file)){
2364
- *vp = JSVAL_VOID;
2365
- break;
2366
- }
2367
-
2368
- switch (file->type) {
2369
- case ASCII:
2370
- *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, asciistring));
2371
- break;
2372
- case UTF8:
2373
- *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, utfstring));
2374
- break;
2375
- case UCS2:
2376
- *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, unicodestring));
2377
- break;
2378
- default:
2379
- JS_ReportWarning(cx, "Unsupported file type %d, proceeding",
2380
- file->type);
2381
- }
2382
- break;
2383
- case FILE_MODE:
2384
- SECURITY_CHECK(cx, NULL, "mode", file);
2385
- JSFILE_CHECK_OPEN("mode");
2386
- bytes = JS_malloc(cx, MODE_SIZE);
2387
- bytes[0] = '\0';
2388
- flag = JS_FALSE;
2389
-
2390
- if ((file->mode&PR_RDONLY)==PR_RDONLY) {
2391
- if (flag) strcat(bytes, ",");
2392
- strcat(bytes, "read");
2393
- flag = JS_TRUE;
2394
- }
2395
- if ((file->mode&PR_WRONLY)==PR_WRONLY) {
2396
- if (flag) strcat(bytes, ",");
2397
- strcat(bytes, "write");
2398
- flag = JS_TRUE;
2399
- }
2400
- if ((file->mode&PR_RDWR)==PR_RDWR) {
2401
- if (flag) strcat(bytes, ",");
2402
- strcat(bytes, "readWrite");
2403
- flag = JS_TRUE;
2404
- }
2405
- if ((file->mode&PR_APPEND)==PR_APPEND) {
2406
- if (flag) strcat(bytes, ",");
2407
- strcat(bytes, "append");
2408
- flag = JS_TRUE;
2409
- }
2410
- if ((file->mode&PR_CREATE_FILE)==PR_CREATE_FILE) {
2411
- if (flag) strcat(bytes, ",");
2412
- strcat(bytes, "create");
2413
- flag = JS_TRUE;
2414
- }
2415
- if ((file->mode&PR_TRUNCATE)==PR_TRUNCATE) {
2416
- if (flag) strcat(bytes, ",");
2417
- strcat(bytes, "replace");
2418
- flag = JS_TRUE;
2419
- }
2420
- if (file->hasAutoflush) {
2421
- if (flag) strcat(bytes, ",");
2422
- strcat(bytes, "hasAutoFlush");
2423
- flag = JS_TRUE;
2424
- }
2425
- *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, bytes));
2426
- JS_free(cx, bytes);
2427
- break;
2428
- case FILE_CREATED:
2429
- SECURITY_CHECK(cx, NULL, "creationTime", file);
2430
- JSFILE_CHECK_NATIVE("creationTime");
2431
- if(((file->isOpen)?
2432
- PR_GetOpenFileInfo(file->handle, &info):
2433
- PR_GetFileInfo(file->path, &info))!=PR_SUCCESS){
2434
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
2435
- JSFILEMSG_CANNOT_ACCESS_FILE_STATUS, file->path);
2436
- goto out;
2437
- }
2438
-
2439
- PR_ExplodeTime(info.creationTime, PR_LocalTimeParameters,&expandedTime);
2440
- *vp = OBJECT_TO_JSVAL(js_NewDateObject(cx, expandedTime.tm_year,
2441
- expandedTime.tm_month,
2442
- expandedTime.tm_mday,
2443
- expandedTime.tm_hour,
2444
- expandedTime.tm_min,
2445
- expandedTime.tm_sec));
2446
- break;
2447
- case FILE_MODIFIED:
2448
- SECURITY_CHECK(cx, NULL, "lastModified", file);
2449
- JSFILE_CHECK_NATIVE("lastModified");
2450
- if(((file->isOpen)?
2451
- PR_GetOpenFileInfo(file->handle, &info):
2452
- PR_GetFileInfo(file->path, &info))!=PR_SUCCESS){
2453
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
2454
- JSFILEMSG_CANNOT_ACCESS_FILE_STATUS, file->path);
2455
- goto out;
2456
- }
2457
-
2458
- PR_ExplodeTime(info.modifyTime, PR_LocalTimeParameters, &expandedTime);
2459
- *vp = OBJECT_TO_JSVAL(js_NewDateObject(cx, expandedTime.tm_year,
2460
- expandedTime.tm_month,
2461
- expandedTime.tm_mday,
2462
- expandedTime.tm_hour,
2463
- expandedTime.tm_min,
2464
- expandedTime.tm_sec));
2465
- break;
2466
- case FILE_SIZE:
2467
- SECURITY_CHECK(cx, NULL, "size", file);
2468
- *vp = js_size(cx, file);
2469
- break;
2470
- case FILE_LENGTH:
2471
- SECURITY_CHECK(cx, NULL, "length", file);
2472
- JSFILE_CHECK_NATIVE("length");
2473
-
2474
- if (js_isDirectory(cx, file)) { /* XXX debug me */
2475
- PRDir *dir;
2476
- PRDirEntry *entry;
2477
- jsint count = 0;
2478
-
2479
- if(!(dir = PR_OpenDir(file->path))){
2480
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
2481
- JSFILEMSG_CANNOT_OPEN_DIR, file->path);
2482
- goto out;
2483
- }
2484
-
2485
- while ((entry = PR_ReadDir(dir, PR_SKIP_BOTH))) {
2486
- count++;
2487
- }
2488
-
2489
- if(!PR_CloseDir(dir)){
2490
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
2491
- JSFILEMSG_OP_FAILED, "close", file->path);
2492
-
2493
- goto out;
2494
- }
2495
-
2496
- *vp = INT_TO_JSVAL(count);
2497
- break;
2498
- }else{
2499
- /* return file size */
2500
- *vp = js_size(cx, file);
2501
- }
2502
- break;
2503
- case FILE_RANDOMACCESS:
2504
- SECURITY_CHECK(cx, NULL, "hasRandomAccess", file);
2505
- JSFILE_CHECK_OPEN("hasRandomAccess");
2506
- *vp = BOOLEAN_TO_JSVAL(file->hasRandomAccess);
2507
- break;
2508
- case FILE_POSITION:
2509
- SECURITY_CHECK(cx, NULL, "position", file);
2510
- JSFILE_CHECK_NATIVE("position");
2511
- JSFILE_CHECK_OPEN("position");
2512
-
2513
- if(!file->hasRandomAccess){
2514
- JS_ReportWarning(cx, "File %s doesn't support random access, can't report the position, proceeding");
2515
- *vp = JSVAL_VOID;
2516
- break;
2517
- }
2518
-
2519
- if (file->isOpen && js_isFile(cx, file)) {
2520
- int pos = PR_Seek(file->handle, 0, PR_SEEK_CUR);
2521
- if(pos!=-1){
2522
- *vp = INT_TO_JSVAL(pos);
2523
- }else{
2524
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
2525
- JSFILEMSG_CANNOT_REPORT_POSITION, file->path);
2526
- goto out;
2527
- }
2528
- }else {
2529
- JS_ReportWarning(cx, "File %s is closed or not a plain file,"
2530
- " can't report position, proceeding");
2531
- goto out;
2532
- }
2533
- break;
2534
- default:
2535
- SECURITY_CHECK(cx, NULL, "file_access", file);
2536
-
2537
- /* this is some other property -- try to use the dir["file"] syntax */
2538
- if (js_isDirectory(cx, file)) {
2539
- PRDir *dir = NULL;
2540
- PRDirEntry *entry = NULL;
2541
- char *prop_name;
2542
-
2543
- str = JS_ValueToString(cx, id);
2544
- if (!str)
2545
- return JS_FALSE;
2546
-
2547
- prop_name = JS_GetStringBytes(str);
2548
-
2549
- /* no native files past this point */
2550
- dir = PR_OpenDir(file->path);
2551
- if(!dir) {
2552
- /* This is probably not a directory */
2553
- JS_ReportWarning(cx, "Can't open directory %s", file->path);
2554
- return JS_FALSE;
2555
- }
2556
-
2557
- while ((entry = PR_ReadDir(dir, PR_SKIP_NONE)) != NULL) {
2558
- if (!strcmp(entry->name, prop_name)){
2559
- bytes = js_combinePath(cx, file->path, prop_name);
2560
- *vp = OBJECT_TO_JSVAL(js_NewFileObject(cx, bytes));
2561
- PR_CloseDir(dir);
2562
- JS_free(cx, bytes);
2563
- return !JSVAL_IS_NULL(*vp);
2564
- }
2565
- }
2566
- PR_CloseDir(dir);
2567
- }
2568
- }
2569
- return JS_TRUE;
2570
-
2571
- out:
2572
- return JS_FALSE;
2573
- }
2574
-
2575
- static JSBool
2576
- file_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
2577
- {
2578
- JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
2579
- jsint slot;
2580
-
2581
- if (JSVAL_IS_STRING(id)){
2582
- return JS_TRUE;
2583
- }
2584
-
2585
- slot = JSVAL_TO_INT(id);
2586
-
2587
- switch (slot) {
2588
- /* File.position = 10 */
2589
- case FILE_POSITION:
2590
- SECURITY_CHECK(cx, NULL, "set_position", file);
2591
- JSFILE_CHECK_NATIVE("set_position");
2592
-
2593
- if(!file->hasRandomAccess){
2594
- JS_ReportWarning(cx, "File %s doesn't support random access, can't "
2595
- "report the position, proceeding");
2596
- goto out;
2597
- }
2598
-
2599
- if (file->isOpen && js_isFile(cx, file)) {
2600
- int32 pos;
2601
- int32 offset;
2602
-
2603
- if (!JS_ValueToInt32(cx, *vp, &offset)){
2604
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
2605
- JSFILEMSG_FIRST_ARGUMENT_MUST_BE_A_NUMBER, "position", *vp);
2606
- goto out;
2607
- }
2608
-
2609
- pos = PR_Seek(file->handle, offset, PR_SEEK_SET);
2610
-
2611
- if(pos!=-1){
2612
- *vp = INT_TO_JSVAL(pos);
2613
- }else{
2614
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
2615
- JSFILEMSG_CANNOT_SET_POSITION, file->path);
2616
- goto out;
2617
- }
2618
- } else {
2619
- JS_ReportWarning(cx, "File %s is closed or not a file, can't set "
2620
- "position, proceeding", file->path);
2621
- goto out;
2622
- }
2623
- }
2624
-
2625
- return JS_TRUE;
2626
- out:
2627
- return JS_FALSE;
2628
- }
2629
-
2630
- /*
2631
- File.currentDir = new File("D:\") or File.currentDir = "D:\"
2632
- */
2633
- static JSBool
2634
- file_currentDirSetter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
2635
- {
2636
- JSFile *file;
2637
-
2638
- file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
2639
-
2640
- /* Look at the rhs and extract a file object from it */
2641
- if (JSVAL_IS_OBJECT(*vp)) {
2642
- if (JS_InstanceOf(cx, obj, &js_FileClass, NULL)) {
2643
- /* Braindamaged rhs -- just return the old value */
2644
- if (file && (!js_exists(cx, file) || !js_isDirectory(cx, file))) {
2645
- JS_GetProperty(cx, obj, CURRENTDIR_PROPERTY, vp);
2646
- return JS_FALSE;
2647
- } else {
2648
- chdir(file->path);
2649
- return JS_TRUE;
2650
- }
2651
- } else {
2652
- return JS_FALSE;
2653
- }
2654
- } else {
2655
- JSObject *rhsObject;
2656
- char *path;
2657
-
2658
- path = JS_GetStringBytes(JS_ValueToString(cx, *vp));
2659
- rhsObject = js_NewFileObject(cx, path);
2660
- if (!rhsObject)
2661
- return JS_FALSE;
2662
-
2663
- if (!file || !js_exists(cx, file) || !js_isDirectory(cx, file)){
2664
- JS_GetProperty(cx, obj, CURRENTDIR_PROPERTY, vp);
2665
- } else {
2666
- *vp = OBJECT_TO_JSVAL(rhsObject);
2667
- chdir(path);
2668
- }
2669
- }
2670
-
2671
- return JS_TRUE;
2672
- }
2673
-
2674
- /* Declare class */
2675
- JSClass js_FileClass = {
2676
- "File", JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_File),
2677
- JS_PropertyStub, JS_PropertyStub, file_getProperty, file_setProperty,
2678
- JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, file_finalize
2679
- };
2680
-
2681
- /* -------------------- Functions exposed to the outside -------------------- */
2682
- JS_PUBLIC_API(JSObject*)
2683
- js_InitFileClass(JSContext *cx, JSObject* obj)
2684
- {
2685
- JSObject *file, *ctor, *afile;
2686
- jsval vp;
2687
- char *currentdir;
2688
- char separator[2];
2689
-
2690
- file = JS_InitClass(cx, obj, NULL, &js_FileClass, file_constructor, 1,
2691
- file_props, file_functions, NULL, NULL);
2692
- if (!file) {
2693
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
2694
- JSFILEMSG_INIT_FAILED);
2695
- return NULL;
2696
- }
2697
-
2698
- ctor = JS_GetConstructor(cx, file);
2699
- if (!ctor) return NULL;
2700
-
2701
- /* Define CURRENTDIR property. We are doing this to get a
2702
- slash at the end of the current dir */
2703
- afile = js_NewFileObject(cx, CURRENT_DIR);
2704
- currentdir = JS_malloc(cx, MAX_PATH_LENGTH);
2705
- currentdir = getcwd(currentdir, MAX_PATH_LENGTH);
2706
- afile = js_NewFileObject(cx, currentdir);
2707
- JS_free(cx, currentdir);
2708
- vp = OBJECT_TO_JSVAL(afile);
2709
- JS_DefinePropertyWithTinyId(cx, ctor, CURRENTDIR_PROPERTY, 0, vp,
2710
- JS_PropertyStub, file_currentDirSetter,
2711
- JSPROP_ENUMERATE | JSPROP_READONLY );
2712
-
2713
- /* Define input */
2714
- vp = OBJECT_TO_JSVAL(js_NewFileObjectFromFILE(cx, stdin,
2715
- STDINPUT_NAME, PR_RDONLY, JS_TRUE, JS_FALSE));
2716
- JS_SetProperty(cx, ctor, "input", &vp);
2717
-
2718
- /* Define output */
2719
- vp = OBJECT_TO_JSVAL(js_NewFileObjectFromFILE(cx, stdout,
2720
- STDOUTPUT_NAME, PR_WRONLY, JS_TRUE, JS_FALSE));
2721
- JS_SetProperty(cx, ctor, "output", &vp);
2722
-
2723
- /* Define error */
2724
- vp = OBJECT_TO_JSVAL(js_NewFileObjectFromFILE(cx, stderr,
2725
- STDERROR_NAME, PR_WRONLY, JS_TRUE, JS_FALSE));
2726
- JS_SetProperty(cx, ctor, "error", &vp);
2727
-
2728
- separator[0] = FILESEPARATOR;
2729
- separator[1] = '\0';
2730
- vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, separator));
2731
- JS_DefinePropertyWithTinyId(cx, ctor, SEPARATOR_PROPERTY, 0, vp,
2732
- JS_PropertyStub, JS_PropertyStub,
2733
- JSPROP_ENUMERATE | JSPROP_READONLY );
2734
- return file;
2735
- }
2736
- #endif /* JS_HAS_FILE_OBJECT */