This file is indexed.

/usr/include/pion/net/HTTPWriter.hpp is in libpion-net-dev 4.0.7+dfsg-2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
// ------------------------------------------------------------------
// pion-net: a C++ framework for building lightweight HTTP interfaces
// ------------------------------------------------------------------
// Copyright (C) 2007-2008 Atomic Labs, Inc.  (http://www.atomiclabs.com)
//
// Distributed under the Boost Software License, Version 1.0.
// See http://www.boost.org/LICENSE_1_0.txt
//

#ifndef __PION_HTTPWRITER_HEADER__
#define __PION_HTTPWRITER_HEADER__

#include <vector>
#include <string>
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
#include <boost/function/function0.hpp>
#include <boost/function/function2.hpp>
#include <boost/asio.hpp>
#include <boost/noncopyable.hpp>
#include <pion/PionConfig.hpp>
#include <pion/PionLogger.hpp>
#include <pion/net/HTTPMessage.hpp>
#include <pion/net/TCPConnection.hpp>


namespace pion {	// begin namespace pion
namespace net {		// begin namespace net (Pion Network Library)

///
/// HTTPWriter: used to asynchronously send HTTP messages
/// 
class PION_NET_API HTTPWriter :
	private boost::noncopyable
{
protected:
	
	/// function called after the HTTP message has been sent
	typedef boost::function1<void,const boost::system::error_code&>	FinishedHandler;

	/// data type for a function that handles write operations
	typedef boost::function2<void,const boost::system::error_code&,std::size_t>	WriteHandler;
	
	
	/**
	 * protected constructor: only derived classes may create objects
	 * 
	 * @param tcp_conn TCP connection used to send the message
	 * @param handler function called after the request has been sent
	 */
	HTTPWriter(TCPConnectionPtr& tcp_conn, FinishedHandler handler)
		: m_logger(PION_GET_LOGGER("pion.net.HTTPWriter")),
		m_tcp_conn(tcp_conn), m_content_length(0), m_stream_is_empty(true), 
		m_client_supports_chunks(true), m_sending_chunks(false),
		m_sent_headers(false), m_finished(handler)
	{}
	
	/**
	 * called after the message is sent
	 * 
	 * @param write_error error status from the last write operation
	 * @param bytes_written number of bytes sent by the last write operation
	 */
	virtual void handleWrite(const boost::system::error_code& write_error,
					 std::size_t bytes_written) = 0;

	
	/**
	 * initializes a vector of write buffers with the HTTP message information
	 *
	 * @param write_buffers vector of write buffers to initialize
	 */
	virtual void prepareBuffersForSend(HTTPMessage::WriteBuffers& write_buffers) = 0;
									  
	/// returns a function bound to HTTPWriter::handleWrite()
	virtual WriteHandler bindToWriteHandler(void) = 0;
	
	/// called after we have finished sending the HTTP message
	inline void finishedWriting(const boost::system::error_code& ec) {
		if (m_finished) m_finished(ec);
	}
	
	
public:

	/// default destructor
	virtual ~HTTPWriter() {}

	/// clears out all of the memory buffers used to cache payload content data
	inline void clear(void) {
		m_content_buffers.clear();
		m_binary_cache.clear();
		m_text_cache.clear();
		m_content_stream.str("");
		m_stream_is_empty = true;
		m_content_length = 0;
	}

	/**
	 * write text (non-binary) payload content
	 *
	 * @param data the data to append to the payload content
	 */
	template <typename T>
	inline void write(const T& data) {
		m_content_stream << data;
		if (m_stream_is_empty) m_stream_is_empty = false;
	}

	/**
	 * write binary payload content
	 *
	 * @param data points to the binary data to append to the payload content
	 * @param length the length, in bytes, of the binary data
	 */
	inline void write(const void *data, size_t length) {
		if (length != 0) {
			flushContentStream();
			m_content_buffers.push_back(m_binary_cache.add(data, length));
			m_content_length += length;
		}
	}
	
	/**
	 * write text (non-binary) payload content; the data written is not
	 * copied, and therefore must persist until the message has finished
	 * sending
	 *
	 * @param data the data to append to the payload content
	 */
	inline void writeNoCopy(const std::string& data) {
		if (! data.empty()) {
			flushContentStream();
			m_content_buffers.push_back(boost::asio::buffer(data));
			m_content_length += data.size();
		}
	}
	
	/**
	 * write binary payload content;  the data written is not copied, and
	 * therefore must persist until the message has finished sending
	 *
	 * @param data points to the binary data to append to the payload content
	 * @param length the length, in bytes, of the binary data
	 */
	inline void writeNoCopy(void *data, size_t length) {
		if (length > 0) {
			flushContentStream();
			m_content_buffers.push_back(boost::asio::buffer(data, length));
			m_content_length += length;
		}
	}

	
	/**
	 * Sends all data buffered as a single HTTP message (without chunking).
	 * Following a call to this function, it is not thread safe to use your
	 * reference to the HTTPWriter object.
	 */
	inline void send(void) {
		sendMoreData(false, bindToWriteHandler());
	}
	
	/**
	 * Sends all data buffered as a single HTTP message (without chunking).
	 * Following a call to this function, it is not thread safe to use your
	 * reference to the HTTPWriter object until the send_handler has been called.
	 *
	 * @param send_handler function that is called after the message has been
	 *                     sent to the client.  Your callback function must end
	 *                     the connection by calling TCPConnection::finish().
	 */
	template <typename SendHandler>
	inline void send(SendHandler send_handler) {
		sendMoreData(false, send_handler);
	}
	
	/**
	 * Sends all data buffered as a single HTTP chunk.  Following a call to this
	 * function, it is not thread safe to use your reference to the HTTPWriter
	 * object until the send_handler has been called.
	 * 
	 * @param send_handler function that is called after the chunk has been sent
	 *                     to the client.  Your callback function must end by
	 *                     calling one of sendChunk() or sendFinalChunk().  Also,
	 *                     be sure to clear() the writer before writing data to it.
	 */
	template <typename SendHandler>
	inline void sendChunk(SendHandler send_handler) {
		m_sending_chunks = true;
		if (!supportsChunkedMessages()) {
			// sending data in chunks, but the client does not support chunking;
			// make sure that the connection will be closed when we are all done
			m_tcp_conn->setLifecycle(TCPConnection::LIFECYCLE_CLOSE);
		}
		// send more data
		sendMoreData(false, send_handler);
	}

	/**
	 * Sends all data buffered (if any) and also sends the final HTTP chunk.
	 * This function (either overloaded version) must be called following any 
	 * calls to sendChunk().
	 * Following a call to this function, it is not thread safe to use your
	 * reference to the HTTPWriter object until the send_handler has been called.
	 *
	 * @param send_handler function that is called after the message has been
	 *                     sent to the client.  Your callback function must end
	 *                     the connection by calling TCPConnection::finish().
	 */ 
	template <typename SendHandler>
	inline void sendFinalChunk(SendHandler send_handler) {
		m_sending_chunks = true;
		sendMoreData(true, send_handler);
	}
	
	/**
	 * Sends all data buffered (if any) and also sends the final HTTP chunk.
	 * This function (either overloaded version) must be called following any 
	 * calls to sendChunk().
	 * Following a call to this function, it is not thread safe to use your
	 * reference to the HTTPWriter object.
	 */ 
	inline void sendFinalChunk(void) {
		m_sending_chunks = true;
		sendMoreData(true, bindToWriteHandler());
	}
	
	
	/// returns a shared pointer to the TCP connection
	inline TCPConnectionPtr& getTCPConnection(void) { return m_tcp_conn; }

	/// returns the length of the payload content (in bytes)
	inline size_t getContentLength(void) const { return m_content_length; }

	/// sets whether or not the client supports chunked messages
	inline void supportsChunkedMessages(bool b) { m_client_supports_chunks = b; }
	
	/// returns true if the client supports chunked messages
	inline bool supportsChunkedMessages() const { return m_client_supports_chunks; }

	/// returns true if we are sending a chunked message to the client
	inline bool sendingChunkedMessage() const { return m_sending_chunks; }
	
	/// sets the logger to be used
	inline void setLogger(PionLogger log_ptr) { m_logger = log_ptr; }
	
	/// returns the logger currently in use
	inline PionLogger getLogger(void) { return m_logger; }

	
private:

	/**
	 * sends all of the buffered data to the client
	 *
	 * @param send_final_chunk true if the final 0-byte chunk should be included
	 * @param send_handler function called after the data has been sent
	 */
	template <typename SendHandler>
	inline void sendMoreData(const bool send_final_chunk, SendHandler send_handler)
	{
		// make sure that we did not lose the TCP connection
		if (! m_tcp_conn->is_open())
			finishedWriting(boost::asio::error::connection_reset);
		// make sure that the content-length is up-to-date
		flushContentStream();
		// prepare the write buffers to be sent
		HTTPMessage::WriteBuffers write_buffers;
		prepareWriteBuffers(write_buffers, send_final_chunk);
		// send data in the write buffers
		m_tcp_conn->async_write(write_buffers, send_handler);
	}
	
	/**
	 * prepares write_buffers for next send operation
	 *
	 * @param write_buffers buffers to which data will be appended
	 * @param send_final_chunk true if the final 0-byte chunk should be included
	 */
	void prepareWriteBuffers(HTTPMessage::WriteBuffers &write_buffers,
							 const bool send_final_chunk);
	
	/// flushes any text data in the content stream after caching it in the TextCache
	inline void flushContentStream(void) {
		if (! m_stream_is_empty) {
			std::string string_to_add(m_content_stream.str());
			if (! string_to_add.empty()) {
				m_content_stream.str("");
				m_content_length += string_to_add.size();
				m_text_cache.push_back(string_to_add);
				m_content_buffers.push_back(boost::asio::buffer(m_text_cache.back()));
			}
			m_stream_is_empty = true;
		}
	}
	
	
	/// used to cache binary data included within the payload content
	class BinaryCache : public std::vector<std::pair<const char *, size_t> > {
	public:
		~BinaryCache() {
			for (iterator i=begin(); i!=end(); ++i) {
				delete[] i->first;
			}
		}
		inline boost::asio::const_buffer add(const void *ptr, const size_t size) {
			char *data_ptr = new char[size];
			memcpy(data_ptr, ptr, size);
			push_back( std::make_pair(data_ptr, size) );
			return boost::asio::buffer(data_ptr, size);
		}
	};
	
	/// used to cache text (non-binary) data included within the payload content
	typedef std::list<std::string>				TextCache;

	
	/// primary logging interface used by this class
	PionLogger								m_logger;

	/// The HTTP connection that we are writing the message to
	TCPConnectionPtr						m_tcp_conn;
	
	/// I/O write buffers that wrap the payload content to be written
	HTTPMessage::WriteBuffers				m_content_buffers;
	
	/// caches binary data included within the payload content
	BinaryCache								m_binary_cache;

	/// caches text (non-binary) data included within the payload content
	TextCache								m_text_cache;
	
	/// incrementally creates strings of text data for the TextCache
	std::ostringstream						m_content_stream;
	
	/// The length (in bytes) of the response content to be sent (Content-Length)
	size_t									m_content_length;

	/// true if the content_stream is empty (avoids unnecessary string copies)
	bool									m_stream_is_empty;
	
	/// true if the HTTP client supports chunked transfer encodings
	bool									m_client_supports_chunks;
	
	/// true if data is being sent to the client using multiple chunks
	bool									m_sending_chunks;
	
	/// true if the HTTP message headers have already been sent
	bool									m_sent_headers;

	/// function called after the HTTP message has been sent
	FinishedHandler							m_finished;
};


/// data type for a HTTPWriter pointer
typedef boost::shared_ptr<HTTPWriter>	HTTPWriterPtr;


/// override operator<< for convenience
template <typename T>
HTTPWriterPtr& operator<<(HTTPWriterPtr& writer, const T& data) {
	writer->write(data);
	return writer;
}


}	// end namespace net
}	// end namespace pion

#endif