~ubuntu-branches/ubuntu/edgy/lurker/edgy

« back to all changes in this revision

Viewing changes to render/Cache.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jonas Meurer
  • Date: 2004-09-26 16:27:51 UTC
  • Revision ID: james.westby@ubuntu.com-20040926162751-z1ohcjltv7ojtg6z
Tags: upstream-1.2
ImportĀ upstreamĀ versionĀ 1.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*  $Id: Cache.cpp,v 1.12 2004/08/20 02:42:45 terpstra Exp $
 
2
 *  
 
3
 *  Cache.h - Helper which transforms xml -> html and caches files
 
4
 *  
 
5
 *  Copyright (C) 2002 - Wesley W. Terpstra
 
6
 *  
 
7
 *  License: GPL
 
8
 *  
 
9
 *  Authors: 'Wesley W. Terpstra' <wesley@terpstra.ca>
 
10
 *  
 
11
 *    This program is free software; you can redistribute it and/or modify
 
12
 *    it under the terms of the GNU General Public License as published by
 
13
 *    the Free Software Foundation; version 2.
 
14
 *    
 
15
 *    This program is distributed in the hope that it will be useful,
 
16
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
18
 *    GNU General Public License for more details.
 
19
 *    
 
20
 *    You should have received a copy of the GNU General Public License
 
21
 *    along with this program; if not, write to the Free Software
 
22
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
23
 */
 
24
 
 
25
#define _XOPEN_SOURCE 500
 
26
#define _FILE_OFFSET_BITS 64
 
27
 
 
28
#include "Cache.h"
 
29
#include "commands.h"
 
30
 
 
31
#include <cerrno>
 
32
#include <cstring>
 
33
#include <cassert>
 
34
 
 
35
#include <unistd.h>
 
36
 
 
37
class streambug : public std::streambuf
 
38
{
 
39
 public:
 
40
        streambug();
 
41
        
 
42
        void set_target(FILE* t) { target = t; }
 
43
        
 
44
 protected:
 
45
        int overflow(int);
 
46
        int sync();
 
47
 
 
48
 private:
 
49
        FILE*   target;
 
50
        char    buf[128]; //8192];
 
51
};
 
52
 
 
53
streambug::streambug()
 
54
 : target(0)
 
55
{
 
56
        setp(&buf[0], &buf[sizeof(buf)-1]);
 
57
        setg(0,0,0); // output only
 
58
}
 
59
 
 
60
int streambug::overflow(int c)
 
61
{
 
62
        assert (target);
 
63
        
 
64
        // Make sure there is a put area
 
65
        if (!pptr()) setp(&buf[0], &buf[sizeof(buf)-1]);
 
66
        
 
67
        // Determine how many characters have been
 
68
        // inserted but not consumed. 
 
69
        std::streamsize w = pptr() - pbase();
 
70
        
 
71
        // If c is not EOF it is a character that must
 
72
        // also be consumed. 
 
73
        if (c != EOF)
 
74
        {
 
75
                // We always leave space
 
76
                *pptr() = c;
 
77
                ++w;
 
78
        }
 
79
        
 
80
        // consume characters.
 
81
        if ((std::streamsize)fwrite(pbase(), 1, w, target) == w)
 
82
        {       // Set up put area. Be sure that there
 
83
                // is space at end for one extra character. 
 
84
                
 
85
                setp(&buf[0], &buf[sizeof(buf)-1]);
 
86
                
 
87
                if (c == EOF) return 0;
 
88
                return c;
 
89
        }
 
90
        else
 
91
        {       // Indicate error.
 
92
                setp(0, 0);
 
93
                return EOF;
 
94
        }
 
95
}
 
96
 
 
97
int streambug::sync()
 
98
{
 
99
        if (pptr() && pptr() > pbase())
 
100
        {       // Flush waiting output
 
101
                return overflow(EOF);
 
102
        }
 
103
        
 
104
        return 0;
 
105
}
 
