summaryrefslogtreecommitdiff
path: root/source4/lib/appweb/ejs-2.0/ejs/system/WIN/ejsHTTP.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/lib/appweb/ejs-2.0/ejs/system/WIN/ejsHTTP.c')
-rwxr-xr-xsource4/lib/appweb/ejs-2.0/ejs/system/WIN/ejsHTTP.c488
1 files changed, 488 insertions, 0 deletions
diff --git a/source4/lib/appweb/ejs-2.0/ejs/system/WIN/ejsHTTP.c b/source4/lib/appweb/ejs-2.0/ejs/system/WIN/ejsHTTP.c
new file mode 100755
index 0000000000..25821f6960
--- /dev/null
+++ b/source4/lib/appweb/ejs-2.0/ejs/system/WIN/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
+ */