summaryrefslogtreecommitdiffstats
path: root/src/dom/js/jsfile.c
diff options
context:
space:
mode:
authorAaron Spike <aaron@ekips.org>2006-04-12 13:20:54 +0000
committeracspike <acspike@users.sourceforge.net>2006-04-12 13:20:54 +0000
commitddfaffe08d23e4663fe759d67ae33fd67fc9ce5b (patch)
tree234f5425a7ef7058e69dc2ab77f89810e4f3ed91 /src/dom/js/jsfile.c
parentfix 1466070 (diff)
downloadinkscape-ddfaffe08d23e4663fe759d67ae33fd67fc9ce5b.tar.gz
inkscape-ddfaffe08d23e4663fe759d67ae33fd67fc9ce5b.zip
Removed file/folder for ishmal
(bzr r478)
Diffstat (limited to 'src/dom/js/jsfile.c')
-rw-r--r--src/dom/js/jsfile.c2610
1 files changed, 0 insertions, 2610 deletions
diff --git a/src/dom/js/jsfile.c b/src/dom/js/jsfile.c
deleted file mode 100644
index ef5e93b29..000000000
--- a/src/dom/js/jsfile.c
+++ /dev/null
@@ -1,2610 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- *
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Communicator client code, released
- * March 31, 1998.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-/*
- * JS File object
- */
-#if JS_HAS_FILE_OBJECT
-
-#include "jsstddef.h"
-
-/* ----------------- Platform-specific includes and defines ----------------- */
-#ifdef XP_MAC
-# define FILESEPARATOR ':'
-# define FILESEPARATOR2 '\0'
-# define CURRENT_DIR "HARD DISK:Desktop Folder"
-/* TODO: #include <???> */
-#elif defined(XP_WIN) || defined(XP_OS2)
-# include <direct.h>
-# include <io.h>
-# include <sys/types.h>
-# include <sys/stat.h>
-# define FILESEPARATOR '\\'
-# define FILESEPARATOR2 '/'
-# define CURRENT_DIR "c:\\"
-# define POPEN _popen
-# define PCLOSE _pclose
-#elif defined(XP_UNIX) || defined(XP_BEOS)
-# include <strings.h>
-# include <stdio.h>
-# include <stdlib.h>
-# include <unistd.h>
-# define FILESEPARATOR '/'
-# define FILESEPARATOR2 '\0'
-# define CURRENT_DIR "/"
-# define POPEN popen
-# define PCLOSE pclose
-#endif
-
-/* --------------- Platform-independent includes and defines ---------------- */
-#include "jsapi.h"
-#include "jsatom.h"
-#include "jscntxt.h"
-#include "jsdate.h"
-#include "jsdbgapi.h"
-#include "jsemit.h"
-#include "jsfun.h"
-#include "jslock.h"
-#include "jsobj.h"
-#include "jsparse.h"
-#include "jsscan.h"
-#include "jsscope.h"
-#include "jsscript.h"
-#include "jsstr.h"
-#include "jsutil.h" /* Added by JSIFY */
-#include <string.h>
-
-/* NSPR dependencies */
-#include "prio.h"
-#include "prerror.h"
-
-#define SPECIAL_FILE_STRING "Special File"
-#define CURRENTDIR_PROPERTY "currentDir"
-#define SEPARATOR_PROPERTY "separator"
-#define FILE_CONSTRUCTOR "File"
-#define PIPE_SYMBOL '|'
-
-#define ASCII 0
-#define UTF8 1
-#define UCS2 2
-
-#define asciistring "text"
-#define utfstring "binary"
-#define unicodestring "unicode"
-
-#define MAX_PATH_LENGTH 1024
-#define MODE_SIZE 256
-#define NUMBER_SIZE 32
-#define MAX_LINE_LENGTH 256
-#define URL_PREFIX "file://"
-
-#define STDINPUT_NAME "Standard input stream"
-#define STDOUTPUT_NAME "Standard output stream"
-#define STDERROR_NAME "Standard error stream"
-
-#define RESOLVE_PATH js_canonicalPath /* js_absolutePath */
-
-/* Error handling */
-typedef enum JSFileErrNum {
-#define MSG_DEF(name, number, count, exception, format) \
- name = number,
-#include "jsfile.msg"
-#undef MSG_DEF
- JSFileErr_Limit
-#undef MSGDEF
-} JSFileErrNum;
-
-#define JSFILE_HAS_DFLT_MSG_STRINGS 1
-
-JSErrorFormatString JSFile_ErrorFormatString[JSFileErr_Limit] = {
-#if JSFILE_HAS_DFLT_MSG_STRINGS
-#define MSG_DEF(name, number, count, exception, format) \
- { format, count } ,
-#else
-#define MSG_DEF(name, number, count, exception, format) \
- { NULL, count } ,
-#endif
-#include "jsfile.msg"
-#undef MSG_DEF
-};
-
-const JSErrorFormatString *
-JSFile_GetErrorMessage(void *userRef, const char *locale,
- const uintN errorNumber)
-{
- if ((errorNumber > 0) && (errorNumber < JSFileErr_Limit))
- return &JSFile_ErrorFormatString[errorNumber];
- else
- return NULL;
-}
-
-#define JSFILE_CHECK_NATIVE(op) \
- if(file->isNative){ \
- JS_ReportWarning(cx, "Cannot call or access \"%s\" on native file %s", \
- op, file->path); \
- goto out; \
- }
-
-#define JSFILE_CHECK_WRITE \
- if (!file->isOpen){ \
- JS_ReportWarning(cx, \
- "File %s is closed, will open it for writing, proceeding", \
- file->path); \
- js_FileOpen(cx, obj, file, "write,append,create"); \
- }else \
- if(!js_canWrite(cx, file)){ \
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, \
- JSFILEMSG_CANNOT_WRITE, file->path); \
- goto out; \
- }
-
-#define JSFILE_CHECK_READ \
- if (!file->isOpen){ \
- JS_ReportWarning(cx, \
- "File %s is closed, will open it for reading, proceeding", \
- file->path); \
- js_FileOpen(cx, obj, file, "read"); \
- }else \
- if(!js_canRead(cx, file)){ \
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, \
- JSFILEMSG_CANNOT_READ, file->path); \
- goto out; \
- }
-
-#define JSFILE_CHECK_OPEN(op) \
- if(!file->isOpen){ \
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, \
- JSFILEMSG_FILE_MUST_BE_CLOSED, op); \
- goto out; \
- }
-
-#define JSFILE_CHECK_CLOSED(op) \
- if(file->isOpen){ \
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, \
- JSFILEMSG_FILE_MUST_BE_OPEN, op); \
- goto out; \
- }
-
-#define JSFILE_CHECK_ONE_ARG(op) \
- if (argc!=1){ \
- char str[NUMBER_SIZE]; \
- \
- sprintf(str, "%d", argc); \
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, \
- JSFILEMSG_EXPECTS_ONE_ARG_ERROR, op, str); \
- goto out; \
- }
-
-
-/*
- Security mechanism, should define a callback for this.
- The parameters are as follows:
- SECURITY_CHECK(JSContext *cx, JSPrincipals *ps, char *op_name, JSFile *file)
-*/
-#define SECURITY_CHECK(cx, ps, op, file) \
- /* Define a callback here... */
-
-
-/* Structure representing the file internally */
-typedef struct JSFile {
- char *path; /* the path to the file. */
- JSBool isOpen;
- JSString *linebuffer; /* temp buffer used by readln. */
- int32 mode; /* mode used to open the file: read, write, append, create, etc.. */
- int32 type; /* Asciiz, utf, unicode */
- char byteBuffer[3]; /* bytes read in advance by js_FileRead ( UTF8 encoding ) */
- jsint nbBytesInBuf; /* number of bytes stored in the buffer above */
- jschar charBuffer; /* character read in advance by readln ( mac files only ) */
- JSBool charBufferUsed; /* flag indicating if the buffer above is being used */
- JSBool hasRandomAccess; /* can the file be randomly accessed? false for stdin, and
- UTF-encoded files. */
- JSBool hasAutoflush; /* should we force a flush for each line break? */
- JSBool isNative; /* if the file is using OS-specific file FILE type */
- /* We can actually put the following two in a union since they should never be used at the same time */
- PRFileDesc *handle; /* the handle for the file, if open. */
- FILE *nativehandle; /* native handle, for stuff NSPR doesn't do. */
- JSBool isPipe; /* if the file is really an OS pipe */
-} JSFile;
-
-/* a few forward declarations... */
-static JSClass file_class;
-JS_PUBLIC_API(JSObject*) js_NewFileObject(JSContext *cx, char *filename);
-static JSBool file_open(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
-static JSBool file_close(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
-
-/* --------------------------- New filename manipulation procesures -------------------------- */
-/* assumes we don't have leading/trailing spaces */
-static JSBool
-js_filenameHasAPipe(const char *filename)
-{
-#ifdef XP_MAC
- /* pipes are not supported on the MAC */
- return JS_FALSE;
-#else
- if(!filename) return JS_FALSE;
- return filename[0]==PIPE_SYMBOL ||
- filename[strlen(filename)-1]==PIPE_SYMBOL;
-#endif
-}
-
-static JSBool
-js_isAbsolute(const char *name)
-{
-#if defined(XP_WIN) || defined(XP_OS2)
- return (strlen(name)>1)?((name[1]==':')?JS_TRUE:JS_FALSE):JS_FALSE;
-#else
- return (name[0]
-# if defined(XP_UNIX) || defined(XP_BEOS)
- ==
-# else
- !=
-# endif
- FILESEPARATOR)?JS_TRUE:JS_FALSE;
-#endif
-}
-
-/*
- Concatinates base and name to produce a valid filename.
- Returned string must be freed.
-*/
-static char*
-js_combinePath(JSContext *cx, const char *base, const char *name)
-{
- int len = strlen(base);
- char* result = (char*)JS_malloc(cx, len+strlen(name)+2);
-
- if (!result) return NULL;
-
- strcpy(result, base);
-
- if (base[len-1]!=FILESEPARATOR
-#if defined(XP_WIN) || defined(XP_OS2)
- && base[len-1]!=FILESEPARATOR2
-#endif
- ) {
- result[len] = FILESEPARATOR;
- result[len+1] = '\0';
- }
- strcat(result, name);
- return result;
-}
-
-/* Extract the last component from a path name. Returned string must be freed */
-static char *
-js_fileBaseName(JSContext *cx, const char *pathname)
-{
- jsint index, aux;
- char *result;
-
-#if defined(XP_WIN) || defined(XP_OS2)
- /* First, get rid of the drive selector */
- if ((strlen(pathname)>=2)&&(pathname[1]==':')) {
- pathname = &pathname[2];
- }
-#endif
- index = strlen(pathname)-1;
- /*
- remove trailing separators -- don't necessarily need to check for
- FILESEPARATOR2, but that's fine
- */
- while ((index>0)&&((pathname[index]==FILESEPARATOR)||
- (pathname[index]==FILESEPARATOR2))) index--;
- aux = index;
- /* now find the next separator */
- while ((index>=0)&&(pathname[index]!=FILESEPARATOR)&&
- (pathname[index]!=FILESEPARATOR2)) index--;
- /* allocate and copy */
- result = (char*)JS_malloc(cx, aux-index+1);
- if (!result) return NULL;
- strncpy(result, &pathname[index+1], aux-index);
- result[aux-index] = '\0';
- return result;
-}
-
-/*
- Returns everytynig but the last component from a path name.
- Returned string must be freed. Returned string must be freed.
-*/
-static char *
-js_fileDirectoryName(JSContext *cx, const char *pathname)
-{
- jsint index;
- char *result;
-
-#if defined(XP_WIN) || defined(XP_OS2)
- char drive = '\0';
- const char *oldpathname = pathname;
-
- /* First, get rid of the drive selector */
- if ((strlen(pathname)>=2)&&(pathname[1]==':')) {
- drive = pathname[0];
- pathname = &pathname[2];
- }
-#endif
- index = strlen(pathname)-1;
- while ((index>0)&&((pathname[index]==FILESEPARATOR)||
- (pathname[index]==FILESEPARATOR2))) index--;
- while ((index>0)&&(pathname[index]!=FILESEPARATOR)&&
- (pathname[index]!=FILESEPARATOR2)) index--;
-
- if (index>=0){
- result = (char*)JS_malloc(cx, index+4);
- if (!result) return NULL;
-#if defined(XP_WIN) || defined(XP_OS2)
- if (drive!='\0') {
- result[0] = toupper(drive);
- result[1] = ':';
- strncpy(&result[2], pathname, index);
- result[index+3] = '\0';
- }else
-#endif
- {
- strncpy(result, pathname, index);
- result[index] = '\0';
- }
-
- /* add terminating separator */
- index = strlen(result)-1;
- result[index] = FILESEPARATOR;
- result[index+1] = '\0';
- } else{
-#if defined(XP_WIN) || defined(XP_OS2)
- result = JS_strdup(cx, oldpathname); /* may include drive selector */
-#else
- result = JS_strdup(cx, pathname);
-#endif
- }
-
- return result;
-}
-
-static char *
-js_absolutePath(JSContext *cx, const char * path)
-{
- JSObject *obj;
- JSString *str;
- jsval prop;
-
- if (js_isAbsolute(path)){
- return JS_strdup(cx, path);
- }else{
- obj = JS_GetGlobalObject(cx);
- if (!JS_GetProperty(cx, obj, FILE_CONSTRUCTOR, &prop)) {
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_FILE_CONSTRUCTOR_UNDEFINED_ERROR);
- return JS_strdup(cx, path);
- }
- obj = JSVAL_TO_OBJECT(prop);
- if (!JS_GetProperty(cx, obj, CURRENTDIR_PROPERTY, &prop)) {
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_FILE_CURRENTDIR_UNDEFINED_ERROR);
- return JS_strdup(cx, path);
- }
- str = JS_ValueToString(cx, prop);
- if (!str ) {
- return JS_strdup(cx, path);
- }
- /* should we have an array of curr dirs indexed by drive for windows? */
- return js_combinePath(cx, JS_GetStringBytes(str), path);
- }
-}
-
-/* Side effect: will remove spaces in the beginning/end of the filename */
-static char *
-js_canonicalPath(JSContext *cx, char *oldpath)
-{
- char *tmp;
- char *path = oldpath;
- char *base, *dir, *current, *result;
- jsint c;
- jsint back = 0;
- unsigned int i = 0, j = strlen(path)-1;
-
- /* This is probably optional */
- /* Remove possible spaces in the beginning and end */
- while(i<strlen(path)-1 && path[i]==' ') i++;
- while(j>=0 && path[j]==' ') j--;
-
- tmp = JS_malloc(cx, j-i+2);
- strncpy(tmp, &path[i], j-i+1);
- tmp[j-i+1] = '\0';
-
- path = tmp;
-
- /* pipe support */
- if(js_filenameHasAPipe(path))
- return JS_strdup(cx, path);
- /* file:// support */
- if(!strncmp(path, URL_PREFIX, strlen(URL_PREFIX)))
- return js_canonicalPath(cx, &path[strlen(URL_PREFIX)-1]);
-
- if (!js_isAbsolute(path))
- path = js_absolutePath(cx, path);
- else
- path = JS_strdup(cx, path);
-
- result = JS_strdup(cx, "");
-
- current = path;
-
- base = js_fileBaseName(cx, current);
- dir = js_fileDirectoryName(cx, current);
-
- /* TODO: MAC -- not going to work??? */
- while (strcmp(dir, current)) {
- if (!strcmp(base, "..")) {
- back++;
- } else
- if(!strcmp(base, ".")){
- /* ??? */
- } else {
- if (back>0)
- back--;
- else {
- tmp = result;
- result = JS_malloc(cx, strlen(base)+1+strlen(tmp)+1);
- if (!result) {
- JS_free(cx, dir);
- JS_free(cx, base);
- JS_free(cx, current);
- return NULL;
- }
- strcpy(result, base);
- c = strlen(result);
- if (*tmp) {
- result[c] = FILESEPARATOR;
- result[c+1] = '\0';
- strcat(result, tmp);
- }
- JS_free(cx, tmp);
- }
- }
- JS_free(cx, current);
- JS_free(cx, base);
- current = dir;
- base = js_fileBaseName(cx, current);
- dir = js_fileDirectoryName(cx, current);
- }
-
- tmp = result;
- result = JS_malloc(cx, strlen(dir)+1+strlen(tmp)+1);
- if (!result) {
- JS_free(cx, dir);
- JS_free(cx, base);
- JS_free(cx, current);
- return NULL;
- }
- strcpy(result, dir);
- c = strlen(result);
- if (tmp[0]!='\0') {
- if ((result[c-1]!=FILESEPARATOR)&&(result[c-1]!=FILESEPARATOR2)) {
- result[c] = FILESEPARATOR;
- result[c+1] = '\0';
- }
- strcat(result, tmp);
- }
- JS_free(cx, tmp);
- JS_free(cx, dir);
- JS_free(cx, base);
- JS_free(cx, current);
-
- return result;
-}
-
-/* -------------------------- Text conversion ------------------------------- */
-/* The following is ripped from libi18n/unicvt.c and include files.. */
-
-/*
- * UTF8 defines and macros
- */
-#define ONE_OCTET_BASE 0x00 /* 0xxxxxxx */
-#define ONE_OCTET_MASK 0x7F /* x1111111 */
-#define CONTINUING_OCTET_BASE 0x80 /* 10xxxxxx */
-#define CONTINUING_OCTET_MASK 0x3F /* 00111111 */
-#define TWO_OCTET_BASE 0xC0 /* 110xxxxx */
-#define TWO_OCTET_MASK 0x1F /* 00011111 */
-#define THREE_OCTET_BASE 0xE0 /* 1110xxxx */
-#define THREE_OCTET_MASK 0x0F /* 00001111 */
-#define FOUR_OCTET_BASE 0xF0 /* 11110xxx */
-#define FOUR_OCTET_MASK 0x07 /* 00000111 */
-#define FIVE_OCTET_BASE 0xF8 /* 111110xx */
-#define FIVE_OCTET_MASK 0x03 /* 00000011 */
-#define SIX_OCTET_BASE 0xFC /* 1111110x */
-#define SIX_OCTET_MASK 0x01 /* 00000001 */
-
-#define IS_UTF8_1ST_OF_1(x) (( (x)&~ONE_OCTET_MASK ) == ONE_OCTET_BASE)
-#define IS_UTF8_1ST_OF_2(x) (( (x)&~TWO_OCTET_MASK ) == TWO_OCTET_BASE)
-#define IS_UTF8_1ST_OF_3(x) (( (x)&~THREE_OCTET_MASK) == THREE_OCTET_BASE)
-#define IS_UTF8_1ST_OF_4(x) (( (x)&~FOUR_OCTET_MASK ) == FOUR_OCTET_BASE)
-#define IS_UTF8_1ST_OF_5(x) (( (x)&~FIVE_OCTET_MASK ) == FIVE_OCTET_BASE)
-#define IS_UTF8_1ST_OF_6(x) (( (x)&~SIX_OCTET_MASK ) == SIX_OCTET_BASE)
-#define IS_UTF8_2ND_THRU_6TH(x) \
- (( (x)&~CONTINUING_OCTET_MASK ) == CONTINUING_OCTET_BASE)
-#define IS_UTF8_1ST_OF_UCS2(x) \
- IS_UTF8_1ST_OF_1(x) \
- || IS_UTF8_1ST_OF_2(x) \
- || IS_UTF8_1ST_OF_3(x)
-
-
-#define MAX_UCS2 0xFFFF
-#define DEFAULT_CHAR 0x003F /* Default char is "?" */
-#define BYTE_MASK 0xBF
-#define BYTE_MARK 0x80
-
-
-/* Function: one_ucs2_to_utf8_char
- *
- * Function takes one UCS-2 char and writes it to a UTF-8 buffer.
- * We need a UTF-8 buffer because we don't know before this
- * function how many bytes of utf-8 data will be written. It also
- * takes a pointer to the end of the UTF-8 buffer so that we don't
- * overwrite data. This function returns the number of UTF-8 bytes
- * of data written, or -1 if the buffer would have been overrun.
- */
-
-#define LINE_SEPARATOR 0x2028
-#define PARAGRAPH_SEPARATOR 0x2029
-static int16 one_ucs2_to_utf8_char(unsigned char *tobufp,
- unsigned char *tobufendp, uint16 onechar)
-{
-
- int16 numUTF8bytes = 0;
-
- if((onechar == LINE_SEPARATOR)||(onechar == PARAGRAPH_SEPARATOR))
- {
- strcpy((char*)tobufp, "\n");
- return strlen((char*)tobufp);;
- }
-
- if (onechar < 0x80) { numUTF8bytes = 1;
- } else if (onechar < 0x800) { numUTF8bytes = 2;
- } else if (onechar <= MAX_UCS2) { numUTF8bytes = 3;
- } else { numUTF8bytes = 2;
- onechar = DEFAULT_CHAR;
- }
-
- tobufp += numUTF8bytes;
-
- /* return error if we don't have space for the whole character */
- if (tobufp > tobufendp) {
- return(-1);
- }
-
-
- switch(numUTF8bytes) {
-
- case 3: *--tobufp = (onechar | BYTE_MARK) & BYTE_MASK; onechar >>=6;
- *--tobufp = (onechar | BYTE_MARK) & BYTE_MASK; onechar >>=6;
- *--tobufp = onechar | THREE_OCTET_BASE;
- break;
-
- case 2: *--tobufp = (onechar | BYTE_MARK) & BYTE_MASK; onechar >>=6;
- *--tobufp = onechar | TWO_OCTET_BASE;
- break;
- case 1: *--tobufp = (unsigned char)onechar; break;
- }
-
- return(numUTF8bytes);
-}
-
-/*
- * utf8_to_ucs2_char
- *
- * Convert a utf8 multibyte character to ucs2
- *
- * inputs: pointer to utf8 character(s)
- * length of utf8 buffer ("read" length limit)
- * pointer to return ucs2 character
- *
- * outputs: number of bytes in the utf8 character
- * -1 if not a valid utf8 character sequence
- * -2 if the buffer is too short
- */
-static int16
-utf8_to_ucs2_char(const unsigned char *utf8p, int16 buflen, uint16 *ucs2p)
-{
- uint16 lead, cont1, cont2;
-
- /*
- * Check for minimum buffer length
- */
- if ((buflen < 1) || (utf8p == NULL)) {
- return -2;
- }
- lead = (uint16) (*utf8p);
-
- /*
- * Check for a one octet sequence
- */
- if (IS_UTF8_1ST_OF_1(lead)) {
- *ucs2p = lead & ONE_OCTET_MASK;
- return 1;
- }
-
- /*
- * Check for a two octet sequence
- */
- if (IS_UTF8_1ST_OF_2(*utf8p)) {
- if (buflen < 2)
- return -2;
- cont1 = (uint16) *(utf8p+1);
- if (!IS_UTF8_2ND_THRU_6TH(cont1))
- return -1;
- *ucs2p = (lead & TWO_OCTET_MASK) << 6;
- *ucs2p |= cont1 & CONTINUING_OCTET_MASK;
- return 2;
- }
-
- /*
- * Check for a three octet sequence
- */
- else if (IS_UTF8_1ST_OF_3(lead)) {
- if (buflen < 3)
- return -2;
- cont1 = (uint16) *(utf8p+1);
- cont2 = (uint16) *(utf8p+2);
- if ( (!IS_UTF8_2ND_THRU_6TH(cont1))
- || (!IS_UTF8_2ND_THRU_6TH(cont2)))
- return -1;
- *ucs2p = (lead & THREE_OCTET_MASK) << 12;
- *ucs2p |= (cont1 & CONTINUING_OCTET_MASK) << 6;
- *ucs2p |= cont2 & CONTINUING_OCTET_MASK;
- return 3;
- }
- else { /* not a valid utf8/ucs2 character */
- return -1;
- }
-}
-
-/* ----------------------------- Helper functions --------------------------- */
-/* Ripped off from lm_win.c .. */
-/* where is strcasecmp?.. for now, it's case sensitive..
- *
- * strcasecmp is in strings.h, but on windows it's called _stricmp...
- * will need to #ifdef this
-*/
-
-static int32
-js_FileHasOption(JSContext *cx, const char *oldoptions, const char *name)
-{
- char *comma, *equal, *current;
- char *options = JS_strdup(cx, oldoptions);
- int32 found = 0;
-
- current = options;
- for (;;) {
- comma = strchr(current, ',');
- if (comma) *comma = '\0';
- equal = strchr(current, '=');
- if (equal) *equal = '\0';
- if (strcmp(current, name) == 0) {
- if (!equal || strcmp(equal + 1, "yes") == 0)
- found = 1;
- else
- found = atoi(equal + 1);
- }
- if (equal) *equal = '=';
- if (comma) *comma = ',';
- if (found || !comma)
- break;
- current = comma + 1;
- }
- JS_free(cx, options);
- return found;
-}
-
-/* empty the buffer */
-static void
-js_ResetBuffers(JSFile * file)
-{
- file->charBufferUsed = JS_FALSE;
- file->nbBytesInBuf = 0;
- file->linebuffer = NULL; /* TODO: check for mem. leak? */
-}
-
-/* Reset file attributes */
-static void
-js_ResetAttributes(JSFile * file){
- file->mode = file->type = 0;
- file->isOpen = JS_FALSE;
- file->handle = NULL;
- file->nativehandle = NULL;
- file->hasRandomAccess = JS_TRUE; /* innocent until proven guilty */
- file->hasAutoflush = JS_FALSE;
- file->isNative = JS_FALSE;
- file->isPipe = JS_FALSE;
-
- js_ResetBuffers(file);
-}
-
-static JSBool
-js_FileOpen(JSContext *cx, JSObject *obj, JSFile *file, char *mode){
- JSString *type, *mask;
- jsval v[2];
- jsval rval;
-
- type = JS_InternString(cx, asciistring);
- mask = JS_NewStringCopyZ(cx, mode);
- v[0] = STRING_TO_JSVAL(mask);
- v[1] = STRING_TO_JSVAL(type);
-
- if (!file_open(cx, obj, 2, v, &rval)) {
- return JS_FALSE;
- }
- return JS_TRUE;
-}
-
-/* Buffered version of PR_Read. Used by js_FileRead */
-static int32
-js_BufferedRead(JSFile * f, char *buf, int32 len)
-{
- int32 count = 0;
-
- while (f->nbBytesInBuf>0&&len>0) {
- buf[0] = f->byteBuffer[0];
- f->byteBuffer[0] = f->byteBuffer[1];
- f->byteBuffer[1] = f->byteBuffer[2];
- f->nbBytesInBuf--;
- len--;
- buf+=1;
- count++;
- }
-
- if (len>0) {
- count+= (!f->isNative)?
- PR_Read(f->handle, buf, len):
- fread(buf, 1, len, f->nativehandle);
- }
- return count;
-}
-
-static int32
-js_FileRead(JSContext *cx, JSFile * file, jschar*buf, int32 len, int32 mode)
-{
- unsigned char*aux;
- int32 count, i;
- jsint remainder;
- unsigned char utfbuf[3];
-
- if (file->charBufferUsed) {
- buf[0] = file->charBuffer;
- buf++;
- len--;
- file->charBufferUsed = JS_FALSE;
- }
-
- switch (mode) {
- case ASCII:
- aux = (unsigned char*)JS_malloc(cx, len);
- if (!aux) {
- return 0;
- }
- count = js_BufferedRead(file, aux, len);
- if (count==-1) {
- JS_free(cx, aux);
- return 0;
- }
- for (i = 0;i<len;i++) {
- buf[i] = (jschar)aux[i];
- }
- JS_free(cx, aux);
- break;
- case UTF8:
- remainder = 0;
- for (count = 0;count<len;count++) {
- i = js_BufferedRead(file, utfbuf+remainder, 3-remainder);
- if (i<=0) {
- return count;
- }
- i = utf8_to_ucs2_char(utfbuf, (int16)i, &buf[count] );
- if (i<0) {
- return count;
- } else {
- if (i==1) {
- utfbuf[0] = utfbuf[1];
- utfbuf[1] = utfbuf[2];
- remainder = 2;
- } else
- if (i==2) {
- utfbuf[0] = utfbuf[2];
- remainder = 1;
- } else
- if (i==3)
- remainder = 0;
- }
- }
- while (remainder>0) {
- file->byteBuffer[file->nbBytesInBuf] = utfbuf[0];
- file->nbBytesInBuf++;
- utfbuf[0] = utfbuf[1];
- utfbuf[1] = utfbuf[2];
- remainder--;
- }
- break;
- case UCS2:
- count = js_BufferedRead(file, (char*)buf, len*2)>>1;
- if (count==-1) {
- return 0;
- }
- break;
- }
-
- if(count==-1){
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_OP_FAILED, "read", file->path);
- }
-
- return count;
-}
-
-static int32
-js_FileSeek(JSContext *cx, JSFile *file, int32 len, int32 mode)
-{
- int32 count, i;
- jsint remainder;
- unsigned char utfbuf[3];
- jschar tmp;
-
- switch (mode) {
- case ASCII:
- count = PR_Seek(file->handle, len, PR_SEEK_CUR);
- break;
- case UTF8:
- remainder = 0;
- for (count = 0;count<len;count++) {
- i = js_BufferedRead(file, utfbuf+remainder, 3-remainder);
- if (i<=0) {
- return 0;
- }
- i = utf8_to_ucs2_char(utfbuf, (int16)i, &tmp );
- if (i<0) {
- return 0;
- } else {
-
- if (i==1) {
- utfbuf[0] = utfbuf[1];
- utfbuf[1] = utfbuf[2];
- remainder = 2;
- } else
- if (i==2) {
- utfbuf[0] = utfbuf[2];
- remainder = 1;
- } else
- if (i==3)
- remainder = 0;
- }
- }
- while (remainder>0) {
- file->byteBuffer[file->nbBytesInBuf] = utfbuf[0];
- file->nbBytesInBuf++;
- utfbuf[0] = utfbuf[1];
- utfbuf[1] = utfbuf[2];
- remainder--;
- }
- break;
- case UCS2:
- count = PR_Seek(file->handle, len*2, PR_SEEK_CUR)/2;
- break;
- }
-
- if(count==-1){
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_OP_FAILED, "seek", file->path);
- }
-
- return count;
-}
-
-static int32
-js_FileWrite(JSContext *cx, JSFile *file, jschar *buf, int32 len, int32 mode)
-{
- unsigned char *aux;
- int32 count, i, j;
- unsigned char *utfbuf;
-
- switch (mode) {
- case ASCII:
- aux = (unsigned char*)JS_malloc(cx, len);
- if (!aux) return 0;
-
- for (i = 0; i<len; i++) {
- aux[i]=buf[i]%256;
- }
-
- count = (!file->isNative)?
- PR_Write(file->handle, aux, len):
- fwrite(aux, 1, len, file->nativehandle);
-
- if (count==-1) {
- JS_free(cx, aux);
- return 0;
- }
- JS_free(cx, aux);
- break;
- case UTF8:
- utfbuf = (unsigned char*)JS_malloc(cx, len*3);
- if (!utfbuf) return 0;
- i = 0;
- for (count = 0;count<len;count++) {
- j = one_ucs2_to_utf8_char(utfbuf+i, utfbuf+len*3, buf[count]);
- if (j==-1) {
- JS_free(cx, utfbuf);
- return 0;
- }
- i+=j;
- }
- j = (!file->isNative)?
- PR_Write(file->handle, utfbuf, i):
- fwrite(utfbuf, 1, i, file->nativehandle);
-
- if (j<i) {
- JS_free(cx, utfbuf);
- return 0;
- }
- JS_free(cx, utfbuf);
- break;
- case UCS2:
- count = (!file->isNative)?
- PR_Write(file->handle, buf, len*2)>>1:
- fwrite(buf, 1, len*2, file->nativehandle)>>1;
-
- if (count==-1) {
- return 0;
- }
- break;
- }
- if(count==-1){
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_OP_FAILED, "write", file->path);
- }
- return count;
-}
-
-/* ----------------------------- Property checkers -------------------------- */
-static JSBool
-js_exists(JSContext *cx, JSFile *file)
-{
- if(!file->isNative){
- return (PR_Access(file->path, PR_ACCESS_EXISTS)==PR_SUCCESS);
- }else{
- /* doesn't make sense for a pipe of stdstream */
- return JS_FALSE;
- }
-}
-
-static JSBool
-js_canRead(JSContext *cx, JSFile *file)
-{
- if(!file->isNative){
- if(file->isOpen&&!(file->mode&PR_RDONLY)) return JS_FALSE;
- return (PR_Access(file->path, PR_ACCESS_READ_OK)==PR_SUCCESS);
- }else{
- if(file->isPipe){
- /* pipe open for reading */
- return file->path[0]==PIPE_SYMBOL;
- }else{
- return !strcmp(file->path, STDINPUT_NAME);
- }
- }
-}
-
-static JSBool
-js_canWrite(JSContext *cx, JSFile *file)
-{
- if(!file->isNative){
- if(file->isOpen&&!(file->mode&PR_WRONLY)) return JS_FALSE;
- return (PR_Access(file->path, PR_ACCESS_WRITE_OK)==PR_SUCCESS);
- }else{
- if(file->isPipe){
- /* pipe open for writing */
- return file->path[strlen(file->path)-1]==PIPE_SYMBOL;
- }else{
- return !strcmp(file->path, STDOUTPUT_NAME) ||
- !strcmp(file->path, STDERROR_NAME);
- }
- }
-}
-
-static JSBool
-js_isFile(JSContext *cx, JSFile *file)
-{
- if(!file->isNative){
- PRFileInfo info;
-
- if ((file->isOpen)?
- PR_GetOpenFileInfo(file->handle, &info):
- PR_GetFileInfo(file->path, &info)!=PR_SUCCESS){
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_CANNOT_ACCESS_FILE_STATUS, file->path);
- return JS_FALSE;
- }else
- return (info.type==PR_FILE_FILE);
- }else{
- /* doesn't make sense for a pipe of stdstream */
- return JS_FALSE;
- }
-}
-
-static JSBool
-js_isDirectory(JSContext *cx, JSFile *file)
-{
- if(!file->isNative){
- PRFileInfo info;
-
- /* hack needed to get get_property to work */
- if(!js_exists(cx, file)) return JS_FALSE;
-
- if ((file->isOpen)?
- PR_GetOpenFileInfo(file->handle, &info):
- PR_GetFileInfo(file->path, &info)!=PR_SUCCESS){
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_CANNOT_ACCESS_FILE_STATUS, file->path);
- return JS_FALSE;
- }else
- return (info.type==PR_FILE_DIRECTORY);
- }else{
- /* doesn't make sense for a pipe of stdstream */
- return JS_FALSE;
- }
-}
-
-static jsval
-js_size(JSContext *cx, JSFile *file)
-{
- PRFileInfo info;
-
- JSFILE_CHECK_NATIVE("size");
-
- if ((file->isOpen)?
- PR_GetOpenFileInfo(file->handle, &info):
- PR_GetFileInfo(file->path, &info)!=PR_SUCCESS){
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_CANNOT_ACCESS_FILE_STATUS, file->path);
- goto out;
- }else
- return INT_TO_JSVAL(info.size);
-out:
- return JSVAL_VOID;
-}
-
-/* Return the parent object */
-static jsval
-js_parent(JSContext *cx, JSFile *file)
-{
- char *str;
-
- /* since we only care about pipes and native files, return NULL */
- if(file->isNative) return JSVAL_VOID;
-
- str = js_fileDirectoryName(cx, file->path);
- /* root.parent = null ??? */
- if(!strcmp(file->path, str) ||
- (!strncmp(str, file->path, strlen(str)-1)&&
- file->path[strlen(file->path)]-1)==FILESEPARATOR){
- return JSVAL_NULL;
- }else{
- return OBJECT_TO_JSVAL(js_NewFileObject(cx, str));
- JS_free(cx, str);
- }
-}
-
-static jsval
-js_name(JSContext *cx, JSFile *file){
- return file->isPipe?
- JSVAL_VOID:
- STRING_TO_JSVAL(JS_NewStringCopyZ(cx, js_fileBaseName(cx, file->path)));
-}
-
-/* ------------------------------ File object methods ---------------------------- */
-static JSBool
-file_open(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
- JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
- JSString *strmode, *strtype;
- char *ctype, *mode;
- int32 mask, type;
- int len;
-
- SECURITY_CHECK(cx, NULL, "open", file);
-
- /* A native file that is already open */
- if(file->isOpen && file->isNative){
- JS_ReportWarning(cx, "Native file %s is already open, proceeding",
- file->path);
- goto good;
- }
-
- /* Close before proceeding */
- if (file->isOpen) {
- JS_ReportWarning(cx,
- "File %s is already open, we will close it and reopen, proceeding",
- file->path);
- if(!file_close(cx, obj, 0, NULL, rval)) goto out;
- }
-
- if(js_isDirectory(cx, file)){
- JS_ReportWarning(cx, "%s seems to be a directory, there is no point in "
- "trying to open it, proceeding", file->path);
- goto good;
- }
-
- /* Path must be defined at this point */
- len = strlen(file->path);
-
- /* Mode */
- if (argc>=1){
- strmode = JS_ValueToString(cx, argv[0]);
- if (!strmode){
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_FIRST_ARGUMENT_OPEN_NOT_STRING_ERROR, argv[0]);
- goto out;
- }
- mode = JS_strdup(cx, JS_GetStringBytes(strmode));
- }else{
- if(file->path[0]==PIPE_SYMBOL){
- /* pipe default mode */
- mode = JS_strdup(cx, "read");
- }else
- if(file->path[len-1]==PIPE_SYMBOL){
- /* pipe default mode */
- mode = JS_strdup(cx, "write");
- }else{
- /* non-destructive, permissive defaults. */
- mode = JS_strdup(cx, "readWrite,append,create");
- }
- }
-
- /* Process the mode */
- mask = 0;
- /* TODO: this is pretty ugly, BTW, we walk thru the string too many times */
- mask|=(js_FileHasOption(cx, mode, "read"))? PR_RDONLY : 0;
- mask|=(js_FileHasOption(cx, mode, "write"))? PR_WRONLY : 0;
- mask|=(js_FileHasOption(cx, mode, "readWrite"))? PR_RDWR : 0;
- mask|=(js_FileHasOption(cx, mode, "append"))? PR_APPEND : 0;
- mask|=(js_FileHasOption(cx, mode, "create"))? PR_CREATE_FILE : 0;
- mask|=(js_FileHasOption(cx, mode, "replace"))? PR_TRUNCATE : 0;
-
- if((mask&PR_RDWR)) mask|=(PR_RDONLY|PR_WRONLY);
- if((mask&PR_RDONLY)&&(mask&PR_WRONLY)) mask|=PR_RDWR;
-
- file->hasAutoflush|=(js_FileHasOption(cx, mode, "autoflush"));
-
- /* Type */
- if (argc>1) {
- strtype = JS_ValueToString(cx, argv[1]);
- if (!strtype) {
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_SECOND_ARGUMENT_OPEN_NOT_STRING_ERROR, argv[1]);
- goto out;
- }
- ctype = JS_GetStringBytes(strtype);
-
- if(!strcmp(ctype, utfstring))
- type = UTF8;
- else
- if (!strcmp(ctype, unicodestring))
- type = UCS2;
- else{
- if(strcmp(ctype, asciistring)){
- JS_ReportWarning(cx, "File type %s is not supported, using "
- "'text' instead, proceeding", ctype);
- }
- type = ASCII;
- }
- }else{
- type = ASCII;
- }
-
- /* Save the relevant fields */
- file->type = type;
- file->mode = mask;
- file->nativehandle = NULL;
- file->hasRandomAccess = (type!=UTF8);
-
- /*
- Deal with pipes here. We can't use NSPR for pipes,
- so we have to use POPEN.
- */
- if(file->path[0]==PIPE_SYMBOL || file->path[len-1]==PIPE_SYMBOL){
- if(file->path[0]==PIPE_SYMBOL && file->path[len-1]==PIPE_SYMBOL){
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_BIDIRECTIONAL_PIPE_NOT_SUPPORTED);
- goto out;
- }else{
- char pipemode[3];
- SECURITY_CHECK(cx, NULL, "pipe_open", file);
-
- if(file->path[0] == PIPE_SYMBOL){
- if(mask & (PR_WRONLY | PR_APPEND | PR_CREATE_FILE | PR_TRUNCATE)){
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_OPEN_MODE_NOT_SUPPORTED_WITH_PIPES,
- mode, file->path);
- goto out;
- }
- /* open(SPOOLER, "| cat -v | lpr -h 2>/dev/null") -- pipe for writing */
- pipemode[0] = 'r';
- pipemode[1] = file->type==UTF8?'b':'t';
- pipemode[2] = '\0';
- file->nativehandle = POPEN(&file->path[1], pipemode);
- }else
- if(file->path[len-1] == PIPE_SYMBOL){
- char *command = JS_malloc(cx, len);
-
- strncpy(command, file->path, len-1);
- command[len-1] = '\0';
- /* open(STATUS, "netstat -an 2>&1 |") */
- pipemode[0] = 'w';
- pipemode[1] = file->type==UTF8?'b':'t';
- pipemode[2] = '\0';
- file->nativehandle = POPEN(command, pipemode);
- JS_free(cx, command);
- }
- /* set the flags */
- file->isNative = JS_TRUE;
- file->isPipe = JS_TRUE;
- file->hasRandomAccess = JS_FALSE;
- }
- }else{
- /* TODO: what about the permissions?? Java ignores the problem... */
- file->handle = PR_Open(file->path, mask, 0644);
- }
-
- js_ResetBuffers(file);
- JS_free(cx, mode);
- mode = NULL;
-
- /* Set the open flag and return result */
- if (file->handle==NULL && file->nativehandle==NULL){
- file->isOpen = JS_FALSE;
-
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_OP_FAILED, "open", file->path);
- goto out;
- }else
- goto good;
-good:
- file->isOpen = JS_TRUE;
- *rval = JSVAL_TRUE;
- return JS_TRUE;
-out:
- if(mode) JS_free(cx, mode);
- *rval = JSVAL_VOID;
- return JS_FALSE;
-}
-
-static JSBool
-file_close(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
- JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
-
- SECURITY_CHECK(cx, NULL, "close", file);
-
- if(!file->isOpen){
- JS_ReportWarning(cx, "File %s is not open, can't close it, proceeding",
- file->path);
- goto out;
- }
-
- if(!file->isPipe){
- if(file->isNative){
- JS_ReportWarning(cx, "Unable to close a native file, proceeding", file->path);
- goto out;
- }else{
- if(file->handle && PR_Close(file->handle)){
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_OP_FAILED, "close", file->path);
-
- goto out;
- }
- }
- }else{
- if(PCLOSE(file->nativehandle)==-1){
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_OP_FAILED, "pclose", file->path);
- goto out;
- }
- }
-
- js_ResetAttributes(file);
- *rval = JSVAL_TRUE;
- return JS_TRUE;
-out:
- *rval = JSVAL_FALSE;
- return JS_FALSE;
-}
-
-
-static JSBool
-file_remove(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
- JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
-
- SECURITY_CHECK(cx, NULL, "remove", file);
- JSFILE_CHECK_NATIVE("remove");
- JSFILE_CHECK_CLOSED("remove");
-
- if ((js_isDirectory(cx, file) ?
- PR_RmDir(file->path) : PR_Delete(file->path))==PR_SUCCESS) {
- js_ResetAttributes(file);
- *rval = JSVAL_TRUE;
- return JS_TRUE;
- } else {
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_OP_FAILED, "remove", file->path);
- goto out;
- }
-out:
- *rval = JSVAL_FALSE;
- return JS_FALSE;
-}
-
-/* Raw PR-based function. No text processing. Just raw data copying. */
-static JSBool
-file_copyTo(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
- JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
- char *dest = NULL;
- PRFileDesc *handle = NULL;
- char *buffer;
- jsval count, size;
- JSBool fileInitiallyOpen=JS_FALSE;
-
- SECURITY_CHECK(cx, NULL, "copyTo", file); /* may need a second argument!*/
- JSFILE_CHECK_ONE_ARG("copyTo");
- JSFILE_CHECK_NATIVE("copyTo");
- /* remeber the state */
- fileInitiallyOpen = file->isOpen;
- JSFILE_CHECK_READ;
-
- dest = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
-
- /* make sure we are not reading a file open for writing */
- if (file->isOpen && !js_canRead(cx, file)) {
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_CANNOT_COPY_FILE_OPEN_FOR_WRITING_ERROR, file->path);
- goto out;
- }
-
- if (file->handle==NULL){
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_OP_FAILED, "open", file->path);
- goto out;
- }
-
- handle = PR_Open(dest, PR_WRONLY|PR_CREATE_FILE|PR_TRUNCATE, 0644);
-
- if(!handle){
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_OP_FAILED, "open", dest);
- goto out;
- }
-
- if ((size=js_size(cx, file))==JSVAL_VOID) {
- goto out;
- }
-
- buffer = JS_malloc(cx, size);
-
- count = INT_TO_JSVAL(PR_Read(file->handle, buffer, size));
-
- /* reading panic */
- if (count!=size) {
- JS_free(cx, buffer);
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_COPY_READ_ERROR, file->path);
- goto out;
- }
-
- count = INT_TO_JSVAL(PR_Write(handle, buffer, JSVAL_TO_INT(size)));
-
- /* writing panic */
- if (count!=size) {
- JS_free(cx, buffer);
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_COPY_WRITE_ERROR, file->path);
- goto out;
- }
-
- JS_free(cx, buffer);
-
- if(!fileInitiallyOpen){
- if(!file_close(cx, obj, 0, NULL, rval)) goto out;
- }
-
- if(PR_Close(handle)!=PR_SUCCESS){
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_OP_FAILED, "close", dest);
- goto out;
- }
-
- *rval = JSVAL_TRUE;
- return JS_TRUE;
-out:
- if(file->isOpen && !fileInitiallyOpen){
- if(PR_Close(file->handle)!=PR_SUCCESS){
- JS_ReportWarning(cx, "Can't close %s, proceeding", file->path);
- }
- }
-
- if(handle && PR_Close(handle)!=PR_SUCCESS){
- JS_ReportWarning(cx, "Can't close %s, proceeding", dest);
- }
-
- *rval = JSVAL_FALSE;
- return JS_FALSE;
-}
-
-static JSBool
-file_renameTo(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
- JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
- char *dest;
-
- SECURITY_CHECK(cx, NULL, "renameTo", file); /* may need a second argument!*/
- JSFILE_CHECK_ONE_ARG("renameTo");
- JSFILE_CHECK_NATIVE("renameTo");
- JSFILE_CHECK_CLOSED("renameTo");
-
- dest = RESOLVE_PATH(cx, JS_GetStringBytes(JS_ValueToString(cx, argv[0])));
-
- if (PR_Rename(file->path, dest)==PR_SUCCESS){
- /* copy the new filename */
- JS_free(cx, file->path);
- file->path = dest;
- *rval = JSVAL_TRUE;
- return JS_TRUE;
- }else{
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_RENAME_FAILED, file->path, dest);
- goto out;
- }
-out:
- *rval = JSVAL_FALSE;
- return JS_FALSE;
-}
-
-static JSBool
-file_flush(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
- JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
-
- SECURITY_CHECK(cx, NULL, "flush", file);
- JSFILE_CHECK_NATIVE("flush");
- JSFILE_CHECK_OPEN("flush");
-
- if (PR_Sync(file->handle)==PR_SUCCESS){
- *rval = JSVAL_TRUE;
- return JS_TRUE;
- }else{
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_OP_FAILED, "flush", file->path);
- goto out;
- }
-out:
- *rval = JSVAL_FALSE;
- return JS_FALSE;
-}
-
-static JSBool
-file_write(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
- JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
- JSString *str;
- int32 count;
- uintN i;
-
- SECURITY_CHECK(cx, NULL, "write", file);
- JSFILE_CHECK_WRITE;
-
- for (i = 0; i<argc; i++) {
- str = JS_ValueToString(cx, argv[i]);
- count = js_FileWrite(cx, file, JS_GetStringChars(str),
- JS_GetStringLength(str), file->type);
- if (count==-1){
- *rval = JSVAL_FALSE;
- return JS_FALSE;
- }
- }
-
- *rval = JSVAL_TRUE;
- return JS_TRUE;
-out:
- *rval = JSVAL_FALSE;
- return JS_FALSE;
-}
-
-static JSBool
-file_writeln(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
- JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
- JSString *str;
-
- SECURITY_CHECK(cx, NULL, "writeln", file);
- JSFILE_CHECK_WRITE;
-
- /* don't report an error here */
- if(!file_write(cx, obj, argc, argv, rval)) return JS_FALSE;
- /* don't do security here -- we passed the check in file_write */
- str = JS_NewStringCopyZ(cx, "\n");
-
- if (js_FileWrite(cx, file, JS_GetStringChars(str), JS_GetStringLength(str),
- file->type)==-1){
- *rval = JSVAL_FALSE;
- return JS_FALSE;
- }
-
- /* eol causes flush if hasAutoflush is turned on */
- if (file->hasAutoflush)
- file_flush(cx, obj, 0, NULL, rval);
-
- *rval = JSVAL_TRUE;
- return JS_TRUE;
-out:
- *rval = JSVAL_FALSE;
- return JS_FALSE;
-}
-
-static JSBool
-file_writeAll(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
- JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
- jsuint i;
- jsuint limit;
- JSObject *array;
- JSObject *elem;
- jsval elemval;
-
- SECURITY_CHECK(cx, NULL, "writeAll", file);
- JSFILE_CHECK_ONE_ARG("writeAll");
- JSFILE_CHECK_WRITE;
-
- if (!JS_IsArrayObject(cx, JSVAL_TO_OBJECT(argv[0]))) {
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_FIRST_ARGUMENT_WRITEALL_NOT_ARRAY_ERROR);
- goto out;
- }
-
- array = JSVAL_TO_OBJECT(argv[0]);
-
- JS_GetArrayLength(cx, array, &limit);
-
- for (i = 0; i<limit; i++) {
- if (!JS_GetElement(cx, array, i, &elemval)) return JS_FALSE;
- elem = JSVAL_TO_OBJECT(elemval);
- file_writeln(cx, obj, 1, &elemval, rval);
- }
-
- *rval = JSVAL_TRUE;
- return JS_TRUE;
-out:
- *rval = JSVAL_FALSE;
- return JS_FALSE;
-}
-
-static JSBool
-file_read(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
- JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
- JSString *str;
- int32 want, count;
- jschar *buf;
-
- SECURITY_CHECK(cx, NULL, "read", file);
- JSFILE_CHECK_ONE_ARG("read");
- JSFILE_CHECK_READ;
-
- if (!JS_ValueToInt32(cx, argv[0], &want)){
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_FIRST_ARGUMENT_MUST_BE_A_NUMBER, "read", argv[0]);
- goto out;
- }
-
- /* want = (want>262144)?262144:want; * arbitrary size limitation */
-
- buf = JS_malloc(cx, want*sizeof buf[0]);
- if (!buf) goto out;
-
- count = js_FileRead(cx, file, buf, want, file->type);
- if (count>0) {
- str = JS_NewUCStringCopyN(cx, buf, count);
- *rval = STRING_TO_JSVAL(str);
- JS_free(cx, buf);
- return JS_TRUE;
- } else {
- JS_free(cx, buf);
- goto out;
- }
-out:
- *rval = JSVAL_FALSE;
- return JS_FALSE;
-}
-
-static JSBool
-file_readln(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
- JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
- JSString *str;
- jschar *buf;
- int32 offset;
- intN room;
- jschar data, data2;
- JSBool endofline;
-
- SECURITY_CHECK(cx, NULL, "readln", file);
- JSFILE_CHECK_READ;
-
- if (!file->linebuffer) {
- buf = JS_malloc(cx, MAX_LINE_LENGTH*(sizeof data));
- if (!buf) goto out;
- file->linebuffer = JS_NewUCString(cx, buf, MAX_LINE_LENGTH);
- }
- room = JS_GetStringLength(file->linebuffer);
- offset = 0;
-
- /* XXX TEST ME!! TODO: yes, please do */
- for(;;) {
- if (!js_FileRead(cx, file, &data, 1, file->type)) {
- endofline = JS_FALSE;
- goto loop;
- }
- switch (data) {
- case '\n' :
- endofline = JS_TRUE;
- goto loop;
- case '\r' :
- if (!js_FileRead(cx, file, &data2, 1, file->type)) {
- endofline = JS_TRUE;
- goto loop;
- }
- if (data2!='\n') { /* We read one char too far. Buffer it. */
- file->charBuffer = data2;
- file->charBufferUsed = JS_TRUE;
- }
- endofline = JS_TRUE;
- goto loop;
- default:
- if (--room < 0) {
- buf = JS_malloc(cx, (offset+MAX_LINE_LENGTH)*sizeof data);
- if (!buf) return JS_FALSE;
- room = MAX_LINE_LENGTH-1;
- memcpy(buf, JS_GetStringChars(file->linebuffer),
- JS_GetStringLength(file->linebuffer));
- /* what follows may not be the cleanest way. */
- file->linebuffer->chars = buf;
- file->linebuffer->length = offset+MAX_LINE_LENGTH;
- }
- file->linebuffer->chars[offset++] = data;
- break;
- }
- }
-loop:
- file->linebuffer->chars[offset] = 0;
- if ((endofline==JS_TRUE)) {
- str = JS_NewUCStringCopyN(cx, JS_GetStringChars(file->linebuffer),
- offset);
- *rval = STRING_TO_JSVAL(str);
- return JS_TRUE;
- }else{
- goto out;
- }
-out:
- *rval = JSVAL_NULL;
- return JS_FALSE;
-}
-
-static JSBool
-file_readAll(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
- JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
- JSObject *array;
- jsint len;
- jsval line;
-
- SECURITY_CHECK(cx, NULL, "readAll", file);
- JSFILE_CHECK_READ;
-
- array = JS_NewArrayObject(cx, 0, NULL);
- len = 0;
-
- while(file_readln(cx, obj, 0, NULL, &line)){
- JS_SetElement(cx, array, len, &line);
- len++;
- }
-
- *rval = OBJECT_TO_JSVAL(array);
- return JS_TRUE;
-out:
- *rval = JSVAL_FALSE;
- return JS_FALSE;
-}
-
-static JSBool
-file_seek(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
- JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
- int32 toskip;
- int32 pos;
-
- SECURITY_CHECK(cx, NULL, "seek", file);
- JSFILE_CHECK_ONE_ARG("seek");
- JSFILE_CHECK_NATIVE("seek");
- JSFILE_CHECK_READ;
-
- if (!JS_ValueToInt32(cx, argv[0], &toskip)){
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_FIRST_ARGUMENT_MUST_BE_A_NUMBER, "seek", argv[0]);
- goto out;
- }
-
- if(!file->hasRandomAccess){
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_NO_RANDOM_ACCESS, file->path);
- goto out;
- }
-
- if(js_isDirectory(cx, file)){
- JS_ReportWarning(cx,"Seek on directories is not supported, proceeding");
- goto out;
- }
-
- pos = js_FileSeek(cx, file, toskip, file->type);
-
- if (pos!=-1) {
- *rval = INT_TO_JSVAL(pos);
- return JS_TRUE;
- }
-out:
- *rval = JSVAL_VOID;
- return JS_FALSE;
-}
-
-static JSBool
-file_list(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
- PRDir *dir;
- PRDirEntry *entry;
- JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
- JSObject *array;
- JSObject *eachFile;
- jsint len;
- jsval v;
- JSRegExp *re = NULL;
- JSFunction *func = NULL;
- JSString *str;
- jsval args[1];
- char *filePath;
-
- SECURITY_CHECK(cx, NULL, "list", file);
- JSFILE_CHECK_NATIVE("list");
-
- if (argc==1) {
- if (JSVAL_IS_REGEXP(cx, argv[0])) {
- re = JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
- }else
- if (JSVAL_IS_FUNCTION(cx, argv[0])) {
- func = JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
- }else{
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_FIRST_ARGUMENT_MUST_BE_A_FUNCTION_OR_REGEX, argv[0]);
- goto out;
- }
- }
-
- if (!js_isDirectory(cx, file)) {
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_CANNOT_DO_LIST_ON_A_FILE, file->path);
- goto out;
- }
-
- dir = PR_OpenDir(file->path);
- if(!dir){
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_OP_FAILED, "open", file->path);
- goto out;
- }
-
- /* create JSArray here... */
- array = JS_NewArrayObject(cx, 0, NULL);
- len = 0;
-
- while ((entry = PR_ReadDir(dir, PR_SKIP_BOTH))!=NULL) {
- /* first, check if we have a regexp */
- if (re!=NULL) {
- size_t index = 0;
-
- str = JS_NewStringCopyZ(cx, entry->name);
- if(!js_ExecuteRegExp(cx, re, str, &index, JS_TRUE, &v)){
- /* don't report anything here */
- goto out;
- }
- /* not matched! */
- if (JSVAL_IS_NULL(v)) {
- continue;
- }
- }else
- if (func!=NULL) {
- str = JS_NewStringCopyZ(cx, entry->name);
- args[0] = STRING_TO_JSVAL(str);
- if(!JS_CallFunction(cx, obj, func, 1, args, &v)){
- goto out;
- }
-
- if (v==JSVAL_FALSE) {
- continue;
- }
- }
-
- filePath = js_combinePath(cx, file->path, (char*)entry->name);
-
- eachFile = js_NewFileObject(cx, filePath);
- JS_free(cx, filePath);
- if (!eachFile){
- JS_ReportWarning(cx, "File %s cannot be retrieved", filePath);
- continue;
- }
- v = OBJECT_TO_JSVAL(eachFile);
- JS_SetElement(cx, array, len, &v);
- JS_SetProperty(cx, array, entry->name, &v);
- len++;
- }
-
- if(PR_CloseDir(dir)!=PR_SUCCESS){
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_OP_FAILED, "close", file->path);
- goto out;
- }
- *rval = OBJECT_TO_JSVAL(array);
- return JS_TRUE;
-out:
- *rval = JSVAL_NULL;
- return JS_FALSE;
-}
-
-static JSBool
-file_mkdir(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
- JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
-
- SECURITY_CHECK(cx, NULL, "mkdir", file);
- JSFILE_CHECK_ONE_ARG("mkdir");
- JSFILE_CHECK_NATIVE("mkdir");
-
- /* if the current file is not a directory, find out the directory name */
- if (!js_isDirectory(cx, file)) {
- char *dir = js_fileDirectoryName(cx, file->path);
- JSObject *dirObj = js_NewFileObject(cx, dir);
-
- JS_free(cx, dir);
-
- /* call file_mkdir with the right set of parameters if needed */
- if (file_mkdir(cx, dirObj, argc, argv, rval))
- return JS_TRUE;
- else
- goto out;
- }else{
- char *dirName = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
- char *fullName;
-
- fullName = js_combinePath(cx, file->path, dirName);
- if (PR_MkDir(fullName, 0755)==PR_SUCCESS){
- *rval = JSVAL_TRUE;
- JS_free(cx, fullName);
- return JS_TRUE;
- }else{
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_OP_FAILED, "mkdir", fullName);
- JS_free(cx, fullName);
- goto out;
- }
- }
-out:
- *rval = JSVAL_FALSE;
- return JS_FALSE;
-}
-
-static JSBool
-file_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval*rval)
-{
- JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
-
- *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, file->path));
- return JS_TRUE;
-}
-
-static JSBool
-file_toURL(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
- JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
- char url[MAX_PATH_LENGTH];
- jschar *urlChars;
-
- JSFILE_CHECK_NATIVE("toURL");
-
- sprintf(url, "file://%s", file->path);
- /* TODO: js_escape in jsstr.h may go away at some point */
-
- urlChars = js_InflateString(cx, url, strlen(url));
- if (urlChars == NULL) return JS_FALSE;
- *rval = STRING_TO_JSVAL(js_NewString(cx, urlChars, strlen(url), 0));
- if (!js_str_escape(cx, obj, 0, rval, rval)) return JS_FALSE;
-
- return JS_TRUE;
-out:
- *rval = JSVAL_VOID;
- return JS_FALSE;
-}
-
-
-static void
-file_finalize(JSContext *cx, JSObject *obj)
-{
- JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
-
- if(file){
- /* close the file before exiting */
- if(file->isOpen && !file->isNative){
- jsval vp;
- file_close(cx, obj, 0, NULL, &vp);
- }
-
- if (file->path)
- JS_free(cx, file->path);
-
- JS_free(cx, file);
- }
-}
-
-/*
- Allocates memory for the file object, sets fields to defaults.
-*/
-static JSFile*
-file_init(JSContext *cx, JSObject *obj, char *bytes)
-{
- JSFile *file;
-
- file = JS_malloc(cx, sizeof *file);
- if (!file) return NULL;
- memset(file, 0 , sizeof *file);
-
- js_ResetAttributes(file);
-
- file->path = RESOLVE_PATH(cx, bytes);
-
- if (!JS_SetPrivate(cx, obj, file)) {
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_CANNOT_SET_PRIVATE_FILE, file->path);
- JS_free(cx, file);
- return NULL;
- }else
- return file;
-}
-
-/* Returns a JSObject. This function is globally visible */
-JS_PUBLIC_API(JSObject*)
-js_NewFileObject(JSContext *cx, char *filename)
-{
- JSObject *obj;
- JSFile *file;
-
- obj = JS_NewObject(cx, &file_class, NULL, NULL);
- if (!obj){
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_OBJECT_CREATION_FAILED, "js_NewFileObject");
- return NULL;
- }
- file = file_init(cx, obj, filename);
- if(!file) return NULL;
- return obj;
-}
-
-/* Internal function, used for cases which NSPR file support doesn't cover */
-JSObject*
-js_NewFileObjectFromFILE(JSContext *cx, FILE *nativehandle, char *filename,
- int32 mode, JSBool open, JSBool randomAccess)
-{
- JSObject *obj;
- JSFile *file;
-#ifdef XP_MAC
- JS_ReportWarning(cx, "Native files are not fully supported on the MAC");
-#endif
-
- obj = JS_NewObject(cx, &file_class, NULL, NULL);
- if (!obj){
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_OBJECT_CREATION_FAILED, "js_NewFileObjectFromFILE");
- return NULL;
- }
- file = file_init(cx, obj, filename);
- if(!file) return NULL;
-
- file->nativehandle = nativehandle;
-
- /* free result of RESOLVE_PATH from file_init. */
- JS_ASSERT(file->path != NULL);
- JS_free(cx, file->path);
-
- file->path = strdup(filename);
- file->isOpen = open;
- file->mode = mode;
- file->hasRandomAccess = randomAccess;
- file->isNative = JS_TRUE;
- return obj;
-}
-
-/*
- Real file constructor that is called from JavaScript.
- Basically, does error processing and calls file_init.
-*/
-static JSBool
-file_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
- jsval *rval)
-{
- JSString *str;
- JSFile *file;
-
- str = (argc==0)?JS_InternString(cx, ""):JS_ValueToString(cx, argv[0]);
-
- if (!str){
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_FIRST_ARGUMENT_CONSTRUCTOR_NOT_STRING_ERROR, argv[0]);
- goto out;
- }
-
- file = file_init(cx, obj, JS_GetStringBytes(str));
- if (!file) goto out;
-
- SECURITY_CHECK(cx, NULL, "constructor", file);
-
- return JS_TRUE;
-out:
- *rval = JSVAL_VOID;
- return JS_FALSE;
-}
-
-/* -------------------- File methods and properties ------------------------- */
-static JSFunctionSpec file_functions[] = {
- { "open", file_open, 0},
- { "close", file_close, 0},
- { "remove", file_remove, 0},
- { "copyTo", file_copyTo, 0},
- { "renameTo", file_renameTo, 0},
- { "flush", file_flush, 0},
- { "seek", file_seek, 0},
- { "read", file_read, 0},
- { "readln", file_readln, 0},
- { "readAll", file_readAll, 0},
- { "write", file_write, 0},
- { "writeln", file_writeln, 0},
- { "writeAll", file_writeAll, 0},
- { "list", file_list, 0},
- { "mkdir", file_mkdir, 0},
- { "toString", file_toString, 0},
- { "toURL", file_toURL, 0},
- {0}
-};
-
-enum file_tinyid {
- FILE_LENGTH = -2,
- FILE_PARENT = -3,
- FILE_PATH = -4,
- FILE_NAME = -5,
- FILE_ISDIR = -6,
- FILE_ISFILE = -7,
- FILE_EXISTS = -8,
- FILE_CANREAD = -9,
- FILE_CANWRITE = -10,
- FILE_OPEN = -11,
- FILE_TYPE = -12,
- FILE_MODE = -13,
- FILE_CREATED = -14,
- FILE_MODIFIED = -15,
- FILE_SIZE = -16,
- FILE_RANDOMACCESS = -17,
- FILE_POSITION = -18,
- FILE_APPEND = -19,
- FILE_REPLACE = -20,
- FILE_AUTOFLUSH = -21,
- FILE_ISNATIVE = -22,
-};
-
-static JSPropertySpec file_props[] = {
- {"length", FILE_LENGTH, JSPROP_ENUMERATE | JSPROP_READONLY },
- {"parent", FILE_PARENT, JSPROP_ENUMERATE | JSPROP_READONLY },
- {"path", FILE_PATH, JSPROP_ENUMERATE | JSPROP_READONLY },
- {"name", FILE_NAME, JSPROP_ENUMERATE | JSPROP_READONLY },
- {"isDirectory", FILE_ISDIR, JSPROP_ENUMERATE | JSPROP_READONLY },
- {"isFile", FILE_ISFILE, JSPROP_ENUMERATE | JSPROP_READONLY },
- {"exists", FILE_EXISTS, JSPROP_ENUMERATE | JSPROP_READONLY },
- {"canRead", FILE_CANREAD, JSPROP_ENUMERATE | JSPROP_READONLY },
- {"canWrite", FILE_CANWRITE, JSPROP_ENUMERATE | JSPROP_READONLY },
- {"canAppend", FILE_APPEND, JSPROP_ENUMERATE | JSPROP_READONLY },
- {"canReplace", FILE_REPLACE, JSPROP_ENUMERATE | JSPROP_READONLY },
- {"isOpen", FILE_OPEN, JSPROP_ENUMERATE | JSPROP_READONLY },
- {"type", FILE_TYPE, JSPROP_ENUMERATE | JSPROP_READONLY },
- {"mode", FILE_MODE, JSPROP_ENUMERATE | JSPROP_READONLY },
- {"creationTime", FILE_CREATED, JSPROP_ENUMERATE | JSPROP_READONLY },
- {"lastModified", FILE_MODIFIED, JSPROP_ENUMERATE | JSPROP_READONLY },
- {"size", FILE_SIZE, JSPROP_ENUMERATE | JSPROP_READONLY },
- {"hasRandomAccess", FILE_RANDOMACCESS, JSPROP_ENUMERATE | JSPROP_READONLY },
- {"hasAutoFlush", FILE_AUTOFLUSH, JSPROP_ENUMERATE | JSPROP_READONLY },
- {"position", FILE_POSITION, JSPROP_ENUMERATE },
- {"isNative", FILE_ISNATIVE, JSPROP_ENUMERATE | JSPROP_READONLY },
- {0}
-};
-
-/* ------------------------- Property getter/setter ------------------------- */
-static JSBool
-file_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
-{
- JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
- char *str;
- jsint tiny;
- PRFileInfo info;
- JSBool flag;
- PRExplodedTime
- expandedTime;
-
- tiny = JSVAL_TO_INT(id);
- if(!file) return JS_TRUE;
-
- switch (tiny) {
- case FILE_PARENT:
- SECURITY_CHECK(cx, NULL, "parent", file);
- *vp = js_parent(cx, file);
- break;
- case FILE_PATH:
- *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, file->path));
- break;
- case FILE_NAME:
- *vp = js_name(cx, file);
- break;
- case FILE_ISDIR:
- SECURITY_CHECK(cx, NULL, "isDirectory", file);
- *vp = BOOLEAN_TO_JSVAL(js_isDirectory(cx, file));
- break;
- case FILE_ISFILE:
- SECURITY_CHECK(cx, NULL, "isFile", file);
- *vp = BOOLEAN_TO_JSVAL(js_isFile(cx, file));
- break;
- case FILE_EXISTS:
- SECURITY_CHECK(cx, NULL, "exists", file);
- *vp = BOOLEAN_TO_JSVAL(js_exists(cx, file));
- break;
- case FILE_ISNATIVE:
- SECURITY_CHECK(cx, NULL, "isNative", file);
- *vp = BOOLEAN_TO_JSVAL(file->isNative);
- break;
- case FILE_CANREAD:
- SECURITY_CHECK(cx, NULL, "canRead", file);
- *vp = BOOLEAN_TO_JSVAL(js_canRead(cx, file));
- break;
- case FILE_CANWRITE:
- SECURITY_CHECK(cx, NULL, "canWrite", file);
- *vp = BOOLEAN_TO_JSVAL(js_canWrite(cx, file));
- break;
- case FILE_OPEN:
- SECURITY_CHECK(cx, NULL, "isOpen", file);
- *vp = BOOLEAN_TO_JSVAL(file->isOpen);
- break;
- case FILE_APPEND :
- SECURITY_CHECK(cx, NULL, "canAppend", file);
- JSFILE_CHECK_OPEN("canAppend");
- *vp = BOOLEAN_TO_JSVAL(!file->isNative &&
- (file->mode&PR_APPEND)==PR_APPEND);
- break;
- case FILE_REPLACE :
- SECURITY_CHECK(cx, NULL, "canReplace", file);
- JSFILE_CHECK_OPEN("canReplace");
- *vp = BOOLEAN_TO_JSVAL(!file->isNative &&
- (file->mode&PR_TRUNCATE)==PR_TRUNCATE);
- break;
- case FILE_AUTOFLUSH :
- SECURITY_CHECK(cx, NULL, "hasAutoFlush", file);
- JSFILE_CHECK_OPEN("hasAutoFlush");
- *vp = BOOLEAN_TO_JSVAL(!file->isNative && file->hasAutoflush);
- break;
- case FILE_TYPE:
- SECURITY_CHECK(cx, NULL, "type", file);
- JSFILE_CHECK_OPEN("type");
- if(js_isDirectory(cx, file)){
- *vp = JSVAL_VOID;
- break;
- }
-
- switch (file->type) {
- case ASCII:
- *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, asciistring));
- break;
- case UTF8:
- *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, utfstring));
- break;
- case UCS2:
- *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, unicodestring));
- break;
- default:
- JS_ReportWarning(cx, "Unsupported file type %d, proceeding",
- file->type);
- }
- break;
- case FILE_MODE:
- SECURITY_CHECK(cx, NULL, "mode", file);
- JSFILE_CHECK_OPEN("mode");
- str = (char*)JS_malloc(cx, MODE_SIZE);
- str[0] = '\0';
- flag = JS_FALSE;
-
- if ((file->mode&PR_RDONLY)==PR_RDONLY) {
- if (flag) strcat(str, ",");
- strcat(str, "read");
- flag = JS_TRUE;
- }
- if ((file->mode&PR_WRONLY)==PR_WRONLY) {
- if (flag) strcat(str, ",");
- strcat(str, "write");
- flag = JS_TRUE;
- }
- if ((file->mode&PR_RDWR)==PR_RDWR) {
- if (flag) strcat(str, ",");
- strcat(str, "readWrite");
- flag = JS_TRUE;
- }
- if ((file->mode&PR_APPEND)==PR_APPEND) {
- if (flag) strcat(str, ",");
- strcat(str, "append");
- flag = JS_TRUE;
- }
- if ((file->mode&PR_CREATE_FILE)==PR_CREATE_FILE) {
- if (flag) strcat(str, ",");
- strcat(str, "create");
- flag = JS_TRUE;
- }
- if ((file->mode&PR_TRUNCATE)==PR_TRUNCATE) {
- if (flag) strcat(str, ",");
- strcat(str, "replace");
- flag = JS_TRUE;
- }
- if (file->hasAutoflush) {
- if (flag) strcat(str, ",");
- strcat(str, "hasAutoFlush");
- flag = JS_TRUE;
- }
- *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, str));
- JS_free(cx, str);
- break;
- case FILE_CREATED:
- SECURITY_CHECK(cx, NULL, "creationTime", file);
- JSFILE_CHECK_NATIVE("creationTime");
- if(((file->isOpen)?
- PR_GetOpenFileInfo(file->handle, &info):
- PR_GetFileInfo(file->path, &info))!=PR_SUCCESS){
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_CANNOT_ACCESS_FILE_STATUS, file->path);
- goto out;
- }
-
- PR_ExplodeTime(info.creationTime, PR_LocalTimeParameters,&expandedTime);
- *vp = OBJECT_TO_JSVAL(js_NewDateObject(cx, expandedTime.tm_year,
- expandedTime.tm_month,
- expandedTime.tm_mday,
- expandedTime.tm_hour,
- expandedTime.tm_min,
- expandedTime.tm_sec));
- break;
- case FILE_MODIFIED:
- SECURITY_CHECK(cx, NULL, "lastModified", file);
- JSFILE_CHECK_NATIVE("lastModified");
- if(((file->isOpen)?
- PR_GetOpenFileInfo(file->handle, &info):
- PR_GetFileInfo(file->path, &info))!=PR_SUCCESS){
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_CANNOT_ACCESS_FILE_STATUS, file->path);
- goto out;
- }
-
- PR_ExplodeTime(info.modifyTime, PR_LocalTimeParameters, &expandedTime);
- *vp = OBJECT_TO_JSVAL(js_NewDateObject(cx, expandedTime.tm_year,
- expandedTime.tm_month,
- expandedTime.tm_mday,
- expandedTime.tm_hour,
- expandedTime.tm_min,
- expandedTime.tm_sec));
- break;
- case FILE_SIZE:
- SECURITY_CHECK(cx, NULL, "size", file);
- *vp = js_size(cx, file);
- break;
- case FILE_LENGTH:
- SECURITY_CHECK(cx, NULL, "length", file);
- JSFILE_CHECK_NATIVE("length");
-
- if (js_isDirectory(cx, file)) { /* XXX debug me */
- PRDir *dir;
- PRDirEntry *entry;
- jsint count = 0;
-
- if(!(dir = PR_OpenDir(file->path))){
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_CANNOT_OPEN_DIR, file->path);
- goto out;
- }
-
- while ((entry = PR_ReadDir(dir, PR_SKIP_BOTH))) {
- count++;
- }
-
- if(!PR_CloseDir(dir)){
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_OP_FAILED, "close", file->path);
-
- goto out;
- }
-
- *vp = INT_TO_JSVAL(count);
- break;
- }else{
- /* return file size */
- *vp = js_size(cx, file);
- }
- break;
- case FILE_RANDOMACCESS:
- SECURITY_CHECK(cx, NULL, "hasRandomAccess", file);
- JSFILE_CHECK_OPEN("hasRandomAccess");
- *vp = BOOLEAN_TO_JSVAL(file->hasRandomAccess);
- break;
- case FILE_POSITION:
- SECURITY_CHECK(cx, NULL, "position", file);
- JSFILE_CHECK_NATIVE("position");
- JSFILE_CHECK_OPEN("position");
-
- if(!file->hasRandomAccess){
- JS_ReportWarning(cx, "File %s doesn't support random access, can't report the position, proceeding");
- *vp = JSVAL_VOID;
- break;
- }
-
- if (file->isOpen && js_isFile(cx, file)) {
- int pos = PR_Seek(file->handle, 0, PR_SEEK_CUR);
- if(pos!=-1){
- *vp = INT_TO_JSVAL(pos);
- }else{
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_CANNOT_REPORT_POSITION, file->path);
- goto out;
- }
- }else {
- JS_ReportWarning(cx, "File %s is closed or not a plain file,"
- " can't report position, proceeding");
- goto out;
- }
- break;
- default:
- SECURITY_CHECK(cx, NULL, "file_access", file);
- /* this is some other property -- try to use the dir["file"] syntax */
- if(js_isDirectory(cx, file)){
- PRDir *dir = NULL;
- PRDirEntry *entry = NULL;
- char *prop_name = JS_GetStringBytes(JS_ValueToString(cx, id));
-
- /* no native files past this point */
- dir = PR_OpenDir(file->path);
- if(!dir) {
- /* This is probably not a directory */
- JS_ReportWarning(cx, "Can't open directory %s", file->path);
- return JS_FALSE;
- }
-
- while((entry = PR_ReadDir(dir, PR_SKIP_NONE))!=NULL){
- if(!strcmp(entry->name, prop_name)){
- str = js_combinePath(cx, file->path, prop_name);
- *vp = OBJECT_TO_JSVAL(js_NewFileObject(cx, str));
- JS_free(cx, str);
- return JS_TRUE;
- }
- }
- }
- }
- return JS_TRUE;
-out:
- *vp = JSVAL_VOID;
- return JS_FALSE;
-}
-
-static JSBool
-file_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
-{
- JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
- jsint slot;
-
- if (JSVAL_IS_STRING(id)){
- return JS_TRUE;
- }
-
- slot = JSVAL_TO_INT(id);
-
- switch (slot) {
- /* File.position = 10 */
- case FILE_POSITION:
- SECURITY_CHECK(cx, NULL, "set_position", file);
- JSFILE_CHECK_NATIVE("set_position");
-
- if(!file->hasRandomAccess){
- JS_ReportWarning(cx, "File %s doesn't support random access, can't "
- "report the position, proceeding");
- goto out;
- }
-
- if (file->isOpen && js_isFile(cx, file)) {
- int32 pos;
- int32 offset;
-
- if (!JS_ValueToInt32(cx, *vp, &offset)){
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_FIRST_ARGUMENT_MUST_BE_A_NUMBER, "position", *vp);
- goto out;
- }
-
- pos = PR_Seek(file->handle, offset, PR_SEEK_SET);
-
- if(pos!=-1){
- *vp = INT_TO_JSVAL(pos);
- }else{
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_CANNOT_SET_POSITION, file->path);
- goto out;
- }
- } else {
- JS_ReportWarning(cx, "File %s is closed or not a file, can't set "
- "position, proceeding", file->path);
- goto out;
- }
- }
-
- return JS_TRUE;
-out:
- *vp = JSVAL_VOID;
- return JS_FALSE;
-}
-
-/*
- File.currentDir = new File("D:\") or File.currentDir = "D:\"
-*/
-static JSBool
-file_currentDirSetter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
-{
- JSObject *rhsObject;
- char *path;
- JSFile *file = JS_GetInstancePrivate(cx, rhsObject, &file_class, NULL);
-
- /* Look at the rhs and extract a file object from it */
- if (JSVAL_IS_OBJECT(*vp)){
- if (JS_InstanceOf(cx, rhsObject, &file_class, NULL)){
- /* Braindamaged rhs -- just return the old value */
- if (file && (!js_exists(cx, file) || !js_isDirectory(cx, file))){
- JS_GetProperty(cx, obj, CURRENTDIR_PROPERTY, vp);
- goto out;
- }else{
- rhsObject = JSVAL_TO_OBJECT(*vp);
- chdir(file->path);
- return JS_TRUE;
- }
- }else
- goto out;
- }else{
- path = JS_GetStringBytes(JS_ValueToString(cx, *vp));
- rhsObject = js_NewFileObject(cx, path);
- if (!rhsObject) goto out;
-
- if (!file || !js_exists(cx, file) || !js_isDirectory(cx, file)){
- JS_GetProperty(cx, obj, CURRENTDIR_PROPERTY, vp);
- }else{
- *vp = OBJECT_TO_JSVAL(rhsObject);
- chdir(path);
- }
- }
- return JS_TRUE;
-out:
- *vp = JSVAL_VOID;
- return JS_FALSE;
-}
-
-/* Declare class */
-static JSClass file_class = {
- FILE_CONSTRUCTOR, JSCLASS_HAS_PRIVATE,
- JS_PropertyStub, JS_PropertyStub, file_getProperty, file_setProperty,
- JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, file_finalize
-};
-
-/* -------------------- Functions exposed to the outside -------------------- */
-JS_PUBLIC_API(JSObject*)
-js_InitFileClass(JSContext *cx, JSObject* obj, JSBool initStandardStreams)
-{
- JSObject *file, *ctor, *afile;
- jsval vp;
- char *currentdir;
- char separator[2];
-
- file = JS_InitClass(cx, obj, NULL, &file_class, file_constructor, 1,
- file_props, file_functions, NULL, NULL);
- if (!file) {
- JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
- JSFILEMSG_INIT_FAILED);
- return NULL;
- }
-
- ctor = JS_GetConstructor(cx, file);
- if (!ctor) return NULL;
-
- /* Define CURRENTDIR property. We are doing this to get a
- slash at the end of the current dir */
- afile = js_NewFileObject(cx, CURRENT_DIR);
- currentdir = JS_malloc(cx, MAX_PATH_LENGTH);
- currentdir = getcwd(currentdir, MAX_PATH_LENGTH);
- afile = js_NewFileObject(cx, currentdir);
- JS_free(cx, currentdir);
- vp = OBJECT_TO_JSVAL(afile);
- JS_DefinePropertyWithTinyId(cx, ctor, CURRENTDIR_PROPERTY, 0, vp,
- JS_PropertyStub, file_currentDirSetter,
- JSPROP_ENUMERATE | JSPROP_READONLY );
-
- if(initStandardStreams){
- /* Code to create stdin, stdout, and stderr. Insert in the appropriate place. */
- /* Define input */
- vp = OBJECT_TO_JSVAL(js_NewFileObjectFromFILE(cx, stdin,
- STDINPUT_NAME, PR_RDONLY, JS_TRUE, JS_FALSE));
- JS_SetProperty(cx, ctor, "input", &vp);
-
- /* Define output */
- vp = OBJECT_TO_JSVAL(js_NewFileObjectFromFILE(cx, stdout,
- STDOUTPUT_NAME, PR_WRONLY, JS_TRUE, JS_FALSE));
- JS_SetProperty(cx, ctor, "output", &vp);
-
- /* Define error */
- vp = OBJECT_TO_JSVAL(js_NewFileObjectFromFILE(cx, stderr,
- STDERROR_NAME, PR_WRONLY, JS_TRUE, JS_FALSE));
- JS_SetProperty(cx, ctor, "error", &vp);
- }
- separator[0] = FILESEPARATOR;
- separator[1] = '\0';
- vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, separator));
- JS_DefinePropertyWithTinyId(cx, ctor, SEPARATOR_PROPERTY, 0, vp,
- JS_PropertyStub, JS_PropertyStub,
- JSPROP_ENUMERATE | JSPROP_READONLY );
- return file;
-}
-#endif /* JS_HAS_FILE_OBJECT */