psyced/world/net/http/library.i
psyc://psyced.org/~lynX 75467224ae +
2010-03-02 21:07:19 +01:00

226 lines
5.1 KiB
OpenEdge ABL

// vim:noexpandtab:syntax=lpc
// $Id: library.i,v 1.40 2008/04/27 08:20:47 lynx Exp $
//
// HTTP function library -lynx
//
// (extension to "simul_efun")
#include <net.h>
#include <services.h>
#include "driver.h"
//#include CONFIG_PATH "ports.h"
#include "ht/http.h"
#if !HAS_PORT(HTTP_PORT, HTTP_PATH)
# undef HTTP_PORT
# define HTTP_PORT 44444 // should return null instead?
#endif
// not worthy of summoning uniform.h for this one..
string htuniform(object server, string prot, mapping headers) {
// it is really totally crazy to trust what the browser says
string host = headers["host"];
int port = HTTP_PORT;
#if __EFUN_DEFINED__(tls_query_connection_state)
#ifndef HTTPS_HOST
string scheme = "http://";
# endif
unless (server) server = this_interactive();
if (tls_query_connection_state(server)) {
#ifdef HTTPS_HOST
return HTTPS_HOST;
#else
scheme = "https://";
# if HAS_TLS_PORT(HTTPS_PORT)
port = HTTPS_PORT;
# endif
#endif
}
# define SCHEME scheme
# define PORT port
#else
# define SCHEME "http://"
# define PORT HTTP_PORT
#endif
unless (host) {
#ifdef HTTP_HOST
return HTTP_HOST;
#else
host = SERVER_HOST;
// HTTP_SERVICE is 80 from services.h
if (port != HTTP_SERVICE) host += ":"+to_string(port);
#endif
}
return SCHEME + host;
}
varargs string htheaders(string type, string extra) {
string out;
unless (stringp(type)) type = DEFAULT_CONTENT_TYPE;
out = "Content-type: "+ type +"\n";
// if (length) {
// printf("Content-length: %d\n", length);
// }
if (extra) out += extra;
return out;
}
varargs string htheaders2(string type, string extra) {
return htheaders(type, extra)
+ "Server: " HTTP_SERVER "\nDate: "+ ctime(time()) +"\n";
}
void htrequireauth(string prot, string type, string realm) {
if (prot) write(HTTP_SVERS + " " + to_string(R_UNAUTHORIZED) +
"Your password, please\n");
if (type == "digest") {
write("WWW-Authenticate: Digest realm=\"" + realm +
"\", nonce=\"" + time() + "\"\n");
} else {
write("WWW-Authenticate: Basic realm=\"" + realm + "\"\n");
}
}
varargs string htredirect(string prot, string target, string comment, int permanent, string extra) {
if (!comment) comment = "Check this out";
if (!target) target = "/";
if (!extra) extra = "";
if (prot) {
printf("%s %d %s\n%s", HTTP_SVERS,
permanent ? R_MOVED : R_FOUND, comment, htheaders());
}
printf("\
Location: %s\n%s\
\n\
<a href=\"%s\">%s</a>.\n\
",
target, extra, target, comment);
return 0;
}
// written and donated by _Marcus_
//
// thanx!!
/* convert %XX escapes to real chars */
static int xx2l(string str) {
int x;
str=lower_case(str);
if (str[0]>='0' && str[0]<='9') x=(str[0]-'0')*16;
if (str[0]>='a' && str[0]<='f') x=(str[0]-'a'+10)*16;
if (str[1]>='0' && str[1]<='9') x+=str[1]-'0';
if (str[1]>='a' && str[1]<='f') x+=str[1]-'a'+10;
return x;
}
/* Content-Encoding: url-encoded */
string urldecode(string txt) {
string *xx;
int i;
txt=implode(explode(txt,"+")," ");
#if __EFUN_DEFINED__(regexplode)
xx=regexplode(txt,"%..");
for (i=1;i<sizeof(xx)-1;i+=2)
xx[i]=sprintf("%c",xx2l(xx[i][1..]));
txt=implode(xx,"");
#endif
return txt;
}
#if 0 // inline this instead, see below
static string c2xx(string c) {
return "%"+ upper_case(sprintf("%x", c[0]));
}
#endif
string urlencode(string txt) {
return regreplace(txt, "[^A-Za-z0-9._~-]", (:
"%"+ upper_case(sprintf("%x", $1[0])) :), 1);
}
#ifndef DEFAULT_HT_TYPE
# define DEFAULT_HT_TYPE "text/plain"
#endif
string content_type(string suffix) {
switch(lower_case(suffix)) {
case "html":
return "text/html";
case "xml":
//return "application/xml";
return "text/xml"; // what type is to be used here?
case "bz2":
return "application/x-bzip2";
case "class":
return "application/octet-stream";
case "css":
return "text/css";
case "gif":
return "image/gif";
case "gz":
return "application/x-gzip";
case "jpeg":
case "jpg":
return "image/jpeg";
case "js":
return "application/x-javascript";
case "pdf":
return "application/pdf";
case "png":
return "image/png";
case "ps":
case "eps":
return "application/postscript";
case "tar":
return "application/tar";
case "zip":
return "application/zip";
case "swf":
return "application/x-shockwave-flash";
default:
return DEFAULT_HT_TYPE;
}
return 0;
}
mapping url_parse_query(mapping query, string qs) {
foreach (string pair : explode(qs, "&")) {
string key, val;
if (sscanf(pair, "%s=%s", key, val)) {
P3(("query: pair: %s, %s\n", urldecode(key),
urldecode(val)))
query[urldecode(key)] = urldecode(val);
} else {
P3(("query: single: %s\n", urldecode(pair)))
query[urldecode(pair)] = 1;
}
}
return query;
}
varargs string make_query_string(mapping params, int sort) {
string q = "";
array(mixed) keys = m_indices(params);
if (sort) keys = sort_array(keys, #'>);
foreach(string key : keys) {
q += (strlen(q) ? "&" : "") + urlencode(to_string(key)) + "=" + urlencode(to_string(params[key]));
}
return q;
}
object checkToken(mapping query) {
string nick;
object user;
if (nick = query["user"]) user = find_person(nick);
if (user && user->validToken(query["token"])) return user;
return 0;
}