1//
2// File2Page.cpp
3//
4// An application that creates a Page Compiler source file from an
5// ordinary file.
6//
7// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
8// and Contributors.
9//
10// SPDX-License-Identifier: BSL-1.0
11//
12
13
14#include "Poco/Util/Application.h"
15#include "Poco/Util/Option.h"
16#include "Poco/Util/OptionSet.h"
17#include "Poco/Util/HelpFormatter.h"
18#include "Poco/Util/AbstractConfiguration.h"
19#include "Poco/AutoPtr.h"
20#include "Poco/File.h"
21#include "Poco/Path.h"
22#include "Poco/FileStream.h"
23#include "Poco/NumberFormatter.h"
24#include "Poco/DateTime.h"
25#include <iostream>
26
27
28using Poco::Util::Application;
29using Poco::Util::Option;
30using Poco::Util::OptionSet;
31using Poco::Util::HelpFormatter;
32using Poco::Util::AbstractConfiguration;
33using Poco::Util::OptionCallback;
34using Poco::NumberFormatter;
35
36
37class File2PageApp: public Application
38{
39public:
40 File2PageApp(): _helpRequested(false)
41 {
42 }
43
44protected:
45 void initialize(Application& self)
46 {
47 loadConfiguration(); // load default configuration files, if present
48 Application::initialize(self);
49 // add your own initialization code here
50 }
51
52 void uninitialize()
53 {
54 // add your own uninitialization code here
55 Application::uninitialize();
56 }
57
58 void reinitialize(Application& self)
59 {
60 Application::reinitialize(self);
61 // add your own reinitialization code here
62 }
63
64 void defineOptions(OptionSet& options)
65 {
66 Application::defineOptions(options);
67
68 options.addOption(
69 Option("help", "h", "Display help information on command line arguments.")
70 .required(false)
71 .repeatable(false)
72 .callback(OptionCallback<File2PageApp>(this, &File2PageApp::handleHelp)));
73
74 options.addOption(
75 Option("contentType", "t", "Specify a content type.")
76 .required(false)
77 .repeatable(false)
78 .argument("MIME-Type")
79 .callback(OptionCallback<File2PageApp>(this, &File2PageApp::handleContentType)));
80
81 options.addOption(
82 Option("contentLanguage", "l", "Specify a content language.")
83 .required(false)
84 .repeatable(false)
85 .argument("language")
86 .callback(OptionCallback<File2PageApp>(this, &File2PageApp::handleContentLang)));
87
88 options.addOption(
89 Option("class", "c", "Specify the handler class name.")
90 .required(false)
91 .repeatable(false)
92 .argument("class-name")
93 .callback(OptionCallback<File2PageApp>(this, &File2PageApp::handleClassName)));
94
95 options.addOption(
96 Option("namespace", "n", "Specify the handler class namespace name.")
97 .required(false)
98 .repeatable(false)
99 .argument("namespace-name")
100 .callback(OptionCallback<File2PageApp>(this, &File2PageApp::handleNamespace)));
101
102 options.addOption(
103 Option("output", "o", "Specify the output file name.")
104 .required(false)
105 .repeatable(false)
106 .argument("path")
107 .callback(OptionCallback<File2PageApp>(this, &File2PageApp::handleOutput)));
108
109 options.addOption(
110 Option("path", "p", "Specify the server path of the file.")
111 .required(false)
112 .repeatable(false)
113 .argument("path")
114 .callback(OptionCallback<File2PageApp>(this, &File2PageApp::handlePath)));
115 }
116
117 void handleHelp(const std::string& name, const std::string& value)
118 {
119 _helpRequested = true;
120 displayHelp();
121 stopOptionsProcessing();
122 }
123
124 void handleContentType(const std::string& name, const std::string& value)
125 {
126 _contentType = value;
127 }
128
129 void handleContentLang(const std::string& name, const std::string& value)
130 {
131 _contentLang = value;
132 }
133
134 void handleClassName(const std::string& name, const std::string& value)
135 {
136 _clazz = value;
137 }
138
139 void handleNamespace(const std::string& name, const std::string& value)
140 {
141 _namespace = value;
142 }
143
144 void handleOutput(const std::string& name, const std::string& value)
145 {
146 _output = value;
147 }
148
149 void handlePath(const std::string& name, const std::string& value)
150 {
151 _path = value;
152 }
153
154 void displayHelp()
155 {
156 HelpFormatter helpFormatter(options());
157 helpFormatter.setCommand(commandName());
158 helpFormatter.setUsage("OPTIONS");
159 helpFormatter.setHeader("Create a PageCompiler source file from a binary file.");
160 helpFormatter.setIndent(8);
161 helpFormatter.format(std::cout);
162 }
163
164 void convert(const std::string& path)
165 {
166 Poco::Path p(path);
167 Poco::Path op(path);
168 if (_output.empty())
169 {
170 op.setExtension("cpsp");
171 }
172 else
173 {
174 op = _output;
175 }
176 if (_contentType.empty())
177 {
178 _contentType = extToContentType(p.getExtension());
179 }
180 if (_clazz.empty())
181 {
182 _clazz = p.getBaseName();
183 }
184 Poco::FileInputStream istr(path);
185 Poco::FileOutputStream ostr(op.toString());
186 ostr << "<%@ page\n"
187 << " contentType=\"" << _contentType << "\"\n";
188 if (!_contentLang.empty())
189 {
190 ostr << " contentLanguage=\"" << _contentLang << "\"\n";
191 }
192 ostr << " form=\"false\"\n"
193 << " namespace=\"" << _namespace << "\"\n"
194 << " class=\"" << _clazz << "\"\n";
195 if (!_path.empty())
196 {
197 ostr << " path=\"" << _path << "\"\n";
198 }
199 ostr << " precondition=\"checkModified(request)\"%><%@"
200 << " impl include=\"Poco/DateTime.h\"\n"
201 << " include=\"Poco/DateTimeParser.h\"\n"
202 << " include=\"Poco/DateTimeFormatter.h\"\n"
203 << " include=\"Poco/DateTimeFormat.h\"%><%!\n\n";
204 ostr << "// " << path << "\n";
205 ostr << "static const unsigned char data[] = {\n\t";
206 int ch = istr.get();
207 int pos = 0;
208 while (ch != -1)
209 {
210 ostr << "0x" << NumberFormatter::formatHex(ch, 2) << ", ";
211 if (pos++ == 16)
212 {
213 ostr << "\n\t";
214 pos = 0;
215 }
216 ch = istr.get();
217 }
218 Poco::File f(path);
219 Poco::DateTime lm = f.getLastModified();
220 ostr << "\n};\n\n\n";
221 ostr << "static bool checkModified(Poco::Net::HTTPServerRequest& request)\n"
222 << "{\n"
223 << "\tPoco::DateTime modified(" << lm.year() << ", " << lm.month() << ", " << lm.day() << ", " << lm.hour() << ", " << lm.minute() << ", " << lm.second() << ");\n"
224 << "\trequest.response().setChunkedTransferEncoding(false);\n"
225 << "\trequest.response().set(\"Last-Modified\", Poco::DateTimeFormatter::format(modified, Poco::DateTimeFormat::HTTP_FORMAT));\n"
226 << "\tif (request.has(\"If-Modified-Since\"))\n"
227 << "\t{\n"
228 << "\t\tPoco::DateTime modifiedSince;\n"
229 << "\t\tint tzd;\n"
230 << "\t\tPoco::DateTimeParser::parse(request.get(\"If-Modified-Since\"), modifiedSince, tzd);\n"
231 << "\t\tif (modified <= modifiedSince)\n"
232 << "\t\t{\n"
233 << "\t\t\trequest.response().setContentLength(0);\n"
234 << "\t\t\trequest.response().setStatusAndReason(Poco::Net::HTTPResponse::HTTP_NOT_MODIFIED);\n"
235 << "\t\t\trequest.response().send();\n"
236 << "\t\t\treturn false;\n"
237 << "\t\t}\n"
238 << "\t}\n"
239 << "\trequest.response().setContentLength(static_cast<int>(sizeof(data)));\n"
240 << "\treturn true;\n"
241 << "}\n"
242 << "%><%\n"
243 << "\tresponseStream.write(reinterpret_cast<const char*>(data), sizeof(data));\n"
244 << "%>";
245 }
246
247 std::string extToContentType(const std::string& ext)
248 {
249 if (ext == "jpg" || ext == "jpeg")
250 return "image/jpeg";
251 else if (ext == "png")
252 return "image/png";
253 else if (ext == "gif")
254 return "image/gif";
255 else if (ext == "ico")
256 return "image/x-icon";
257 else if (ext == "htm")
258 return "text/html";
259 else if (ext == "html")
260 return "text/html";
261 else if (ext == "css")
262 return "text/css";
263 else if (ext == "js")
264 return "application/javascript";
265 else if (ext == "xml")
266 return "text/xml";
267 else
268 return "application/binary";
269 }
270
271 int main(const std::vector<std::string>& args)
272 {
273 if (!_helpRequested)
274 {
275 for (std::vector<std::string>::const_iterator it = args.begin(); it != args.end(); ++it)
276 {
277 convert(*it);
278 }
279 }
280 return Application::EXIT_OK;
281 }
282
283private:
284 bool _helpRequested;
285 std::string _contentType;
286 std::string _contentLang;
287 std::string _clazz;
288 std::string _namespace;
289 std::string _output;
290 std::string _path;
291};
292
293
294POCO_APP_MAIN(File2PageApp)
295