Also filter single quotes and / in html_entities() to prevent XSS attack in normal...
[libi2ncommon] / src / pipestream.hxx
CommitLineData
e93545dd
GE
1/***************************************************************************
2 inpipestream.hxx - C++ streambuffer wrapper
3 -------------------
4 begin : Thu Dec 27 2001
5 copyright : (C) 2001 by Intra2net AG
6 email : intranator@intra2net.com
7 ***************************************************************************/
8
9#ifndef _PIPESTREAM
10#define _PIPESTREAM
11
be3dbe32
TJ
12#include <stdio.h>
13
e93545dd
GE
14#include <string>
15#include <streambuf>
be3dbe32
TJ
16#include <istream>
17#include <ostream>
e93545dd
GE
18#include <cstdio>
19
20#include "exception.hxx"
21
22// ATTENTION: A lot of mysterious STL bugs occured
23// with a "real" buffer (buffer larger than 1 byte and up to 100 bytes)
24// -> Keep it slow and working!
25
26class inpipebuf : public std::streambuf
27{
20a79471
TJ
28protected:
29 char buffer;
30 FILE *pipe;
31
32 // "callback" variables for destructor to store exit status
33 bool *status_set;
34 int *exit_status;
35
36public:
37 inpipebuf(const std::string& command)
38 {
39 status_set = NULL;
40 exit_status = NULL;
41
42 pipe = popen (command.c_str(), "r");
43 if (pipe == NULL)
44 throw EXCEPTION (pipestream_error, "can't open program or permission denied");
45
46 // force underflow
47 setg (&buffer, &buffer, &buffer);
48 }
49
50 ~inpipebuf()
51 {
52 if (pipe != NULL) {
53 int pclose_exit = pclose (pipe);
54
55 if (exit_status && pclose_exit != -1) {
56 *status_set = true;
57 *exit_status = pclose_exit;
58 }
59
60 pipe = NULL;
61 }
62 }
63
64 void store_exit_status(bool *_status_set, int *_exit_status)
65 { status_set = _status_set; exit_status = _exit_status; }
66
67protected:
68 virtual int_type underflow()
69 {
70 if (gptr() < egptr())
71 return traits_type::to_int_type(*gptr());
72
73 buffer = fgetc (pipe);
74 if (feof (pipe))
75 {
76 // ERROR or EOF
77 return EOF;
78 }
79
80 setg (&buffer, &buffer, &buffer+sizeof(char));
81
82 return traits_type::to_int_type(*gptr());
83 }
84};
e93545dd
GE
85
86class inpipestream : public std::istream
87{
20a79471
TJ
88protected:
89 inpipebuf buf;
90
91public:
92 inpipestream(const std::string& command)
93 : buf(command), std::istream(&buf)
94 {}
95
96 void store_exit_status(bool *_status_set, int *_exit_status)
97 { buf.store_exit_status(_status_set, _exit_status); }
e93545dd
GE
98};
99
100class outpipebuf : public std::streambuf
101{
20a79471
TJ
102protected:
103 FILE *pipe;
104
105 // "callback" variables for destructor to store exit status
106 bool *status_set;
107 int *exit_status;
108
109public:
110 outpipebuf(const std::string& command)
111 {
112 status_set = NULL;
113 exit_status = NULL;
114
115 pipe = popen (command.c_str(), "w");
116 if (pipe == NULL)
117 throw EXCEPTION (pipestream_error, "can't open program or permission denied");
118 }
119
120 ~outpipebuf()
121 {
122 if (pipe != NULL) {
123 int pclose_exit = pclose (pipe);
124
125 if (exit_status && pclose_exit != -1) {
126 *status_set = true;
127 *exit_status = pclose_exit;
128 }
129
130 pipe = NULL;
131 }
132 }
133
134 void store_exit_status(bool *_status_set, int *_exit_status)
135 { status_set = _status_set; exit_status = _exit_status; }
136
137protected:
138 virtual int_type overflow(int_type c)
139 {
140 if (c != EOF)
141 {
142 if (fputc(c,pipe)==EOF)
143 return EOF;
144 }
145 return c;
146 }
147
148 virtual std::streamsize xsputn(const char* s, std::streamsize num)
149 {
150 return fwrite(s,num,1,pipe);
151 }
e93545dd
GE
152};
153
154class outpipestream : public std::ostream
155{
20a79471
TJ
156protected:
157 outpipebuf buf;
158public:
159 outpipestream(const std::string& command)
160 : buf(command), std::ostream(&buf)
161 {}
162
163 void store_exit_status(bool *_status_set, int *_exit_status)
164 { buf.store_exit_status(_status_set, _exit_status); }
e93545dd
GE
165};
166
167#endif