1998-11-05 03:08:43 +03:00
|
|
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Netscape Public License
|
|
|
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
|
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
|
|
* http://www.mozilla.org/NPL/
|
|
|
|
*
|
|
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* NPL.
|
|
|
|
*
|
|
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
|
|
* Communications Corporation. Portions created by Netscape are
|
|
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
|
|
* Reserved.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* JS File object
|
|
|
|
*/
|
1999-01-06 05:30:27 +03:00
|
|
|
#if JS_HAS_FILE_OBJECT
|
1998-11-05 03:08:43 +03:00
|
|
|
|
|
|
|
#ifndef _WINDOWS
|
|
|
|
# include <strings.h>
|
|
|
|
# include <stdio.h>
|
|
|
|
# include <stdlib.h>
|
|
|
|
# include <unistd.h>
|
|
|
|
#else
|
|
|
|
# include "direct.h"
|
1999-01-08 05:03:09 +03:00
|
|
|
# include <io.h>
|
|
|
|
# include <sys/types.h>
|
|
|
|
# include <sys/stat.h>
|
1998-11-05 03:08:43 +03:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#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 */
|
|
|
|
|
|
|
|
/* NSPR dependencies */
|
|
|
|
#include "prio.h"
|
|
|
|
#include "prerror.h"
|
|
|
|
#include "jsutil.h" /* Added by JSIFY */
|
|
|
|
|
1998-12-31 08:58:26 +03:00
|
|
|
typedef enum JSFileErrNum {
|
|
|
|
#define MSG_DEF(name, number, count, exception, format) \
|
|
|
|
name = number,
|
|
|
|
#include "jsfile.msg"
|
|
|
|
#undef MSG_DEF
|
|
|
|
JSShellErr_Limit
|
|
|
|
#undef MSGDEF
|
|
|
|
} JSFileErrNum;
|
|
|
|
|
1998-11-05 03:08:43 +03:00
|
|
|
#define SPECIAL_FILE_STRING "Special File"
|
|
|
|
#define CURRENTDIR_PROPERTY "currentDir"
|
1998-12-31 08:58:26 +03:00
|
|
|
#define FILE_CONSTRUCTOR "File"
|
|
|
|
#define PIPE_SYMBOL '|'
|
1998-11-05 03:08:43 +03:00
|
|
|
|
|
|
|
#define ASCII 0
|
|
|
|
#define UTF8 1
|
|
|
|
#define UCS2 2
|
|
|
|
|
|
|
|
#define asciistring "ascii"
|
1998-12-31 08:58:26 +03:00
|
|
|
#define utfstring "binary"
|
1998-11-05 03:08:43 +03:00
|
|
|
#define unicodestring "unicode"
|
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
#define MAX_PATH_LENGTH 1024
|
1999-01-08 05:03:09 +03:00
|
|
|
#define MSG_SIZE 256
|
1999-01-02 07:02:36 +03:00
|
|
|
#define URL_PREFIX "file://"
|
1998-11-05 03:08:43 +03:00
|
|
|
|
1999-01-08 05:03:09 +03:00
|
|
|
static JSBool
|
|
|
|
filenameHasAPipe(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
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Platform dependent code goes here. */
|
1998-11-05 03:08:43 +03:00
|
|
|
#ifdef XP_MAC
|
|
|
|
# define LINEBREAK "\012"
|
|
|
|
# define LINEBREAK_LEN 1
|
|
|
|
# define FILESEPARATOR ':'
|
|
|
|
# define FILESEPARATOR2 '\0'
|
|
|
|
# define CURRENT_DIR "HARD DISK:Desktop Folder"
|
|
|
|
|
|
|
|
static JSBool
|
|
|
|
isAbsolute(char*name)
|
|
|
|
{
|
|
|
|
return (name[0]!=FILESEPARATOR);
|
|
|
|
}
|
|
|
|
|
1998-12-31 08:58:26 +03:00
|
|
|
/* We assume: base is a valid absolute path, not ending with :
|
1998-11-05 03:08:43 +03:00
|
|
|
name is a valid relative path. */
|
1998-12-31 08:58:26 +03:00
|
|
|
static char *
|
1999-01-02 07:02:36 +03:00
|
|
|
combinePath(JSContext *cx, char *base, char *name)
|
1998-11-05 03:08:43 +03:00
|
|
|
{
|
1999-01-02 07:02:36 +03:00
|
|
|
char* tmp = (char*)JS_malloc(cx, strlen(base)+strlen(name)+2);
|
|
|
|
|
|
|
|
if (!tmp) return NULL;
|
1999-01-01 07:37:28 +03:00
|
|
|
strcpy(tmp, base);
|
1999-01-05 05:18:26 +03:00
|
|
|
i = strlen(base)-1;
|
1998-11-05 03:08:43 +03:00
|
|
|
if (base[i]!=FILESEPARATOR) {
|
1999-01-05 05:18:26 +03:00
|
|
|
tmp[i+1] = FILESEPARATOR;
|
|
|
|
tmp[i+2] = '\0';
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
1999-01-01 07:37:28 +03:00
|
|
|
strcat(tmp, name);
|
1998-11-05 03:08:43 +03:00
|
|
|
return tmp;
|
|
|
|
}
|
|
|
|
|
1998-12-31 08:58:26 +03:00
|
|
|
/* Extracts the filename from a path. Returned string must be freed */
|
1998-11-05 03:08:43 +03:00
|
|
|
static char *
|
|
|
|
fileBaseName(JSContext *cx, char * pathname)
|
|
|
|
{
|
1999-01-01 07:37:28 +03:00
|
|
|
jsint index, aux;
|
1998-11-05 03:08:43 +03:00
|
|
|
char *basename;
|
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
index = strlen(pathname)-1;
|
|
|
|
aux = index;
|
1998-11-05 03:08:43 +03:00
|
|
|
while ((index>=0)&&(pathname[index]!=FILESEPARATOR)) index--;
|
|
|
|
basename = (char*)JS_malloc(cx, aux-index+1);
|
1999-01-02 07:02:36 +03:00
|
|
|
if (!basename) return NULL;
|
1999-01-05 05:18:26 +03:00
|
|
|
strncpy(basename, &pathname[index+1], aux-index);
|
|
|
|
basename[aux-index] = '\0';
|
1998-11-05 03:08:43 +03:00
|
|
|
return basename;
|
|
|
|
}
|
|
|
|
|
1998-12-31 08:58:26 +03:00
|
|
|
/* Extracts the directory name from a path. Returned string must be freed */
|
1998-11-05 03:08:43 +03:00
|
|
|
static char *
|
|
|
|
fileDirectoryName(JSContext *cx, char * pathname)
|
|
|
|
{
|
|
|
|
jsint index;
|
|
|
|
char *dirname;
|
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
index = strlen(pathname)-1;
|
1998-11-05 03:08:43 +03:00
|
|
|
while ((index>0)&&(pathname[index]!=FILESEPARATOR)) index--;
|
|
|
|
|
|
|
|
if (index>=0) {
|
1999-01-05 05:18:26 +03:00
|
|
|
dirname = (char*)JS_malloc(cx, index+2);
|
1999-01-02 07:02:36 +03:00
|
|
|
if (!dirname) return NULL;
|
1999-01-01 07:37:28 +03:00
|
|
|
strncpy(dirname, pathname, index);
|
1999-01-05 05:18:26 +03:00
|
|
|
dirname[index] = FILESEPARATOR;
|
|
|
|
dirname[index+1] = '\0';
|
1998-11-05 03:08:43 +03:00
|
|
|
} else
|
1999-01-05 05:18:26 +03:00
|
|
|
dirname = JS_strdup(cx, pathname);
|
1998-11-05 03:08:43 +03:00
|
|
|
return dirname;
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
1999-01-01 07:37:28 +03:00
|
|
|
# if defined(XP_PC) || defined(_WINDOWS) || defined(OS2)
|
1998-11-05 03:08:43 +03:00
|
|
|
# define LINEBREAK "\015\012"
|
|
|
|
# define LINEBREAK_LEN 2
|
|
|
|
# define FILESEPARATOR '\\'
|
|
|
|
# define FILESEPARATOR2 '/'
|
|
|
|
# define CURRENT_DIR "c:\\"
|
1999-01-05 05:18:26 +03:00
|
|
|
# define POPEN _popen
|
|
|
|
# define PCLOSE _pclose
|
1999-01-02 07:02:36 +03:00
|
|
|
|
1998-11-05 03:08:43 +03:00
|
|
|
static JSBool
|
|
|
|
isAbsolute(char*name)
|
|
|
|
{
|
1998-12-31 08:58:26 +03:00
|
|
|
if (strlen(name)<2)
|
1998-11-05 03:08:43 +03:00
|
|
|
return JS_FALSE;
|
|
|
|
|
|
|
|
if (name[1]==':')
|
|
|
|
return JS_TRUE;
|
|
|
|
|
|
|
|
return JS_FALSE; /* First approximation, ignore "/tmp" case.. */
|
|
|
|
}
|
|
|
|
|
1998-12-31 08:58:26 +03:00
|
|
|
/* We assume: base is a valid absolute path, starting with x:, ending with /.
|
1998-11-05 03:08:43 +03:00
|
|
|
name is a valid relative path, and may have a drive selector. */
|
1998-12-31 08:58:26 +03:00
|
|
|
static char *
|
|
|
|
combinePath(JSContext *cx, char *base, char*name)
|
1998-11-05 03:08:43 +03:00
|
|
|
{
|
|
|
|
jsint i;
|
|
|
|
char *tmp, *tmp1;
|
|
|
|
|
|
|
|
if ((strlen(name)>=2)&&(name[1]==':')) { /* remove a drive selector if there's one.*/
|
1999-01-05 05:18:26 +03:00
|
|
|
tmp1 = &name[2];
|
1998-11-05 03:08:43 +03:00
|
|
|
} else
|
1999-01-05 05:18:26 +03:00
|
|
|
tmp1 = name;
|
1998-11-05 03:08:43 +03:00
|
|
|
|
|
|
|
tmp = (char*)JS_malloc(cx, strlen(base)+strlen(tmp1)+2);
|
1999-01-02 07:02:36 +03:00
|
|
|
if (!tmp) return NULL;
|
1999-01-01 07:37:28 +03:00
|
|
|
strcpy(tmp, base);
|
1999-01-05 05:18:26 +03:00
|
|
|
i = strlen(base)-1;
|
1998-11-05 03:08:43 +03:00
|
|
|
if ((base[i]!=FILESEPARATOR)&&(base[i]!=FILESEPARATOR2)) {
|
1999-01-05 05:18:26 +03:00
|
|
|
tmp[i+1] = FILESEPARATOR;
|
|
|
|
tmp[i+2] = '\0';
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
1999-01-01 07:37:28 +03:00
|
|
|
strcat(tmp, tmp1);
|
1998-11-05 03:08:43 +03:00
|
|
|
return tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* returned string must be freed */
|
|
|
|
static char *
|
|
|
|
fileBaseName(JSContext *cx, char * pathname)
|
|
|
|
{
|
1999-01-01 07:37:28 +03:00
|
|
|
jsint index, aux;
|
1998-11-05 03:08:43 +03:00
|
|
|
char *basename;
|
|
|
|
|
|
|
|
/* First, get rid of the drive selector */
|
|
|
|
if ((strlen(pathname)>=2)&&(pathname[1]==':')) {
|
1999-01-05 05:18:26 +03:00
|
|
|
pathname = &pathname[2];
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
index = strlen(pathname)-1;
|
1998-11-05 03:08:43 +03:00
|
|
|
while ((index>0)&&((pathname[index]==FILESEPARATOR)||
|
|
|
|
(pathname[index]==FILESEPARATOR2))) index--;
|
1999-01-05 05:18:26 +03:00
|
|
|
aux = index;
|
1998-11-05 03:08:43 +03:00
|
|
|
while ((index>=0)&&(pathname[index]!=FILESEPARATOR)&&
|
|
|
|
(pathname[index]!=FILESEPARATOR2)) index--;
|
|
|
|
basename = (char*)JS_malloc(cx, aux-index+3);
|
1999-01-02 07:02:36 +03:00
|
|
|
if (!basename) return NULL;
|
1999-01-05 05:18:26 +03:00
|
|
|
strncpy(basename, &pathname[index+1], aux-index);
|
|
|
|
basename[aux-index] = '\0';
|
1998-11-05 03:08:43 +03:00
|
|
|
return basename;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* returned string must be freed */
|
|
|
|
static char *
|
|
|
|
fileDirectoryName(JSContext *cx, char * pathname)
|
|
|
|
{
|
|
|
|
jsint index;
|
1999-01-02 07:02:36 +03:00
|
|
|
char *dirname, *backpathname;
|
1999-01-05 05:18:26 +03:00
|
|
|
char drive = '\0';
|
1998-11-05 03:08:43 +03:00
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
backpathname = pathname;
|
1998-11-05 03:08:43 +03:00
|
|
|
/* First, get rid of the drive selector */
|
|
|
|
if ((strlen(pathname)>=2)&&(pathname[1]==':')) {
|
1999-01-05 05:18:26 +03:00
|
|
|
drive = pathname[0];
|
|
|
|
pathname = &pathname[2];
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
index = strlen(pathname)-1;
|
1998-11-05 03:08:43 +03:00
|
|
|
while ((index>0)&&((pathname[index]==FILESEPARATOR)||
|
|
|
|
(pathname[index]==FILESEPARATOR2))) index--;
|
|
|
|
while ((index>0)&&(pathname[index]!=FILESEPARATOR)&&
|
|
|
|
(pathname[index]!=FILESEPARATOR2)) index--;
|
|
|
|
|
1999-01-02 07:02:36 +03:00
|
|
|
if (index>=0){
|
1999-01-05 05:18:26 +03:00
|
|
|
dirname = (char*)JS_malloc(cx, index+4);
|
1999-01-02 07:02:36 +03:00
|
|
|
if (!dirname) return NULL;
|
|
|
|
|
1998-11-05 03:08:43 +03:00
|
|
|
if (drive!='\0') {
|
1999-01-05 05:18:26 +03:00
|
|
|
dirname[0] = toupper(drive);
|
|
|
|
dirname[1] = ':';
|
|
|
|
strncpy(&dirname[2], pathname, index);
|
|
|
|
dirname[index+2] = FILESEPARATOR;
|
|
|
|
dirname[index+3] = '\0';
|
1998-11-05 03:08:43 +03:00
|
|
|
} else {
|
1999-01-01 07:37:28 +03:00
|
|
|
strncpy(dirname, pathname, index);
|
1999-01-05 05:18:26 +03:00
|
|
|
dirname[index] = FILESEPARATOR;
|
|
|
|
dirname[index+1] = '\0';
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
} else
|
1999-01-05 05:18:26 +03:00
|
|
|
dirname = JS_strdup(cx, backpathname); /* may include drive selector */
|
1998-11-05 03:08:43 +03:00
|
|
|
|
|
|
|
return dirname;
|
|
|
|
}
|
|
|
|
|
|
|
|
# else
|
|
|
|
# ifdef XP_UNIX
|
|
|
|
# define LINEBREAK "\012"
|
|
|
|
# define LINEBREAK_LEN 1
|
|
|
|
# define FILESEPARATOR '/'
|
|
|
|
# define FILESEPARATOR2 '\0'
|
|
|
|
# define CURRENT_DIR "/"
|
1999-01-07 07:41:20 +03:00
|
|
|
# define POPEN popen
|
1999-01-05 05:18:26 +03:00
|
|
|
# define PCLOSE pclose
|
1998-11-05 03:08:43 +03:00
|
|
|
|
|
|
|
static JSBool
|
|
|
|
isAbsolute(char*name)
|
|
|
|
{
|
|
|
|
return (name[0]==FILESEPARATOR);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We assume: base is a valid absolute path[, ending with /]. name is a valid relative path. */
|
1998-12-31 08:58:26 +03:00
|
|
|
static char *
|
|
|
|
combinePath(JSContext *cx, char *base, char*name)
|
1998-11-05 03:08:43 +03:00
|
|
|
{
|
|
|
|
jsint i;
|
|
|
|
char * tmp;
|
|
|
|
tmp = (char*)JS_malloc(cx, strlen(base)+strlen(name)+2);
|
1999-01-02 07:02:36 +03:00
|
|
|
if (!tmp) return NULL;
|
1999-01-01 07:37:28 +03:00
|
|
|
strcpy(tmp, base);
|
1999-01-05 05:18:26 +03:00
|
|
|
i = strlen(base)-1;
|
1998-11-05 03:08:43 +03:00
|
|
|
if (base[i]!=FILESEPARATOR) {
|
1999-01-05 05:18:26 +03:00
|
|
|
tmp[i+1] = FILESEPARATOR;
|
|
|
|
tmp[i+2] = '\0';
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
1999-01-01 07:37:28 +03:00
|
|
|
strcat(tmp, name);
|
1998-11-05 03:08:43 +03:00
|
|
|
return tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* returned string must be freed */
|
|
|
|
static char *
|
|
|
|
fileBaseName(JSContext *cx, char * pathname)
|
|
|
|
{
|
1999-01-01 07:37:28 +03:00
|
|
|
jsint index, aux;
|
1998-11-05 03:08:43 +03:00
|
|
|
char *basename;
|
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
index = strlen(pathname)-1;
|
1998-11-05 03:08:43 +03:00
|
|
|
while ((index>0)&&((pathname[index]==FILESEPARATOR)||
|
|
|
|
(pathname[index]==FILESEPARATOR2))) index--;
|
1999-01-05 05:18:26 +03:00
|
|
|
aux = index;
|
1998-11-05 03:08:43 +03:00
|
|
|
while ((index>=0)&&(pathname[index]!=FILESEPARATOR)&&
|
|
|
|
(pathname[index]!=FILESEPARATOR2)) index--;
|
|
|
|
basename = (char*)JS_malloc(cx, aux-index+1);
|
1999-01-02 07:02:36 +03:00
|
|
|
if (!basename) return NULL;
|
1999-01-05 05:18:26 +03:00
|
|
|
strncpy(basename, &pathname[index+1], aux-index);
|
|
|
|
basename[aux-index] = '\0';
|
1998-11-05 03:08:43 +03:00
|
|
|
return basename;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* returned string must be freed */
|
|
|
|
static char *
|
|
|
|
fileDirectoryName(JSContext *cx, char * pathname)
|
|
|
|
{
|
|
|
|
jsint index;
|
|
|
|
char *dirname;
|
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
index = strlen(pathname)-1;
|
1998-11-05 03:08:43 +03:00
|
|
|
while ((index>0)&&((pathname[index]==FILESEPARATOR)||
|
|
|
|
(pathname[index]==FILESEPARATOR2))) index--;
|
|
|
|
while ((index>0)&&(pathname[index]!=FILESEPARATOR)&&
|
|
|
|
(pathname[index]!=FILESEPARATOR2)) index--;
|
|
|
|
|
|
|
|
if (index>=0) {
|
1999-01-05 05:18:26 +03:00
|
|
|
dirname = (char*)JS_malloc(cx, index+2);
|
1999-01-02 07:02:36 +03:00
|
|
|
if (!dirname) return NULL;
|
1999-01-01 07:37:28 +03:00
|
|
|
strncpy(dirname, pathname, index);
|
1999-01-05 05:18:26 +03:00
|
|
|
dirname[index] = FILESEPARATOR;
|
|
|
|
dirname[index+1] = '\0';
|
1998-11-05 03:08:43 +03:00
|
|
|
} else
|
1999-01-05 05:18:26 +03:00
|
|
|
dirname = JS_strdup(cx, pathname);
|
1998-11-05 03:08:43 +03:00
|
|
|
return dirname;
|
|
|
|
}
|
|
|
|
|
|
|
|
# endif /* UNIX */
|
|
|
|
# endif /* WIN */
|
|
|
|
#endif /* MAC */
|
|
|
|
|
|
|
|
|
|
|
|
/* returned string must be freed.. */
|
|
|
|
static char *
|
|
|
|
absolutePath(JSContext *cx, char * path)
|
|
|
|
{
|
|
|
|
JSObject *obj;
|
|
|
|
JSString *str;
|
|
|
|
jsval prop;
|
|
|
|
|
|
|
|
if (isAbsolute(path))
|
1999-01-01 07:37:28 +03:00
|
|
|
return JS_strdup(cx, path);
|
1998-11-05 03:08:43 +03:00
|
|
|
else {
|
1999-01-05 05:18:26 +03:00
|
|
|
obj = JS_GetGlobalObject(cx);
|
1999-01-01 07:37:28 +03:00
|
|
|
if (!JS_GetProperty(cx, obj, FILE_CONSTRUCTOR, &prop)) {
|
1998-12-31 08:58:26 +03:00
|
|
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
|
|
|
JSFILEMSG_FILE_CONSTRUCTOR_UNDEFINED_ERROR);
|
1999-01-01 07:37:28 +03:00
|
|
|
return JS_strdup(cx, path);
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
1999-01-05 05:18:26 +03:00
|
|
|
obj = JSVAL_TO_OBJECT(prop);
|
1999-01-01 07:37:28 +03:00
|
|
|
if (!JS_GetProperty(cx, obj, CURRENTDIR_PROPERTY, &prop)) {
|
1998-12-31 08:58:26 +03:00
|
|
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
|
|
|
JSFILEMSG_FILE_CURRENTDIR_UNDEFINED_ERROR);
|
1999-01-01 07:37:28 +03:00
|
|
|
return JS_strdup(cx, path);
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
1999-01-05 05:18:26 +03:00
|
|
|
str = JS_ValueToString(cx, prop);
|
1998-11-05 03:08:43 +03:00
|
|
|
if (!str ) {
|
1999-01-01 07:37:28 +03:00
|
|
|
return JS_strdup(cx, path);
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
return combinePath(cx, JS_GetStringBytes(str), path); /* should we have an array of current dirs indexed by drive for windows? */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* this function should be in the platform specific side. */
|
|
|
|
/* :: is not handled. */
|
|
|
|
static char *
|
1999-01-01 07:37:28 +03:00
|
|
|
canonicalPath(JSContext *cx, char *path)
|
1998-11-05 03:08:43 +03:00
|
|
|
{
|
|
|
|
char *tmp1, *tmp;
|
|
|
|
char *base, *dir, *current, *result;
|
|
|
|
jsint c;
|
1999-01-05 05:18:26 +03:00
|
|
|
jsint back = 0;
|
|
|
|
unsigned int i = 0, j = strlen(path)-1;
|
1999-01-01 07:37:28 +03:00
|
|
|
|
|
|
|
/* TODO: 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);
|
1999-01-05 05:18:26 +03:00
|
|
|
tmp[j-i+1] = '\0';
|
1999-01-01 07:37:28 +03:00
|
|
|
|
|
|
|
strcpy(path, tmp);
|
|
|
|
JS_free(cx, tmp);
|
|
|
|
|
1999-01-02 07:02:36 +03:00
|
|
|
/* pipe support */
|
|
|
|
if(filenameHasAPipe(path))
|
|
|
|
return JS_strdup(cx, path);
|
|
|
|
/* file:// support */
|
|
|
|
if(!strncmp(path, URL_PREFIX, strlen(URL_PREFIX)))
|
|
|
|
return strdup(&path[strlen(URL_PREFIX)-1]);
|
1998-11-05 03:08:43 +03:00
|
|
|
|
|
|
|
if (!isAbsolute(path))
|
1999-01-05 05:18:26 +03:00
|
|
|
tmp1 = absolutePath(cx, path);
|
1998-11-05 03:08:43 +03:00
|
|
|
else
|
1999-01-05 05:18:26 +03:00
|
|
|
tmp1 = JS_strdup(cx, path);
|
1998-12-31 08:58:26 +03:00
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
result = JS_strdup(cx, "");
|
1998-11-05 03:08:43 +03:00
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
current = tmp1;
|
1998-11-05 03:08:43 +03:00
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
base = fileBaseName(cx, current);
|
|
|
|
dir = fileDirectoryName(cx, current);
|
1999-01-06 05:51:26 +03:00
|
|
|
/* TODO: MAC??? */
|
1999-01-01 07:37:28 +03:00
|
|
|
while (strcmp(dir, current)) {
|
1999-01-05 05:18:26 +03:00
|
|
|
if (!strcmp(base, "..")) {
|
1998-11-05 03:08:43 +03:00
|
|
|
back++;
|
|
|
|
} else
|
1999-01-05 05:18:26 +03:00
|
|
|
if(!strcmp(base, ".")){
|
1999-01-02 07:02:36 +03:00
|
|
|
|
1998-11-05 03:08:43 +03:00
|
|
|
} else {
|
1998-12-31 08:58:26 +03:00
|
|
|
if (back>0)
|
1998-11-05 03:08:43 +03:00
|
|
|
back--;
|
|
|
|
else {
|
1999-01-05 05:18:26 +03:00
|
|
|
tmp = result;
|
|
|
|
result = JS_malloc(cx, strlen(base)+1+strlen(tmp)+1);
|
1998-11-05 03:08:43 +03:00
|
|
|
if (!result) {
|
1999-01-01 07:37:28 +03:00
|
|
|
JS_free(cx, dir);
|
|
|
|
JS_free(cx, base);
|
|
|
|
JS_free(cx, current);
|
1998-11-05 03:08:43 +03:00
|
|
|
return NULL;
|
|
|
|
}
|
1999-01-01 07:37:28 +03:00
|
|
|
strcpy(result, base);
|
1999-01-05 05:18:26 +03:00
|
|
|
c = strlen(result);
|
1998-11-05 03:08:43 +03:00
|
|
|
if (strlen(tmp)>0) {
|
1999-01-05 05:18:26 +03:00
|
|
|
result[c] = FILESEPARATOR;
|
|
|
|
result[c+1] = '\0';
|
1999-01-01 07:37:28 +03:00
|
|
|
strcat(result, tmp);
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
1999-01-01 07:37:28 +03:00
|
|
|
JS_free(cx, tmp);
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
}
|
1999-01-01 07:37:28 +03:00
|
|
|
JS_free(cx, current);
|
|
|
|
JS_free(cx, base);
|
1999-01-05 05:18:26 +03:00
|
|
|
current = dir;
|
|
|
|
base = fileBaseName(cx, current);
|
|
|
|
dir = fileDirectoryName(cx, current);
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
1999-01-05 05:18:26 +03:00
|
|
|
tmp = result;
|
|
|
|
result = JS_malloc(cx, strlen(dir)+1+strlen(tmp)+1);
|
1998-11-05 03:08:43 +03:00
|
|
|
if (!result) {
|
1999-01-01 07:37:28 +03:00
|
|
|
JS_free(cx, dir);
|
|
|
|
JS_free(cx, base);
|
|
|
|
JS_free(cx, current);
|
1998-11-05 03:08:43 +03:00
|
|
|
return NULL;
|
|
|
|
}
|
1999-01-01 07:37:28 +03:00
|
|
|
strcpy(result, dir);
|
1999-01-05 05:18:26 +03:00
|
|
|
c = strlen(result);
|
1998-11-05 03:08:43 +03:00
|
|
|
if (strlen(tmp)>0) {
|
|
|
|
if ((result[c-1]!=FILESEPARATOR)&&(result[c-1]!=FILESEPARATOR2)) {
|
1999-01-05 05:18:26 +03:00
|
|
|
result[c] = FILESEPARATOR;
|
|
|
|
result[c+1] = '\0';
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
1999-01-01 07:37:28 +03:00
|
|
|
strcat(result, tmp);
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
1999-01-01 07:37:28 +03:00
|
|
|
JS_free(cx, tmp);
|
|
|
|
JS_free(cx, dir);
|
|
|
|
JS_free(cx, base);
|
|
|
|
JS_free(cx, current);
|
1998-11-05 03:08:43 +03:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
/* ---------------- Text format conversion ------------------------- */
|
1998-11-05 03:08:43 +03:00
|
|
|
/* 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)
|
|
|
|
|
|
|
|
|
1998-12-31 08:58:26 +03:00
|
|
|
#define MAX_UCS2 0xFFFF
|
|
|
|
#define DEFAULT_CHAR 0x003F /* Default char is "?" */
|
1998-11-05 03:08:43 +03:00
|
|
|
#define BYTE_MASK 0xBF
|
|
|
|
#define BYTE_MARK 0x80
|
|
|
|
|
|
|
|
|
|
|
|
/* Function: one_ucs2_to_utf8_char
|
1998-12-31 08:58:26 +03:00
|
|
|
*
|
1998-11-05 03:08:43 +03:00
|
|
|
* Function takes one UCS-2 char and writes it to a UTF-8 buffer.
|
1998-12-31 08:58:26 +03:00
|
|
|
* We need a UTF-8 buffer because we don't know before this
|
1998-11-05 03:08:43 +03:00
|
|
|
* 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
|
1998-12-31 08:58:26 +03:00
|
|
|
static int16 one_ucs2_to_utf8_char(unsigned char *tobufp,
|
1998-11-05 03:08:43 +03:00
|
|
|
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;
|
1998-12-31 08:58:26 +03:00
|
|
|
}
|
|
|
|
|
1998-11-05 03:08:43 +03:00
|
|
|
tobufp += numUTF8bytes;
|
|
|
|
|
|
|
|
/* return error if we don't have space for the whole character */
|
|
|
|
if (tobufp > tobufendp) {
|
1998-12-31 08:58:26 +03:00
|
|
|
return(-1);
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef struct JSFile {
|
1999-01-01 07:37:28 +03:00
|
|
|
char *path; /* the path to the file. */
|
1999-01-07 07:17:23 +03:00
|
|
|
JSBool isOpen;
|
1999-01-01 07:37:28 +03:00
|
|
|
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 */
|
1999-01-02 07:02:36 +03:00
|
|
|
char byteBuffer[3]; /* bytes read in advance by js_FileRead ( UTF8 encoding ) */
|
1999-01-01 07:37:28 +03:00
|
|
|
jsint nbBytesInBuf; /* number of bytes stored in the buffer above */
|
|
|
|
jschar charBuffer; /* character read in advance by readln ( mac files only ) */
|
1998-11-05 03:08:43 +03:00
|
|
|
JSBool charBufferUsed; /* flag indicating if the buffer above is being used */
|
1999-01-08 05:03:09 +03:00
|
|
|
JSBool hasRandomAccess; /* can the file be randomly accessed? false for stdin, and
|
1998-11-05 03:08:43 +03:00
|
|
|
UTF-encoded files. */
|
1999-01-08 05:03:09 +03:00
|
|
|
JSBool hasAutoflush; /* should we force a flush for each line break? */
|
1999-01-07 07:17:23 +03:00
|
|
|
JSBool isNative; /* if the file is using OS-specific file FILE type */
|
|
|
|
|
|
|
|
union{ /* anonymous union */
|
|
|
|
PRFileDesc *handle; /* the handle for the file, if open. */
|
|
|
|
FILE *nativehandle; /* native handle, for stuff NSPR doesn't do. */
|
|
|
|
};
|
1999-01-05 05:18:26 +03:00
|
|
|
JSBool isAPipe; /* if the file is really an OS pipe */
|
1998-11-05 03:08:43 +03:00
|
|
|
} JSFile;
|
|
|
|
|
1999-01-05 06:51:30 +03:00
|
|
|
/* a few forward declarations... */
|
|
|
|
static JSClass file_class;
|
1999-01-08 05:03:09 +03:00
|
|
|
JS_EXPORT_API(JSObject*) js_NewFileObject(JSContext *cx, char *filename);
|
1999-01-07 07:41:20 +03:00
|
|
|
JS_EXPORT_API(JSObject*) js_NewFileObjectFromFILEFromFILE(JSContext *cx, FILE *f, char *filename, JSBool open);
|
1999-01-05 06:51:30 +03:00
|
|
|
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);
|
|
|
|
|
1999-01-02 07:02:36 +03:00
|
|
|
/* ------------------------------- 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
|
1999-01-08 05:03:09 +03:00
|
|
|
*/
|
|
|
|
|
1999-01-02 07:02:36 +03:00
|
|
|
static int32
|
1999-01-08 05:03:09 +03:00
|
|
|
js_FileHasOption(JSContext *cx, char *oldoptions, char *name)
|
1999-01-02 07:02:36 +03:00
|
|
|
{
|
1999-01-08 05:03:09 +03:00
|
|
|
char *comma, *equal, *current;
|
|
|
|
char *options = JS_strdup(cx, oldoptions);
|
1999-01-02 07:02:36 +03:00
|
|
|
int32 found = 0;
|
|
|
|
|
1999-01-08 05:03:09 +03:00
|
|
|
current = options;
|
1999-01-02 07:02:36 +03:00
|
|
|
for (;;) {
|
1999-01-08 05:03:09 +03:00
|
|
|
comma = strchr(current, ', ');
|
1999-01-02 07:02:36 +03:00
|
|
|
if (comma) *comma = '\0';
|
1999-01-08 05:03:09 +03:00
|
|
|
equal = strchr(current, ' = ');
|
1999-01-02 07:02:36 +03:00
|
|
|
if (equal) *equal = '\0';
|
1999-01-08 05:03:09 +03:00
|
|
|
if (strcmp(current, name) == 0) {
|
1999-01-02 07:02:36 +03:00
|
|
|
if (!equal || strcmp(equal + 1, "yes") == 0)
|
|
|
|
found = 1;
|
|
|
|
else
|
|
|
|
found = atoi(equal + 1);
|
|
|
|
}
|
|
|
|
if (equal) *equal = '=';
|
|
|
|
if (comma) *comma = ',';
|
|
|
|
if (found || !comma)
|
|
|
|
break;
|
1999-01-08 05:03:09 +03:00
|
|
|
current = comma + 1;
|
1999-01-02 07:02:36 +03:00
|
|
|
}
|
1999-01-08 05:03:09 +03:00
|
|
|
JS_free(cx, options);
|
1999-01-02 07:02:36 +03:00
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
1998-12-31 08:58:26 +03:00
|
|
|
static void
|
1999-01-02 07:02:36 +03:00
|
|
|
js_ResetBuffers(JSFile * file)
|
1998-11-05 03:08:43 +03:00
|
|
|
{
|
1999-01-05 05:18:26 +03:00
|
|
|
file->charBufferUsed = JS_FALSE;
|
|
|
|
file->nbBytesInBuf = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Reset file attributes */
|
|
|
|
static void
|
|
|
|
js_ResetAttributes(JSFile * file){
|
1999-01-07 07:17:23 +03:00
|
|
|
file->isOpen = JS_FALSE;
|
1999-01-05 05:18:26 +03:00
|
|
|
file->handle = NULL;
|
|
|
|
file->nativehandle = NULL;
|
1999-01-08 05:03:09 +03:00
|
|
|
file->hasRandomAccess = JS_TRUE; /* innocent until proven guilty */
|
1999-01-07 07:17:23 +03:00
|
|
|
file->isNative = JS_FALSE;
|
1999-01-05 05:18:26 +03:00
|
|
|
file->isAPipe = JS_FALSE;
|
|
|
|
js_ResetBuffers(file);
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
|
1999-01-05 06:51:30 +03:00
|
|
|
static JSBool
|
|
|
|
js_FileOpen(JSContext *cx, JSObject *obj, JSFile *file, char *mode){
|
|
|
|
JSString *type, *mask;
|
|
|
|
jsval v[2];
|
|
|
|
jsval rval;
|
|
|
|
|
|
|
|
type = JS_NewStringCopyZ(cx, utfstring);
|
|
|
|
mask = JS_NewStringCopyZ(cx, mode);
|
|
|
|
v[0] = STRING_TO_JSVAL(type);
|
|
|
|
v[1] = STRING_TO_JSVAL(mask);
|
|
|
|
|
|
|
|
if (!file_open(cx, obj, 2, v, &rval)) {
|
|
|
|
/* TODO: do we need error reporting here? */
|
|
|
|
return JS_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-01-02 07:02:36 +03:00
|
|
|
/* Buffered version of PR_Read. Used by js_FileRead */
|
1998-11-05 03:08:43 +03:00
|
|
|
static int32
|
1999-01-07 07:17:23 +03:00
|
|
|
js_BufferedRead(JSFile * f, char *buf, int32 len)
|
1998-11-05 03:08:43 +03:00
|
|
|
{
|
1999-01-05 05:18:26 +03:00
|
|
|
int32 count = 0;
|
1999-01-08 05:03:09 +03:00
|
|
|
|
1998-11-05 03:08:43 +03:00
|
|
|
while (f->nbBytesInBuf>0&&len>0) {
|
1999-01-05 05:18:26 +03:00
|
|
|
buf[0] = f->byteBuffer[0];
|
|
|
|
f->byteBuffer[0] = f->byteBuffer[1];
|
|
|
|
f->byteBuffer[1] = f->byteBuffer[2];
|
1998-11-05 03:08:43 +03:00
|
|
|
f->nbBytesInBuf--;
|
|
|
|
len--;
|
|
|
|
buf+=1;
|
|
|
|
count++;
|
|
|
|
}
|
1999-01-08 05:03:09 +03:00
|
|
|
|
1998-11-05 03:08:43 +03:00
|
|
|
if (len>0) {
|
1999-01-08 05:03:09 +03:00
|
|
|
count+= (!f->isNative)?
|
|
|
|
PR_Read(f->handle, buf, len):
|
|
|
|
fread(buf, 1, len, f->nativehandle);
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int32
|
1999-01-02 07:02:36 +03:00
|
|
|
js_FileRead(JSContext *cx, JSFile * f, jschar*buf, int32 len, int32 mode)
|
1998-11-05 03:08:43 +03:00
|
|
|
{
|
|
|
|
unsigned char*aux;
|
1999-01-01 07:37:28 +03:00
|
|
|
int32 count, i;
|
1998-11-05 03:08:43 +03:00
|
|
|
jsint remainder;
|
|
|
|
unsigned char utfbuf[3];
|
|
|
|
|
|
|
|
if (f->charBufferUsed) {
|
1999-01-05 05:18:26 +03:00
|
|
|
buf[0] = f->charBuffer;
|
1998-11-05 03:08:43 +03:00
|
|
|
buf++;
|
|
|
|
len--;
|
1999-01-05 05:18:26 +03:00
|
|
|
f->charBufferUsed = JS_FALSE;
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (mode) {
|
|
|
|
case ASCII:
|
|
|
|
aux = (unsigned char*)JS_malloc(cx, len);
|
|
|
|
if (!aux) {
|
|
|
|
return 0;
|
|
|
|
}
|
1999-01-05 05:18:26 +03:00
|
|
|
count = js_BufferedRead(f, aux, len);
|
1998-11-05 03:08:43 +03:00
|
|
|
if (count==-1) {
|
|
|
|
JS_free(cx, aux);
|
|
|
|
return 0;
|
|
|
|
}
|
1999-01-05 05:18:26 +03:00
|
|
|
for (i = 0;i<len;i++) {
|
|
|
|
buf[i] = (jschar)aux[i];
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
JS_free(cx, aux);
|
|
|
|
break;
|
|
|
|
case UTF8:
|
|
|
|
remainder = 0;
|
1999-01-05 05:18:26 +03:00
|
|
|
for (count = 0;count<len;count++) {
|
|
|
|
i = js_BufferedRead(f, utfbuf+remainder, 3-remainder);
|
1998-11-05 03:08:43 +03:00
|
|
|
if (i<=0) {
|
|
|
|
return count;
|
|
|
|
}
|
1999-01-05 05:18:26 +03:00
|
|
|
i = utf8_to_ucs2_char(utfbuf, (int16)i, &buf[count] );
|
1998-11-05 03:08:43 +03:00
|
|
|
if (i<0) {
|
|
|
|
return count;
|
|
|
|
} else {
|
|
|
|
if (i==1) {
|
1999-01-05 05:18:26 +03:00
|
|
|
utfbuf[0] = utfbuf[1];
|
|
|
|
utfbuf[1] = utfbuf[2];
|
|
|
|
remainder = 2;
|
1998-11-05 03:08:43 +03:00
|
|
|
} else
|
|
|
|
if (i==2) {
|
1999-01-05 05:18:26 +03:00
|
|
|
utfbuf[0] = utfbuf[2];
|
|
|
|
remainder = 1;
|
1998-11-05 03:08:43 +03:00
|
|
|
} else
|
|
|
|
if (i==3)
|
1999-01-05 05:18:26 +03:00
|
|
|
remainder = 0;
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
while (remainder>0) {
|
1999-01-05 05:18:26 +03:00
|
|
|
f->byteBuffer[f->nbBytesInBuf] = utfbuf[0];
|
1998-11-05 03:08:43 +03:00
|
|
|
f->nbBytesInBuf++;
|
1999-01-05 05:18:26 +03:00
|
|
|
utfbuf[0] = utfbuf[1];
|
|
|
|
utfbuf[1] = utfbuf[2];
|
1998-11-05 03:08:43 +03:00
|
|
|
remainder--;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case UCS2:
|
1999-01-05 05:18:26 +03:00
|
|
|
count = js_BufferedRead(f, (char*)buf, len*2)>>1;
|
1998-11-05 03:08:43 +03:00
|
|
|
if (count==-1) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
1999-01-08 05:37:38 +03:00
|
|
|
|
|
|
|
if(count==-1){
|
|
|
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
|
|
|
JSFILEMSG_READ_FAILED, file->path);
|
|
|
|
}
|
|
|
|
|
1998-11-05 03:08:43 +03:00
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int32
|
1999-01-02 07:02:36 +03:00
|
|
|
js_FileSkip(JSFile * f, int32 len, int32 mode)
|
1998-11-05 03:08:43 +03:00
|
|
|
{
|
1999-01-01 07:37:28 +03:00
|
|
|
int32 count, i;
|
1998-11-05 03:08:43 +03:00
|
|
|
jsint remainder;
|
|
|
|
unsigned char utfbuf[3];
|
|
|
|
jschar tmp;
|
|
|
|
|
|
|
|
switch (mode) {
|
|
|
|
case ASCII:
|
1999-01-08 05:03:09 +03:00
|
|
|
count = (!f->isNative)?
|
|
|
|
PR_Seek(f->handle, len, PR_SEEK_CUR):
|
|
|
|
fseek(f->nativehandle, len, SEEK_CUR);
|
1998-11-05 03:08:43 +03:00
|
|
|
break;
|
|
|
|
case UTF8:
|
|
|
|
remainder = 0;
|
1999-01-05 05:18:26 +03:00
|
|
|
for (count = 0;count<len;count++) {
|
|
|
|
i = js_BufferedRead(f, utfbuf+remainder, 3-remainder);
|
1998-11-05 03:08:43 +03:00
|
|
|
if (i<=0) {
|
|
|
|
return 0;
|
|
|
|
}
|
1999-01-05 05:18:26 +03:00
|
|
|
i = utf8_to_ucs2_char(utfbuf, (int16)i, &tmp );
|
1998-11-05 03:08:43 +03:00
|
|
|
if (i<0) {
|
1998-12-31 08:58:26 +03:00
|
|
|
return 0;
|
1998-11-05 03:08:43 +03:00
|
|
|
} else {
|
1998-12-31 08:58:26 +03:00
|
|
|
|
1998-11-05 03:08:43 +03:00
|
|
|
if (i==1) {
|
1999-01-05 05:18:26 +03:00
|
|
|
utfbuf[0] = utfbuf[1];
|
|
|
|
utfbuf[1] = utfbuf[2];
|
|
|
|
remainder = 2;
|
1998-11-05 03:08:43 +03:00
|
|
|
} else
|
|
|
|
if (i==2) {
|
1999-01-05 05:18:26 +03:00
|
|
|
utfbuf[0] = utfbuf[2];
|
|
|
|
remainder = 1;
|
1998-11-05 03:08:43 +03:00
|
|
|
} else
|
|
|
|
if (i==3)
|
1999-01-05 05:18:26 +03:00
|
|
|
remainder = 0;
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
while (remainder>0) {
|
1999-01-05 05:18:26 +03:00
|
|
|
f->byteBuffer[f->nbBytesInBuf] = utfbuf[0];
|
1998-11-05 03:08:43 +03:00
|
|
|
f->nbBytesInBuf++;
|
1999-01-05 05:18:26 +03:00
|
|
|
utfbuf[0] = utfbuf[1];
|
|
|
|
utfbuf[1] = utfbuf[2];
|
1998-11-05 03:08:43 +03:00
|
|
|
remainder--;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case UCS2:
|
1999-01-08 05:03:09 +03:00
|
|
|
count = (!f->isNative)?
|
|
|
|
PR_Seek(f->handle, len*2, PR_SEEK_CUR)/2:
|
|
|
|
fseek(f->nativehandle, len*2, SEEK_CUR)/2;
|
1998-11-05 03:08:43 +03:00
|
|
|
break;
|
|
|
|
}
|
1999-01-08 05:37:38 +03:00
|
|
|
|
|
|
|
if(count==-1){
|
|
|
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
|
|
|
JSFILEMSG_SKIP_FAILED, file->path);
|
|
|
|
}
|
|
|
|
|
1998-11-05 03:08:43 +03:00
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int32
|
1999-01-08 05:37:38 +03:00
|
|
|
js_FileWrite(JSContext *cx, JSFile *file, jschar *buf, int32 len, int32 mode)
|
1998-11-05 03:08:43 +03:00
|
|
|
{
|
1999-01-08 05:37:38 +03:00
|
|
|
unsigned char *aux;
|
|
|
|
int32 count, i, j;
|
|
|
|
unsigned char *utfbuf;
|
|
|
|
|
1998-11-05 03:08:43 +03:00
|
|
|
switch (mode) {
|
|
|
|
case ASCII:
|
|
|
|
aux = (unsigned char*)JS_malloc(cx, len);
|
1999-01-02 07:02:36 +03:00
|
|
|
if (!aux) return 0;
|
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
for (i = 0; i<len; i++) {
|
1998-11-05 03:08:43 +03:00
|
|
|
aux[i]=buf[i]%256;
|
|
|
|
}
|
1999-01-08 05:03:09 +03:00
|
|
|
|
1999-01-08 05:37:38 +03:00
|
|
|
count = (!file->isNative)?
|
|
|
|
PR_Write(file->handle, aux, len):
|
|
|
|
fwrite(aux, 1, len, file->nativehandle);
|
1999-01-08 05:03:09 +03:00
|
|
|
|
1998-11-05 03:08:43 +03:00
|
|
|
if (count==-1) {
|
|
|
|
JS_free(cx, aux);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
JS_free(cx, aux);
|
|
|
|
break;
|
|
|
|
case UTF8:
|
|
|
|
utfbuf = (unsigned char*)JS_malloc(cx, len*3);
|
1999-01-02 07:02:36 +03:00
|
|
|
if (!utfbuf) return 0;
|
1999-01-05 05:18:26 +03:00
|
|
|
i = 0;
|
|
|
|
for (count = 0;count<len;count++) {
|
|
|
|
j = one_ucs2_to_utf8_char(utfbuf+i, utfbuf+len*3, buf[count]);
|
1998-11-05 03:08:43 +03:00
|
|
|
if (j==-1) {
|
|
|
|
JS_free(cx, utfbuf);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
i+=j;
|
|
|
|
}
|
1999-01-08 05:37:38 +03:00
|
|
|
j = (!file->isNative)?
|
|
|
|
PR_Write(file->handle, utfbuf, i):
|
|
|
|
fwrite(utfbuf, 1, i, file->nativehandle);
|
1999-01-08 05:03:09 +03:00
|
|
|
|
1998-11-05 03:08:43 +03:00
|
|
|
if (j<i) {
|
|
|
|
JS_free(cx, utfbuf);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
JS_free(cx, utfbuf);
|
|
|
|
break;
|
1998-12-31 08:58:26 +03:00
|
|
|
case UCS2:
|
1999-01-08 05:37:38 +03:00
|
|
|
count = (!file->isNative)?
|
|
|
|
PR_Write(file->handle, buf, len*2)>>1:
|
|
|
|
fwrite(buf, 1, len*2, file->nativehandle)>>1;
|
1999-01-08 05:03:09 +03:00
|
|
|
|
1998-11-05 03:08:43 +03:00
|
|
|
if (count==-1) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
1999-01-08 05:37:38 +03:00
|
|
|
if(count==-1){
|
|
|
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
|
|
|
JSFILEMSG_WRITE_FAILED, file->path);
|
|
|
|
}
|
1998-11-05 03:08:43 +03:00
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
/* ----------------------------- non-file access methods ------------------------- */
|
1998-11-05 03:08:43 +03:00
|
|
|
static JSBool
|
1999-01-07 07:41:20 +03:00
|
|
|
js_exists(JSFile *file)
|
1998-11-05 03:08:43 +03:00
|
|
|
{
|
1999-01-05 05:18:26 +03:00
|
|
|
/* SECURITY */
|
1999-01-07 07:41:20 +03:00
|
|
|
if(!file->isNative){
|
|
|
|
return (PR_Access(file->path, PR_ACCESS_EXISTS)==PR_SUCCESS);
|
|
|
|
}else{
|
1999-01-08 05:03:09 +03:00
|
|
|
return (access(file->path, PR_ACCESS_EXISTS)==PR_SUCCESS);
|
1999-01-07 07:41:20 +03:00
|
|
|
}
|
1999-01-05 05:18:26 +03:00
|
|
|
}
|
1998-11-05 03:08:43 +03:00
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
static JSBool
|
|
|
|
js_canRead(JSFile *file)
|
|
|
|
{
|
1999-01-08 05:03:09 +03:00
|
|
|
if(file->isOpen&&!(file->mode&PR_RDONLY)) return JS_FALSE;
|
1999-01-05 05:18:26 +03:00
|
|
|
/* SECURITY */
|
1999-01-07 07:41:20 +03:00
|
|
|
if(!file->isNative){
|
1999-01-08 05:03:09 +03:00
|
|
|
return (PR_Access(file->path, PR_ACCESS_READ_OK)==PR_SUCCESS);
|
1999-01-07 07:41:20 +03:00
|
|
|
}else{
|
1999-01-08 05:03:09 +03:00
|
|
|
return (access(file->path, PR_ACCESS_READ_OK)==PR_SUCCESS);
|
1999-01-07 07:41:20 +03:00
|
|
|
}
|
1999-01-05 05:18:26 +03:00
|
|
|
}
|
1998-11-05 03:08:43 +03:00
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
static JSBool
|
|
|
|
js_canWrite(JSFile *file)
|
|
|
|
{
|
1999-01-08 05:03:09 +03:00
|
|
|
if(file->isOpen&&!(file->mode&PR_WRONLY)) return JS_FALSE;
|
1999-01-05 05:18:26 +03:00
|
|
|
/* SECURITY */
|
1999-01-07 07:41:20 +03:00
|
|
|
if(!file->isNative){
|
1999-01-08 05:03:09 +03:00
|
|
|
return (PR_Access(file->path, PR_ACCESS_WRITE_OK)==PR_SUCCESS);
|
1999-01-07 07:41:20 +03:00
|
|
|
}else{
|
1999-01-08 05:03:09 +03:00
|
|
|
return (access(file->path, PR_ACCESS_WRITE_OK)==PR_SUCCESS);
|
1999-01-07 07:41:20 +03:00
|
|
|
}
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
static JSBool
|
|
|
|
js_isFile(JSFile *file)
|
|
|
|
{
|
|
|
|
/* SECURITY */
|
1999-01-07 07:17:23 +03:00
|
|
|
if(!file->isNative){
|
1999-01-08 05:03:09 +03:00
|
|
|
PRFileInfo info;
|
|
|
|
|
1999-01-07 07:17:23 +03:00
|
|
|
if ((file->isOpen)?
|
|
|
|
PR_GetOpenFileInfo(file->handle, &info):
|
|
|
|
PR_GetFileInfo(file->path, &info)!=PR_SUCCESS){
|
|
|
|
/* TODO: report error */
|
|
|
|
return JS_FALSE;
|
|
|
|
}else
|
|
|
|
return (info.type==PR_FILE_FILE);
|
1999-01-05 05:18:26 +03:00
|
|
|
}else{
|
1999-01-08 05:03:09 +03:00
|
|
|
struct stat buf;
|
|
|
|
if(stat(file->path, &buf)){
|
|
|
|
/* TODO: report error */
|
|
|
|
return JS_FALSE;
|
|
|
|
}
|
|
|
|
return (buf.st_mode&_S_IFREG);
|
1999-01-05 05:18:26 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static JSBool
|
|
|
|
js_isDirectory(JSFile *file)
|
|
|
|
{
|
|
|
|
/* SECURITY */
|
1999-01-07 07:17:23 +03:00
|
|
|
if(!file->isNative){
|
1999-01-08 05:03:09 +03:00
|
|
|
PRFileInfo info;
|
|
|
|
|
1999-01-07 07:17:23 +03:00
|
|
|
if ((file->isOpen)?
|
|
|
|
PR_GetOpenFileInfo(file->handle, &info):
|
|
|
|
PR_GetFileInfo(file->path, &info)!=PR_SUCCESS){
|
|
|
|
/* TODO: report error */
|
|
|
|
return JS_FALSE;
|
|
|
|
}else
|
|
|
|
return (info.type==PR_FILE_DIRECTORY);
|
1999-01-05 05:18:26 +03:00
|
|
|
}else{
|
1999-01-08 05:03:09 +03:00
|
|
|
struct stat buf;
|
|
|
|
if(stat(file->path, &buf )){
|
|
|
|
/* TODO: report error */
|
|
|
|
return JS_FALSE;
|
|
|
|
}
|
|
|
|
return (buf.st_mode&_S_IFDIR);
|
1999-01-05 05:18:26 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-01-08 05:03:09 +03:00
|
|
|
static int
|
1999-01-08 05:37:38 +03:00
|
|
|
js_size(JSContext *cx, JSFile *file)
|
1999-01-08 05:03:09 +03:00
|
|
|
{
|
|
|
|
/* SECURITY */
|
|
|
|
if(!file->isNative){
|
|
|
|
PRFileInfo info;
|
|
|
|
|
|
|
|
if ((file->isOpen)?
|
|
|
|
PR_GetOpenFileInfo(file->handle, &info):
|
|
|
|
PR_GetFileInfo(file->path, &info)!=PR_SUCCESS){
|
|
|
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
|
|
|
JSFILEMSG_CANNOT_ACCESS_FILE_STATUS, file->path);
|
|
|
|
return -1;
|
|
|
|
}else
|
|
|
|
return info.size;
|
|
|
|
}else{
|
|
|
|
struct stat buf;
|
|
|
|
if(stat(file->path, &buf)){
|
|
|
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
|
|
|
JSFILEMSG_CANNOT_ACCESS_FILE_STATUS, file->path);
|
|
|
|
return -1;
|
|
|
|
}else
|
|
|
|
return buf.st_size;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
/* -------------------------------- File methods ------------------------------ */
|
1998-11-05 03:08:43 +03:00
|
|
|
static JSBool
|
|
|
|
file_open(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|
|
|
{
|
1998-12-31 08:58:26 +03:00
|
|
|
JSFile *file;
|
|
|
|
JSString *strmode, *strtype;
|
|
|
|
char *ctype;
|
|
|
|
char *mode;
|
1998-11-05 03:08:43 +03:00
|
|
|
int32 mask;
|
|
|
|
int32 type;
|
1999-01-01 07:37:28 +03:00
|
|
|
int len;
|
1998-11-05 03:08:43 +03:00
|
|
|
|
|
|
|
file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
|
|
|
|
|
1999-01-01 07:37:28 +03:00
|
|
|
/* A native file that is already open */
|
1999-01-07 07:17:23 +03:00
|
|
|
if(file->isOpen && file->isNative){
|
1999-01-08 05:03:09 +03:00
|
|
|
JS_ReportWarning(cx, "Native file %s is already open, proceeding", file->path);
|
|
|
|
*rval = JSVAL_TRUE;
|
1999-01-01 07:37:28 +03:00
|
|
|
return JS_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Close before proceeding */
|
1999-01-07 07:17:23 +03:00
|
|
|
if (file->isOpen) {
|
|
|
|
JS_ReportWarning(cx, "File %s is already open, we will close it and reopen, proceeding");
|
1999-01-01 07:37:28 +03:00
|
|
|
file_close(cx, obj, 0, NULL, rval);
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
|
1999-01-01 07:37:28 +03:00
|
|
|
/* Path not defined */
|
1998-12-31 08:58:26 +03:00
|
|
|
if (!file->path) return JS_FALSE;
|
1999-01-01 07:37:28 +03:00
|
|
|
len = strlen(file->path);
|
1998-11-05 03:08:43 +03:00
|
|
|
|
1999-01-01 07:37:28 +03:00
|
|
|
/* Mode */
|
|
|
|
if (argc>=2){
|
|
|
|
strmode = JS_ValueToString(cx, argv[1]);
|
|
|
|
if (!strmode){
|
1998-12-31 08:58:26 +03:00
|
|
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
1999-01-01 07:37:28 +03:00
|
|
|
JSFILEMSG_SECOND_ARGUMENT_OPEN_NOT_STRING_ERROR, argv[1]);
|
1998-11-05 03:08:43 +03:00
|
|
|
return JS_FALSE;
|
|
|
|
}
|
1999-01-01 07:37:28 +03:00
|
|
|
mode = JS_strdup(cx, JS_GetStringBytes(strmode));
|
|
|
|
}else{
|
|
|
|
if(file->path[0]==PIPE_SYMBOL){
|
|
|
|
mode = JS_strdup(cx, "readOnly"); /* pipe default mode */
|
|
|
|
}else
|
|
|
|
if(file->path[len-1]==PIPE_SYMBOL){
|
|
|
|
mode = JS_strdup(cx, "writeOnly"); /* pipe default mode */
|
|
|
|
}else{
|
|
|
|
mode = JS_strdup(cx, "readWrite, append, create"); /* non-destructive, permissive defaults. */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Process the mode */
|
1999-01-05 05:18:26 +03:00
|
|
|
mask = 0;
|
1999-01-01 07:37:28 +03:00
|
|
|
/* TODO: this is pretty ugly, BTW, we walk thru the string too many times */
|
1999-01-08 05:03:09 +03:00
|
|
|
mask|=(js_FileHasOption(cx, mode, "readOnly"))? PR_RDONLY : 0;
|
|
|
|
mask|=(js_FileHasOption(cx, mode, "writeOnly"))? 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;
|
1999-01-01 07:37:28 +03:00
|
|
|
|
|
|
|
if ((mask&(PR_RDONLY|PR_WRONLY))==0) mask|=PR_RDWR;
|
|
|
|
|
1999-01-08 05:03:09 +03:00
|
|
|
file->hasAutoflush|=(js_FileHasOption(cx, mode, "hasAutoflush"));
|
1999-01-01 07:37:28 +03:00
|
|
|
|
|
|
|
JS_free(cx, mode);
|
|
|
|
|
|
|
|
/* Type */
|
1998-11-05 03:08:43 +03:00
|
|
|
if (argc>=1) {
|
|
|
|
strtype = JS_ValueToString(cx, argv[0]);
|
|
|
|
if (!strtype) {
|
1998-12-31 08:58:26 +03:00
|
|
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
1999-01-01 07:37:28 +03:00
|
|
|
JSFILEMSG_FIRST_ARGUMENT_OPEN_NOT_STRING_ERROR, argv[0]);
|
1998-11-05 03:08:43 +03:00
|
|
|
return JS_FALSE;
|
|
|
|
}
|
|
|
|
ctype = JS_GetStringBytes(strtype);
|
1999-01-01 07:37:28 +03:00
|
|
|
}else{
|
1998-11-05 03:08:43 +03:00
|
|
|
ctype = "";
|
1999-01-01 07:37:28 +03:00
|
|
|
}
|
1998-11-05 03:08:43 +03:00
|
|
|
|
1999-01-01 07:37:28 +03:00
|
|
|
if (!strcmp(ctype, asciistring))
|
1999-01-05 05:18:26 +03:00
|
|
|
type = ASCII;
|
1998-11-05 03:08:43 +03:00
|
|
|
else
|
1999-01-01 07:37:28 +03:00
|
|
|
if (!strcmp(ctype, unicodestring))
|
1999-01-05 05:18:26 +03:00
|
|
|
type = UCS2;
|
1998-11-05 03:08:43 +03:00
|
|
|
else
|
1999-01-05 05:18:26 +03:00
|
|
|
type = UTF8;
|
1998-11-05 03:08:43 +03:00
|
|
|
|
1999-01-01 07:37:28 +03:00
|
|
|
/* Save the relevant fields */
|
1999-01-05 05:18:26 +03:00
|
|
|
file->type = type;
|
|
|
|
file->mode = mask;
|
|
|
|
file->nativehandle = NULL;
|
1999-01-08 05:03:09 +03:00
|
|
|
file->hasRandomAccess = (type!=UTF8);
|
1998-11-05 03:08:43 +03:00
|
|
|
|
1999-01-02 07:02:36 +03:00
|
|
|
/*
|
|
|
|
Deal with pipes here. We can't use NSPR for pipes,
|
1999-01-05 05:18:26 +03:00
|
|
|
so we have to use POPEN.
|
1999-01-02 07:02:36 +03:00
|
|
|
*/
|
1999-01-01 07:37:28 +03:00
|
|
|
if(file->path[0]==PIPE_SYMBOL || file->path[len-1]==PIPE_SYMBOL){
|
1999-01-02 07:02:36 +03:00
|
|
|
if(file->path[0]==PIPE_SYMBOL && file->path[len-1]){
|
|
|
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
|
|
|
JSFILEMSG_BIDIRECTIONAL_PIPE_NOT_SUPPORTED);
|
|
|
|
return JS_FALSE;
|
1999-01-01 07:37:28 +03:00
|
|
|
}else{
|
|
|
|
char pipemode[3];
|
1999-01-05 05:18:26 +03:00
|
|
|
/* special SECURITY */
|
|
|
|
|
1999-01-01 07:37:28 +03:00
|
|
|
if(file->path[0] == PIPE_SYMBOL){
|
|
|
|
if(mask & (PR_RDONLY | PR_APPEND | PR_CREATE_FILE | PR_TRUNCATE)){
|
1999-01-02 07:02:36 +03:00
|
|
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
|
|
|
JSFILEMSG_OPEN_MODE_NOT_SUPPORTED_WITH_PIPES,
|
|
|
|
mode, file->path);
|
1999-01-01 07:37:28 +03:00
|
|
|
return JS_FALSE;
|
|
|
|
}
|
|
|
|
/* open(SPOOLER, "| cat -v | lpr -h 2>/dev/null") -- pipe for writing */
|
|
|
|
pipemode[0] = 'w';
|
|
|
|
pipemode[1] = file->type==UTF8?'b':'t';
|
|
|
|
pipemode[2] = '\0';
|
|
|
|
file->nativehandle = POPEN(&file->path[1], pipemode);
|
|
|
|
}else
|
1999-01-02 07:02:36 +03:00
|
|
|
if(file->path[len-1] == PIPE_SYMBOL){
|
|
|
|
char *command = JS_malloc(cx, len);
|
|
|
|
|
|
|
|
strncpy(command, file->path, len-1);
|
1999-01-05 05:18:26 +03:00
|
|
|
command[len-1] = '\0';
|
1999-01-01 07:37:28 +03:00
|
|
|
/* open(STATUS, "netstat -an 2>&1 |") */
|
|
|
|
pipemode[0] = 'r';
|
|
|
|
pipemode[1] = file->type==UTF8?'b':'t';
|
|
|
|
pipemode[2] = '\0';
|
1999-01-02 07:02:36 +03:00
|
|
|
file->nativehandle = POPEN(command, pipemode);
|
|
|
|
JS_free(cx, command);
|
1999-01-01 07:37:28 +03:00
|
|
|
}
|
1999-01-07 07:17:23 +03:00
|
|
|
/* set the flags */
|
|
|
|
file->isNative = JS_TRUE;
|
1999-01-05 05:18:26 +03:00
|
|
|
file->isAPipe = JS_TRUE;
|
1999-01-01 07:37:28 +03:00
|
|
|
}
|
|
|
|
}else{
|
1999-01-05 05:18:26 +03:00
|
|
|
/* SECURITY */
|
|
|
|
/* TODO: what about the permissions?? Java seems to ignore the problem.. */
|
1999-01-01 07:37:28 +03:00
|
|
|
file->handle = PR_Open(file->path, mask, 0644);
|
|
|
|
}
|
1998-11-05 03:08:43 +03:00
|
|
|
|
1999-01-02 07:02:36 +03:00
|
|
|
js_ResetBuffers(file);
|
1998-11-05 03:08:43 +03:00
|
|
|
|
1999-01-01 07:37:28 +03:00
|
|
|
/* Set the open flag and return result */
|
|
|
|
if (file->handle==NULL && file->nativehandle==NULL){
|
1999-01-08 05:03:09 +03:00
|
|
|
file->isOpen = JS_FALSE;
|
|
|
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
|
|
|
JSFILEMSG_OPEN_FAILED, file->path);
|
1999-01-02 07:02:36 +03:00
|
|
|
return JS_FALSE;
|
1999-01-01 07:37:28 +03:00
|
|
|
}else{
|
1999-01-07 07:17:23 +03:00
|
|
|
file->isOpen = JS_TRUE;
|
1999-01-08 05:03:09 +03:00
|
|
|
*rval = JSVAL_TRUE;
|
1999-01-02 07:02:36 +03:00
|
|
|
return JS_TRUE;
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static JSBool
|
|
|
|
file_close(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|
|
|
{
|
|
|
|
JSFile *file;
|
|
|
|
|
1999-01-07 07:17:23 +03:00
|
|
|
/* SECURITY ? */
|
1998-11-05 03:08:43 +03:00
|
|
|
file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
|
|
|
|
|
1999-01-07 07:17:23 +03:00
|
|
|
if(!file->isOpen){
|
|
|
|
JS_ReportWarning(cx, "File %s is not open, can't close it, proceeding", file->path);
|
|
|
|
}
|
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
if(!file->isAPipe){
|
1999-01-07 07:17:23 +03:00
|
|
|
if ((!file->isNative)?
|
1999-01-05 05:18:26 +03:00
|
|
|
PR_Close(file->handle):
|
|
|
|
fclose(file->nativehandle)!=0){
|
1999-01-08 05:03:09 +03:00
|
|
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
|
|
|
JSFILEMSG_CLOSE_FAILED, file->path);
|
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
return JS_FALSE;
|
|
|
|
}
|
|
|
|
}else{
|
|
|
|
if(PCLOSE(file->nativehandle)==-1){
|
1999-01-08 05:03:09 +03:00
|
|
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
|
|
|
JSFILEMSG_PCLOSE_FAILED, file->path);
|
1999-01-05 05:18:26 +03:00
|
|
|
return JS_FALSE;
|
|
|
|
}
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
js_ResetAttributes(file);
|
|
|
|
*rval = JSVAL_TRUE;
|
1998-11-05 03:08:43 +03:00
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
return JS_TRUE;
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static JSBool
|
1999-01-05 05:18:26 +03:00
|
|
|
file_remove(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
1998-11-05 03:08:43 +03:00
|
|
|
{
|
1999-01-05 05:18:26 +03:00
|
|
|
JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);;
|
1998-12-31 08:58:26 +03:00
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
/* SECURITY */
|
1999-01-08 05:03:09 +03:00
|
|
|
if(!file->isNative){
|
|
|
|
if ((js_isDirectory(file) ? PR_RmDir(file->path) : PR_Delete(file->path))==PR_SUCCESS) {
|
|
|
|
js_ResetAttributes(file);
|
|
|
|
*rval = JSVAL_TRUE;
|
|
|
|
} else {
|
|
|
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
|
|
|
JSFILEMSG_REMOVE_FAILED, file->path);
|
|
|
|
return JS_FALSE;
|
|
|
|
}
|
|
|
|
}else{
|
|
|
|
if ((js_isDirectory(file) ? rmdir(file->path) : remove(file->path))==PR_SUCCESS) {
|
|
|
|
js_ResetAttributes(file);
|
|
|
|
*rval = JSVAL_TRUE;
|
|
|
|
} else {
|
|
|
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
|
|
|
JSFILEMSG_REMOVE_FAILED, file->path);
|
|
|
|
return JS_FALSE;
|
|
|
|
}
|
1999-01-05 05:18:26 +03:00
|
|
|
}
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
/* Raw PR-based function. No text processing. Just raw data copying. */
|
1998-11-05 03:08:43 +03:00
|
|
|
static JSBool
|
1999-01-05 05:18:26 +03:00
|
|
|
file_copyTo(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
1998-11-05 03:08:43 +03:00
|
|
|
{
|
1999-01-05 05:18:26 +03:00
|
|
|
JSFile *file;
|
1999-01-08 05:37:38 +03:00
|
|
|
char *dest = NULL;
|
1999-01-08 05:03:09 +03:00
|
|
|
PRFileDesc *handle = NULL;
|
1999-01-05 05:18:26 +03:00
|
|
|
char *buffer;
|
1999-01-08 05:03:09 +03:00
|
|
|
uint32 count, size;
|
|
|
|
JSBool fileInitiallyOpen=JS_FALSE;
|
|
|
|
|
|
|
|
/* SECURITY */
|
1999-01-02 07:02:36 +03:00
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
if (argc!=1){
|
1999-01-08 05:03:09 +03:00
|
|
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
|
|
|
JSFILEMSG_EXPECTS_ONE_ARG_ERROR, "copyTo", argc);
|
|
|
|
goto out;
|
1999-01-05 05:18:26 +03:00
|
|
|
}
|
1998-11-05 03:08:43 +03:00
|
|
|
|
|
|
|
file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
|
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
dest = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
|
|
|
|
|
|
|
|
/* SECURITY */
|
|
|
|
/* make sure we are not reading a file open for writing */
|
1999-01-07 07:17:23 +03:00
|
|
|
if (file->isOpen && (file->mode&PR_WRONLY)) {
|
1999-01-05 05:18:26 +03:00
|
|
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
|
|
|
JSFILEMSG_CANNOT_COPY_FILE_OPEN_FOR_WRITING_ERROR, file->path);
|
|
|
|
return JS_FALSE;
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
/* open a closed file */
|
1999-01-07 07:17:23 +03:00
|
|
|
if(!file->isOpen){
|
1999-01-08 05:37:38 +03:00
|
|
|
js_FileOpen(cx, obj, file, "readOnly");
|
1999-01-08 05:03:09 +03:00
|
|
|
}else
|
|
|
|
fileInitiallyOpen = JS_TRUE;
|
|
|
|
|
|
|
|
if (file->handle==NULL && file->nativehandle==NULL){
|
|
|
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
|
|
|
JSFILEMSG_OPEN_FAILED, file->path);
|
1999-01-08 05:37:38 +03:00
|
|
|
goto out;
|
1999-01-08 05:03:09 +03:00
|
|
|
}else
|
1999-01-08 05:37:38 +03:00
|
|
|
file->isOpen = JS_TRUE;
|
1998-11-05 03:08:43 +03:00
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
handle = PR_Open(dest, PR_WRONLY|PR_CREATE_FILE|PR_TRUNCATE, 0644);
|
1998-11-05 03:08:43 +03:00
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
if(!handle){
|
1999-01-08 05:03:09 +03:00
|
|
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
|
|
|
JSFILEMSG_OPEN_FAILED, dest);
|
|
|
|
goto out;
|
1999-01-05 05:18:26 +03:00
|
|
|
}
|
1998-11-05 03:08:43 +03:00
|
|
|
|
1999-01-08 05:37:38 +03:00
|
|
|
if ((size=js_size(cx, file))!=-1) {
|
1999-01-08 05:03:09 +03:00
|
|
|
goto out;
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
|
1999-01-08 05:03:09 +03:00
|
|
|
buffer = JS_malloc(cx, size);
|
1998-11-05 03:08:43 +03:00
|
|
|
|
1999-01-08 05:03:09 +03:00
|
|
|
count = (!file->isNative)?
|
|
|
|
PR_Read(file->handle, buffer, size):
|
|
|
|
fread(buffer, 1, size, file->nativehandle);
|
1998-11-05 03:08:43 +03:00
|
|
|
|
1999-01-08 05:03:09 +03:00
|
|
|
/* reading panic */
|
|
|
|
if (count!=size) {
|
1999-01-01 07:37:28 +03:00
|
|
|
JS_free(cx, buffer);
|
1998-12-31 08:58:26 +03:00
|
|
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
|
|
|
JSFILEMSG_COPY_READ_ERROR, file->path);
|
1999-01-08 05:03:09 +03:00
|
|
|
goto out;
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
1999-01-05 05:18:26 +03:00
|
|
|
|
1999-01-08 05:03:09 +03:00
|
|
|
count = PR_Write(handle, buffer, size);
|
1999-01-05 05:18:26 +03:00
|
|
|
|
1999-01-08 05:03:09 +03:00
|
|
|
/* writing panic */
|
|
|
|
if (count!=size) {
|
1999-01-01 07:37:28 +03:00
|
|
|
JS_free(cx, buffer);
|
1998-12-31 08:58:26 +03:00
|
|
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
|
|
|
JSFILEMSG_COPY_WRITE_ERROR, file->path);
|
1999-01-08 05:03:09 +03:00
|
|
|
goto out;
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
1999-01-05 05:18:26 +03:00
|
|
|
|
1999-01-01 07:37:28 +03:00
|
|
|
JS_free(cx, buffer);
|
1999-01-08 05:37:38 +03:00
|
|
|
|
1999-01-08 05:03:09 +03:00
|
|
|
if(((!file->isNative)?PR_Close(file->handle):fclose(file->nativehandle))!=PR_SUCCESS){
|
1999-01-08 05:37:38 +03:00
|
|
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
|
|
|
JSFILEMSG_CLOSE_FAILED, file->path);
|
|
|
|
goto out;
|
1999-01-05 05:18:26 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if(PR_Close(handle)!=PR_SUCCESS){
|
1999-01-08 05:37:38 +03:00
|
|
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
|
|
|
JSFILEMSG_CLOSE_FAILED, dest);
|
|
|
|
goto out;
|
|
|
|
}
|
1998-11-05 03:08:43 +03:00
|
|
|
|
|
|
|
*rval = JSVAL_TRUE;
|
|
|
|
return JS_TRUE;
|
1999-01-08 05:03:09 +03:00
|
|
|
out:
|
1999-01-08 05:37:38 +03:00
|
|
|
if(file->isOpen && !fileInitiallyOpen){
|
1999-01-08 05:03:09 +03:00
|
|
|
if((!file->isNative)?PR_Close(file->handle):fclose(file->nativehandle)!=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;
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static JSBool
|
|
|
|
file_renameTo(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|
|
|
{
|
|
|
|
JSFile *file;
|
1999-01-05 05:18:26 +03:00
|
|
|
char *dest;
|
1998-11-05 03:08:43 +03:00
|
|
|
|
|
|
|
if (argc<1) {
|
1999-01-08 05:37:38 +03:00
|
|
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
|
|
|
JSFILEMSG_EXPECTS_ONE_ARG_ERROR, "rename", argc);
|
|
|
|
*rval = JSVAL_TRUE;
|
|
|
|
return JS_FALSE;
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
|
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
dest = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
|
1998-11-05 03:08:43 +03:00
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
/* SECURITY */
|
1999-01-08 05:03:09 +03:00
|
|
|
if (((!file->isNative)?PR_Rename(file->path, dest):rename(file->path, dest))==PR_SUCCESS){
|
1999-01-08 05:37:38 +03:00
|
|
|
*rval = JSVAL_TRUE;
|
1999-01-05 05:18:26 +03:00
|
|
|
return JS_TRUE;
|
|
|
|
}else{
|
1999-01-08 05:37:38 +03:00
|
|
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
|
|
|
JSFILEMSG_RENAME_FAILED, file->path, dest);
|
|
|
|
*rval = JSVAL_FALSE;
|
1999-01-05 05:18:26 +03:00
|
|
|
return JS_FALSE;
|
|
|
|
}
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static JSBool
|
|
|
|
file_flush(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|
|
|
{
|
1999-01-05 05:18:26 +03:00
|
|
|
JSFile *file;
|
1998-11-05 03:08:43 +03:00
|
|
|
|
|
|
|
file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
|
|
|
|
|
1999-01-07 07:17:23 +03:00
|
|
|
if (!file->isOpen) {
|
1998-12-31 08:58:26 +03:00
|
|
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
|
|
|
JSFILEMSG_CANNOT_FLUSH_CLOSE_FILE_ERROR, file->path);
|
1998-11-05 03:08:43 +03:00
|
|
|
return JS_FALSE;
|
|
|
|
}
|
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
/* SECURITY */
|
1999-01-07 07:17:23 +03:00
|
|
|
if ((!file->isNative)?PR_Sync(file->handle):fflush(file->nativehandle)==PR_SUCCESS)
|
1999-01-05 05:18:26 +03:00
|
|
|
*rval = JSVAL_TRUE;
|
|
|
|
else{
|
1999-01-08 05:03:09 +03:00
|
|
|
/* TODO: report error */
|
1999-01-05 05:18:26 +03:00
|
|
|
return JS_FALSE;
|
|
|
|
}
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static JSBool
|
|
|
|
file_write(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|
|
|
{
|
1999-01-05 05:18:26 +03:00
|
|
|
uintN i;
|
|
|
|
JSFile *file;
|
|
|
|
JSString *str;
|
|
|
|
int32 count;
|
1998-11-05 03:08:43 +03:00
|
|
|
|
|
|
|
file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
|
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
/* SECURITY */
|
|
|
|
/* open file if necessary */
|
1999-01-07 07:17:23 +03:00
|
|
|
if (!file->isOpen) {
|
1999-01-05 06:51:30 +03:00
|
|
|
js_FileOpen(cx, obj, file, "create, append, writeOnly");
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
1998-12-31 08:58:26 +03:00
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
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){
|
1999-01-08 05:37:38 +03:00
|
|
|
*rval = JSVAL_FALSE;
|
1999-01-05 05:18:26 +03:00
|
|
|
return JS_FALSE;
|
|
|
|
}
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
*rval = JSVAL_TRUE;
|
|
|
|
return JS_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static JSBool
|
|
|
|
file_writeln(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|
|
|
{
|
|
|
|
JSFile *file;
|
|
|
|
JSString *str;
|
|
|
|
|
|
|
|
file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
|
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
/* 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, LINEBREAK);
|
1998-11-05 03:08:43 +03:00
|
|
|
|
1999-01-08 05:03:09 +03:00
|
|
|
if (js_FileWrite(cx, file, JS_GetStringChars(str), JS_GetStringLength(str), file->type)==-1){
|
1999-01-08 05:37:38 +03:00
|
|
|
*rval = JSVAL_FALSE;
|
1999-01-05 05:18:26 +03:00
|
|
|
return JS_FALSE;
|
|
|
|
}
|
1998-11-05 03:08:43 +03:00
|
|
|
|
1999-01-08 05:03:09 +03:00
|
|
|
/* eol causes flush if hasAutoflush is turned on */
|
|
|
|
if (file->hasAutoflush)
|
1999-01-05 05:18:26 +03:00
|
|
|
file_flush(cx, obj, 0, NULL, NULL);
|
1998-11-05 03:08:43 +03:00
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
*rval = JSVAL_TRUE;
|
1998-11-05 03:08:43 +03:00
|
|
|
return JS_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static JSBool
|
|
|
|
file_writeAll(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|
|
|
{
|
|
|
|
JSFile *file;
|
1999-01-05 05:18:26 +03:00
|
|
|
jsuint i;
|
|
|
|
jsuint limit;
|
1998-11-05 03:08:43 +03:00
|
|
|
JSObject *array;
|
|
|
|
JSObject *elem;
|
|
|
|
jsval elemval;
|
|
|
|
|
|
|
|
file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
|
1999-01-05 05:18:26 +03:00
|
|
|
/* SECURITY */
|
1998-11-05 03:08:43 +03:00
|
|
|
|
|
|
|
if (argc<1) {
|
1998-12-31 08:58:26 +03:00
|
|
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
|
|
|
JSFILEMSG_WRITEALL_EXPECTS_ONE_ARG_ERROR);
|
1999-01-08 05:37:38 +03:00
|
|
|
goto out;
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!JS_IsArrayObject(cx, JSVAL_TO_OBJECT(argv[0]))) {
|
1998-12-31 08:58:26 +03:00
|
|
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
|
|
|
JSFILEMSG_FIRST_ARGUMENT_WRITEALL_NOT_ARRAY_ERROR);
|
1999-01-08 05:37:38 +03:00
|
|
|
goto out;
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
1999-01-05 05:18:26 +03:00
|
|
|
array = JSVAL_TO_OBJECT(argv[0]);
|
1998-11-05 03:08:43 +03:00
|
|
|
if (!JS_GetArrayLength(cx, array, &limit)) {
|
1999-01-05 05:18:26 +03:00
|
|
|
/* TODO: error */
|
1999-01-08 05:37:38 +03:00
|
|
|
goto out;
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
1998-12-31 08:58:26 +03:00
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
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);
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
*rval = JSVAL_TRUE;
|
|
|
|
return JS_TRUE;
|
1999-01-08 05:37:38 +03:00
|
|
|
out:
|
|
|
|
*rval = JSVAL_FALSE;
|
|
|
|
return JS_FALSE;
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static JSBool
|
|
|
|
file_read(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|
|
|
{
|
|
|
|
JSFile *file;
|
|
|
|
JSString *str;
|
1999-01-01 07:37:28 +03:00
|
|
|
int32 want, count;
|
1998-11-05 03:08:43 +03:00
|
|
|
jschar *buf;
|
|
|
|
|
|
|
|
file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
|
1999-01-05 05:18:26 +03:00
|
|
|
/* SECURITY */
|
1999-01-08 05:37:38 +03:00
|
|
|
|
|
|
|
if (argc!=1){
|
|
|
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
|
|
|
JSFILEMSG_EXPECTS_ONE_ARG_ERROR, "copyTo", argc);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
1999-01-07 07:17:23 +03:00
|
|
|
if (!file->isOpen) {
|
1999-01-05 06:51:30 +03:00
|
|
|
js_FileOpen(cx, obj, file, "readOnly");
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
1998-12-31 08:58:26 +03:00
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
if (!JS_ValueToInt32(cx, argv[0], &want)){
|
1999-01-08 05:37:38 +03:00
|
|
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
|
|
|
JSFILEMSG_FIRST_ARGUMENT__MUST_BE_A_NUMBER, "read", argv[0]);
|
|
|
|
goto out;
|
1999-01-05 05:18:26 +03:00
|
|
|
}
|
1998-11-05 03:08:43 +03:00
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
/* want = (want>262144)?262144:want; * arbitrary size limitation */
|
1998-12-31 08:58:26 +03:00
|
|
|
|
1999-01-01 07:37:28 +03:00
|
|
|
buf = JS_malloc(cx, want*sizeof buf[0]);
|
1999-01-08 05:37:38 +03:00
|
|
|
if (!buf) goto out;
|
1998-11-05 03:08:43 +03:00
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
count = js_FileRead(cx, file, buf, want, file->type);
|
1998-11-05 03:08:43 +03:00
|
|
|
if (count>0) {
|
1999-01-05 05:18:26 +03:00
|
|
|
/* TODO: do we need unicode here? */
|
|
|
|
str = JS_NewUCStringCopyN(cx, buf, count);
|
|
|
|
*rval = STRING_TO_JSVAL(str);
|
|
|
|
JS_free(cx, buf);
|
|
|
|
return JS_TRUE;
|
1998-11-05 03:08:43 +03:00
|
|
|
} else {
|
1999-01-05 05:18:26 +03:00
|
|
|
JS_free(cx, buf);
|
1999-01-08 05:37:38 +03:00
|
|
|
goto out;
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
1999-01-08 05:37:38 +03:00
|
|
|
out:
|
|
|
|
*rval = JSVAL_FALSE;
|
|
|
|
return JS_FALSE;
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static JSBool
|
|
|
|
file_readln(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|
|
|
{
|
|
|
|
JSFile *file;
|
|
|
|
JSString *str;
|
|
|
|
jschar *buf;
|
|
|
|
int32 offset;
|
|
|
|
intN room;
|
1999-01-01 07:37:28 +03:00
|
|
|
jschar data, data2;
|
1999-01-05 06:51:30 +03:00
|
|
|
JSBool endofline;
|
1998-11-05 03:08:43 +03:00
|
|
|
|
|
|
|
file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
|
|
|
|
|
1999-01-05 06:51:30 +03:00
|
|
|
/* SECURITY */
|
1999-01-07 07:17:23 +03:00
|
|
|
if (!file->isOpen){
|
1999-01-05 06:51:30 +03:00
|
|
|
js_FileOpen(cx, obj, file, "readOnly");
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!file->linebuffer) {
|
|
|
|
buf = JS_malloc(cx, 128*(sizeof data));
|
1999-01-02 07:02:36 +03:00
|
|
|
if (!buf) return JS_FALSE;
|
1999-01-05 05:18:26 +03:00
|
|
|
file->linebuffer = JS_NewUCString(cx, buf, 128);
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
1999-01-05 05:18:26 +03:00
|
|
|
room = JS_GetStringLength(file->linebuffer);
|
|
|
|
offset = 0;
|
1998-11-05 03:08:43 +03:00
|
|
|
|
1999-01-05 06:51:30 +03:00
|
|
|
/* XXX TEST ME!! TODO: yes, please do */
|
1998-11-05 03:08:43 +03:00
|
|
|
for(;;) {
|
1999-01-05 05:18:26 +03:00
|
|
|
if (!js_FileRead(cx, file, &data, 1, file->type)) {
|
|
|
|
endofline = JS_FALSE;
|
1998-11-05 03:08:43 +03:00
|
|
|
goto loop;
|
|
|
|
}
|
|
|
|
switch (data) {
|
1998-12-31 08:58:26 +03:00
|
|
|
case '\n' :
|
1999-01-05 05:18:26 +03:00
|
|
|
endofline = JS_TRUE;
|
1998-11-05 03:08:43 +03:00
|
|
|
goto loop;
|
|
|
|
case '\r' :
|
1999-01-05 05:18:26 +03:00
|
|
|
if (!js_FileRead(cx, file, &data2, 1, file->type)) {
|
|
|
|
endofline = JS_TRUE;
|
1998-11-05 03:08:43 +03:00
|
|
|
goto loop;
|
|
|
|
}
|
|
|
|
if (data2!='\n') { /* we read one char to far. buffer it. */
|
1999-01-05 05:18:26 +03:00
|
|
|
file->charBuffer = data2;
|
|
|
|
file->charBufferUsed = JS_TRUE;
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
1999-01-05 05:18:26 +03:00
|
|
|
endofline = JS_TRUE;
|
1998-11-05 03:08:43 +03:00
|
|
|
goto loop;
|
|
|
|
default:
|
|
|
|
if (--room < 0) {
|
|
|
|
buf = JS_malloc(cx, (offset+ 128)*sizeof data);
|
1999-01-02 07:02:36 +03:00
|
|
|
if (!buf) return JS_FALSE;
|
1998-11-05 03:08:43 +03:00
|
|
|
room = 127;
|
1999-01-01 07:37:28 +03:00
|
|
|
memcpy(buf, JS_GetStringChars(file->linebuffer),
|
1998-11-05 03:08:43 +03:00
|
|
|
JS_GetStringLength(file->linebuffer));
|
|
|
|
/* what follows may not be the cleanest way. */
|
|
|
|
file->linebuffer->chars = buf;
|
1999-01-05 05:18:26 +03:00
|
|
|
file->linebuffer->length = offset+128;
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
file->linebuffer->chars[offset++] = data;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
loop:
|
1999-01-05 05:18:26 +03:00
|
|
|
file->linebuffer->chars[offset] = 0;
|
1998-11-05 03:08:43 +03:00
|
|
|
if ((endofline==JS_TRUE)) {
|
1999-01-05 06:51:30 +03:00
|
|
|
str = JS_NewUCStringCopyN(cx, JS_GetStringChars(file->linebuffer),
|
|
|
|
offset);
|
|
|
|
*rval = STRING_TO_JSVAL(str);
|
|
|
|
return JS_TRUE;
|
|
|
|
} else{
|
|
|
|
*rval = JSVAL_NULL;
|
|
|
|
return JS_FALSE;
|
|
|
|
}
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static JSBool
|
|
|
|
file_readAll(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|
|
|
{
|
|
|
|
JSFile *file;
|
|
|
|
JSObject *array;
|
1999-01-08 05:37:38 +03:00
|
|
|
jsint len, size;
|
1998-11-05 03:08:43 +03:00
|
|
|
jsval line;
|
1999-01-05 05:18:26 +03:00
|
|
|
JSBool ok = JS_TRUE;
|
1998-11-05 03:08:43 +03:00
|
|
|
|
|
|
|
file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
|
|
|
|
|
1999-01-05 06:51:30 +03:00
|
|
|
/* SECURITY */
|
1999-01-05 05:18:26 +03:00
|
|
|
array = JS_NewArrayObject(cx, 0, NULL);
|
1998-11-05 03:08:43 +03:00
|
|
|
len = 0;
|
|
|
|
|
1999-01-07 07:17:23 +03:00
|
|
|
if (!file->isOpen) {
|
1999-01-05 06:51:30 +03:00
|
|
|
js_FileOpen(cx, obj, file, "readOnly");
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
|
1999-01-08 05:37:38 +03:00
|
|
|
if(size = js_size(cx, file)==-1) goto out;
|
1998-11-05 03:08:43 +03:00
|
|
|
|
1999-01-05 06:51:30 +03:00
|
|
|
while (ok&&
|
1999-01-08 05:37:38 +03:00
|
|
|
(size>(JSUint32)
|
1999-01-07 07:17:23 +03:00
|
|
|
((!file->isNative)?
|
1999-01-05 06:51:30 +03:00
|
|
|
PR_Seek(file->handle, 0, PR_SEEK_CUR):
|
|
|
|
fseek(file->nativehandle, 0, SEEK_CUR)))) {
|
1999-01-08 05:37:38 +03:00
|
|
|
if(!file_readln(cx, obj, 0, NULL, &line)) goto out;
|
1999-01-05 06:51:30 +03:00
|
|
|
JS_SetElement(cx, array, len, &line);
|
|
|
|
len++;
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
|
1999-01-05 06:51:30 +03:00
|
|
|
*rval = OBJECT_TO_JSVAL(array);
|
1998-11-05 03:08:43 +03:00
|
|
|
return JS_TRUE;
|
1999-01-08 05:37:38 +03:00
|
|
|
out:
|
|
|
|
*rval = JSVAL_FALSE;
|
|
|
|
return JS_FALSE;
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static JSBool
|
|
|
|
file_skip(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|
|
|
{
|
|
|
|
JSFile *file;
|
1999-01-05 06:51:30 +03:00
|
|
|
int32 toskip;
|
1998-11-05 03:08:43 +03:00
|
|
|
|
1999-01-08 05:37:38 +03:00
|
|
|
if (argc!=1){
|
|
|
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
|
|
|
JSFILEMSG_EXPECTS_ONE_ARG_ERROR, "copyTo", argc);
|
|
|
|
goto out;
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
1998-12-31 08:58:26 +03:00
|
|
|
|
1999-01-05 06:51:30 +03:00
|
|
|
if (!JS_ValueToInt32(cx, argv[0], &toskip)){
|
1999-01-08 05:37:38 +03:00
|
|
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
|
|
|
JSFILEMSG_FIRST_ARGUMENT_MUST_BE_A_NUMBER, "skip", argv[0]);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
|
|
|
|
|
|
|
|
/* SECURITY */
|
|
|
|
if (!file->isOpen) {
|
|
|
|
if(!js_FileOpen(cx, obj, file, "readOnly")) goto out;
|
1999-01-05 06:51:30 +03:00
|
|
|
}
|
1998-11-05 03:08:43 +03:00
|
|
|
|
1999-01-05 06:51:30 +03:00
|
|
|
if (js_FileSkip(file, toskip, file->type)!=toskip) {
|
1999-01-08 05:37:38 +03:00
|
|
|
goto out;
|
1999-01-05 06:51:30 +03:00
|
|
|
}else
|
|
|
|
return JS_TRUE;
|
1999-01-08 05:37:38 +03:00
|
|
|
out:
|
|
|
|
*rval = JSVAL_FALSE;
|
|
|
|
return JS_FALSE;
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static JSBool
|
1998-12-31 08:58:26 +03:00
|
|
|
file_list(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
1998-11-05 03:08:43 +03:00
|
|
|
{
|
1999-01-05 06:51:30 +03:00
|
|
|
PRDir *dir;
|
|
|
|
PRDirEntry *entry;
|
|
|
|
JSFile *file;
|
|
|
|
JSObject *array;
|
1999-01-06 05:30:27 +03:00
|
|
|
JSObject *eachFile;
|
1999-01-05 06:51:30 +03:00
|
|
|
jsint len;
|
|
|
|
jsval v;
|
|
|
|
JSRegExp *re = NULL;
|
|
|
|
JSFunction *func = NULL;
|
1999-01-06 05:30:27 +03:00
|
|
|
JSString *str;
|
1999-01-05 06:51:30 +03:00
|
|
|
jsval args[1];
|
1999-01-06 05:30:27 +03:00
|
|
|
char *filePath;
|
1998-11-05 03:08:43 +03:00
|
|
|
|
1999-01-05 06:51:30 +03:00
|
|
|
/* SECURITY */
|
|
|
|
file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
|
1998-11-05 03:08:43 +03:00
|
|
|
|
|
|
|
if (argc>0) {
|
1999-01-01 07:37:28 +03:00
|
|
|
if (JSVAL_IS_REGEXP(cx, argv[0])) {
|
1999-01-05 06:51:30 +03:00
|
|
|
re = JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
|
|
|
|
}else
|
1999-01-01 07:37:28 +03:00
|
|
|
if (JSVAL_IS_FUNCTION(cx, argv[0])) {
|
1999-01-05 06:51:30 +03:00
|
|
|
func = JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
|
|
|
|
}else{
|
|
|
|
/* TODO: error */
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
if (!js_isDirectory(file)) {
|
1999-01-05 06:51:30 +03:00
|
|
|
*rval = JSVAL_NULL;
|
|
|
|
return JS_FALSE; /* or return an empty array? or do a readAll? */
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
1999-01-05 06:51:30 +03:00
|
|
|
|
1999-01-06 05:30:27 +03:00
|
|
|
/* TODO: native support? */
|
1999-01-07 07:17:23 +03:00
|
|
|
if(file->isNative){
|
1999-01-06 05:30:27 +03:00
|
|
|
/* TODO: error */
|
|
|
|
return JS_FALSE;
|
|
|
|
}
|
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
dir = PR_OpenDir(file->path);
|
1999-01-05 06:51:30 +03:00
|
|
|
if(!dir){
|
|
|
|
/* TODO: */
|
|
|
|
return JS_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* create JSArray here... */
|
1999-01-05 05:18:26 +03:00
|
|
|
array = JS_NewArrayObject(cx, 0, NULL);
|
|
|
|
len = 0;
|
1998-12-31 08:58:26 +03:00
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
while ((entry = PR_ReadDir(dir, PR_SKIP_BOTH))!=NULL) {
|
1999-01-06 05:30:27 +03:00
|
|
|
/* first, check if we have a regexp */
|
1998-11-05 03:08:43 +03:00
|
|
|
if (re!=NULL) {
|
1999-01-06 05:30:27 +03:00
|
|
|
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 */
|
|
|
|
return JS_FALSE;
|
|
|
|
}
|
|
|
|
/* not matched! */
|
|
|
|
if (JSVAL_IS_NULL(v)) {
|
1998-11-05 03:08:43 +03:00
|
|
|
continue;
|
|
|
|
}
|
1999-01-06 05:30:27 +03:00
|
|
|
}else
|
1998-11-05 03:08:43 +03:00
|
|
|
if (func!=NULL) {
|
1999-01-06 05:30:27 +03:00
|
|
|
str = JS_NewStringCopyZ(cx, entry->name);
|
|
|
|
args[0] = STRING_TO_JSVAL(str);
|
|
|
|
if(!JS_CallFunction(cx, obj, func, 1, args, &v)){
|
|
|
|
return JS_FALSE;
|
|
|
|
}
|
|
|
|
|
1998-11-05 03:08:43 +03:00
|
|
|
if (v==JSVAL_FALSE) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
1999-01-05 06:51:30 +03:00
|
|
|
|
1999-01-06 05:30:27 +03:00
|
|
|
filePath = combinePath(cx, file->path, (char*)entry->name);
|
1998-11-05 03:08:43 +03:00
|
|
|
|
1999-01-06 05:30:27 +03:00
|
|
|
eachFile = js_NewFileObject(cx, filePath);
|
|
|
|
JS_free(cx, filePath);
|
|
|
|
if (!eachFile){
|
|
|
|
/* TODO: error */
|
|
|
|
return JS_FALSE;
|
|
|
|
}
|
|
|
|
v = OBJECT_TO_JSVAL(eachFile);
|
1998-11-05 03:08:43 +03:00
|
|
|
JS_SetElement(cx, array, len, &v);
|
|
|
|
JS_SetProperty(cx, array, entry->name, &v); /* accessible by name.. make sense I think.. */
|
|
|
|
len++;
|
|
|
|
}
|
|
|
|
|
1999-01-06 05:30:27 +03:00
|
|
|
if(!PR_CloseDir(dir)){
|
|
|
|
/* TODO: error */
|
|
|
|
return JS_FALSE;
|
|
|
|
}
|
1999-01-05 06:51:30 +03:00
|
|
|
*rval = OBJECT_TO_JSVAL(array);
|
1998-11-05 03:08:43 +03:00
|
|
|
return JS_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static JSBool
|
1998-12-31 08:58:26 +03:00
|
|
|
file_mkdir(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
1998-11-05 03:08:43 +03:00
|
|
|
{
|
1999-01-06 05:30:27 +03:00
|
|
|
JSFile *file;
|
1998-11-05 03:08:43 +03:00
|
|
|
|
1999-01-07 07:17:23 +03:00
|
|
|
if (argc!=1){
|
|
|
|
/* TODO: error reporting */
|
|
|
|
return JS_FALSE;
|
|
|
|
}
|
|
|
|
|
1998-11-05 03:08:43 +03:00
|
|
|
file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
|
1999-01-06 05:30:27 +03:00
|
|
|
/* SECURITY */
|
1998-11-05 03:08:43 +03:00
|
|
|
|
1999-01-06 05:30:27 +03:00
|
|
|
/* if the current file is not a directory, find out the directory name */
|
|
|
|
if (!js_isDirectory(file)) {
|
|
|
|
char *dir = 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)) {
|
1998-11-05 03:08:43 +03:00
|
|
|
return JS_FALSE;
|
|
|
|
}
|
1999-01-06 05:30:27 +03:00
|
|
|
}else{
|
1999-01-07 07:17:23 +03:00
|
|
|
char *dirName = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
|
|
|
|
char *fullName;
|
|
|
|
|
|
|
|
fullName = combinePath(cx, file->path, dirName);
|
|
|
|
if (PR_MkDir(fullName, 0755)==PR_SUCCESS){
|
|
|
|
*rval = JSVAL_TRUE;
|
|
|
|
JS_free(cx, fullName);
|
|
|
|
return JS_TRUE;
|
|
|
|
}else{
|
|
|
|
/* TODO: error */
|
|
|
|
JS_free(cx, fullName);
|
|
|
|
return JS_FALSE;
|
|
|
|
}
|
1999-01-06 05:30:27 +03:00
|
|
|
}
|
1999-01-05 05:18:26 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static JSBool
|
|
|
|
file_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|
|
|
{
|
|
|
|
JSFile *file;
|
|
|
|
|
|
|
|
file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
|
1999-01-06 05:30:27 +03:00
|
|
|
/* SECURITY ? */
|
1999-01-05 05:18:26 +03:00
|
|
|
*rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, file->path));
|
1998-11-05 03:08:43 +03:00
|
|
|
return JS_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static JSFunctionSpec file_functions[] = {
|
|
|
|
{ "toString", file_toString, 0},
|
|
|
|
{ "open", file_open, 0},
|
|
|
|
{ "close", file_close, 0},
|
|
|
|
{ "remove", file_remove, 0},
|
|
|
|
{ "copyTo", file_copyTo, 0},
|
|
|
|
{ "renameTo", file_renameTo, 0},
|
|
|
|
{ "flush", file_flush, 0},
|
|
|
|
{ "skip", file_skip, 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},
|
|
|
|
{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,
|
1999-01-07 07:17:23 +03:00
|
|
|
FILE_OPEN = -11,
|
1998-11-05 03:08:43 +03:00
|
|
|
FILE_TYPE = -12,
|
|
|
|
FILE_MODE = -13,
|
|
|
|
FILE_CREATED = -14,
|
|
|
|
FILE_MODIFIED = -15,
|
|
|
|
FILE_SIZE = -16,
|
|
|
|
FILE_RANDOMACCESS = -17,
|
1999-01-08 05:03:09 +03:00
|
|
|
FILE_POSITION = -18,
|
|
|
|
FILE_APPEND = -19,
|
|
|
|
FILE_REPLACE = -20,
|
|
|
|
FILE_AUTOFLUSH = -21,
|
1998-11-05 03:08:43 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
static JSPropertySpec file_props[] = {
|
1999-01-08 05:03:09 +03:00
|
|
|
{"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 },
|
1998-11-05 03:08:43 +03:00
|
|
|
{0}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
static JSBool
|
1998-11-05 03:08:43 +03:00
|
|
|
file_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|
|
|
{
|
1999-01-06 05:30:27 +03:00
|
|
|
JSFile *file;
|
|
|
|
char *str;
|
|
|
|
jsint tiny;
|
|
|
|
PRFileInfo info;
|
|
|
|
PRExplodedTime
|
|
|
|
expandedTime;
|
|
|
|
JSObject *newobj;
|
1998-11-05 03:08:43 +03:00
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
tiny = JSVAL_TO_INT(id);
|
1999-01-06 05:30:27 +03:00
|
|
|
file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
|
1999-01-07 07:17:23 +03:00
|
|
|
if(!file) return JS_TRUE;
|
1998-11-05 03:08:43 +03:00
|
|
|
|
1999-01-06 05:51:26 +03:00
|
|
|
/* SECURITY ??? */
|
1998-11-05 03:08:43 +03:00
|
|
|
switch (tiny) {
|
|
|
|
case FILE_PARENT:
|
1999-01-08 05:03:09 +03:00
|
|
|
str = fileDirectoryName(cx, file->path);
|
|
|
|
/* root.parent = null */
|
|
|
|
if(!strcmp(file->path, str) || !strncmp(str, file->path, strlen(str)-1)){
|
|
|
|
*vp = JSVAL_NULL;
|
|
|
|
}else{
|
1999-01-07 07:41:20 +03:00
|
|
|
newobj = js_NewFileObject(cx, str);
|
|
|
|
JS_free(cx, str);
|
|
|
|
*vp = OBJECT_TO_JSVAL(newobj);
|
1999-01-08 05:03:09 +03:00
|
|
|
}
|
1998-11-05 03:08:43 +03:00
|
|
|
break;
|
|
|
|
case FILE_PATH:
|
1999-01-01 07:37:28 +03:00
|
|
|
*vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, file->path));
|
1998-11-05 03:08:43 +03:00
|
|
|
break;
|
|
|
|
case FILE_NAME:
|
1999-01-05 05:18:26 +03:00
|
|
|
str = fileBaseName(cx, file->path);
|
1999-01-06 05:30:27 +03:00
|
|
|
*vp = STRING_TO_JSVAL(JS_NewString(cx, str, strlen(str)));
|
1998-11-05 03:08:43 +03:00
|
|
|
break;
|
|
|
|
case FILE_ISDIR:
|
1999-01-05 05:18:26 +03:00
|
|
|
*vp = BOOLEAN_TO_JSVAL(js_isDirectory(file));
|
1998-11-05 03:08:43 +03:00
|
|
|
break;
|
|
|
|
case FILE_ISFILE:
|
1999-01-05 05:18:26 +03:00
|
|
|
*vp = BOOLEAN_TO_JSVAL(js_isFile(file));
|
1998-11-05 03:08:43 +03:00
|
|
|
break;
|
|
|
|
case FILE_EXISTS:
|
1999-01-05 05:18:26 +03:00
|
|
|
*vp = BOOLEAN_TO_JSVAL(js_exists(file));
|
1998-11-05 03:08:43 +03:00
|
|
|
break;
|
|
|
|
case FILE_CANREAD:
|
1999-01-05 05:18:26 +03:00
|
|
|
*vp = BOOLEAN_TO_JSVAL(js_canRead(file));
|
1998-11-05 03:08:43 +03:00
|
|
|
break;
|
|
|
|
case FILE_CANWRITE:
|
1999-01-05 05:18:26 +03:00
|
|
|
*vp = BOOLEAN_TO_JSVAL(js_canWrite(file));
|
1998-11-05 03:08:43 +03:00
|
|
|
break;
|
1999-01-07 07:17:23 +03:00
|
|
|
case FILE_OPEN:
|
|
|
|
*vp = BOOLEAN_TO_JSVAL(file->isOpen);
|
1998-11-05 03:08:43 +03:00
|
|
|
break;
|
1999-01-08 05:03:09 +03:00
|
|
|
case FILE_APPEND :
|
|
|
|
*vp = BOOLEAN_TO_JSVAL((file->mode&PR_APPEND)==PR_APPEND);
|
|
|
|
break;
|
|
|
|
case FILE_REPLACE :
|
|
|
|
*vp = BOOLEAN_TO_JSVAL((file->mode&PR_TRUNCATE)==PR_TRUNCATE);
|
|
|
|
break;
|
|
|
|
case FILE_AUTOFLUSH :
|
|
|
|
*vp = BOOLEAN_TO_JSVAL(file->hasAutoflush);
|
|
|
|
break;
|
1998-11-05 03:08:43 +03:00
|
|
|
case FILE_TYPE:
|
|
|
|
switch (file->type) {
|
1998-12-31 08:58:26 +03:00
|
|
|
case ASCII:
|
1999-01-01 07:37:28 +03:00
|
|
|
*vp = STRING_TO_JSVAL(JS_NewString(cx, asciistring, strlen(asciistring)));
|
1998-11-05 03:08:43 +03:00
|
|
|
break;
|
|
|
|
case UTF8:
|
1999-01-01 07:37:28 +03:00
|
|
|
*vp = STRING_TO_JSVAL(JS_NewString(cx, utfstring, strlen(utfstring)));
|
1998-11-05 03:08:43 +03:00
|
|
|
break;
|
|
|
|
case UCS2:
|
1999-01-01 07:37:28 +03:00
|
|
|
*vp = STRING_TO_JSVAL(JS_NewString(cx, unicodestring, strlen(unicodestring)));
|
1998-11-05 03:08:43 +03:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
; /* time to panic, or to do nothing.. */
|
|
|
|
}
|
|
|
|
break;
|
1999-01-08 05:03:09 +03:00
|
|
|
/*case FILE_MODE:
|
|
|
|
str = (char*)JS_malloc(cx, 200);
|
1999-01-05 05:18:26 +03:00
|
|
|
str[0] = '\0';
|
|
|
|
flag = JS_FALSE;
|
1998-11-05 03:08:43 +03:00
|
|
|
|
|
|
|
if ((file->mode&PR_RDONLY)==PR_RDONLY) {
|
1999-01-05 05:18:26 +03:00
|
|
|
if (flag) strcat(str, ",");
|
|
|
|
strcat(str, "readOnly");
|
|
|
|
flag = JS_TRUE;
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
if ((file->mode&PR_WRONLY)==PR_WRONLY) {
|
1999-01-05 05:18:26 +03:00
|
|
|
if (flag) strcat(str, ",");
|
|
|
|
strcat(str, "writeOnly");
|
|
|
|
flag = JS_TRUE;
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
if ((file->mode&PR_RDWR)==PR_RDWR) {
|
1999-01-05 05:18:26 +03:00
|
|
|
if (flag) strcat(str, ",");
|
|
|
|
strcat(str, "readWrite");
|
|
|
|
flag = JS_TRUE;
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
if ((file->mode&PR_APPEND)==PR_APPEND) {
|
1999-01-05 05:18:26 +03:00
|
|
|
if (flag) strcat(str, ",");
|
|
|
|
strcat(str, "append");
|
|
|
|
flag = JS_TRUE;
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
if ((file->mode&PR_CREATE_FILE)==PR_CREATE_FILE) {
|
1999-01-05 05:18:26 +03:00
|
|
|
if (flag) strcat(str, ",");
|
|
|
|
strcat(str, "create");
|
|
|
|
flag = JS_TRUE;
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
if ((file->mode&PR_TRUNCATE)==PR_TRUNCATE) {
|
1999-01-05 05:18:26 +03:00
|
|
|
if (flag) strcat(str, ",");
|
|
|
|
strcat(str, "replace");
|
|
|
|
flag = JS_TRUE;
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
1999-01-08 05:03:09 +03:00
|
|
|
if (file->hasAutoflush) {
|
1999-01-05 05:18:26 +03:00
|
|
|
if (flag) strcat(str, ",");
|
1999-01-08 05:03:09 +03:00
|
|
|
strcat(str, "hasAutoflush");
|
1999-01-05 05:18:26 +03:00
|
|
|
flag = JS_TRUE;
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
1999-01-06 05:30:27 +03:00
|
|
|
*vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, str));
|
1998-11-05 03:08:43 +03:00
|
|
|
JS_free(cx, str);
|
|
|
|
break;
|
1999-01-08 05:03:09 +03:00
|
|
|
*/
|
1998-11-05 03:08:43 +03:00
|
|
|
case FILE_CREATED:
|
1999-01-07 07:17:23 +03:00
|
|
|
if(!file->isNative){
|
|
|
|
if(((file->isOpen)?
|
1999-01-06 05:30:27 +03:00
|
|
|
PR_GetOpenFileInfo(file->handle, &info):
|
|
|
|
PR_GetFileInfo(file->path, &info))!=PR_SUCCESS){
|
|
|
|
/* TODO: error */
|
|
|
|
return JS_FALSE;
|
|
|
|
}
|
|
|
|
}else{
|
|
|
|
/* TODO: error */
|
|
|
|
return JS_FALSE;
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
1998-12-31 08:58:26 +03:00
|
|
|
|
1998-11-05 03:08:43 +03:00
|
|
|
PR_ExplodeTime(info.creationTime, PR_LocalTimeParameters, &expandedTime);
|
1999-01-06 05:30:27 +03:00
|
|
|
*vp = OBJECT_TO_JSVAL(js_NewDateObject(cx, expandedTime.tm_year,
|
1998-11-05 03:08:43 +03:00
|
|
|
expandedTime.tm_month,
|
|
|
|
expandedTime.tm_mday,
|
|
|
|
expandedTime.tm_hour,
|
|
|
|
expandedTime.tm_min,
|
1999-01-06 05:30:27 +03:00
|
|
|
expandedTime.tm_sec));
|
1998-11-05 03:08:43 +03:00
|
|
|
break;
|
|
|
|
case FILE_MODIFIED:
|
1999-01-07 07:17:23 +03:00
|
|
|
if(!file->isNative){
|
|
|
|
if(((file->isOpen)?
|
1999-01-06 05:30:27 +03:00
|
|
|
PR_GetOpenFileInfo(file->handle, &info):
|
|
|
|
PR_GetFileInfo(file->path, &info))!=PR_SUCCESS){
|
|
|
|
/* TODO: error */
|
|
|
|
return JS_FALSE;
|
|
|
|
}
|
|
|
|
}else{
|
|
|
|
/* TODO: error */
|
|
|
|
return JS_FALSE;
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
1998-12-31 08:58:26 +03:00
|
|
|
|
1998-11-05 03:08:43 +03:00
|
|
|
PR_ExplodeTime(info.modifyTime, PR_LocalTimeParameters, &expandedTime);
|
1999-01-06 05:30:27 +03:00
|
|
|
*vp = OBJECT_TO_JSVAL(js_NewDateObject(cx, expandedTime.tm_year,
|
1998-11-05 03:08:43 +03:00
|
|
|
expandedTime.tm_month,
|
|
|
|
expandedTime.tm_mday,
|
|
|
|
expandedTime.tm_hour,
|
|
|
|
expandedTime.tm_min,
|
1999-01-06 05:30:27 +03:00
|
|
|
expandedTime.tm_sec));
|
1998-11-05 03:08:43 +03:00
|
|
|
break;
|
|
|
|
case FILE_LENGTH:
|
1999-01-07 07:17:23 +03:00
|
|
|
if(!file->isNative){
|
1999-01-06 05:30:27 +03:00
|
|
|
if (js_isDirectory(file)) { /* XXX debug me */
|
|
|
|
PRDir *dir;
|
|
|
|
PRDirEntry *entry;
|
|
|
|
jsint count = 0;
|
|
|
|
|
|
|
|
if(!(dir = PR_OpenDir(file->path))){
|
|
|
|
/* TODO: error */
|
|
|
|
return JS_FALSE;
|
|
|
|
}
|
1998-11-05 03:08:43 +03:00
|
|
|
|
1999-01-08 05:03:09 +03:00
|
|
|
while ((entry = PR_ReadDir(dir, PR_SKIP_BOTH))) {
|
1999-01-06 05:30:27 +03:00
|
|
|
count++;
|
|
|
|
}
|
1999-01-05 06:51:30 +03:00
|
|
|
|
1999-01-06 05:30:27 +03:00
|
|
|
if(!PR_CloseDir(dir)){
|
|
|
|
/* TODO: error */
|
|
|
|
return JS_FALSE;
|
|
|
|
}
|
1998-11-05 03:08:43 +03:00
|
|
|
|
1999-01-06 05:30:27 +03:00
|
|
|
*vp = INT_TO_JSVAL(count);
|
|
|
|
break;
|
|
|
|
}else{
|
|
|
|
/* return file size */
|
1999-01-07 07:17:23 +03:00
|
|
|
if(((file->isOpen)?
|
1999-01-06 05:30:27 +03:00
|
|
|
PR_GetOpenFileInfo(file->handle, &info):
|
|
|
|
PR_GetFileInfo(file->path, &info))!=PR_SUCCESS){
|
|
|
|
/* TODO: error */
|
|
|
|
return JS_FALSE;
|
|
|
|
}
|
|
|
|
*vp = INT_TO_JSVAL(info.size);
|
|
|
|
}
|
|
|
|
}else{
|
|
|
|
/* TODO: error */
|
|
|
|
return JS_FALSE;
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
1999-01-06 05:51:26 +03:00
|
|
|
|
1998-11-05 03:08:43 +03:00
|
|
|
break;
|
|
|
|
case FILE_RANDOMACCESS:
|
1999-01-08 05:03:09 +03:00
|
|
|
*vp = BOOLEAN_TO_JSVAL(file->hasRandomAccess);
|
1998-11-05 03:08:43 +03:00
|
|
|
break;
|
|
|
|
case FILE_POSITION:
|
1999-01-07 07:17:23 +03:00
|
|
|
if (file->isOpen) {
|
|
|
|
*vp = INT_TO_JSVAL(!file->isNative?
|
1999-01-06 05:30:27 +03:00
|
|
|
PR_Seek(file->handle, 0, PR_SEEK_CUR):
|
|
|
|
fseek(file->nativehandle, 0, SEEK_CUR));
|
1999-01-05 06:51:30 +03:00
|
|
|
}else {
|
1999-01-06 05:30:27 +03:00
|
|
|
/* TODO: warning? */
|
1999-01-05 06:51:30 +03:00
|
|
|
*vp = JSVAL_VOID;
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
break;
|
1999-01-06 05:30:27 +03:00
|
|
|
default:{
|
1998-12-25 05:31:49 +03:00
|
|
|
/* this is some other property -- try to use the dir["file"] syntax */
|
1999-01-05 05:18:26 +03:00
|
|
|
if(js_isDirectory(file)){
|
1998-12-25 05:31:49 +03:00
|
|
|
PRDir *dir = NULL;
|
|
|
|
PRDirEntry *entry = NULL;
|
1999-01-01 07:37:28 +03:00
|
|
|
char* prop_name = JS_GetStringBytes(JS_ValueToString(cx, id));
|
1998-12-25 05:31:49 +03:00
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
dir = PR_OpenDir(file->path);
|
1999-01-06 05:30:27 +03:00
|
|
|
if(!dir) {
|
1999-01-08 05:03:09 +03:00
|
|
|
/* Don't return false, just proceed, this shouldn't happen */
|
|
|
|
JS_ReportWarning(cx, "Can't open directory %s", file->path);
|
|
|
|
return JS_TRUE;
|
1999-01-06 05:30:27 +03:00
|
|
|
}
|
1999-01-01 07:37:28 +03:00
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
while((entry = PR_ReadDir(dir, PR_SKIP_NONE))!=NULL){
|
1998-12-25 05:31:49 +03:00
|
|
|
if(!strcmp(entry->name, prop_name)){
|
1999-01-01 07:37:28 +03:00
|
|
|
str = combinePath(cx, file->path, prop_name);
|
1999-01-05 05:18:26 +03:00
|
|
|
*vp = OBJECT_TO_JSVAL(js_NewFileObject(cx, str));
|
1998-12-25 05:31:49 +03:00
|
|
|
JS_free(cx, str);
|
|
|
|
return JS_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1999-01-06 05:30:27 +03:00
|
|
|
}
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
return JS_TRUE;
|
|
|
|
}
|
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
static JSBool
|
1998-11-05 03:08:43 +03:00
|
|
|
file_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|
|
|
{
|
1999-01-06 05:51:26 +03:00
|
|
|
JSFile *file;
|
|
|
|
jsint slot;
|
|
|
|
int32 offset;
|
|
|
|
int32 count;
|
1998-11-05 03:08:43 +03:00
|
|
|
|
|
|
|
file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
|
|
|
|
|
1999-01-06 05:51:26 +03:00
|
|
|
/* SECURITY ? */
|
1999-01-01 07:37:28 +03:00
|
|
|
if (JSVAL_IS_STRING(id)){
|
1998-11-05 03:08:43 +03:00
|
|
|
return JS_TRUE;
|
|
|
|
}
|
1998-12-31 08:58:26 +03:00
|
|
|
|
1998-11-05 03:08:43 +03:00
|
|
|
slot = JSVAL_TO_INT(id);
|
|
|
|
|
1999-01-06 05:51:26 +03:00
|
|
|
|
1998-11-05 03:08:43 +03:00
|
|
|
switch (slot) {
|
1999-01-06 05:51:26 +03:00
|
|
|
/* File.position = 10 */
|
1998-11-05 03:08:43 +03:00
|
|
|
case FILE_POSITION:
|
1999-01-08 05:03:09 +03:00
|
|
|
if (file->hasRandomAccess) {
|
1999-01-05 05:18:26 +03:00
|
|
|
offset = JSVAL_TO_INT(*vp);
|
1999-01-07 07:17:23 +03:00
|
|
|
count = (!file->isNative)?
|
1999-01-08 05:03:09 +03:00
|
|
|
PR_Seek(file->handle, offset, PR_SEEK_SET):
|
1999-01-06 05:51:26 +03:00
|
|
|
fseek(file->nativehandle, offset, SEEK_SET);
|
1999-01-02 07:02:36 +03:00
|
|
|
js_ResetBuffers(file);
|
1998-11-05 03:08:43 +03:00
|
|
|
*vp = INT_TO_JSVAL(count);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return JS_TRUE;
|
|
|
|
}
|
|
|
|
|
1999-01-06 05:51:26 +03:00
|
|
|
/*
|
|
|
|
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;
|
|
|
|
|
|
|
|
/* Look at the rhs and extract a file object from it */
|
|
|
|
if (JSVAL_IS_OBJECT(*vp)){
|
|
|
|
if (JS_InstanceOf(cx, rhsObject, &file_class, NULL)){
|
|
|
|
file = JS_GetInstancePrivate(cx, rhsObject, &file_class, NULL);
|
|
|
|
/* Braindamaged rhs -- just return the old value */
|
|
|
|
if (file && (!js_exists(file) || !js_isDirectory(file))){
|
|
|
|
JS_GetProperty(cx, obj, CURRENTDIR_PROPERTY, vp);
|
|
|
|
return JS_FALSE;
|
|
|
|
}else{
|
|
|
|
rhsObject = JSVAL_TO_OBJECT(*vp);
|
|
|
|
chdir(file->path);
|
|
|
|
return JS_TRUE;
|
|
|
|
}
|
|
|
|
}else
|
|
|
|
return JS_FALSE;
|
|
|
|
}else{
|
|
|
|
path = JS_GetStringBytes(JS_ValueToString(cx, *vp));
|
|
|
|
rhsObject = js_NewFileObject(cx, path);
|
|
|
|
if (!rhsObject) return JS_FALSE;
|
|
|
|
|
|
|
|
file = JS_GetInstancePrivate(cx, rhsObject, &file_class, NULL);
|
|
|
|
if (!file || !js_exists(file) || !js_isDirectory(file)){
|
|
|
|
JS_GetProperty(cx, obj, CURRENTDIR_PROPERTY, vp);
|
|
|
|
}else{
|
|
|
|
*vp = OBJECT_TO_JSVAL(rhsObject);
|
|
|
|
chdir(path);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return JS_TRUE;
|
|
|
|
}
|
|
|
|
|
1999-01-02 07:02:36 +03:00
|
|
|
static void
|
1998-11-05 03:08:43 +03:00
|
|
|
file_finalize(JSContext *cx, JSObject *obj)
|
|
|
|
{
|
|
|
|
JSFile *file;
|
1999-01-06 05:51:26 +03:00
|
|
|
|
1998-11-05 03:08:43 +03:00
|
|
|
file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
|
|
|
|
JS_free(cx, file->path);
|
|
|
|
if (file->linebuffer)
|
|
|
|
JS_free(cx, file->linebuffer);
|
|
|
|
JS_free(cx, file);
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
};
|
|
|
|
|
1999-01-01 07:37:28 +03:00
|
|
|
/*
|
|
|
|
Allocates memory for the file object, sets fields to defaults.
|
|
|
|
*/
|
1998-11-05 03:08:43 +03:00
|
|
|
static JSFile*
|
1999-01-01 07:37:28 +03:00
|
|
|
file_init(JSContext *cx, JSObject *obj, char *bytes)
|
1998-11-05 03:08:43 +03:00
|
|
|
{
|
|
|
|
JSFile *file;
|
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
file = JS_malloc(cx, sizeof *file);
|
|
|
|
if (!file) return NULL;
|
1998-11-05 03:08:43 +03:00
|
|
|
memset(file, 0 , sizeof *file);
|
|
|
|
|
1999-01-01 07:37:28 +03:00
|
|
|
/* canonize the path */
|
1999-01-05 05:18:26 +03:00
|
|
|
file->path = canonicalPath(cx, bytes);
|
1998-11-05 03:08:43 +03:00
|
|
|
|
1999-01-07 07:17:23 +03:00
|
|
|
js_ResetAttributes(file);
|
1998-11-05 03:08:43 +03:00
|
|
|
|
|
|
|
if (!JS_SetPrivate(cx, obj, file)) {
|
1999-01-05 05:18:26 +03:00
|
|
|
/* TODO: report error */
|
1998-11-05 03:08:43 +03:00
|
|
|
JS_free(cx, file);
|
|
|
|
return NULL;
|
1999-01-05 05:18:26 +03:00
|
|
|
}else
|
|
|
|
return file;
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
|
1999-01-01 07:37:28 +03:00
|
|
|
/* Returns a JSObject */
|
1999-01-05 05:18:26 +03:00
|
|
|
JS_EXPORT_API(JSObject*)
|
1999-01-08 05:03:09 +03:00
|
|
|
js_NewFileObject(JSContext *cx, char *filename)
|
1998-12-31 08:58:26 +03:00
|
|
|
{
|
1999-01-01 07:37:28 +03:00
|
|
|
JSObject *obj;
|
|
|
|
JSFile *file;
|
1998-12-31 08:58:26 +03:00
|
|
|
|
1999-01-01 07:37:28 +03:00
|
|
|
obj = JS_NewObject(cx, &file_class, NULL, NULL);
|
1999-01-06 05:51:26 +03:00
|
|
|
if (!obj){
|
|
|
|
/* TODO: error ? */
|
|
|
|
return NULL;
|
|
|
|
}
|
1999-01-08 05:03:09 +03:00
|
|
|
file = file_init(cx, obj, filename);
|
1999-01-01 07:37:28 +03:00
|
|
|
if(!file) return NULL;
|
|
|
|
return obj;
|
1998-12-31 08:58:26 +03:00
|
|
|
}
|
|
|
|
|
1999-01-01 07:37:28 +03:00
|
|
|
/* Internal function, used for cases which NSPR file support doesn't cover */
|
1999-01-05 05:18:26 +03:00
|
|
|
JS_EXPORT_API(JSObject*)
|
|
|
|
js_NewFileObjectFromFILE(JSContext *cx, FILE *nativehandle, char *filename, JSBool open)
|
1998-11-05 03:08:43 +03:00
|
|
|
{
|
|
|
|
JSObject *obj;
|
1999-01-01 07:37:28 +03:00
|
|
|
JSFile *file;
|
1999-01-07 07:41:20 +03:00
|
|
|
#ifdef XP_MAC
|
|
|
|
JS_ReportWarning(cx, "Native files are not fully supported on the MAC");
|
|
|
|
#endif
|
1999-01-01 07:37:28 +03:00
|
|
|
|
|
|
|
obj = JS_NewObject(cx, &file_class, NULL, NULL);
|
1999-01-06 05:51:26 +03:00
|
|
|
if (!obj){
|
|
|
|
/* TODO: error ? */
|
|
|
|
return NULL;
|
|
|
|
}
|
1999-01-01 07:37:28 +03:00
|
|
|
file = file_init(cx, obj, filename);
|
|
|
|
if(!file) return NULL;
|
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
file->nativehandle = nativehandle;
|
|
|
|
file->path = strdup(filename);
|
1999-01-07 07:17:23 +03:00
|
|
|
file->isOpen = open;
|
|
|
|
file->isNative = JS_TRUE;
|
1998-11-05 03:08:43 +03:00
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
1999-01-01 07:37:28 +03:00
|
|
|
/*
|
|
|
|
Real file constructor that is called from JavaScript.
|
|
|
|
Basically, does error processing and calls file_init.
|
|
|
|
*/
|
1998-11-05 03:08:43 +03:00
|
|
|
static JSBool
|
1998-12-31 08:58:26 +03:00
|
|
|
File(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
1998-11-05 03:08:43 +03:00
|
|
|
{
|
|
|
|
JSString *str;
|
|
|
|
JSFile *file;
|
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
str = (argc==0)?JS_InternString(cx, ""):JS_ValueToString(cx, argv[0]);
|
1999-01-01 07:37:28 +03:00
|
|
|
|
|
|
|
if (!str){
|
1998-12-31 08:58:26 +03:00
|
|
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
|
|
|
JSFILEMSG_FIRST_ARGUMENT_CONSTRUCTOR_NOT_STRING_ERROR, argv[0]);
|
1998-11-05 03:08:43 +03:00
|
|
|
return JS_FALSE;
|
|
|
|
}
|
|
|
|
|
1999-01-06 05:51:26 +03:00
|
|
|
/* SECURITY? */
|
1999-01-01 07:37:28 +03:00
|
|
|
file = file_init(cx, obj, JS_GetStringBytes(str));
|
1999-01-06 05:51:26 +03:00
|
|
|
if (!file) return JS_FALSE;
|
1998-11-05 03:08:43 +03:00
|
|
|
|
|
|
|
return JS_TRUE;
|
|
|
|
}
|
|
|
|
|
1999-01-05 05:18:26 +03:00
|
|
|
JS_EXPORT_API(JSObject*)
|
1998-12-31 08:58:26 +03:00
|
|
|
js_InitFileClass(JSContext *cx, JSObject* obj)
|
1998-11-05 03:08:43 +03:00
|
|
|
{
|
1999-01-06 05:51:26 +03:00
|
|
|
JSObject *file, *ctor, *afile;
|
1998-12-31 08:58:26 +03:00
|
|
|
JSFile *fileObj;
|
|
|
|
jsval vp;
|
|
|
|
char *currentdir;
|
|
|
|
|
1998-11-05 03:08:43 +03:00
|
|
|
file = JS_InitClass(cx, obj, NULL, &file_class, File, 1,
|
|
|
|
file_props, file_functions, NULL, NULL);
|
1998-12-31 08:58:26 +03:00
|
|
|
if (!file) return NULL;
|
1998-11-05 03:08:43 +03:00
|
|
|
|
1999-01-07 07:17:23 +03:00
|
|
|
/* SECURITY -- need to make sure we want to have default streams */
|
1998-11-05 03:08:43 +03:00
|
|
|
ctor = JS_GetConstructor(cx, file);
|
1998-12-31 08:58:26 +03:00
|
|
|
if (!ctor) return NULL;
|
1998-11-05 03:08:43 +03:00
|
|
|
|
1998-12-31 08:58:26 +03:00
|
|
|
/* Define CURRENTDIR property. We are doing this to get a
|
|
|
|
slash at the end of the current dir */
|
1999-01-05 05:18:26 +03:00
|
|
|
afile = js_NewFileObject(cx, CURRENT_DIR);
|
|
|
|
currentdir = JS_malloc(cx, MAX_PATH_LENGTH);
|
|
|
|
currentdir = getcwd(currentdir, MAX_PATH_LENGTH);
|
|
|
|
afile = js_NewFileObject(cx, currentdir);
|
1998-11-05 03:08:43 +03:00
|
|
|
JS_free(cx, currentdir);
|
|
|
|
vp = OBJECT_TO_JSVAL(afile);
|
|
|
|
JS_DefinePropertyWithTinyId(cx, ctor, CURRENTDIR_PROPERTY, 0, vp,
|
|
|
|
JS_PropertyStub, file_currentDirSetter, JSPROP_ENUMERATE);
|
|
|
|
|
1999-01-08 05:03:09 +03:00
|
|
|
#ifdef JS_FILE_HAS_STANDARD_STREAMS
|
|
|
|
# ifdef XP_MAC
|
|
|
|
# error "Standard streams are not supported on the MAC, turn JS_FILE_HAS_STANDARD_STREAMS off"
|
|
|
|
# else
|
1999-01-07 07:17:23 +03:00
|
|
|
/* Code to create stdin, stdout, and stderr. Insert in the appropriate place. */
|
|
|
|
/* Define input */
|
|
|
|
afile = js_NewFileObjectFromFILE(cx, stdin, SPECIAL_FILE_STRING, JS_TRUE);
|
|
|
|
if (!afile) return NULL;
|
|
|
|
fileObj = JS_GetInstancePrivate(cx, afile, &file_class, NULL);
|
1999-01-08 05:03:09 +03:00
|
|
|
fileObj->hasRandomAccess = JS_FALSE;
|
1999-01-07 07:17:23 +03:00
|
|
|
vp = OBJECT_TO_JSVAL(afile);
|
|
|
|
JS_SetProperty(cx, ctor, "input", &vp);
|
|
|
|
|
|
|
|
/* Define output */
|
|
|
|
afile = js_NewFileObjectFromFILE(cx, stdout, SPECIAL_FILE_STRING, JS_TRUE);
|
|
|
|
if (!afile) return NULL;
|
|
|
|
fileObj = JS_GetInstancePrivate(cx, afile, &file_class, NULL);
|
1999-01-08 05:03:09 +03:00
|
|
|
fileObj->hasRandomAccess = JS_FALSE;
|
1999-01-07 07:17:23 +03:00
|
|
|
vp = OBJECT_TO_JSVAL(afile);
|
|
|
|
JS_SetProperty(cx, ctor, "output", &vp);
|
|
|
|
|
|
|
|
/* Define error */
|
|
|
|
afile = js_NewFileObjectFromFILE(cx, stderr, SPECIAL_FILE_STRING, JS_TRUE);
|
|
|
|
if (!afile)
|
|
|
|
return NULL;
|
|
|
|
fileObj = JS_GetInstancePrivate(cx, afile, &file_class, NULL);
|
1999-01-08 05:03:09 +03:00
|
|
|
fileObj->hasRandomAccess = JS_FALSE;
|
1999-01-07 07:17:23 +03:00
|
|
|
vp = OBJECT_TO_JSVAL(afile);
|
|
|
|
JS_SetProperty(cx, ctor, "error", &vp);
|
1999-01-08 05:03:09 +03:00
|
|
|
# endif
|
1999-01-07 07:17:23 +03:00
|
|
|
#endif
|
1998-11-05 03:08:43 +03:00
|
|
|
}
|
|
|
|
#endif /* JS_HAS_FILE_OBJECT */
|