106
 
 
107
Cache::Cache(const Config& cfg, const string& command, const string& parameter, const string& ext)
 
108
 : bug(new streambug), o(bug)
 
109
{
 
110
        if (chdir(command.c_str()) != 0)
 
111
        {
 
112
                cout << "Status: 200 OK\r\n";
 
113
                cout << "Content-Type: text/html\r\n\r\n";
 
114
                cout << error(_("Entering command dir"), command + ":" + strerror(errno),
 
115
                        _("Perhaps the directory does not exist to which "
 
116
                          "the cache file is being written."));
 
117
                exit(1);
 
118
        }
 
119
        
 
120
        if (cfg.web_cache)
 
121
        {
 
122
                cache = fopen(parameter.c_str(), "w+");
 
123
                if (!cache)
 
124
                {
 
125
                        cout << "Status: 200 OK\r\n";
 
126
                        cout << "Content-Type: text/html\r\n\r\n";
 
127
                        cout << error(_("Creating cache file"), parameter + ":" + strerror(errno),
 
128
                                _("Perhaps the user which runs lurker.cgi does not have write "
 
129
                                  "permissions to this directory."));
 
130
                        exit(1);
 
131
                }
 
132
        }
 
133
        else
 
134
        {
 
135
                cache = stdout;
 
136
        }
 
137
        
 
138
        cout << "Status: 200 OK\r\n";
 
139
        if (ext == "html")
 
140
        {
 
141
                char buf[10] = "";
 
142
                if (cache != stdout) sprintf(buf, " >&%d", fileno(cache));
 
143
                string command = cfg.xslt + buf;
 
144
                
 
145
                output = popen(command.c_str(), "w");
 
146
                if (!output)
 
147
                {
 
148
                        cout << "Content-Type: text/html\r\n\r\n";
 
149
                        cout << error(_("Opening xslt pipeline"), strerror(errno),
 
150
                                _("The specified xslt pipeline in your config "
 
151
                                  "file, entry xslt, could not be opened. "
 
152
                                  "Please ensure that the command correctly "
 
153
                                  "streams xml into html for you."));
 
154
                        exit(1);
 
155
                }
 
156
                
 
157
                cout << "Content-Type: text/html; charset=UTF-8\r\n\r\n";
 
158
        }
 
159
        else if (ext == "txt")
 
160
        {
 
161
                cout << "Content-Type: text/plain\r\n\r\n";
 
162
                output = cache;
 
163
        }
 
164
        else if (ext == "rfc822")
 
165
        {
 
166
                cout << "Content-Type: message/rfc822\r\n\r\n";
 
167
                output = cache;
 
168
        }
 
169
        else if (ext == "xml")
 
170
        {
 
171
                cout << "Content-Type: text/xml; charset=UTF-8\r\n\r\n";
 
172
                output = cache;
 
173
        }
 
174
        else
 
175
        {
 
176
                cout << "Content-Type: text/html\r\n\r\n";
 
177
                cout << error(_("Unknown file type"), ext,
 
178
                        _("The requested extension is not supported by lurker. "
 
179
                          "Please reformulate your request."));
 
180
                exit(1);
 
181
        }
 
182
        
 
183
        cout.flush(); // in case of stdout writing next (ick)
 
184
        bug->set_target(output);
 
185
}
 
186
 
 
187
Cache::~Cache()
 
188
{
 
189
        o.flush();
 
190
        
 
191
        if (output != cache)
 
192
                pclose(output);
 
193
        
 
194
        if (cache != stdout)
 
195
        {
 
196
                // reset to the start of the cache file
 
197
                fflush(cache);
 
198
                fseek(cache, 0, SEEK_SET);
 
199
                fflush(cache);
 
200
                
 
201
                // Begin streaming to cout
 
202
                char buf[4096];
 
203
                size_t got;
 
204
                
 
205
                while ((got = fread(buf, 1, sizeof(buf), cache)) != 0)
 
206
                        cout.write(buf, got);
 
207
        }
 
208
        
 
209
        // All done!
 
210
}