ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/repos/Bender/Bender.cpp
Revision: 627
Committed: 2005-12-24T22:30:44-08:00 (19 years, 5 months ago) by douglas
File size: 3066 byte(s)
Log Message:
Hmm.

File Contents

# Content
1 // Bender
2 //
3 // Douglas Thrift
4 //
5 // $Id$
6
7 #include <cxx/standard.hh>
8
9 #include <api/pcre/regex.hpp>
10 #include <api/environment.hpp>
11 #include <api/files.hpp>
12 #include <api/process.hpp>
13 #include <app/simple.hpp>
14 #include <ios/helpers.hpp>
15 #include <xml/document.hpp>
16 #include <xml/nodeset.hpp>
17 #include <xml/parse.hpp>
18
19 class Bender
20 {
21 private:
22 void bend(const cse::String& path, const cse::String& agent);
23 void bend(const cse::String& path);
24 void pass(const cse::String& path);
25 public:
26 Bender();
27 };
28
29 struct Environment
30 {
31 cse::String get(const cse::String& name) { try { return api::TheEnvironment.Get(name); } catch (ext::Exception) { return cse::String(); } }
32 } env;
33
34 int Main(const app::Options& options)
35 {
36 Bender bender;
37
38 return 0;
39 }
40
41 Bender::Bender()
42 {
43 cse::String path(env.get(_B("PATH_TRANSLATED")));
44 api::Pcre::RegEx script(_S<ios::String>() << _B("^") << env.get(_B("SCRIPT_NAME")));
45
46 if (!path.IsEmpty() && script(env.get(_B("REQUEST_URI"))))
47 {
48 try
49 {
50 _S<api::FileReader> file(path);
51
52 bend(path, env.get(_B("HTTP_USER_AGENT")));
53 }
54 catch (ext::Exception)
55 {
56 api::Cout << _B("Status: 404\r\n")
57 << _B("Content-Type: text/html; charset=ISO-8859-1\r\n\r\n")
58 << _B("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n")
59 << _B("<html><head>\n")
60 << _B("<title>404 Not Found</title>\n")
61 << _B("</head><body>\n")
62 << _B("<h1>Not Found</h1>\n")
63 << _B("<p>The requested URL ") << env.get(_B("PATH_INFO"))
64 << _B(" was not found on this server.</p>\n")
65 << _B("<hr />\n")
66 << env.get(_B("SERVER_SIGNATURE")) << _B("</body></html>\n");
67 }
68 }
69 else api::Cout << _B("Location: http://computers.douglasthrift.net/bender.xml\r\n\r\n");
70 }
71
72 void Bender::bend(const cse::String& path, const cse::String& agent)
73 {
74 api::Pcre::RegEx opera(_B("Opera[ /]\\d+\\.\\d+")), gecko(_B("rv:(\\d+)\\.(\\d+).*\\) Gecko"));
75
76 if (opera(agent))
77 bend(path);
78 else if (api::Pcre::RegEx::Match match = gecko(agent))
79 {
80 int major_(lexical_cast<int>(match[1])), minor_(lexical_cast<int>(match[2]));
81
82 if (major_ > 1 || (major_ == 1 && minor_ >= 5))
83 pass(path);
84 else
85 bend(path);
86 }
87 else
88 bend(path);
89 }
90
91 void Bender::bend(const cse::String& path)
92 {
93 _R<xml::Document> document(xml::Parse(_B("bender.xml")));
94 _R<xml::Node> node(*document/_B("bender"));
95 cse::String program(*node/_B("program"));
96 _L<cse::String> args;
97
98 _foreach (const xml::NodeSet, arg, *node/_B("argument"))
99 args.InsertLast(**arg);
100
101 args.InsertLast(path);
102
103 _S<api::Process> xslt(program, args);
104 _S<ios::String> output;
105
106 ios::ReadToWrite(*xslt.GetReader(), output);
107
108 if (!output.IsEmpty())
109 {
110 cse::String type(_B("text/xml"));
111 api::Pcre::RegEx content("http-equiv=\"Content-Type\" content=\"(.*)\"");
112
113 if (api::Pcre::RegEx::Match match = content(output))
114 type = match[1];
115
116 api::Cout << "Content-Type: " << type << "\r\n\r\n" << output;
117 }
118 else
119 pass(path);
120 }
121
122 void Bender::pass(const cse::String& path)
123 {
124 api::Cout << _B("Content-Type: text/xml\r\n\r\n");
125
126 _S<api::FileReader> file(path);
127
128 ios::ReadToWrite(file, api::Cout);
129 }

Properties

Name Value
svn:eol-style native
svn:keywords Id