static EjsVar *getHostVar(void *handle, int field) { switch (field) { case ES_ejs_web_Host_documentRoot: return createString(ejs, getHeader(handle, "DOCUMENT_ROOT")); case ES_ejs_web_Host_name: return createString(ejs, getHeader(handle, "SERVER_NAME")); case ES_ejs_web_Host_protocol: return createString(ejs, getHeader(handle, "REQUEST_TRANSPORT")); #if TODO case ES_ejs_web_Host_isVirtualHost: return (EjsVar*) ejsCreateBoolean(ejs, host->flags & MA_HOST_VHOST); case ES_ejs_web_Host_isNamedVirtualHost: return (EjsVar*) ejsCreateBoolean(ejs, host->flags & MA_HOST_NAMED_VHOST); #endif case ES_ejs_web_Host_software: return createString(ejs, EJS_SERVER_NAME); case ES_ejs_web_Host_logErrors: return (EjsVar*) ((web->flags & EJS_WEB_FLAG_BROWSER_ERRORS) ? ejs->falseValue : ejs->trueValue); } ejsThrowOutOfBoundsError(ejs, "Bad property slot reference"); return 0; }
static EjsVar *getResponseVar(void *handle, int field) { Ejs *ejs; MaConn *conn; MaResponse *resp; conn = handle; resp = conn->response; ejs = ((EjsWeb*) maGetHandlerQueueData(conn))->ejs; switch (field) { case ES_ejs_web_Response_code: return (EjsVar*) ejsCreateNumber(ejs, resp->code); case ES_ejs_web_Response_filename: return (EjsVar*) createString(ejs, resp->filename); case ES_ejs_web_Response_headers: return (EjsVar*) createHeaders(ejs, conn->response->headers); case ES_ejs_web_Response_mimeType: return (EjsVar*) createString(ejs, resp->mimeType); default: ejsThrowOutOfBoundsError(ejs, "Bad property slot reference"); return 0; } }
/* Index into a file and extract a byte. This is random access reading. */ static EjsNumber *getFileProperty(Ejs *ejs, EjsFile *fp, int slotNum) { MprOff offset; int c; if (!(fp->mode & EJS_FILE_OPEN)) { ejsThrowIOError(ejs, "File is not open"); return 0; } #if KEEP if (fp->mode & EJS_FILE_READ) { if (slotNum >= fp->info.size) { ejsThrowOutOfBoundsError(ejs, "Bad file index"); return 0; } } if (slotNum < 0) { ejsThrowOutOfBoundsError(ejs, "Bad file index"); return 0; } #endif #if ME_CC_MMU && FUTURE // must check against mapped size here. c = fp->mapped[slotNum]; #else offset = mprSeekFile(fp->file, SEEK_CUR, 0); if (offset != slotNum) { if (mprSeekFile(fp->file, SEEK_SET, slotNum) != slotNum) { ejsThrowIOError(ejs, "Cannot seek to file offset"); return 0; } } c = mprPeekFileChar(fp->file); if (c < 0) { ejsThrowIOError(ejs, "Cannot read file"); return 0; } #endif return ejsCreateNumber(ejs, c); }
/* Read data bytes from a file. If offset is < 0, then append to the write position. function read(buffer: ByteArray, offset: Number = 0, count: Number = -1): Number */ static EjsNumber *readFile(Ejs *ejs, EjsFile *fp, int argc, EjsObj **argv) { EjsByteArray *buffer; MprPath info; ssize offset, count, totalRead; assert(1 <= argc && argc <= 3); buffer = (EjsByteArray*) argv[0]; offset = (argc >= 2) ? ejsGetInt(ejs, argv[1]): 0; count = (argc >= 3) ? ejsGetInt(ejs, argv[2]): -1; if (fp->file == 0) { ejsThrowStateError(ejs, "File not open"); return 0; } if (!(fp->mode & EJS_FILE_READ)) { ejsThrowStateError(ejs, "File not opened for reading"); return 0; } if (offset >= buffer->size) { ejsThrowOutOfBoundsError(ejs, "Bad read offset value"); return 0; } if (offset < 0) { offset = buffer->writePosition; } else if (offset == 0) { ejsSetByteArrayPositions(ejs, buffer, 0, 0); } if (count < 0) { // TODO OPT could this be cached in fp->info if (mprGetPathInfo(fp->path, &info) == 0) { count = (int) info.size; count -= (int) mprGetFilePosition(fp->file); } else { count = ME_MAX_BUFFER; } assert(count >= 0); } totalRead = readData(ejs, fp, buffer, offset, count); if (totalRead < 0) { return 0; } else if (totalRead == 0) { return ESV(zero); } ejsSetByteArrayPositions(ejs, buffer, -1, offset + totalRead); return ejsCreateNumber(ejs, (MprNumber) totalRead); }
/* function read(buffer: ByteArray, offset: Number = 0, count: Number = -1): Number Returns a count of bytes read. Non-blocking if a callback is defined. Otherwise, blocks. Offset: -1 then read to the buffer write position, >= 0 then read to that offset count: -1 then read as much as the buffer will hold. If buffer is growable, read all content. If not growable, read the buffer size. If count >= 0, then read that number of bytes. */ static EjsNumber *http_read(Ejs *ejs, EjsHttp *hp, int argc, EjsObj **argv) { EjsByteArray *buffer; HttpConn *conn; MprOff contentLength; ssize offset, count; conn = hp->conn; buffer = (EjsByteArray*) argv[0]; offset = (argc >= 2) ? ejsGetInt(ejs, argv[1]) : 0; count = (argc >= 3) ? ejsGetInt(ejs, argv[2]): -1; if (!waitForResponseHeaders(hp)) { return 0; } contentLength = httpGetContentLength(conn); if (conn->state >= HTTP_STATE_PARSED && contentLength == hp->readCount) { /* End of input */ return ESV(null); } if (offset < 0) { offset = buffer->writePosition; } else if (offset < buffer->size) { ejsSetByteArrayPositions(ejs, buffer, offset, offset); } else { ejsThrowOutOfBoundsError(ejs, "Bad read offset value"); return 0; } if (count < 0 && !buffer->resizable) { count = buffer->size - offset; } if ((count = readHttpData(ejs, hp, count)) < 0) { assert(ejs->exception); return 0; } else if (count == 0 && conn->state > HTTP_STATE_CONTENT) { return ESV(null); } hp->readCount += count; if (ejsCopyToByteArray(ejs, buffer, offset, (char*) mprGetBufStart(hp->responseContent), count) != count) { ejsThrowMemoryError(ejs); } ejsSetByteArrayPositions(ejs, buffer, -1, buffer->writePosition + count); mprAdjustBufStart(hp->responseContent, count); mprResetBufIfEmpty(hp->responseContent); return ejsCreateNumber(ejs, (MprNumber) count); }
static EjsVar *getResponseVar(void *handle, int field) { switch (field) { case ES_ejs_web_Response_code: return (EjsVar*) ejsCreateNumber(ejs, responseCode); #if TODO case ES_ejs_web_Response_filename: return (EjsVar*) createString(ejs, programName); #endif case ES_ejs_web_Response_headers: return (EjsVar*) createHeaderObject(ejs, responseHeaders); case ES_ejs_web_Response_mimeType: return (EjsVar*) createString(ejs, responseMimeType); default: ejsThrowOutOfBoundsError(ejs, "Bad property slot reference"); return 0; } }
static EjsVar *getHostVar(void *handle, int field) { Ejs *ejs; MaConn *conn; MaHost *host; EjsWeb *web; conn = handle; host = conn->host; ejs = ((EjsWeb*) maGetHandlerQueueData(conn))->ejs; switch (field) { case ES_ejs_web_Host_documentRoot: return createString(ejs, host->documentRoot); case ES_ejs_web_Host_name: return createString(ejs, host->name); case ES_ejs_web_Host_protocol: return createString(ejs, host->secure ? "https" : "http"); case ES_ejs_web_Host_isVirtualHost: return (EjsVar*) ejsCreateBoolean(ejs, host->flags & MA_HOST_VHOST); case ES_ejs_web_Host_isNamedVirtualHost: return (EjsVar*) ejsCreateBoolean(ejs, host->flags & MA_HOST_NAMED_VHOST); case ES_ejs_web_Host_software: return createString(ejs, MA_SERVER_NAME); case ES_ejs_web_Host_logErrors: web = ejs->handle; return (EjsVar*) ((web->flags & EJS_WEB_FLAG_BROWSER_ERRORS) ? ejs->falseValue : ejs->trueValue); } ejsThrowOutOfBoundsError(ejs, "Bad property slot reference"); return 0; }
static EjsVar *getRequestVar(void *handle, int field) { switch (field) { case ES_ejs_web_Request_accept: return createString(ejs, getHeader(handle, "HTTP_ACCEPT")); case ES_ejs_web_Request_acceptCharset: return createString(ejs, getHeader(handle, "HTTP_ACCEPT_CHARSET")); case ES_ejs_web_Request_acceptEncoding: return createString(ejs, getHeader(handle, "HTTP_ACCEPT_ENCODING")); case ES_ejs_web_Request_authAcl: case ES_ejs_web_Request_authGroup: case ES_ejs_web_Request_authUser: // TODO return (EjsVar*) ejs->undefinedValue; case ES_ejs_web_Request_authType: return createString(ejs, getHeader(handle, "HTTP_AUTH_TYPE")); #if TODO case ES_ejs_web_Request_connection: return createString(ejs, req->connection); #endif case ES_ejs_web_Request_contentLength: return (EjsVar*) ejsCreateNumber(ejs, contentLength); case ES_ejs_web_Request_cookies: if (cookie) { return (EjsVar*) ejsCreateCookies(ejs); } else { return ejs->nullValue; } break; case ES_ejs_web_Request_extension: return createString(ejs, ext); case ES_ejs_web_Request_files: // TODO return (EjsVar*) ejs->undefinedValue; case ES_ejs_web_Request_headers: return (EjsVar*) createHeaderObject(ejs, requestHeaders); case ES_ejs_web_Request_hostName: return createString(ejs, getHeader(handle, "HTTP_HOST")); case ES_ejs_web_Request_method: return createString(ejs, getHeader(handle, "REQUEST_METHOD")); case ES_ejs_web_Request_mimeType: return createString(ejs, getHeader(handle, "CONTENT_TYPE")); case ES_ejs_web_Request_pathInfo: return createString(ejs, getHeader(handle, "PATH_INFO")); case ES_ejs_web_Request_pathTranslated: return createString(ejs, getHeader(handle, "PATH_TRANSLATED")); case ES_ejs_web_Request_pragma: return createString(ejs, getHeader(handle, "HTTP_PRAGMA")); case ES_ejs_web_Request_query: return createString(ejs, getHeader(handle, "QUERY_STRING")); case ES_ejs_web_Request_originalUri: return createString(ejs, getHeader(handle, "REQUEST_URI")); case ES_ejs_web_Request_referrer: return createString(ejs, getHeader(handle, "HTTP_REFERRER")); case ES_ejs_web_Request_remoteAddress: return createString(ejs, getHeader(handle, "REMOTE_ADDR")); case ES_ejs_web_Request_remoteHost: #if BLD_FEATURE_REVERSE_DNS && BLD_UNIX_LIKE { /* * This feature has denial of service risks. Doing a reverse DNS will be slower, * and can potentially hang the web server. Use at your own risk!! Not supported for windows. */ struct addrinfo *result; char name[MPR_MAX_STRING]; int rc; if (getaddrinfo(remoteIpAddr, NULL, NULL, &result) == 0) { rc = getnameinfo(result->ai_addr, sizeof(struct sockaddr), name, sizeof(name), NULL, 0, NI_NAMEREQD); freeaddrinfo(result); if (rc == 0) { return createString(ejs, name); } } } #endif return createString(ejs, getHeader(handle, "REMOTE_ADDR")); case ES_ejs_web_Request_sessionID: return createString(ejs, web->session ? web->session->id : ""); case ES_ejs_web_Request_url: return createString(ejs, uri); case ES_ejs_web_Request_userAgent: return createString(ejs, getHeader(handle, "HTTP_USER_AGENT")); } ejsThrowOutOfBoundsError(ejs, "Bad property slot reference"); return 0; }
static EjsVar *getRequestVar(void *handle, int field) { Ejs *ejs; EjsWeb *web; MaConn *conn; MaRequest *req; conn = handle; req = conn->request; ejs = ((EjsWeb*) maGetHandlerQueueData(conn))->ejs; switch (field) { case ES_ejs_web_Request_accept: return createString(ejs, req->accept); case ES_ejs_web_Request_acceptCharset: return createString(ejs, req->acceptCharset); case ES_ejs_web_Request_acceptEncoding: return createString(ejs, req->acceptEncoding); case ES_ejs_web_Request_authAcl: case ES_ejs_web_Request_authGroup: case ES_ejs_web_Request_authUser: // TODO return (EjsVar*) ejs->undefinedValue; case ES_ejs_web_Request_authType: return createString(ejs, req->authType); case ES_ejs_web_Request_connection: return createString(ejs, req->connection); case ES_ejs_web_Request_contentLength: return (EjsVar*) ejsCreateNumber(ejs, req->length); case ES_ejs_web_Request_cookies: if (req->cookie) { return (EjsVar*) ejsCreateCookies(ejs); } else { return ejs->nullValue; } break; case ES_ejs_web_Request_extension: return createString(ejs, req->parsedUri->ext); case ES_ejs_web_Request_files: return (EjsVar*) ejs->undefinedValue; case ES_ejs_web_Request_headers: return (EjsVar*) createHeaders(ejs, conn->request->headers); case ES_ejs_web_Request_hostName: return createString(ejs, req->hostName); case ES_ejs_web_Request_method: return createString(ejs, req->methodName); case ES_ejs_web_Request_mimeType: return createString(ejs, req->mimeType); case ES_ejs_web_Request_pathInfo: return createString(ejs, req->pathInfo); case ES_ejs_web_Request_pathTranslated: return createString(ejs, req->pathTranslated); case ES_ejs_web_Request_pragma: return createString(ejs, req->pragma); case ES_ejs_web_Request_query: return createString(ejs, req->parsedUri->query); case ES_ejs_web_Request_originalUri: return createString(ejs, req->parsedUri->originalUri); case ES_ejs_web_Request_referrer: return createString(ejs, req->referer); case ES_ejs_web_Request_remoteAddress: return createString(ejs, conn->remoteIpAddr); case ES_ejs_web_Request_remoteHost: #if BLD_FEATURE_REVERSE_DNS && BLD_UNIX_LIKE { /* * This feature has denial of service risks. Doing a reverse DNS will be slower, * and can potentially hang the web server. Use at your own risk!! Not supported for windows. */ struct addrinfo *result; char name[MPR_MAX_STRING]; int rc; if (getaddrinfo(remoteIpAddr, NULL, NULL, &result) == 0) { rc = getnameinfo(result->ai_addr, sizeof(struct sockaddr), name, sizeof(name), NULL, 0, NI_NAMEREQD); freeaddrinfo(result); if (rc == 0) { return createString(ejs, name); } } } #endif return createString(ejs, conn->remoteIpAddr); case ES_ejs_web_Request_sessionID: web = ejs->handle; return createString(ejs, web->session ? web->session->id : ""); case ES_ejs_web_Request_url: return createString(ejs, req->url); case ES_ejs_web_Request_userAgent: return createString(ejs, req->userAgent); } ejsThrowOutOfBoundsError(ejs, "Bad property slot reference"); return 0; }