📄 jsfile.c
字号:
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Mozilla Communicator client code, released * March 31, 1998. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** *//* * JS File object */#if JS_HAS_FILE_OBJECT#include "jsstddef.h"/* ----------------- Platform-specific includes and defines ----------------- */#ifdef XP_MAC# define FILESEPARATOR ':'# define FILESEPARATOR2 '\0'# define CURRENT_DIR "HARD DISK:Desktop Folder"/* TODO: #include <???> */#elif defined(XP_WIN) || defined(XP_OS2)# include <direct.h># include <io.h># include <sys/types.h># include <sys/stat.h># define FILESEPARATOR '\\'# define FILESEPARATOR2 '/'# define CURRENT_DIR "c:\\"# define POPEN _popen# define PCLOSE _pclose#elif defined(XP_UNIX) || defined(XP_BEOS)# include <strings.h># include <stdio.h># include <stdlib.h># include <unistd.h># define FILESEPARATOR '/'# define FILESEPARATOR2 '\0'# define CURRENT_DIR "/"# define POPEN popen# define PCLOSE pclose#endif/* --------------- Platform-independent includes and defines ---------------- */#include "jsapi.h"#include "jsatom.h"#include "jscntxt.h"#include "jsdate.h"#include "jsdbgapi.h"#include "jsemit.h"#include "jsfun.h"#include "jslock.h"#include "jsobj.h"#include "jsparse.h"#include "jsscan.h"#include "jsscope.h"#include "jsscript.h"#include "jsstr.h"#include "jsutil.h" /* Added by JSIFY */#include <string.h>/* NSPR dependencies */#include "prio.h"#include "prerror.h"#define SPECIAL_FILE_STRING "Special File"#define CURRENTDIR_PROPERTY "currentDir"#define SEPARATOR_PROPERTY "separator"#define FILE_CONSTRUCTOR "File"#define PIPE_SYMBOL '|'#define ASCII 0#define UTF8 1#define UCS2 2#define asciistring "text"#define utfstring "binary"#define unicodestring "unicode"#define MAX_PATH_LENGTH 1024#define MODE_SIZE 256#define NUMBER_SIZE 32#define MAX_LINE_LENGTH 256#define URL_PREFIX "file://"#define STDINPUT_NAME "Standard input stream"#define STDOUTPUT_NAME "Standard output stream"#define STDERROR_NAME "Standard error stream"#define RESOLVE_PATH js_canonicalPath /* js_absolutePath *//* Error handling */typedef enum JSFileErrNum {#define MSG_DEF(name, number, count, exception, format) \ name = number,#include "jsfile.msg"#undef MSG_DEF JSFileErr_Limit#undef MSGDEF} JSFileErrNum;#define JSFILE_HAS_DFLT_MSG_STRINGS 1JSErrorFormatString JSFile_ErrorFormatString[JSFileErr_Limit] = {#if JSFILE_HAS_DFLT_MSG_STRINGS#define MSG_DEF(name, number, count, exception, format) \ { format, count } ,#else#define MSG_DEF(name, number, count, exception, format) \ { NULL, count } ,#endif#include "jsfile.msg"#undef MSG_DEF};const JSErrorFormatString *JSFile_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber){ if ((errorNumber > 0) && (errorNumber < JSFileErr_Limit)) return &JSFile_ErrorFormatString[errorNumber]; else return NULL;}#define JSFILE_CHECK_NATIVE(op) \ if(file->isNative){ \ JS_ReportWarning(cx, "Cannot call or access \"%s\" on native file %s", \ op, file->path); \ goto out; \ }#define JSFILE_CHECK_WRITE \ if (!file->isOpen){ \ JS_ReportWarning(cx, \ "File %s is closed, will open it for writing, proceeding", \ file->path); \ js_FileOpen(cx, obj, file, "write,append,create"); \ }else \ if(!js_canWrite(cx, file)){ \ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, \ JSFILEMSG_CANNOT_WRITE, file->path); \ goto out; \ }#define JSFILE_CHECK_READ \ if (!file->isOpen){ \ JS_ReportWarning(cx, \ "File %s is closed, will open it for reading, proceeding", \ file->path); \ js_FileOpen(cx, obj, file, "read"); \ }else \ if(!js_canRead(cx, file)){ \ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, \ JSFILEMSG_CANNOT_READ, file->path); \ goto out; \ }#define JSFILE_CHECK_OPEN(op) \ if(!file->isOpen){ \ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, \ JSFILEMSG_FILE_MUST_BE_CLOSED, op); \ goto out; \ }#define JSFILE_CHECK_CLOSED(op) \ if(file->isOpen){ \ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, \ JSFILEMSG_FILE_MUST_BE_OPEN, op); \ goto out; \ }#define JSFILE_CHECK_ONE_ARG(op) \ if (argc!=1){ \ char str[NUMBER_SIZE]; \ \ sprintf(str, "%d", argc); \ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, \ JSFILEMSG_EXPECTS_ONE_ARG_ERROR, op, str); \ goto out; \ }/* Security mechanism, should define a callback for this. The parameters are as follows: SECURITY_CHECK(JSContext *cx, JSPrincipals *ps, char *op_name, JSFile *file)*/#define SECURITY_CHECK(cx, ps, op, file) \ /* Define a callback here... *//* Structure representing the file internally */typedef struct JSFile { char *path; /* the path to the file. */ JSBool isOpen; JSString *linebuffer; /* temp buffer used by readln. */ int32 mode; /* mode used to open the file: read, write, append, create, etc.. */ int32 type; /* Asciiz, utf, unicode */ char byteBuffer[3]; /* bytes read in advance by js_FileRead ( UTF8 encoding ) */ jsint nbBytesInBuf; /* number of bytes stored in the buffer above */ jschar charBuffer; /* character read in advance by readln ( mac files only ) */ JSBool charBufferUsed; /* flag indicating if the buffer above is being used */ JSBool hasRandomAccess; /* can the file be randomly accessed? false for stdin, and UTF-encoded files. */ JSBool hasAutoflush; /* should we force a flush for each line break? */ JSBool isNative; /* if the file is using OS-specific file FILE type */ /* We can actually put the following two in a union since they should never be used at the same time */ PRFileDesc *handle; /* the handle for the file, if open. */ FILE *nativehandle; /* native handle, for stuff NSPR doesn't do. */ JSBool isPipe; /* if the file is really an OS pipe */} JSFile;/* a few forward declarations... */static JSClass file_class;JS_PUBLIC_API(JSObject*) js_NewFileObject(JSContext *cx, char *filename);static JSBool file_open(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);static JSBool file_close(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);/* --------------------------- New filename manipulation procesures -------------------------- *//* assumes we don't have leading/trailing spaces */static JSBooljs_filenameHasAPipe(const char *filename){#ifdef XP_MAC /* pipes are not supported on the MAC */ return JS_FALSE;#else if(!filename) return JS_FALSE; return filename[0]==PIPE_SYMBOL || filename[strlen(filename)-1]==PIPE_SYMBOL;#endif}static JSBooljs_isAbsolute(const char *name){#if defined(XP_WIN) || defined(XP_OS2) return (strlen(name)>1)?((name[1]==':')?JS_TRUE:JS_FALSE):JS_FALSE;#else return (name[0]# if defined(XP_UNIX) || defined(XP_BEOS) ==# else !=# endif FILESEPARATOR)?JS_TRUE:JS_FALSE;#endif}/* Concatinates base and name to produce a valid filename. Returned string must be freed.*/static char*js_combinePath(JSContext *cx, const char *base, const char *name){ int len = strlen(base); char* result = (char*)JS_malloc(cx, len+strlen(name)+2); if (!result) return NULL; strcpy(result, base); if (base[len-1]!=FILESEPARATOR#if defined(XP_WIN) || defined(XP_OS2) && base[len-1]!=FILESEPARATOR2#endif ) { result[len] = FILESEPARATOR; result[len+1] = '\0'; } strcat(result, name); return result;}/* Extract the last component from a path name. Returned string must be freed */static char *js_fileBaseName(JSContext *cx, const char *pathname){ jsint index, aux; char *result;#if defined(XP_WIN) || defined(XP_OS2) /* First, get rid of the drive selector */ if ((strlen(pathname)>=2)&&(pathname[1]==':')) { pathname = &pathname[2]; }#endif index = strlen(pathname)-1; /* remove trailing separators -- don't necessarily need to check for FILESEPARATOR2, but that's fine */ while ((index>0)&&((pathname[index]==FILESEPARATOR)|| (pathname[index]==FILESEPARATOR2))) index--; aux = index; /* now find the next separator */ while ((index>=0)&&(pathname[index]!=FILESEPARATOR)&& (pathname[index]!=FILESEPARATOR2)) index--; /* allocate and copy */ result = (char*)JS_malloc(cx, aux-index+1); if (!result) return NULL; strncpy(result, &pathname[index+1], aux-index); result[aux-index] = '\0'; return result;}/* Returns everytynig but the last component from a path name. Returned string must be freed. Returned string must be freed.*/static char *js_fileDirectoryName(JSContext *cx, const char *pathname){ jsint index; char *result;#if defined(XP_WIN) || defined(XP_OS2) char drive = '\0'; const char *oldpathname = pathname; /* First, get rid of the drive selector */ if ((strlen(pathname)>=2)&&(pathname[1]==':')) { drive = pathname[0]; pathname = &pathname[2]; }#endif index = strlen(pathname)-1; while ((index>0)&&((pathname[index]==FILESEPARATOR)|| (pathname[index]==FILESEPARATOR2))) index--; while ((index>0)&&(pathname[index]!=FILESEPARATOR)&& (pathname[index]!=FILESEPARATOR2)) index--; if (index>=0){ result = (char*)JS_malloc(cx, index+4); if (!result) return NULL;#if defined(XP_WIN) || defined(XP_OS2) if (drive!='\0') { result[0] = toupper(drive); result[1] = ':'; strncpy(&result[2], pathname, index); result[index+3] = '\0'; }else#endif { strncpy(result, pathname, index); result[index] = '\0'; } /* add terminating separator */ index = strlen(result)-1; result[index] = FILESEPARATOR; result[index+1] = '\0'; } else{#if defined(XP_WIN) || defined(XP_OS2) result = JS_strdup(cx, oldpathname); /* may include drive selector */#else result = JS_strdup(cx, pathname);#endif } return result;}static char *js_absolutePath(JSContext *cx, const char * path){ JSObject *obj; JSString *str; jsval prop; if (js_isAbsolute(path)){ return JS_strdup(cx, path); }else{ obj = JS_GetGlobalObject(cx); if (!JS_GetProperty(cx, obj, FILE_CONSTRUCTOR, &prop)) { JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, JSFILEMSG_FILE_CONSTRUCTOR_UNDEFINED_ERROR); return JS_strdup(cx, path); } obj = JSVAL_TO_OBJECT(prop); if (!JS_GetProperty(cx, obj, CURRENTDIR_PROPERTY, &prop)) { JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, JSFILEMSG_FILE_CURRENTDIR_UNDEFINED_ERROR); return JS_strdup(cx, path); } str = JS_ValueToString(cx, prop); if (!str ) { return JS_strdup(cx, path); } /* should we have an array of curr dirs indexed by drive for windows? */ return js_combinePath(cx, JS_GetStringBytes(str), path); }}/* Side effect: will remove spaces in the beginning/end of the filename */static char *js_canonicalPath(JSContext *cx, char *oldpath){ char *tmp; char *path = oldpath; char *base, *dir, *current, *result; jsint c; jsint back = 0; unsigned int i = 0, j = strlen(path)-1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -