static void cacheAtClient(HttpConn *conn) { HttpTx *tx; HttpCache *cache; cchar *value; tx = conn->tx; cache = conn->tx->cache; if (!mprLookupKey(tx->headers, "Cache-Control")) { if ((value = mprLookupKey(conn->tx->headers, "Cache-Control")) != 0) { if (strstr(value, "max-age") == 0) { httpAppendHeader(conn, "Cache-Control", "max-age=%d", cache->clientLifespan / MPR_TICKS_PER_SEC); } } else { httpAddHeader(conn, "Cache-Control", "max-age=%d", cache->clientLifespan / MPR_TICKS_PER_SEC); } #if UNUSED && KEEP { /* Old HTTP/1.0 clients don't understand Cache-Control */ struct tm tm; mprDecodeUniversalTime(&tm, conn->http->now + (expires * MPR_TICKS_PER_SEC)); httpAddHeader(conn, "Expires", "%s", mprFormatTime(MPR_HTTP_DATE, &tm)); } #endif } }
static void testFormatTime(MprTestGroup *gp) { MprTime now; struct tm tm; char *str; now = mprGetTime(gp); mprDecodeLocalTime(gp, &tm, now); str = mprFormatTime(gp, NULL, &tm); assert(str && *str); }
/* * Build an ASCII time string. If sbuf is NULL we use the current time, else we use the last modified time of sbuf */ char *maGetDateString(MprCtx ctx, MprPath *sbuf) { MprTime when; struct tm tm; if (sbuf == 0) { when = mprGetTime(ctx); } else { when = (MprTime) sbuf->mtime * MPR_TICKS_PER_SEC; } mprDecodeUniversalTime(ctx, &tm, when); return mprFormatTime(ctx, MPR_HTTP_DATE, &tm); }
/* * Get a date string. If sbuf is non-null, get the modified time of that file. If null, then get the current system time. */ static char *makeDateString(MprPath *sbuf) { MprTime when; struct tm tm; if (sbuf == 0) { when = mprGetTime(mpr); } else { when = (MprTime) sbuf->mtime * MPR_TICKS_PER_SEC; } mprDecodeUniversalTime(mpr, &tm, when); return mprFormatTime(mpr, MPR_RFC_DATE, &tm); }
/* * Add a response cookie */ static void setCookie(void *handle, cchar *name, cchar *value, cchar *path, cchar *cookieDomain, int lifetime, bool isSecure) { struct tm tm; cchar *userAgent, *hostName; char dateStr[64], *cp, *expiresAtt, *expires, *domainAtt, *domain, *secure; if (path == 0) { path = "/"; } userAgent = getHeader(handle, "HTTP_USER_AGENT"); hostName = getHeader(handle, "HTTP_HOST"); /* * Fix for Safari and Bonjour addresses with a trailing ".". Safari discards cookies without a domain specifier * or with a domain that includes a trailing ".". Solution: include an explicit domain and trim the trailing ".". * * User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_6; en-us) * AppleWebKit/530.0+ (KHTML, like Gecko) Version/3.1.2 Safari/525.20.1 */ if (cookieDomain == 0 && userAgent && strstr(userAgent, "AppleWebKit") != 0) { domain = mprStrdup(mpr, hostName); if ((cp = strchr(domain, ':')) != 0) { *cp = '\0'; } if (*domain && domain[strlen(domain) - 1] == '.') { domain[strlen(domain) - 1] = '\0'; } else { domain = 0; } } else { domain = 0; } if (domain) { domainAtt = "; domain="; } else { domainAtt = ""; } if (lifetime > 0) { mprDecodeUniversalTime(mpr, &tm, mprGetTime(mpr) + (lifetime * MPR_TICKS_PER_SEC)); mprFormatTime(mpr, MPR_HTTP_DATE, &tm); expiresAtt = "; expires="; expires = dateStr; } else { expires = expiresAtt = ""; } if (isSecure) { secure = "; secure"; } else { secure = ";"; } /* * Allow multiple cookie headers. Even if the same name. Later definitions take precedence */ setHeader(handle, 1, "Set-Cookie", mprStrcat(mpr, -1, name, "=", value, "; path=", path, domainAtt, domain, expiresAtt, expires, secure, NULL)); setHeader(handle, 0, "Cache-control", "no-cache=\"set-cookie\""); }