ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/repos/Bender/Bender.cpp
Revision: 909
Committed: 2007-04-29T20:05:49-07:00 (18 years, 1 month ago) by douglas
File size: 3089 byte(s)
Log Message:
Oops!

File Contents

# User Rev Content
1 Douglas Thrift 109 // Bender
2     //
3     // Douglas Thrift
4     //
5     // $Id$
6    
7 douglas 627 #include <cxx/standard.hh>
8 Douglas Thrift 109
9 douglas 627 #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 Douglas Thrift 113
19 douglas 350 class Bender
20     {
21     private:
22 douglas 627 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 douglas 350 public:
26     Bender();
27     };
28    
29 douglas 339 struct Environment
30 Douglas Thrift 109 {
31 douglas 898 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 Douglas Thrift 268 } env;
43 Douglas Thrift 119
44 Douglas Thrift 268 int Main(const app::Options& options)
45     {
46     Bender bender;
47    
48 Douglas Thrift 109 return 0;
49     }
50    
51     Bender::Bender()
52     {
53 douglas 627 cse::String path(env.get(_B("PATH_TRANSLATED")));
54     api::Pcre::RegEx script(_S<ios::String>() << _B("^") << env.get(_B("SCRIPT_NAME")));
55 Douglas Thrift 111
56 douglas 909 if (!path.IsEmpty() && !script(env.get(_B("REQUEST_URI"))))
57 Douglas Thrift 111 {
58 Douglas Thrift 266 try
59 Douglas Thrift 119 {
60 douglas 627 _S<api::FileReader> file(path);
61 Douglas Thrift 119
62 douglas 627 bend(path, env.get(_B("HTTP_USER_AGENT")));
63 Douglas Thrift 119 }
64 douglas 376 catch (ext::Exception)
65 Douglas Thrift 121 {
66 douglas 627 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 Douglas Thrift 121 }
78 Douglas Thrift 111 }
79 douglas 898 else
80     api::Cout << _B("Location: http://computers.douglasthrift.net/bender.xml\r\n\r\n");
81 Douglas Thrift 109 }
82 Douglas Thrift 114
83 douglas 627 void Bender::bend(const cse::String& path, const cse::String& agent)
84 Douglas Thrift 114 {
85 douglas 627 api::Pcre::RegEx opera(_B("Opera[ /]\\d+\\.\\d+")), gecko(_B("rv:(\\d+)\\.(\\d+).*\\) Gecko"));
86 Douglas Thrift 114
87 douglas 627 if (opera(agent))
88     bend(path);
89     else if (api::Pcre::RegEx::Match match = gecko(agent))
90 Douglas Thrift 114 {
91 douglas 627 int major_(lexical_cast<int>(match[1])), minor_(lexical_cast<int>(match[2]));
92 Douglas Thrift 117
93 douglas 627 if (major_ > 1 || (major_ == 1 && minor_ >= 5))
94     pass(path);
95     else
96     bend(path);
97 Douglas Thrift 114 }
98 douglas 627 else
99     bend(path);
100 Douglas Thrift 114 }
101    
102 douglas 627 void Bender::bend(const cse::String& path)
103 Douglas Thrift 114 {
104 douglas 627 _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 Douglas Thrift 272
109 douglas 627 _foreach (const xml::NodeSet, arg, *node/_B("argument"))
110     args.InsertLast(**arg);
111 douglas 397
112 Douglas Thrift 272 args.InsertLast(path);
113    
114 douglas 397 _S<api::Process> xslt(program, args);
115     _S<ios::String> output;
116 Douglas Thrift 116
117 Douglas Thrift 266 ios::ReadToWrite(*xslt.GetReader(), output);
118    
119     if (!output.IsEmpty())
120 Douglas Thrift 116 {
121 douglas 627 cse::String type(_B("text/xml"));
122     api::Pcre::RegEx content("http-equiv=\"Content-Type\" content=\"(.*)\"");
123 Douglas Thrift 116
124 douglas 627 if (api::Pcre::RegEx::Match match = content(output))
125     type = match[1];
126 Douglas Thrift 119
127 Douglas Thrift 266 api::Cout << "Content-Type: " << type << "\r\n\r\n" << output;
128 Douglas Thrift 116 }
129 douglas 627 else
130     pass(path);
131 Douglas Thrift 114 }
132 Douglas Thrift 116
133 douglas 627 void Bender::pass(const cse::String& path)
134 Douglas Thrift 116 {
135 douglas 627 api::Cout << _B("Content-Type: text/xml\r\n\r\n");
136 Douglas Thrift 116
137 douglas 627 _S<api::FileReader> file(path);
138 Douglas Thrift 116
139 Douglas Thrift 266 ios::ReadToWrite(file, api::Cout);
140 Douglas Thrift 116 }

Properties

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