2 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or
8 // (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 #include "gnashconfig.h"
27 #include <boost/algorithm/string/case_conv.hpp>
29 #include <dirent.h> // used by scandir()
30 #include "GnashSystemIOHeaders.h" // used by unlink()
31 #include <fcntl.h> // used by asyncmode()
36 #include "as_object.h"
37 #include "Global_as.h"
39 #include "Array_as.h" // used by scandir()
40 #include "as_function.h"
47 static const int BUFSIZE
= 1024;
49 as_value
fileio_fopen(const fn_call
& fn
);
50 as_value
fileio_fread(const fn_call
& fn
);
51 as_value
fileio_fgetc(const fn_call
& fn
);
52 as_value
fileio_fgets(const fn_call
& fn
);
53 as_value
fileio_gets(const fn_call
& fn
);
54 as_value
fileio_fwrite(const fn_call
& fn
);
55 as_value
fileio_fputc(const fn_call
& fn
);
56 as_value
fileio_fputs(const fn_call
& fn
);
57 as_value
fileio_puts(const fn_call
& fn
);
58 as_value
fileio_fclose(const fn_call
& fn
);
59 as_value
fileio_getchar(const fn_call
& fn
);
60 as_value
fileio_putchar(const fn_call
& fn
);
61 as_value
fileio_fflush(const fn_call
& fn
);
62 as_value
fileio_ftell(const fn_call
& fn
);
63 as_value
fileio_feof(const fn_call
& fn
);
64 as_value
fileio_fseek(const fn_call
& fn
);
65 as_value
fileio_unlink(const fn_call
& fn
);
66 as_value
fileio_asyncmode(const fn_call
& fn
);
68 // <Udo> I needed a scandir() function and implemented it here for simplicity.
69 // Maybe this should be moved to a dedicated extension and a different class?
70 // The scandir() syntax comes from PHP, since the C syntax is not quite
71 // applicable in ActionScript.
72 // Same applies for unlink(). Maybe a class FileOP or sim. would be
74 as_value
fileio_scandir(const fn_call
& fn
);
76 LogFile
& dbglogfile
= LogFile::getDefaultInstance();
78 // TODO: Document this class !!
79 class FileIO
: public Relay
85 bool fopen(const std::string
&filespec
, const std::string
&mode
);
87 int fread(std::string
&str
);
89 std::string
&fgets(std::string
&str
);
91 int fwrite(const std::string
&str
);
93 bool fputs(const std::string
&str
);
97 int fseek(long offset
);
98 int fseek(long offset
, int whence
);
100 bool asyncmode(bool async
);
102 bool unlink(const std::string
&filespec
);
105 std::string _filespec
;
109 attachInterface(as_object
& obj
)
111 Global_as
& gl
= getGlobal(obj
);
113 obj
.init_member("fopen", gl
.createFunction(fileio_fopen
));
114 obj
.init_member("fread", gl
.createFunction(fileio_fread
));
115 obj
.init_member("fgetc", gl
.createFunction(fileio_fgetc
));
116 obj
.init_member("fgets", gl
.createFunction(fileio_fgets
));
117 obj
.init_member("gets", gl
.createFunction(fileio_fgets
));
118 obj
.init_member("getchar", gl
.createFunction(fileio_getchar
));
120 obj
.init_member("fwrite", gl
.createFunction(fileio_fwrite
));
121 obj
.init_member("fputc", gl
.createFunction(fileio_fputc
));
122 obj
.init_member("fputs", gl
.createFunction(fileio_fputs
));
123 obj
.init_member("puts", gl
.createFunction(fileio_puts
));
124 obj
.init_member("putchar", gl
.createFunction(fileio_putchar
));
126 obj
.init_member("fflush", gl
.createFunction(fileio_fflush
));
127 obj
.init_member("fseek", gl
.createFunction(fileio_fseek
));
128 obj
.init_member("ftell", gl
.createFunction(fileio_ftell
));
129 obj
.init_member("asyncmode", gl
.createFunction(fileio_asyncmode
));
130 obj
.init_member("feof", gl
.createFunction(fileio_feof
));
131 obj
.init_member("fclose", gl
.createFunction(fileio_fclose
));
133 obj
.init_member("unlink", gl
.createFunction(fileio_unlink
));
135 obj
.init_member("scandir", gl
.createFunction(fileio_scandir
));
139 fileio_ctor(const fn_call
& fn
)
141 as_object
* obj
= ensure
<ValidThis
>(fn
);
142 obj
->setRelay(new FileIO());
145 IF_VERBOSE_ASCODING_ERRORS(
146 std::stringstream ss
; fn
.dump_args(ss
);
147 log_aserror("new FileIO(%s): all arguments discarded",
164 // GNASH_REPORT_FUNCTION;
171 // GNASH_REPORT_FUNCTION;
173 return ::fflush(_stream
);
181 // GNASH_REPORT_FUNCTION;
183 ::fseek(_stream
, 0L, SEEK_SET
);
188 FileIO::fseek(long offset
)
190 // GNASH_REPORT_FUNCTION;
192 return ::fseek(_stream
, offset
, SEEK_SET
);
198 FileIO::fseek(long offset
, int whence
)
200 // GNASH_REPORT_FUNCTION;
202 return ::fseek(_stream
, offset
, whence
);
210 // GNASH_REPORT_FUNCTION;
212 return ::ftell(_stream
);
218 FileIO::asyncmode(bool async
)
220 // GNASH_REPORT_FUNCTION;
223 int fd
= fileno(_stream
);
225 long flags
= fcntl(fd
, F_GETFL
);
230 res
= fcntl(fd
, F_SETFL
, flags
|O_NONBLOCK
);
232 res
= fcntl(fd
, F_SETFL
, flags
&(~O_NONBLOCK
));
242 // GNASH_REPORT_FUNCTION;
244 return ::feof(_stream
);
250 FileIO::fopen(const string
&filespec
, const string
&mode
)
252 // GNASH_REPORT_FUNCTION;
253 _stream
= ::fopen(filespec
.c_str(), mode
.c_str());
263 FileIO::fread(string
&str
)
265 // GNASH_REPORT_FUNCTION;
269 memset(buf
, 0, BUFSIZE
);
270 ret
= ::fread(buf
, 1, BUFSIZE
, _stream
);
281 // GNASH_REPORT_FUNCTION;
283 return ::fgetc(_stream
);
289 FileIO::fgets(std::string
&str
)
291 // GNASH_REPORT_FUNCTION;
294 memset(buf
, 0, BUFSIZE
);
295 char* res
= ::fgets(buf
, BUFSIZE
, _stream
);
299 str
= ""; // we might want to return NULL to the VM ?
306 FileIO::fwrite(const string
&str
)
308 // GNASH_REPORT_FUNCTION;
309 return ::fwrite(str
.c_str(), str
.size(), 1, _stream
);
316 // GNASH_REPORT_FUNCTION;
318 if (::fputc(c
, _stream
)) {
326 FileIO::fputs(const string
&str
)
328 // GNASH_REPORT_FUNCTION;
330 if (::fputs(str
.c_str(), _stream
)) {
340 // GNASH_REPORT_FUNCTION;
342 int ret
= ::fclose(_stream
);
350 FileIO::unlink(const std::string
&filespec
)
352 // GNASH_REPORT_FUNCTION;
353 return ::unlink(filespec
.c_str()) >= 0;
358 fileio_fopen(const fn_call
& fn
)
360 // GNASH_REPORT_FUNCTION;
361 FileIO
* ptr
= ensure
<ThisIsNative
<FileIO
> >(fn
);
365 IF_VERBOSE_ASCODING_ERRORS(
366 std::stringstream ss
; fn
.dump_args(ss
);
367 log_aserror("FileIO.fopen(%s): need two arguments", ss
.str().c_str());
369 return as_value(false);
372 string filespec
= fn
.arg(0).to_string();
373 string mode
= fn
.arg(1).to_string();
374 return as_value(ptr
->fopen(filespec
, mode
));
379 fileio_fclose(const fn_call
& fn
)
381 // GNASH_REPORT_FUNCTION;
382 FileIO
* ptr
= ensure
<ThisIsNative
<FileIO
> >(fn
);
385 return as_value(ptr
->fclose());
389 fileio_fread(const fn_call
& fn
)
391 // GNASH_REPORT_FUNCTION;
392 FileIO
* ptr
= ensure
<ThisIsNative
<FileIO
> >(fn
);
396 int count
= ptr
->fread(str
);
399 return as_value(false);
401 return as_value(str
.c_str());
406 fileio_fgetc(const fn_call
& fn
)
408 // GNASH_REPORT_FUNCTION;
409 FileIO
* ptr
= ensure
<ThisIsNative
<FileIO
> >(fn
);
411 int i
= ptr
->fgetc();
413 if ((i
==EOF
) || (i
<0)) {
414 return as_value(false); // possible in async mode
416 char c
[2]="x"; // set to 1 char to get the zero byte!
423 fileio_fgets(const fn_call
& fn
)
425 // GNASH_REPORT_FUNCTION;
426 FileIO
* ptr
= ensure
<ThisIsNative
<FileIO
> >(fn
);
429 str
= ptr
->fgets(str
);
430 return as_value(str
.c_str());
434 fileio_gets(const fn_call
& fn
)
436 // GNASH_REPORT_FUNCTION;
437 FileIO
* ptr
= ensure
<ThisIsNative
<FileIO
> >(fn
);
440 memset(buf
, 0, BUFSIZE
);
441 string str
= ::gets(buf
);
442 return as_value(buf
);
445 // Read a single character from standard in
447 fileio_getchar(const fn_call
& fn
)
449 // GNASH_REPORT_FUNCTION;
450 FileIO
* ptr
= ensure
<ThisIsNative
<FileIO
> >(fn
);
453 char *c
= reinterpret_cast<char *>(&i
);
458 fileio_fwrite(const fn_call
& fn
)
460 // GNASH_REPORT_FUNCTION;
461 FileIO
* ptr
= ensure
<ThisIsNative
<FileIO
> >(fn
);
463 string str
= fn
.arg(0).to_string();
464 return as_value(ptr
->fputs(str
));
468 fileio_fputc(const fn_call
& fn
)
470 // GNASH_REPORT_FUNCTION;
471 FileIO
* ptr
= ensure
<ThisIsNative
<FileIO
> >(fn
);
473 int c
= (int) toNumber(fn
.arg(0), getVM(fn
));
474 return as_value(ptr
->fputc(c
));
478 fileio_fputs(const fn_call
& fn
)
480 // GNASH_REPORT_FUNCTION;
481 FileIO
* ptr
= ensure
<ThisIsNative
<FileIO
> >(fn
);
483 string str
= fn
.arg(0).to_string();
484 return as_value(ptr
->fputs(str
));
487 // print to standard put
489 fileio_puts(const fn_call
& fn
)
491 // GNASH_REPORT_FUNCTION;
492 string str
= fn
.arg(0).to_string();
493 return as_value(::puts(str
.c_str()));
497 fileio_putchar(const fn_call
& fn
)
499 // GNASH_REPORT_FUNCTION;
500 FileIO
* ptr
= ensure
<ThisIsNative
<FileIO
> >(fn
);
502 string x
= fn
.arg(0).to_string();
503 return as_value(::putchar(x
[0]));
507 fileio_fflush(const fn_call
& fn
)
509 // GNASH_REPORT_FUNCTION;
510 FileIO
* ptr
= ensure
<ThisIsNative
<FileIO
> >(fn
);
512 return as_value(ptr
->fflush());
516 fileio_fseek(const fn_call
& fn
)
518 // GNASH_REPORT_FUNCTION;
519 FileIO
* ptr
= ensure
<ThisIsNative
<FileIO
> >(fn
);
521 long c
= static_cast<long>(toNumber(fn
.arg(0), getVM(fn
)));
522 return as_value(ptr
->fseek(c
));
526 fileio_ftell(const fn_call
& fn
)
528 // GNASH_REPORT_FUNCTION;
529 FileIO
* ptr
= ensure
<ThisIsNative
<FileIO
> >(fn
);
531 int i
= ptr
->ftell();
536 fileio_asyncmode(const fn_call
& fn
)
538 // GNASH_REPORT_FUNCTION;
539 FileIO
* ptr
= ensure
<ThisIsNative
<FileIO
> >(fn
);
541 bool b
= toBool(fn
.arg(0), getVM(fn
));
542 return as_value(ptr
->asyncmode(b
));
546 fileio_feof(const fn_call
& fn
)
548 // GNASH_REPORT_FUNCTION;
549 FileIO
* ptr
= ensure
<ThisIsNative
<FileIO
> >(fn
);
551 bool b
= ptr
->feof();
556 fileio_unlink(const fn_call
& fn
)
558 // GNASH_REPORT_FUNCTION;
559 FileIO
* ptr
= ensure
<ThisIsNative
<FileIO
> >(fn
);
561 string str
= fn
.arg(0).to_string();
562 return as_value(ptr
->unlink(str
));
566 fileio_scandir(const fn_call
& fn
)
568 // GNASH_REPORT_FUNCTION;
570 // TODO: Check optional second parameter and sort array if it's true
573 if (!fn
.nargs
) return as_value(false);
575 const std::string
& dir
= fn
.arg(0).to_string();
577 struct dirent
**namelist
;
579 const int n
= ::scandir(dir
.c_str(), &namelist
, 0, alphasort
);
582 return as_value(false);
585 Global_as
& gl
= getGlobal(fn
);
587 as_object
* array
= gl
.createArray();
589 for (int idx
= 0; idx
< n
; ++idx
) {
590 array
->set_member(arrayKey(vm
, idx
), namelist
[idx
]->d_name
);
595 return as_value(array
);
601 fileio_class_init(as_object
& where
, const ObjectURI
& /* uri */)
603 // GNASH_REPORT_FUNCTION;
604 Global_as
& gl
= getGlobal(where
);
606 as_object
* proto
= createObject(gl
);
607 attachInterface(*proto
);
608 as_object
* cl
= gl
.createClass(&fileio_ctor
, proto
);
610 where
.init_member("FileIO", cl
);
615 } // end of gnash namespace
619 // indent-tabs-mode: nil