1 /** 2 * Filter 3 * 4 * Copyright: 5 * (C) 1999-2007 Jack Lloyd 6 * (C) 2014-2015 Etienne Cimon 7 * (C) 2013 Joel Low 8 * 9 * License: 10 * Botan is released under the Simplified BSD License (see LICENSE.md) 11 */ 12 module botan.filters.filter; 13 14 import memutils.vector; 15 import botan.utils.types; 16 import botan.filters.secqueue; 17 import botan.utils.exceptn; 18 19 interface Filterable { 20 public: 21 /** 22 * Returns: descriptive name for this filter 23 */ 24 @property string name() const; 25 26 /** 27 * Write a portion of a message to this filter. 28 * 29 * Params: 30 * input = the input as a ubyte array 31 * length = the length of the ubyte array input 32 */ 33 void write(const(ubyte)* input, size_t length); 34 35 /** 36 * Start a new message. Must be closed by endMsg() before another 37 * message can be started. 38 */ 39 void startMsg(); 40 41 /** 42 * Notify that the current message is finished; flush buffers and 43 * do end-of-message processing (if any). 44 */ 45 void endMsg(); 46 47 /** 48 * Check whether this filter is an attachable filter. 49 * Returns: true if this filter is attachable, false otherwise 50 */ 51 bool attachable(); 52 53 /** 54 * Params: 55 * filters = the filters to set 56 * count = number of items in filters 57 */ 58 void setNext(Filter* filters, size_t size); 59 60 } 61 62 /** 63 * This class represents general abstract filter objects. 64 */ 65 abstract class Filter : Filterable 66 { 67 public: 68 /** 69 * Write a portion of a message to this filter. 70 * 71 * Params: 72 * input = the input as a ubyte array 73 */ 74 final void write(const(ubyte)[] input) { write(input.ptr, input.length); } 75 76 abstract void write(const(ubyte)* input, size_t length); 77 78 /** 79 * Params: 80 * input = some input for the filter 81 * length = the length of in 82 */ 83 void send(const(ubyte)* input, size_t length) 84 { 85 if (!length) 86 return; 87 88 bool nothing_attached = true; 89 foreach (size_t j; 0 .. totalPorts()) 90 if (m_next[j]) 91 { 92 if (m_write_queue.length) 93 m_next[j].write(m_write_queue.ptr, m_write_queue.length); 94 m_next[j].write(input, length); 95 nothing_attached = false; 96 } 97 98 if (nothing_attached) 99 m_write_queue ~= input[0 .. length]; 100 else 101 m_write_queue.clear(); 102 } 103 104 105 /** 106 * Params: 107 * input = some input for the filter 108 */ 109 final void send(ubyte input) { send(&input, 1); } 110 111 /** 112 * Params: 113 * input = some input for the filter 114 */ 115 final void send(ALLOC)(auto const ref Vector!(ubyte, ALLOC) input) { send(input.ptr, input.length); } 116 117 /** 118 * Params: 119 * input = some input for the filter 120 */ 121 final void send(ALLOC)(auto const ref RefCounted!(Vector!(ubyte, ALLOC), ALLOC) input) { send(input.ptr, input.length); } 122 123 /** 124 * Params: 125 * input = some input for the filter 126 * length = the number of bytes of in to send 127 */ 128 final void send(ALLOC)(auto const ref Vector!(ubyte, ALLOC) input, size_t length) 129 { 130 send(input.ptr, length); 131 } 132 133 /** 134 * Params: 135 * input = some input for the filter 136 * length = the number of bytes of in to send 137 */ 138 final void send(ALLOC)(auto const ref RefCounted!(Vector!(ubyte, ALLOC), ALLOC) input, size_t length) 139 { 140 send(input.ptr, length); 141 } 142 143 /* 144 * Filter Constructor 145 */ 146 this() 147 { 148 m_next.resize(1); 149 m_port_num = 0; 150 m_filter_owns = 0; 151 m_owned = false; 152 } 153 154 /** 155 * Start a new message in this and all following filters. Only for 156 * internal use, not intended for use in client applications. 157 */ 158 void newMsg() 159 { 160 startMsg(); 161 foreach (size_t j; 0 .. totalPorts()) 162 if (m_next[j]) 163 m_next[j].newMsg(); 164 } 165 166 /** 167 * End a new message in this and all following filters. Only for 168 * internal use, not intended for use in client applications. 169 */ 170 void finishMsg() 171 { 172 endMsg(); 173 foreach (size_t j; 0 .. totalPorts()) 174 if (m_next[j]) 175 m_next[j].finishMsg(); 176 } 177 178 /* 179 * Return the total number of ports 180 */ 181 size_t totalPorts() const 182 { 183 return m_next.length; 184 } 185 186 size_t currentPort() const { return m_port_num; } 187 188 /** 189 * Set the active port 190 * Params: 191 * new_port = the new value 192 */ 193 void setPort(size_t new_port) 194 { 195 if (new_port >= totalPorts()) 196 throw new InvalidArgument("Filter: Invalid port number"); 197 m_port_num = new_port; 198 } 199 200 size_t owns() const { return m_filter_owns; } 201 202 /** 203 * Attach another filter to this one 204 * Params: 205 * new_filter = filter to attach 206 */ 207 void attach(Filter new_filter) 208 { 209 if (new_filter) 210 { 211 Filter last = this; 212 while (last.getNext()) 213 last = last.getNext(); 214 last.m_next[last.currentPort()] = new_filter; 215 } 216 } 217 218 /** 219 * Params: 220 * filters = the filters to set 221 * size = number of items in filters 222 */ 223 override void setNext(Filter* filters, size_t size) 224 { 225 m_next.clear(); 226 227 m_port_num = 0; 228 m_filter_owns = 0; 229 230 while (size && filters && (filters[size-1] is null)) 231 --size; 232 233 if (filters && size) 234 m_next[] = filters[0 .. size]; 235 } 236 237 238 /* 239 * Return the next Filter in the logical chain 240 */ 241 Filter getNext() const 242 { 243 if (m_port_num < m_next.length) 244 return m_next[m_port_num]; 245 return null; 246 } 247 248 abstract bool attachable() { return true; } 249 abstract void startMsg() {} 250 abstract void endMsg() {} 251 abstract @property string name() const; 252 253 SecureVector!ubyte m_write_queue; 254 Vector!Filter m_next; 255 size_t m_port_num, m_filter_owns; 256 257 // true if filter belongs to a pipe -. prohibit filter sharing! 258 bool m_owned; 259 } 260 261 /** 262 * This is the abstract FanoutFilter base class. 263 **/ 264 class FanoutFilter : Filter, Filterable 265 { 266 protected: 267 /** 268 * Increment the number of filters past us that we own 269 */ 270 void incrOwns() { ++m_filter_owns; } 271 272 void setNext(Filter f, size_t n) { super.setNext(&f, 1); } 273 274 override void setPort(size_t n) { setPort(n); } 275 276 override void setNext(Filter* f, size_t n) { super.setNext(f, n); } 277 278 override void attach(Filter f) { attach(f); } 279 280 } 281 282 /** 283 * The type of checking to be performed by decoders: 284 * NONE - no checks, IGNORE_WS - perform checks, but ignore 285 * whitespaces, FULL_CHECK - perform checks, also complain 286 * about white spaces. 287 */ 288 alias DecoderChecking = ubyte; 289 enum : DecoderChecking { NONE, IGNORE_WS, FULL_CHECK }