ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/repos/Bender/Bender.cpp
Revision: 898
Committed: 2007-04-28T21:18:18-07:00 (18 years, 1 month ago) by douglas
File size: 3088 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)
32 {
33 try
34 {
35 return api::TheEnvironment.Get(name);
36 }
37 catch (ext::Exception)
38 {
39 return cse::String();
40 }
41 }
42 } env;
43
44 int Main(const app::Options& options)
45 {
46 Bender bender;
47
48 return 0;
49 }
50
51 Bender::Bender()
52 {
53 cse::String path(env.get(_B("PATH_TRANSLATED")));
54 api::Pcre::RegEx script(_S<ios::String>() << _B("^") << env.get(_B("SCRIPT_NAME")));
55
56 if (!path.IsEmpty() && script(env.get(_B("REQUEST_URI"))))
57 {
58 try
59 {
60 _S<api::FileReader> file(path);
61
62 bend(path, env.get(_B("HTTP_USER_AGENT")));
63 }
64 catch (ext::Exception)
65 {
66 api::Cout << _B("Status: 404\r\n")
67 << _B("Content-Type: text/html; charset=ISO-8859-1\r\n\r\n")
68 << _B("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n")
69 << _B("<html><head>\n")
70 << _B("<title>404 Not Found</title>\n")
71 << _B("</head><body>\n")
72 << _B("<h1>Not Found</h1>\n")
73 << _B("<p>The requested URL ") << env.get(_B("PATH_INFO"))
74 << _B(" was not found on this server.</p>\n")
75 << _B("<hr />\n")
76 << env.get(_B("SERVER_SIGNATURE")) << _B("</body></html>\n");
77 }
78 }
79 else
80 api::Cout << _B("Location: http://computers.douglasthrift.net/bender.xml\r\n\r\n");
81 }
82
83 void Bender::bend(const cse::String& path, const cse::String& agent)
84 {
85 api::Pcre::RegEx opera(_B("Opera[ /]\\d+\\.\\d+")), gecko(_B("rv:(\\d+)\\.(\\d+).*\\) Gecko"));
86
87 if (opera(agent))
88 bend(path);
89 else if (api::Pcre::RegEx::Match match = gecko(agent))
90 {
91 int major_(lexical_cast<int>(match[1])), minor_(lexical_cast<int>(match[2]));
92
93 if (major_ > 1 || (major_ == 1 && minor_ >= 5))
94 pass(path);
95 else
96 bend(path);
97 }
98 else
99 bend(path);
100 }
101
102 void Bender::bend(const cse::String& path)
103 {
104 _R<xml::Document> document(xml::Parse(_B("bender.xml")));
105 _R<xml::Node> node(*document/_B("bender"));
106 cse::String program(*node/_B("program"));
107 _L<cse::String> args;
108
109 _foreach (const xml::NodeSet, arg, *node/_B("argument"))
110 args.InsertLast(**arg);
111
112 args.InsertLast(path);
113
114 _S<api::Process> xslt(program, args);
115 _S<ios::String> output;
116
117 ios::ReadToWrite(*xslt.GetReader(), output);
118
119 if (!output.IsEmpty())
120 {
121 cse::String type(_B("text/xml"));
122 api::Pcre::RegEx content("http-equiv=\"Content-Type\" content=\"(.*)\"");
123
124 if (api::Pcre::RegEx::Match match = content(output))
125 type = match[1];
126
127 api::Cout << "Content-Type: " << type << "\r\n\r\n" << output;
128 }
129 else
130 pass(path);
131 }
132
133 void Bender::pass(const cse::String& path)
134 {
135 api::Cout << _B("Content-Type: text/xml\r\n\r\n");
136
137 _S<api::FileReader> file(path);
138
139 ios::ReadToWrite(file, api::Cout);
140 }

Properties

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