diff options
Diffstat (limited to 'source4/lib/appweb/ejs-2.0/ejs/system/UNIX')
5 files changed, 1062 insertions, 0 deletions
diff --git a/source4/lib/appweb/ejs-2.0/ejs/system/UNIX/.ignore b/source4/lib/appweb/ejs-2.0/ejs/system/UNIX/.ignore new file mode 100644 index 0000000000..fb5a29031e --- /dev/null +++ b/source4/lib/appweb/ejs-2.0/ejs/system/UNIX/.ignore @@ -0,0 +1 @@ +.updated diff --git a/source4/lib/appweb/ejs-2.0/ejs/system/UNIX/Makefile b/source4/lib/appweb/ejs-2.0/ejs/system/UNIX/Makefile new file mode 100755 index 0000000000..424747052a --- /dev/null +++ b/source4/lib/appweb/ejs-2.0/ejs/system/UNIX/Makefile @@ -0,0 +1,21 @@ +# +# Makefile to build the EJS Object Model for WIN +# +# Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. +# + +COMPILE := *.c +EXPORT_OBJECTS := yes +MAKE_IFLAGS := -I../.. -I../../../mpr + +include make.dep + +compileExtra: .updated + +.updated: $(FILES) + @touch .updated + +## Local variables: +## tab-width: 4 +## End: +## vim: tw=78 sw=4 ts=4 diff --git a/source4/lib/appweb/ejs-2.0/ejs/system/UNIX/ejsFile.c b/source4/lib/appweb/ejs-2.0/ejs/system/UNIX/ejsFile.c new file mode 100644 index 0000000000..772303152e --- /dev/null +++ b/source4/lib/appweb/ejs-2.0/ejs/system/UNIX/ejsFile.c @@ -0,0 +1,98 @@ +/* + * @file ejsFile.c + * @brief File class for the EJ System Object Model + */ +/********************************** Copyright *********************************/ +/* + * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. + */ +/********************************** Includes **********************************/ + +#include "ejs.h" + +/******************************************************************************/ +/* + * Default Constructor + */ + +/******************************************************************************/ +/************************************ Methods *********************************/ +/******************************************************************************/ +/* + * function open(); + */ + +static int openProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) +{ + ejsTrace(ep, "File.open()\n"); + return 0; +} + +/******************************************************************************/ +/* + * function close(); + */ + +static int closeProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) +{ + ejsTrace(ep, "File.close()\n"); + return 0; +} + +/******************************************************************************/ +/* + * function read(); + */ + +static int readProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) +{ + ejsTrace(ep, "File.read()\n"); + return 0; +} + +/******************************************************************************/ +/* + * function write(); + */ + +static int writeProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) +{ + ejsTrace(ep, "File.write()\n"); + return 0; +} + +/******************************************************************************/ +/******************************** Initialization ******************************/ +/******************************************************************************/ + +int ejsDefineFileClass(Ejs *ep) +{ + EjsVar *fileClass; + + fileClass = ejsDefineClass(ep, "File", "Object", 0); + if (fileClass == 0) { + return MPR_ERR_CANT_INITIALIZE; + } + + /* + * Define the methods + */ + ejsDefineCMethod(ep, fileClass, "open", openProc, 0); + ejsDefineCMethod(ep, fileClass, "close", closeProc, 0); + ejsDefineCMethod(ep, fileClass, "read", readProc, 0); + ejsDefineCMethod(ep, fileClass, "write", writeProc, 0); + + return ejsObjHasErrors(fileClass) ? MPR_ERR_CANT_INITIALIZE: 0; +} + +/******************************************************************************/ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim:tw=78 + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ diff --git a/source4/lib/appweb/ejs-2.0/ejs/system/UNIX/ejsFileSystem.c b/source4/lib/appweb/ejs-2.0/ejs/system/UNIX/ejsFileSystem.c new file mode 100755 index 0000000000..7b39c16e4d --- /dev/null +++ b/source4/lib/appweb/ejs-2.0/ejs/system/UNIX/ejsFileSystem.c @@ -0,0 +1,454 @@ +/* + * @file ejsFileSystem.c + * @brief FileSystem class for the EJ System Object Model + * MOB -- this is almost the same as for Windows. Should common up. + */ +/********************************** Copyright *********************************/ +/* + * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. + */ +/********************************** Includes **********************************/ + +#include "ejs.h" +#include <dirent.h> + +/******************************************************************************/ +/************************************ Methods *********************************/ +/******************************************************************************/ +/* + * function void access(string path); + * MOB - API insufficient. Access for read or write? + */ + +static int accessProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) +{ + int rc; + + if (argc != 1 || !ejsVarIsString(argv[0])) { + ejsError(ejs, EJS_ARG_ERROR, "Bad usage: access(path)"); + return -1; + } + + rc = access(argv[0]->string, 04); + + ejsSetReturnValueToBoolean(ejs, (rc == 0) ? 1 : 0); + return 0; +} + +/******************************************************************************/ +/* + * function void mkdir(string path); + */ + +static int mkdirProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) +{ + if (argc != 1 || !ejsVarIsString(argv[0])) { + ejsError(ejs, EJS_ARG_ERROR, "Bad usage: mkdir(path)"); + return -1; + } + + if (mprMakeDirPath(ejs, argv[0]->string) < 0) { + ejsError(ejs, EJS_IO_ERROR, "Cant create directory"); + return -1; + } + return 0; +} + +/******************************************************************************/ +/* + * function void rmdir(string path); + */ + +static int rmdirProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) +{ + int rc; + + if (argc != 1 || !ejsVarIsString(argv[0])) { + ejsError(ejs, EJS_ARG_ERROR, "Bad usage: mkdir(path)"); + return -1; + } + + rc = mprDeleteDir(ejs, argv[0]->string); + + if (rc < 0) { + ejsError(ejs, EJS_IO_ERROR, "Cant remove directory"); + return -1; + } + return 0; +} + +/******************************************************************************/ +/* + * function void dirList(string path, [bool enumDirs]); + * MOB -- need pattern to match (what about "." and ".." and ".*" + */ + +static int dirListProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) +{ + DIR *dir; + struct dirent *dirent; + char path[MPR_MAX_FNAME]; + EjsVar *array, *vp; + uchar enumDirs; + + if (argc < 1 || !ejsVarIsString(argv[0])) { + ejsError(ejs, EJS_ARG_ERROR, "Bad usage: dirList(path)"); + return -1; + } + if (argc == 2) { + enumDirs = ejsVarToBoolean(argv[1]); + } else { + enumDirs = 0; + } + array = ejsCreateArray(ejs, 0); + ejsMakeObjPermanent(array, 1); + + /* + * First collect the files + */ + mprSprintf(path, sizeof(path), "%s/*.*", argv[0]->string); + + dir = opendir(path); + if (dir == 0) { + ejsError(ejs, EJS_ARG_ERROR, "Can't enumerate dirList(path)"); + return -1; + } + + while ((dirent = readdir(dir)) != 0) { + if (dirent->d_name[0] == '.') { + continue; + } + if (!enumDirs || (dirent->d_type & DT_DIR)) { + mprSprintf(path, sizeof(path), "%s/%s", argv[0]->string, + dirent->d_name); + vp = ejsCreateStringVar(ejs, path); + ejsAddArrayElt(ejs, array, vp, EJS_SHALLOW_COPY); + ejsFreeVar(ejs, vp); + } + } + + closedir(dir); + + ejsSetReturnValue(ejs, array); + ejsMakeObjPermanent(array, 0); + + /* + * Can free now as the return value holds the reference + */ + ejsFreeVar(ejs, array); + + return 0; +} + +/******************************************************************************/ +/* + * function void getFreeSpace(); + */ + +static int getFreeSpaceProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) +{ +#if UNUSED + MprApp *app; + uint space; + + app = mprGetApp(ejs); + space = IFILEMGR_GetFreeSpace(app->fileMgr, 0); + ejsSetReturnValueToInteger(ejs, space); +#endif + + return 0; +} + +/******************************************************************************/ +/* + * function void writeFile(string path, var data); + */ + +static int writeFileProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) +{ + MprFile *file; + char *data, *buf; + int bytes, length, rc; + + if (argc != 2 || !ejsVarIsString(argv[0])) { + ejsError(ejs, EJS_ARG_ERROR, "Bad usage: writeFile(path, var)"); + return -1; + } + + if (ejsVarIsString(argv[1])) { + data = argv[1]->string; + length = argv[1]->length; + buf = 0; + } else { + buf = data = ejsVarToString(ejs, argv[1]); + length = strlen(data); + } + + /* + * Create fails if already present + */ + rc = mprDelete(ejs, argv[0]->string); + file = mprOpen(ejs, argv[0]->string, O_CREAT | O_WRONLY | O_BINARY, 0664); + if (file == 0) { + ejsError(ejs, EJS_IO_ERROR, "Cant create %s", argv[0]->string); + mprFree(buf); + return -1; + } + + rc = 0; + bytes = mprWrite(file, data, length); + if (bytes != length) { + ejsError(ejs, EJS_IO_ERROR, "Write error to %s", argv[1]->string); + rc = -1; + } + + mprClose(file); + + mprFree(buf); + return rc; +} + +/******************************************************************************/ +/* + * function string readFile(string path); + */ + +static int readFileProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) +{ + MprApp *app; + MprFile *file; + MprBuf *buf; + char *data; + int bytes, rc; + + if (argc != 1 || !ejsVarIsString(argv[0])) { + ejsError(ejs, EJS_ARG_ERROR, "Bad usage: readFile(path)"); + return -1; + } + buf = mprCreateBuf(ejs, MPR_BUF_INCR, MPR_MAX_BUF); + if (buf == 0) { + ejsMemoryError(ejs); + return -1; + } + + data = mprAlloc(ejs, MPR_BUFSIZE); + if (buf == 0) { + mprFree(buf); + ejsMemoryError(ejs); + return -1; + } + + app = mprGetApp(ejs); + file = mprOpen(ejs, argv[0]->string, O_RDONLY, 0664); + if (file == 0) { + ejsError(ejs, EJS_IO_ERROR, "Cant open %s", argv[0]->string); + mprFree(buf); + return -1; + } + + rc = 0; + while ((bytes = mprRead(file, data, MPR_BUFSIZE)) > 0) { + if (mprPutBlockToBuf(buf, data, bytes) != bytes) { + ejsError(ejs, EJS_IO_ERROR, "Write error to %s", argv[1]->string); + rc = -1; + break; + } + } + + ejsSetReturnValueToBinaryString(ejs, (uchar*) mprGetBufStart(buf), + mprGetBufLength(buf)); + + mprClose(file); + mprFree(data); + mprFree(buf); + + return rc; +} + +/******************************************************************************/ +/* + * function void remove(string path); + */ + +static int removeProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) +{ + int rc; + + if (argc != 1 || !ejsVarIsString(argv[0])) { + ejsError(ejs, EJS_ARG_ERROR, "Bad usage: remove(path)"); + return -1; + } + + rc = unlink(argv[0]->string); + if (rc < 0) { + ejsError(ejs, EJS_IO_ERROR, "Cant remove file"); + return -1; + } + return 0; +} + +/******************************************************************************/ +/* + * function void rename(string from, string to); + */ + +static int renameProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) +{ + int rc; + + if (argc != 2 || !ejsVarIsString(argv[0]) || !ejsVarIsString(argv[1])) { + ejsError(ejs, EJS_ARG_ERROR, "Bad usage: rename(old, new)"); + return -1; + } + + unlink(argv[1]->string); + rc = rename(argv[0]->string, argv[1]->string); + if (rc < 0) { + ejsError(ejs, EJS_IO_ERROR, "Cant rename file"); + return -1; + } + return 0; +} + +/******************************************************************************/ +/* + * function void copy(string old, string new); + */ + +static int copyProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) +{ + MprFile *from, *to; + char *buf; + uint bytes; + int rc; + + if (argc != 2 || !ejsVarIsString(argv[0]) || !ejsVarIsString(argv[1])) { + ejsError(ejs, EJS_ARG_ERROR, "Bad usage: copy(old, new)"); + return -1; + } + + buf = mprAlloc(ejs, MPR_BUFSIZE); + if (buf == 0) { + ejsMemoryError(ejs); + return -1; + } + + from = mprOpen(ejs, argv[0]->string, O_RDONLY | O_BINARY, 0664); + if (from == 0) { + ejsError(ejs, EJS_IO_ERROR, "Cant open %s", argv[0]->string); + mprFree(buf); + return -1; + } + + to = mprOpen(ejs, argv[1]->string, O_CREAT | O_BINARY, 0664); + if (to == 0) { + ejsError(ejs, EJS_IO_ERROR, "Cant create %s", argv[1]->string); + mprClose(from); + mprFree(buf); + return -1; + } + + rc = 0; + while ((bytes = mprRead(from, buf, MPR_BUFSIZE)) > 0) { + if (mprWrite(to, buf, bytes) != bytes) { + ejsError(ejs, EJS_IO_ERROR, "Write error to %s", argv[1]->string); + rc = -1; + break; + } + } + + mprClose(from); + mprClose(to); + mprFree(buf); + + return rc; +} + +/******************************************************************************/ +/* + * function FileInfo getFileInfo(string path); + * + * MOB -- should create a real class FileInfo + */ + +static int getFileInfoProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) +{ + MprFileInfo info; + EjsVar *fileInfo; + int rc; + + if (argc != 1 || !ejsVarIsString(argv[0])) { + ejsError(ejs, EJS_ARG_ERROR, "Bad usage: getFileInfo(path)"); + return -1; + } + + fileInfo = ejsCreateObjVar(ejs); + if (fileInfo == 0) { + ejsMemoryError(ejs); + return -1; + } + ejsMakeObjPermanent(fileInfo, 1); + + rc = mprGetFileInfo(ejs, argv[0]->string, &info); + if (rc < 0) { + ejsMakeObjPermanent(fileInfo, 0); + ejsFreeVar(ejs, fileInfo); + ejsError(ejs, EJS_IO_ERROR, "Cant get file info for %s", + argv[0]->string); + return -1; + } + + ejsSetPropertyToInteger(ejs, fileInfo, "created", info.ctime); + ejsSetPropertyToInteger(ejs, fileInfo, "length", info.size); + ejsSetPropertyToBoolean(ejs, fileInfo, "isDir", info.isDir); + + ejsSetReturnValue(ejs, fileInfo); + ejsMakeObjPermanent(fileInfo, 0); + + return 0; +} + +/******************************************************************************/ +/******************************** Initialization ******************************/ +/******************************************************************************/ + +int ejsDefineFileSystemClass(Ejs *ejs) +{ + EjsVar *fileSystemClass; + + fileSystemClass = ejsDefineClass(ejs, "FileSystem", "Object", 0); + if (fileSystemClass == 0) { + return MPR_ERR_CANT_INITIALIZE; + } + + /* + * Define the methods + */ + ejsDefineCMethod(ejs, fileSystemClass, "access", accessProc, 0); + ejsDefineCMethod(ejs, fileSystemClass, "mkdir", mkdirProc, 0); + ejsDefineCMethod(ejs, fileSystemClass, "rmdir", rmdirProc, 0); + ejsDefineCMethod(ejs, fileSystemClass, "dirList", dirListProc, 0); + ejsDefineCMethod(ejs, fileSystemClass, "writeFile", writeFileProc, 0); + ejsDefineCMethod(ejs, fileSystemClass, "readFile", readFileProc, 0); + ejsDefineCMethod(ejs, fileSystemClass, "remove", removeProc, 0); + ejsDefineCMethod(ejs, fileSystemClass, "rename", renameProc, 0); + ejsDefineCMethod(ejs, fileSystemClass, "copy", copyProc, 0); + ejsDefineCMethod(ejs, fileSystemClass, "getFileInfo", getFileInfoProc, 0); + + // MOB -- should be a property with accessor + ejsDefineCMethod(ejs, fileSystemClass, "getFreeSpace", getFreeSpaceProc, 0); + + return ejsObjHasErrors(fileSystemClass) ? MPR_ERR_CANT_INITIALIZE: 0; +} + +/******************************************************************************/ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim:tw=78 + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ diff --git a/source4/lib/appweb/ejs-2.0/ejs/system/UNIX/ejsHTTP.c b/source4/lib/appweb/ejs-2.0/ejs/system/UNIX/ejsHTTP.c new file mode 100755 index 0000000000..25821f6960 --- /dev/null +++ b/source4/lib/appweb/ejs-2.0/ejs/system/UNIX/ejsHTTP.c @@ -0,0 +1,488 @@ +/* + * @file ejsHTTP.c + * @brief HTTP class for the EJ System Object Model + */ +/********************************** Copyright *********************************/ +/* + * Copyright (c) Mbedthis Software LLC, 2005-2006. All Rights Reserved. + */ +/********************************** Includes **********************************/ + +#include "ejs.h" + +#if UNUSED +/*********************************** Defines **********************************/ + +#define EJS_WEB_PROPERTY "-web" +#define EJS_HTTP_PROPERTY "-http" + +#define EJS_HTTP_DISPOSED 550 + +/* + * Control structure for one HTTP request structure + */ +typedef struct HTTPControl { + Ejs *ejs; + IWebResp *webResp; + AEECallback *callback; + MprBuf *buf; + EjsVar *thisObj; + char *url; + MprTime requestStarted; + uint timeout; +} HTTPControl; + +/****************************** Forward Declarations **************************/ + +static void cleanup(HTTPControl *hp); +static int createWeb(Ejs *ejs, EjsVar *thisObj); +static void brewCallback(HTTPControl *hp); +static int httpDestructor(Ejs *ejs, EjsVar *vp); +static void httpCallback(HTTPControl *hp, int responseCode); +static int setCallback(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv); + +/******************************************************************************/ +/* + * Constructor + */ + +int ejsHTTPConstructor(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) +{ + if (argc != 0 && argc != 2) { + ejsError(ejs, EJS_ARG_ERROR, + "Bad usage: HTTP([obj = this, method = onComplete]);"); + return -1; + } + + if (createWeb(ejs, thisObj) < 0) { + return -1; + } + + setCallback(ejs, thisObj, argc, argv); + return 0; +} + +/******************************************************************************/ + +static int createWeb(Ejs *ejs, EjsVar *thisObj) +{ + MprApp *app; + void *web; + + app = mprGetApp(ejs); + + /* + * Create one instance of IWeb for the entire application. Do it here + * so only widgets that require HTTP incurr the overhead. + */ + web = mprGetKeyValue(ejs, "bpWeb"); + if (web == 0) { + if (ISHELL_CreateInstance(app->shell, AEECLSID_WEB, &web) != SUCCESS) { + ejsError(ejs, EJS_IO_ERROR, "Can't create IWEB"); + return -1; + } + } + mprSetKeyValue(ejs, "bpWeb", web); + return 0; +} + +/******************************************************************************/ +/************************************ Methods *********************************/ +/******************************************************************************/ +/* + * function setCallback(obj, methodString); + */ + +static int setCallback(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) +{ + if (argc >= 1) { + ejsSetProperty(ejs, thisObj, "obj", argv[0]); + } else { + ejsSetProperty(ejs, thisObj, "obj", thisObj); + } + + if (argc >= 2) { + ejsSetProperty(ejs, thisObj, "method", argv[1]); + } else { + ejsSetPropertyToString(ejs, thisObj, "method", "onComplete"); + } + + return 0; +} + +/******************************************************************************/ +/* + * function fetch(); + */ + +static int fetchProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) +{ + HTTPControl *hp; + EjsProperty *pp; + MprApp *app; + IWeb *web; + + if (argc != 1 || !ejsVarIsString(argv[0])) { + ejsError(ejs, EJS_ARG_ERROR, "Bad usage: fetch(url)"); + return -1; + } + + app = mprGetApp(ejs); + web = (IWeb*) mprGetKeyValue(ejs, "bpWeb"); + + /* + * Web options + * + * WEBOPT_USERAGENT (char*) sets user agent + * WEBOPT_HANDLERDATA (void*) + * WEBOPT_CONNECTTIMEOUT (uint) msec + * WEBOPT_CONTENTLENGTH (long) + * WEBOPT_IDLECONNTIMEOUT (int) + * WEBOPT_ACTIVEXACTIONST (uint) Number of active requests + * + * WEBREQUEST_REDIRECT redirect transparently + * + */ + + hp = mprAllocType(ejs, HTTPControl); + if (hp == 0) { + ejsMemoryError(ejs); + return -1; + } + + hp->ejs = ejs; + hp->buf = mprCreateBuf(hp, MPR_BUF_INCR, MPR_MAX_BUF); + if (hp->buf == 0) { + mprFree(hp); + ejsMemoryError(ejs); + return -1; + } + + /* + * We copy thisObj because we need to preserve both the var and the object. + * We pass the var to brewCallback and so it must persist. The call to + * ejsMakeObjPermanent will stop the GC from collecting the object. + */ + hp->thisObj = ejsDupVar(ejs, thisObj, EJS_SHALLOW_COPY); + ejsSetVarName(ejs, hp->thisObj, "internalHttp"); + + /* + * Must keep a reference to the http object + */ + ejsMakeObjPermanent(hp->thisObj, 1); + + /* + * Make a property so we can access the HTTPControl structure from other + * methods. + */ + pp = ejsSetPropertyToPtr(ejs, thisObj, EJS_HTTP_PROPERTY, hp, 0); + ejsMakePropertyEnumerable(pp, 0); + ejsSetObjDestructor(ejs, hp->thisObj, httpDestructor); + + hp->url = mprStrdup(hp, argv[0]->string); + + hp->timeout = ejsGetPropertyAsInteger(ejs, thisObj, "timeout"); + mprGetTime(hp, &hp->requestStarted); + + hp->callback = mprAllocTypeZeroed(hp, AEECallback); + CALLBACK_Init(hp->callback, brewCallback, hp); + + hp->webResp = 0; + IWEB_GetResponse(web, + (web, &hp->webResp, hp->callback, hp->url, + WEBOPT_HANDLERDATA, hp, + WEBOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)", + WEBOPT_CONNECTTIMEOUT, hp->timeout, + WEBOPT_COPYOPTS, TRUE, + WEBOPT_CONTENTLENGTH, 0, + WEBOPT_END)); + + ejsSetPropertyToString(ejs, thisObj, "status", "active"); + + return 0; +} + +/******************************************************************************/ +/* + * Called whenver the http object is deleted. + */ + +static int httpDestructor(Ejs *ejs, EjsVar *thisObj) +{ + HTTPControl *hp; + + /* + * If the httpCallback has run, then this property will not exist + */ + hp = ejsGetPropertyAsPtr(ejs, thisObj, EJS_HTTP_PROPERTY); + + if (hp) { + cleanup(hp); + } + + return 0; +} + +/******************************************************************************/ +/* + * Stop the request immediately without calling the callback + */ + +static int stopProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) +{ + HTTPControl *hp; + + hp = ejsGetPropertyAsPtr(ejs, thisObj, EJS_HTTP_PROPERTY); + + if (hp) { + cleanup(hp); + } + + return 0; +} + +/******************************************************************************/ +/* + * Brew HTTP callback. Invoked for any return data. + */ + +static void brewCallback(HTTPControl *hp) +{ + Ejs *ejs; + EjsVar *thisObj; + ISource *source; + WebRespInfo *info; + char data[MPR_BUF_INCR]; + int bytes; + + mprAssert(hp); + mprAssert(hp->webResp); + + info = IWEBRESP_GetInfo(hp->webResp); + + if (info == 0) { + mprAssert(info); + /* should not happen */ + return; + } + + ejs = hp->ejs; + thisObj = hp->thisObj; + + if (! WEB_ERROR_SUCCEEDED(info->nCode)) { + ejsSetPropertyToString(ejs, thisObj, "status", "error"); + httpCallback(hp, info->nCode); + return; + } + + if (hp->timeout) { + if (mprGetTimeRemaining(hp, hp->requestStarted, hp->timeout) <= 0) { + ejsSetPropertyToString(ejs, thisObj, "status", "timeout"); + httpCallback(hp, 504); + return; + } + } + + /* + * Normal success + */ + source = info->pisMessage; + mprAssert(source); + + bytes = ISOURCE_Read(source, data, sizeof(data)); + + switch (bytes) { + case ISOURCE_WAIT: // No data yet + ISOURCE_Readable(source, hp->callback); + break; + + case ISOURCE_ERROR: + ejsSetPropertyToString(ejs, thisObj, "status", "error"); + httpCallback(hp, info->nCode); + break; + + case ISOURCE_END: + mprAddNullToBuf(hp->buf); + ejsSetPropertyToString(ejs, thisObj, "status", "complete"); + httpCallback(hp, info->nCode); + break; + + default: + if (bytes > 0) { + if (mprPutBlockToBuf(hp->buf, data, bytes) != bytes) { + ejsSetPropertyToString(ejs, thisObj, "status", "partialData"); + httpCallback(hp, 500); + } + } + ISOURCE_Readable(source, hp->callback); + break; + } +} + +/******************************************************************************/ +/* + * Invoke the HTTP completion method + */ + +static void httpCallback(HTTPControl *hp, int responseCode) +{ + Ejs *ejs; + EjsVar *thisObj, *callbackObj; + MprArray *args; + char *msg; + const char *callbackMethod; + + mprAssert(hp); + mprAssert(hp->webResp); + + thisObj = hp->thisObj; + ejs = hp->ejs; + + ejsSetPropertyToInteger(ejs, thisObj, "responseCode", responseCode); + if (mprGetBufLength(hp->buf) > 0) { + ejsSetPropertyToBinaryString(ejs, thisObj, "responseData", + mprGetBufStart(hp->buf), mprGetBufLength(hp->buf)); + } + + callbackObj = ejsGetPropertyAsVar(ejs, thisObj, "obj"); + callbackMethod = ejsGetPropertyAsString(ejs, thisObj, "method"); + + if (callbackObj != 0 && callbackMethod != 0) { + + args = mprCreateItemArray(ejs, EJS_INC_ARGS, EJS_MAX_ARGS); + mprAddItem(args, ejsDupVar(ejs, hp->thisObj, EJS_SHALLOW_COPY)); + + if (ejsRunMethod(ejs, callbackObj, callbackMethod, args) < 0) { + msg = ejsGetErrorMsg(ejs); + mprError(ejs, MPR_LOC, "HTTP callback failed. Details: %s", msg); + } + ejsFreeMethodArgs(ejs, args); + + } else if (ejsRunMethod(ejs, thisObj, "onComplete", 0) < 0) { + msg = ejsGetErrorMsg(ejs); + mprError(ejs, MPR_LOC, "HTTP onComplete failed. Details: %s", msg); + } + + cleanup(hp); +} + +/******************************************************************************/ +/* + * Cleanup + */ + +static void cleanup(HTTPControl *hp) +{ + Ejs *ejs; + MprApp *app; + int rc; + + mprAssert(hp); + mprAssert(hp->webResp); + + ejs = hp->ejs; + + if (hp->webResp) { + rc = IWEBRESP_Release(hp->webResp); + // mprAssert(rc == 0); + hp->webResp = 0; + } + + if (hp->callback) { + CALLBACK_Cancel(hp->callback); + mprFree(hp->callback); + hp->callback = 0; + } + + /* + * Once the property is deleted, then if the destructor runs, it will + * notice that the EJS_HTTP_PROPERTY is undefined. + */ + ejsDeleteProperty(ejs, hp->thisObj, EJS_HTTP_PROPERTY); + + /* + * Allow garbage collection to work on thisObj + */ + ejsMakeObjPermanent(hp->thisObj, 0); + ejsFreeVar(ejs, hp->thisObj); + + mprFree(hp->buf); + mprFree(hp->url); + + mprFree(hp); + + app = mprGetApp(ejs); + + + ISHELL_SendEvent(app->shell, (AEECLSID) app->classId, EVT_USER, 0, 0); +} + +/******************************************************************************/ +/******************************** Initialization ******************************/ +/******************************************************************************/ + +int ejsDefineHTTPClass(Ejs *ejs) +{ + EjsVar *httpClass; + + httpClass = + ejsDefineClass(ejs, "HTTP", "Object", ejsHTTPConstructor); + if (httpClass == 0) { + return MPR_ERR_CANT_INITIALIZE; + } + + /* + * Define the methods + */ + ejsDefineCMethod(ejs, httpClass, "fetch", fetchProc, 0); + ejsDefineCMethod(ejs, httpClass, "stop", stopProc, 0); + ejsDefineCMethod(ejs, httpClass, "setCallback", setCallback, 0); + +#if FUTURE + ejsDefineCMethod(ejs, httpClass, "put", put, 0); + ejsDefineCMethod(ejs, httpClass, "upload", upload, 0); + ejsDefineCMethod(ejs, httpClass, "addUploadFile", addUploadFile, 0); + ejsDefineCMethod(ejs, httpClass, "addPostData", addPostData, 0); + ejsDefineCMethod(ejs, httpClass, "setUserPassword", setUserPassword, 0); + ejsDefineCMethod(ejs, httpClass, "addCookie", addCookie, 0); +#endif + + /* + * Define properties + */ + ejsSetPropertyToString(ejs, httpClass, "status", "inactive"); + + /* This default should come from player.xml */ + + ejsSetPropertyToInteger(ejs, httpClass, "timeout", 30 * 1000); + ejsSetPropertyToInteger(ejs, httpClass, "responseCode", 0); + + return ejsObjHasErrors(httpClass) ? MPR_ERR_CANT_INITIALIZE: 0; +} + +/******************************************************************************/ + +void ejsTermHTTPClass(Ejs *ejs) +{ + IWeb *web; + int rc; + + web = (IWeb*) mprGetKeyValue(ejs, "bpWeb"); + if (web) { + rc = IWEB_Release(web); + mprAssert(rc == 0); + } +} + +#endif +/******************************************************************************/ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim:tw=78 + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ |