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

# 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 627 cse::String get(const cse::String& name) { try { return api::TheEnvironment.Get(name); } catch (ext::Exception) { return cse::String(); } }
32 Douglas Thrift 268 } env;
33 Douglas Thrift 119
34 Douglas Thrift 268 int Main(const app::Options& options)
35     {
36     Bender bender;
37    
38 Douglas Thrift 109 return 0;
39     }
40    
41     Bender::Bender()
42     {
43 douglas 627 cse::String path(env.get(_B("PATH_TRANSLATED")));
44     api::Pcre::RegEx script(_S<ios::String>() << _B("^") << env.get(_B("SCRIPT_NAME")));
45 Douglas Thrift 111
46 douglas 627 if (!path.IsEmpty() && script(env.get(_B("REQUEST_URI"))))
47 Douglas Thrift 111 {
48 Douglas Thrift 266 try
49 Douglas Thrift 119 {
50 douglas 627 _S<api::FileReader> file(path);
51 Douglas Thrift 119
52 douglas 627 bend(path, env.get(_B("HTTP_USER_AGENT")));
53 Douglas Thrift 119 }
54 douglas 376 catch (ext::Exception)
55 Douglas Thrift 121 {
56 douglas 627 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 Douglas Thrift 121 }
68 Douglas Thrift 111 }
69 douglas 627 else api::Cout << _B("Location: http://computers.douglasthrift.net/bender.xml\r\n\r\n");
70 Douglas Thrift 109 }
71 Douglas Thrift 114
72 douglas 627 void Bender::bend(const cse::String& path, const cse::String& agent)
73 Douglas Thrift 114 {
74 douglas 627 api::Pcre::RegEx opera(_B("Opera[ /]\\d+\\.\\d+")), gecko(_B("rv:(\\d+)\\.(\\d+).*\\) Gecko"));
75 Douglas Thrift 114
76 douglas 627 if (opera(agent))
77     bend(path);
78     else if (api::Pcre::RegEx::Match match = gecko(agent))
79 Douglas Thrift 114 {
80 douglas 627 int major_(lexical_cast<int>(match[1])), minor_(lexical_cast<int>(match[2]));
81 Douglas Thrift 117
82 douglas 627 if (major_ > 1 || (major_ == 1 && minor_ >= 5))
83     pass(path);
84     else
85     bend(path);
86 Douglas Thrift 114 }
87 douglas 627 else
88     bend(path);
89 Douglas Thrift 114 }
90    
91 douglas 627 void Bender::bend(const cse::String& path)
92 Douglas Thrift 114 {
93 douglas 627 _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 Douglas Thrift 272
98 douglas 627 _foreach (const xml::NodeSet, arg, *node/_B("argument"))
99     args.InsertLast(**arg);
100 douglas 397
101 Douglas Thrift 272 args.InsertLast(path);
102    
103 douglas 397 _S<api::Process> xslt(program, args);
104     _S<ios::String> output;
105 Douglas Thrift 116
106 Douglas Thrift 266 ios::ReadToWrite(*xslt.GetReader(), output);
107    
108     if (!output.IsEmpty())
109 Douglas Thrift 116 {
110 douglas 627 cse::String type(_B("text/xml"));
111     api::Pcre::RegEx content("http-equiv=\"Content-Type\" content=\"(.*)\"");
112 Douglas Thrift 116
113 douglas 627 if (api::Pcre::RegEx::Match match = content(output))
114     type = match[1];
115 Douglas Thrift 119
116 Douglas Thrift 266 api::Cout << "Content-Type: " << type << "\r\n\r\n" << output;
117 Douglas Thrift 116 }
118 douglas 627 else
119     pass(path);
120 Douglas Thrift 114 }
121 Douglas Thrift 116
122 douglas 627 void Bender::pass(const cse::String& path)
123 Douglas Thrift 116 {
124 douglas 627 api::Cout << _B("Content-Type: text/xml\r\n\r\n");
125 Douglas Thrift 116
126 douglas 627 _S<api::FileReader> file(path);
127 Douglas Thrift 116
128 Douglas Thrift 266 ios::ReadToWrite(file, api::Cout);
129 Douglas Thrift 116 }

Properties

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