1 //
2 // This file is part of the aMule Project.
3 //
4 // Copyright (c) 2003-2011 aMule Team ( admin@amule.org / http://www.amule.org )
5 // Copyright (c) 2002-2011 Merkur ( devs@emule-project.net / http://www.emule-project.net )
6 //
7 // Any parts of this program derived from the xMule, lMule or eMule project,
8 // or contributed by third-party developers are copyrighted by their
9 // respective authors.
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; either version 2 of the License, or
14 // (at your option) any later version.
15 //
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA
24 //
25 
26 #ifndef SAFEFILE_H
27 #define SAFEFILE_H
28 
29 
30 #include <wx/filename.h>			// Needed for wxFileName
31 #include <common/MuleDebug.h>			// Needef for CMuleException
32 #include "Tag.h"
33 
34 namespace Kademlia {
35 	class CUInt128;
36 }
37 using Kademlia::CUInt128;
38 class CMD4Hash;
39 
40 
41 /**
42  * This class provides a interface for safe file IO.
43  *
44  * Basic IO operations will either succeed or throw an exception,
45  * so that failure cannot be ignored. There are currently 3 types
46  * of failures: Read past EOF, errors while reading, and errors
47  * while writing.
48  *
49  * Beyond basic IO, the interface provides functions for reading
50  * and writing a number of simple data-types. These are all written
51  * and read as little-endian in order to allow for communication
52  * across platforms.
53  *
54  * Note that when empty areas are created, for instance by seeking
55  * past the end, then writing, the value of bytes where no data was
56  * explicitly written is not specified.
57  */
58 class CFileDataIO
59 {
60 public:
61 	/**
62 	 * The Destructor does nothing, but is needed to allow
63 	 * for safe deletion objects via CFileDataIO pointers.
64 	 */
65 	virtual ~CFileDataIO();
66 
67 
68 	/**
69 	 * Must return the current position in the file.
70 	 */
71 	virtual uint64 GetPosition() const = 0;
72 
73 	/**
74 	 * Must return the length of the file-object in bytes.
75 	 */
76 	virtual uint64 GetLength() const = 0;
77 
78 	/**
79 	 * Returns true when the file-position is past or at the end of the file.
80 	 */
81 	virtual bool Eof() const;
82 
83 
84 	/**
85 	 * Changes the file position.
86 	 *
87 	 * Note that seeking to an negative position is an illegal operation.
88 	 *
89 	 * @see wxFile::Seek
90 	 */
91 	virtual uint64 Seek(sint64 offset, wxSeekMode from = wxFromStart) const;
92 
93 
94 	/**
95 	 * Reads 'count' bytes into 'buffer'.
96 	 *
97 	 * @param buffer The target buffer.
98 	 * @param count The number of bytes to read.
99 	 *
100 	 * Note that Read will read the specified number of
101 	 * bytes unless this would read past the end of the
102 	 * file. In that case, a CEOFException is thrown and
103 	 * the position and target buffer is left unchanged.
104 	 *
105 	 * However, it is also possible that the read will
106 	 * fail due to IO errors (bad hardware, ect), in which
107 	 * case an CIOFailureException will be thrown.
108 	 */
109 	virtual void Read(void* buffer, size_t count) const;
110 
111 	/**
112 	 * Write 'count' bytes from 'buffer' into the file.
113 	 *
114 	 * @param buffer The source-data buffer.
115 	 * @param count The number of bytes to write.
116 	 *
117 	 * Note that Write will throw a CIOFailureException
118 	 * if it fails to write the specified number of bytes,
119 	 * which can be caused by hardware failures, lack of
120 	 * free space, etc.
121 	 */
122 	virtual void Write(const void* buffer, size_t count);
123 
124 
125 	/**
126 	 * Reads the given type from the file, stored as little-endian.
127 	 *
128 	 * @see CSafeFileIO::Read
129 	 */
130 	//@{
131 	virtual uint8		ReadUInt8() const;
132 	virtual uint16		ReadUInt16() const;
133 	virtual uint32		ReadUInt32() const;
134 	virtual uint64		ReadUInt64() const;
135 	virtual CUInt128	ReadUInt128() const;
136 	virtual CMD4Hash	ReadHash() const;
137 	virtual float		ReadFloat() const;
138 	virtual unsigned char*	ReadBsob(uint8* size) const;
139 	//@}
140 
141 	/**
142 	 * Reads a string from the file.
143 	 *
144 	 * @param bOptUTF8 Specifies if the string is UTF8 encoded.
145 	 * @param lenBytes The number of bytes used to store the string length.
146 	 * @param SafeRead Avoids throwing CEOFException, see below.
147 	 * @return The resulting text-string.
148 	 *
149 	 * Note that when SafeRead is set to true, CSafeFileIO will crop the length
150 	 * read from the lenght-field (see lenBytes), so that at most GetLength() -
151 	 * GetPosition() bytes are read.
152 	 *
153 	 * @see CSafeFileIO::Read
154 	 */
155 	virtual wxString	ReadString(bool bOptUTF8, uint8 lenBytes = 2, bool SafeRead = false) const;
156 
157 	/**
158 	 * Reads a string from the file, where the length is specified directly.
159 	 *
160 	 * @param bOptUTF8 Specifies if the string is UTF8 encoded.
161 	 * @param length The length of the string.
162 	 * @return The resulting text-string.
163 	 *
164 	 * This function is typically used when the text-fields length is not stored
165 	 * as an integer-field in front of the text-field.
166 	 */
167 	virtual wxString	ReadOnlyString(bool bOptUTF8, uint16 length) const;
168 
169 
170 	/**
171 	 * Writes a value of the given type to the file, storing it as little-endian.
172 	 *
173 	 * @see CSafeFileIO::Write
174 	 */
175 	//@{
176 	virtual void WriteUInt8(uint8 value);
177 	virtual void WriteUInt16(uint16 value);
178 	virtual void WriteUInt32(uint32 value);
179 	virtual void WriteUInt64(uint64 value);
180 	virtual void WriteUInt128(const CUInt128& value);
181 	virtual void WriteHash(const CMD4Hash& value);
182 	virtual void WriteFloat(float value);
183 	virtual void WriteBsob( const unsigned char* val, uint8 size);
184 	//@}
185 
186 	/**
187 	 * Writes a text-string to the file.
188 	 *
189 	 * @param str The string to be written.
190 	 * @param encoding The text-ecoding, see EUtf8Str.
191 	 * @param lenBytes The number of bytes used to store the string length.
192 	 *
193 	 * Valid values for the 'lenBytes' parameters is 0 bytes (no length field),
194 	 * 2 bytes and 4 bytes.
195 	 *
196 	 * @see CSafeFileIO::Write
197 	 */
198 	virtual void WriteString(const wxString& str, EUtf8Str encoding = utf8strNone, uint8 lenBytes = 2);
199 
200 /* Warning: Special Kad functions, needs documentation */
201 
202 	CTag*		ReadTag(bool bOptACP = false) const;
203 	void		ReadTagPtrList(TagPtrList* taglist, bool bOptACP = false) const;
204 
205 	void		WriteTag(const CTag& tag);
206 	void		WriteTagPtrList(const TagPtrList& tagList);
207 
208 /* Special ED2Kv2 function */
209 	uint64		GetIntTagValue() const;
210 
211 /* Some functions I added for simplicity */
212 	// Very obvious
IsEmpty()213 	bool IsEmpty() { return (GetLength() == 0); }
214 
215 	// Appends to the end
Append(const uint8 * buffer,int n)216 	void Append(const uint8* buffer, int n) { Seek(0, wxFromEnd); Write(buffer, n); }
217 
218 protected:
219 	/**
220 	 * The actual read / write function, as implemented by subclasses.
221 	 *
222 	 * @param buffer The buffer to read data into / write data from.
223 	 * @param count The number of bytes to read / written.
224 	 * @return The number of bytes read / written or -1 in case of errors.
225 	 *
226 	 * Note that the return value must be the actual number of bytes
227 	 * read or written, with the exception that in case of errors, -1
228 	 * may be returned. This is because the return value is used to
229 	 * detect if the operation succeded.
230 	 *
231 	 * This function should not throw Either of the CSafeIOExceptions,
232 	 * this is done by the CSafeFileIO::Read and the CSafeFileIO::Write
233 	 * functions.
234 	 */
235 	//@{
236 	virtual sint64 doRead(void* buffer, size_t count) const = 0;
237 	virtual sint64 doWrite(const void* buffer, size_t count) = 0;
238 	//@}
239 
240 	/**
241 	 * The actual seek function, as implemented by subclasses.
242 	 *
243 	 * @param offset The absolute offset to seek to.
244 	 * @return The resulting offset.
245 	 *
246 	 * This function should not throw of the CSafeIOExceptions,
247 	 * this is handled by the CSafeFileIO::Seek. At the moment,
248 	 * seeks that fail are considered a fatal error.
249 	 */
250 	virtual sint64 doSeek(sint64 offset) const = 0;
251 
252 private:
253 	/**
254 	 * Helper-function that does the actual writing of the string.
255 	 *
256 	 * @param str The string to be written.
257 	 * @param encoding The encoding of the string.
258 	 * @param lenBytes The number of bytes used to store the string length.
259 	 *
260 	 */
261 	void WriteStringCore(const char* str, EUtf8Str encoding, uint8 lenBytes);
262 };
263 
264 
265 /**
266  * The base class of IO exceptions used by
267  * the CSafeFileIO interface and implementations
268  * of the interface.
269  */
270 struct CSafeIOException : public CMuleException
271 {
272 	CSafeIOException(const wxString& type, const wxString& desc);
273 };
274 
275 
276 /**
277  * This exception is thrown when attempts are
278  * made at reading past the end of the file.
279  *
280  * This typically happens when a invalid packet
281  * is received that is shorter than expected and
282  * is not fatal.
283  */
284 struct CEOFException : public CSafeIOException {
285 	CEOFException(const wxString& desc);
286 };
287 
288 
289 /**
290  * This exception reflects a failure in performing
291  * basic IO operations read and write. It will be
292  * thrown in case a read or a write fails to read
293  * or write the specified number of bytes.
294  */
295 struct CIOFailureException : public CSafeIOException {
296 	CIOFailureException(const wxString& type, const wxString& desc);
297 	CIOFailureException(const wxString& desc);
298 };
299 
300 
301 #endif // SAFEFILE_H
302 // File_checked_for_headers
303