ObjFW  Check-in [67917b918a]

Overview
Comment:Move a few classes and categories so they have their own files.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 67917b918a4aff2565bd07e75953dad0565f31613bc3bf2a3dfd0c78da4b38e1
User & Date: js on 2010-06-12 20:47:29
Other Links: manifest | tags
Context
2010-06-13
00:16
Add protocol to type of delegate of OFApplication. check-in: 1009e97dcd user: js tags: trunk
2010-06-12
20:47
Move a few classes and categories so they have their own files. check-in: 67917b918a user: js tags: trunk
19:47
Several OFXMLParser improvements. See details. check-in: 9d79d92d9a user: js tags: trunk
Changes

Modified src/Makefile from [a2fadbd234] to [6ef5c721ca].

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
       OFDataArray.m		\
       OFDictionary.m		\
       OFExceptions.m		\
       OFFile.m			\
       OFHash.m			\
       OFEnumerator.m		\
       OFList.m			\

       OFMutableArray.m		\
       OFMutableDictionary.m	\
       OFMutableString.m	\
       OFNumber.m		\
       OFObject.m		\
       ${OFPLUGIN_M}		\
       OFSeekableStream.m	\

       OFSocket.m		\
       OFStream.m		\
       OFString.m		\




       OFTCPSocket.m		\
       ${OFTHREAD_M}		\
       OFURLEncoding.m		\
       OFXMLElement.m		\
       OFXMLParser.m		\
       unicode.m

INCLUDES := ${SRCS:.m=.h}	\
	    ObjFW.h		\
	    asprintf.h		\







>







>



>
>
>
>


|







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
       OFDataArray.m		\
       OFDictionary.m		\
       OFExceptions.m		\
       OFFile.m			\
       OFHash.m			\
       OFEnumerator.m		\
       OFList.m			\
       OFMD5Hash.m		\
       OFMutableArray.m		\
       OFMutableDictionary.m	\
       OFMutableString.m	\
       OFNumber.m		\
       OFObject.m		\
       ${OFPLUGIN_M}		\
       OFSeekableStream.m	\
       OFSHA1Hash.m		\
       OFSocket.m		\
       OFStream.m		\
       OFString.m		\
       OFString+Hashing.m	\
       OFString+URLEncoding.m	\
       OFString+XMLEscaping.m	\
       OFString+XMLUnescaping.m	\
       OFTCPSocket.m		\
       ${OFTHREAD_M}		\
       OFXMLAttribute.m		\
       OFXMLElement.m		\
       OFXMLParser.m		\
       unicode.m

INCLUDES := ${SRCS:.m=.h}	\
	    ObjFW.h		\
	    asprintf.h		\

Modified src/OFHash.h from [c880c1bfa4] to [90cfc63c8c].

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
/*
 * Copyright (c) 2008 - 2010
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE included in
 * the packaging of this file.
 */

#import "OFObject.h"
#import "OFString.h"

#define OF_MD5_DIGEST_SIZE  16
#define OF_SHA1_DIGEST_SIZE 20

extern int _OFHashing_reference;

/**
 * \brief A base class for classes providing hash functions.
 */
@interface OFHash: OFObject
{
	BOOL	 calculated;












<
<
<
<
<
<







1
2
3
4
5
6
7
8
9
10
11
12






13
14
15
16
17
18
19
/*
 * Copyright (c) 2008 - 2010
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE included in
 * the packaging of this file.
 */

#import "OFObject.h"







/**
 * \brief A base class for classes providing hash functions.
 */
@interface OFHash: OFObject
{
	BOOL	 calculated;
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
- (uint8_t*)digest;

/**
 * \return A boolean whether the hash has already been calculated
 */
- (BOOL)calculated;
@end

/**
 * \brief A class which provides functions to create an MD5 hash.
 */
@interface OFMD5Hash: OFHash
{
	uint32_t buf[4];
	uint32_t bits[2];
	uint8_t	 in[64];
}

/**
 * \return A new autoreleased MD5 Hash
 */
+ md5Hash;
@end

/**
 * \brief A class which provides functions to create an SHA1 hash.
 */
@interface OFSHA1Hash: OFHash
{
	uint32_t state[5];
	uint64_t count;
	char	 buffer[64];
	uint8_t	 digest[OF_SHA1_DIGEST_SIZE];
}

/**
 * \return A new autoreleased SHA1 Hash
 */
+ sha1Hash;
@end

/**
 * The OFString (OFHashing) category provides methods to calculate hashes for
 * strings.
 */
@interface OFString (OFHashing)
/**
 * \return The MD5 hash of the string as an autoreleased OFString
 */
- (OFString*)md5Hash;

/**
 * \return The SHA1 hash of the string as an autoreleased OFString
 */
- (OFString*)sha1Hash;
@end







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
39
40
41
42
43
44
45

















































- (uint8_t*)digest;

/**
 * \return A boolean whether the hash has already been calculated
 */
- (BOOL)calculated;
@end

















































Modified src/OFHash.m from [f0a4e26a0e] to [0764c2c77a].

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
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
/*
 * Copyright (c) 2008 - 2010
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE included in
 * the packaging of this file.
 */

#include "config.h"

#include <string.h>

#import "OFHash.h"
#import "OFAutoreleasePool.h"
#import "OFExceptions.h"
#import "macros.h"

int _OFHashing_reference;

@implementation OFHash
- (void)updateWithBuffer: (const char*)buffer
		  ofSize: (size_t)size
{
	@throw [OFNotImplementedException newWithClass: isa
					      selector: _cmd];
}

- (uint8_t*)digest
{
	@throw [OFNotImplementedException newWithClass: isa
					      selector: _cmd];
}

- (BOOL)calculated
{
	return calculated;
}
@end

/*
 * MD5
 */

/* The four MD5 core functions - F1 is optimized somewhat */
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define F2(x, y, z) F1(z, x, y)
#define F3(x, y, z) (x ^ y ^ z)
#define F4(x, y, z) (y ^ (x | ~z))

/* This is the central step in the MD5 algorithm. */
#define MD5STEP(f, w, x, y, z, data, s) \
	(w += f(x, y, z) + data, w = w << s | w >> (32 - s), w += x)

static inline void
md5_transform(uint32_t buf[4], const uint32_t in[16])
{
	register uint32_t a, b, c, d;

	a = buf[0];
	b = buf[1];
	c = buf[2];
	d = buf[3];

	MD5STEP(F1, a, b, c, d, in[0]  + 0xD76AA478, 7);
	MD5STEP(F1, d, a, b, c, in[1]  + 0xE8C7B756, 12);
	MD5STEP(F1, c, d, a, b, in[2]  + 0x242070DB, 17);
	MD5STEP(F1, b, c, d, a, in[3]  + 0xC1BDCEEE, 22);
	MD5STEP(F1, a, b, c, d, in[4]  + 0xF57C0FAF, 7);
	MD5STEP(F1, d, a, b, c, in[5]  + 0x4787C62A, 12);
	MD5STEP(F1, c, d, a, b, in[6]  + 0xA8304613, 17);
	MD5STEP(F1, b, c, d, a, in[7]  + 0xFD469501, 22);
	MD5STEP(F1, a, b, c, d, in[8]  + 0x698098D8, 7);
	MD5STEP(F1, d, a, b, c, in[9]  + 0x8B44F7AF, 12);
	MD5STEP(F1, c, d, a, b, in[10] + 0xFFFF5BB1, 17);
	MD5STEP(F1, b, c, d, a, in[11] + 0x895CD7Be, 22);
	MD5STEP(F1, a, b, c, d, in[12] + 0x6B901122, 7);
	MD5STEP(F1, d, a, b, c, in[13] + 0xFD987193, 12);
	MD5STEP(F1, c, d, a, b, in[14] + 0xA679438e, 17);
	MD5STEP(F1, b, c, d, a, in[15] + 0x49B40821, 22);

	MD5STEP(F2, a, b, c, d, in[1]  + 0xF61E2562, 5);
	MD5STEP(F2, d, a, b, c, in[6]  + 0xC040B340, 9);
	MD5STEP(F2, c, d, a, b, in[11] + 0x265E5A51, 14);
	MD5STEP(F2, b, c, d, a, in[0]  + 0xE9B6C7AA, 20);
	MD5STEP(F2, a, b, c, d, in[5]  + 0xD62F105D, 5);
	MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
	MD5STEP(F2, c, d, a, b, in[15] + 0xD8A1E681, 14);
	MD5STEP(F2, b, c, d, a, in[4]  + 0xE7D3FBC8, 20);
	MD5STEP(F2, a, b, c, d, in[9]  + 0x21E1CDE6, 5);
	MD5STEP(F2, d, a, b, c, in[14] + 0xC33707D6, 9);
	MD5STEP(F2, c, d, a, b, in[3]  + 0xF4D50D87, 14);
	MD5STEP(F2, b, c, d, a, in[8]  + 0x455A14ED, 20);
	MD5STEP(F2, a, b, c, d, in[13] + 0xA9E3E905, 5);
	MD5STEP(F2, d, a, b, c, in[2]  + 0xFCEFA3F8, 9);
	MD5STEP(F2, c, d, a, b, in[7]  + 0x676F02D9, 14);
	MD5STEP(F2, b, c, d, a, in[12] + 0x8D2A4C8a, 20);

	MD5STEP(F3, a, b, c, d, in[5]  + 0xFFFA3942, 4);
	MD5STEP(F3, d, a, b, c, in[8]  + 0x8771F681, 11);
	MD5STEP(F3, c, d, a, b, in[11] + 0x6D9D6122, 16);
	MD5STEP(F3, b, c, d, a, in[14] + 0xFDE5380c, 23);
	MD5STEP(F3, a, b, c, d, in[1]  + 0xA4BEEA44, 4);
	MD5STEP(F3, d, a, b, c, in[4]  + 0x4BDECFA9, 11);
	MD5STEP(F3, c, d, a, b, in[7]  + 0xF6BB4B60, 16);
	MD5STEP(F3, b, c, d, a, in[10] + 0xBEBFBC70, 23);
	MD5STEP(F3, a, b, c, d, in[13] + 0x289B7EC6, 4);
	MD5STEP(F3, d, a, b, c, in[0]  + 0xEAA127FA, 11);
	MD5STEP(F3, c, d, a, b, in[3]  + 0xD4EF3085, 16);
	MD5STEP(F3, b, c, d, a, in[6]  + 0x04881D05, 23);
	MD5STEP(F3, a, b, c, d, in[9]  + 0xD9D4D039, 4);
	MD5STEP(F3, d, a, b, c, in[12] + 0xE6DB99E5, 11);
	MD5STEP(F3, c, d, a, b, in[15] + 0x1FA27CF8, 16);
	MD5STEP(F3, b, c, d, a, in[2]  + 0xC4AC5665, 23);

	MD5STEP(F4, a, b, c, d, in[0]  + 0xF4292244, 6);
	MD5STEP(F4, d, a, b, c, in[7]  + 0x432AFF97, 10);
	MD5STEP(F4, c, d, a, b, in[14] + 0xAB9423A7, 15);
	MD5STEP(F4, b, c, d, a, in[5]  + 0xFC93A039, 21);
	MD5STEP(F4, a, b, c, d, in[12] + 0x655B59C3, 6);
	MD5STEP(F4, d, a, b, c, in[3]  + 0x8F0CCC92, 10);
	MD5STEP(F4, c, d, a, b, in[10] + 0xFFEFF47d, 15);
	MD5STEP(F4, b, c, d, a, in[1]  + 0x85845DD1, 21);
	MD5STEP(F4, a, b, c, d, in[8]  + 0x6FA87E4F, 6);
	MD5STEP(F4, d, a, b, c, in[15] + 0xFE2CE6E0, 10);
	MD5STEP(F4, c, d, a, b, in[6]  + 0xA3014314, 15);
	MD5STEP(F4, b, c, d, a, in[13] + 0x4E0811A1, 21);
	MD5STEP(F4, a, b, c, d, in[4]  + 0xF7537E82, 6);
	MD5STEP(F4, d, a, b, c, in[11] + 0xBD3AF235, 10);
	MD5STEP(F4, c, d, a, b, in[2]  + 0x2AD7D2BB, 15);
	MD5STEP(F4, b, c, d, a, in[9]  + 0xEB86D391, 21);

	buf[0] += a;
	buf[1] += b;
	buf[2] += c;
	buf[3] += d;
}

@implementation OFMD5Hash
+ md5Hash
{
	return [[[self alloc] init] autorelease];
}

- init
{
	self = [super init];

	buf[0] = 0x67452301;
	buf[1] = 0xEFCDAB89;
	buf[2] = 0x98BADCFE;
	buf[3] = 0x10325476;

	return self;
}

- (void)updateWithBuffer: (const char*)buffer
		  ofSize: (size_t)size
{
	uint32_t t;

	if (size == 0)
		return;

	if (calculated)
		@throw [OFHashAlreadyCalculatedException newWithClass: isa];

	/* Update bitcount */
	t = bits[0];
	if ((bits[0] = t + ((uint32_t)size << 3)) < t)
		/* Carry from low to high */
		bits[1]++;
	bits[1] += size >> 29;

	/* Bytes already in shsInfo->data */
	t = (t >> 3) & 0x3F;

	/* Handle any leading odd-sized chunks */
	if (t) {
		uint8_t *p = in + t;

		t = 64 - t;

		if (size < t) {
			memcpy(p, buffer, size);
			return;
		}

		memcpy(p, buffer, t);
		OF_BSWAP32_V_IF_BE((uint32_t*)in, 16);
		md5_transform(buf, (uint32_t*)in);

		buffer += t;
		size -= t;
	}

	/* Process data in 64-byte chunks */
	while (size >= 64) {
		memcpy(in, buffer, 64);
		OF_BSWAP32_V_IF_BE((uint32_t*)in, 16);
		md5_transform(buf, (uint32_t*)in);

		buffer += 64;
		size -= 64;
	}

	/* Handle any remaining bytes of data. */
	memcpy(in, buffer, size);
}

- (uint8_t*)digest
{
	uint8_t	*p;
	size_t	count;

	if (calculated)
		return (uint8_t*)buf;

	/* Compute number of bytes mod 64 */
	count = (bits[0] >> 3) & 0x3F;

	/*
	 * Set the first char of padding to 0x80. This is safe since there is
	 * always at least one byte free
	 */
	p = in + count;
	*p++ = 0x80;

	/* Bytes of padding needed to make 64 bytes */
	count = 64 - 1 - count;

	/* Pad out to 56 mod 64 */
	if (count < 8) {
		/* Two lots of padding: Pad the first block to 64 bytes */
		memset(p, 0, count);
		OF_BSWAP32_V_IF_BE((uint32_t*)in, 16);
		md5_transform(buf, (uint32_t*)in);

		/* Now fill the next block with 56 bytes */
		memset(in, 0, 56);
	} else {
		/* Pad block to 56 bytes */
		memset(p, 0, count - 8);
	}
	OF_BSWAP32_V_IF_BE((uint32_t*)in, 14);

	/* Append length in bits and transform */
	((uint32_t*)in)[14] = bits[0];
	((uint32_t*)in)[15] = bits[1];

	md5_transform(buf, (uint32_t*)in);
	OF_BSWAP32_V_IF_BE(buf, 4);

	calculated = YES;

	return (uint8_t*)buf;
}
@end

#undef F1
#undef F2
#undef F3
#undef F4
#undef MD5STEP

/*
 * SHA1
 */

/* blk0() and blk() perform the initial expand. */
#ifndef OF_BIG_ENDIAN
#define blk0(i)							\
	(block->l[i] = (OF_ROL(block->l[i], 24) & 0xFF00FF00) |	\
	    (OF_ROL(block->l[i], 8) & 0x00FF00FF))
#else
#define blk0(i) block->l[i]
#endif
#define blk(i) \
	(block->l[i & 15] = OF_ROL(block->l[(i + 13) & 15] ^	\
	    block->l[(i + 8) & 15] ^ block->l[(i + 2) & 15] ^	\
	    block->l[i & 15], 1))

/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
#define R0(v, w, x, y, z, i)						\
	z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + OF_ROL(v, 5);	\
	w = OF_ROL(w, 30);
#define R1(v, w, x, y, z, i)						\
	z += ((w & (x ^ y)) ^ y) + blk(i) +  0x5A827999 + OF_ROL(v, 5);	\
	w = OF_ROL(w, 30);
#define R2(v, w, x, y, z, i)						\
	z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + OF_ROL(v, 5);		\
	w = OF_ROL(w, 30);
#define R3(v, w, x, y, z, i)						     \
	z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + OF_ROL(v, 5); \
	w = OF_ROL(w, 30);
#define R4(v, w, x, y, z, i)						\
	z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + OF_ROL(v, 5);		\
	w = OF_ROL(w, 30);

/// \cond internal
typedef union {
	char	 c[64];
	uint32_t l[16];
} sha1_c64l16_t;
/// \endcond

static inline void
sha1_transform(uint32_t state[5], const char buffer[64])
{
	uint32_t      a, b, c, d, e;
	char	      workspace[64];
	sha1_c64l16_t *block;

	block = (sha1_c64l16_t*)workspace;
	memcpy(block, buffer, 64);

	/* Copy state[] to working vars */
	a = state[0];
	b = state[1];
	c = state[2];
	d = state[3];
	e = state[4];

	/* 4 rounds of 20 operations each. Loop unrolled. */
	R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
	R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
	R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
	R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
	R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
	R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
	R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
	R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
	R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
	R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
	R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
	R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
	R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
	R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
	R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
	R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
	R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
	R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
	R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
	R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);

	/* Add the working vars back into state[] */
	state[0] += a;
	state[1] += b;
	state[2] += c;
	state[3] += d;
	state[4] += e;
}

static inline void
sha1_update(uint32_t *state, uint64_t *count, char *buffer,
    const char *buf, size_t size)
{
	size_t i, j;

	j = (size_t)((*count >> 3) & 63);
	*count += (size << 3);

	if ((j + size) > 63) {
		memcpy(&buffer[j], buf, (i = 64 - j));

		sha1_transform(state, buffer);

		for (; i + 63 < size; i += 64)
			sha1_transform(state, &buf[i]);

		j = 0;
	} else
		i = 0;

	memcpy(&buffer[j], &buf[i], size - i);
}

@implementation OFSHA1Hash
+ sha1Hash
{
	return [[[self alloc] init] autorelease];
}

- init
{
	self = [super init];

	state[0] = 0x67452301;
	state[1] = 0xEFCDAB89;
	state[2] = 0x98BADCFE;
	state[3] = 0x10325476;
	state[4] = 0xC3D2E1F0;

	return self;
}

- (void)updateWithBuffer: (const char*)buf
		  ofSize: (size_t)size
{
	if (size == 0)
		return;

	if (calculated)
		@throw [OFHashAlreadyCalculatedException newWithClass: isa];

	sha1_update(state, &count, buffer, buf, size);
}

- (uint8_t*)digest
{
	size_t i;
	char   finalcount[8];

	if (calculated)
		return digest;

	for (i = 0; i < 8; i++)
		/* Endian independent */
		finalcount[i] = (char)((count >> ((7 - (i & 7)) * 8)) & 255);
	sha1_update(state, &count, buffer, "\200", 1);

	while ((count & 504) != 448)
		sha1_update(state, &count, buffer, "\0", 1);
	/* Should cause a sha1_transform() */
	sha1_update(state, &count, buffer, finalcount, 8);

	for (i = 0; i < OF_SHA1_DIGEST_SIZE; i++)
		digest[i] = (char)((state[i >> 2] >>
		    ((3 - (i & 3)) * 8)) & 255);

	calculated = YES;

	return digest;
}
@end

#undef blk0
#undef blk
#undef R0
#undef R1
#undef R2
#undef R3
#undef R4

@implementation OFString (OFHashing)
- (OFString*)md5Hash
{
	OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];
	OFMD5Hash *hash = [OFMD5Hash md5Hash];
	uint8_t *digest;
	char ret_c[32];
	size_t i;

	[hash updateWithBuffer: string
			ofSize: length];
	digest = [hash digest];

	for (i = 0; i < 16; i++) {
		uint8_t high, low;

		high = digest[i] >> 4;
		low  = digest[i] & 0x0F;

		ret_c[i * 2] = (high > 9 ? high - 10 + 'a' : high + '0');
		ret_c[i * 2 + 1] = (low > 9 ? low - 10 + 'a' : low + '0');
	}

	[pool release];

	return [OFString stringWithCString: ret_c
				    length: 32];
}

- (OFString*)sha1Hash
{
	OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];
	OFMD5Hash *hash = [OFSHA1Hash sha1Hash];
	uint8_t *digest;
	char ret_c[40];
	size_t i;

	[hash updateWithBuffer: string
			ofSize: length];
	digest = [hash digest];

	for (i = 0; i < 20; i++) {
		uint8_t high, low;

		high = digest[i] >> 4;
		low  = digest[i] & 0x0F;

		ret_c[i * 2] = (high > 9 ? high - 10 + 'a' : high + '0');
		ret_c[i * 2 + 1] = (low > 9 ? low - 10 + 'a' : low + '0');
	}

	[pool release];

	return [OFString stringWithCString: ret_c
				    length: 40];
}
@end













<
<

<

<
<
<




















<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
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














































































































































































































































































































































































































































































/*
 * Copyright (c) 2008 - 2010
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE included in
 * the packaging of this file.
 */

#include "config.h"



#import "OFHash.h"

#import "OFExceptions.h"




@implementation OFHash
- (void)updateWithBuffer: (const char*)buffer
		  ofSize: (size_t)size
{
	@throw [OFNotImplementedException newWithClass: isa
					      selector: _cmd];
}

- (uint8_t*)digest
{
	@throw [OFNotImplementedException newWithClass: isa
					      selector: _cmd];
}

- (BOOL)calculated
{
	return calculated;
}
@end














































































































































































































































































































































































































































































Added src/OFMD5Hash.h version [06018586de].





























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008 - 2010
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE included in
 * the packaging of this file.
 */

#import "OFHash.h"

#define OF_MD5_DIGEST_SIZE  16

/**
 * \brief A class which provides functions to create an MD5 hash.
 */
@interface OFMD5Hash: OFHash
{
	uint32_t buf[4];
	uint32_t bits[2];
	uint8_t	 in[64];
}

/**
 * \return A new autoreleased MD5 Hash
 */
+ md5Hash;
@end

Added src/OFMD5Hash.m version [063d887ad6].



















































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008 - 2010
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE included in
 * the packaging of this file.
 */

#include "config.h"

#include <string.h>

#import "OFMD5Hash.h"
#import "OFExceptions.h"
#import "macros.h"

/* The four MD5 core functions - F1 is optimized somewhat */
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define F2(x, y, z) F1(z, x, y)
#define F3(x, y, z) (x ^ y ^ z)
#define F4(x, y, z) (y ^ (x | ~z))

/* This is the central step in the MD5 algorithm. */
#define MD5STEP(f, w, x, y, z, data, s) \
	(w += f(x, y, z) + data, w = w << s | w >> (32 - s), w += x)

static void
md5_transform(uint32_t buf[4], const uint32_t in[16])
{
	register uint32_t a, b, c, d;

	a = buf[0];
	b = buf[1];
	c = buf[2];
	d = buf[3];

	MD5STEP(F1, a, b, c, d, in[0]  + 0xD76AA478, 7);
	MD5STEP(F1, d, a, b, c, in[1]  + 0xE8C7B756, 12);
	MD5STEP(F1, c, d, a, b, in[2]  + 0x242070DB, 17);
	MD5STEP(F1, b, c, d, a, in[3]  + 0xC1BDCEEE, 22);
	MD5STEP(F1, a, b, c, d, in[4]  + 0xF57C0FAF, 7);
	MD5STEP(F1, d, a, b, c, in[5]  + 0x4787C62A, 12);
	MD5STEP(F1, c, d, a, b, in[6]  + 0xA8304613, 17);
	MD5STEP(F1, b, c, d, a, in[7]  + 0xFD469501, 22);
	MD5STEP(F1, a, b, c, d, in[8]  + 0x698098D8, 7);
	MD5STEP(F1, d, a, b, c, in[9]  + 0x8B44F7AF, 12);
	MD5STEP(F1, c, d, a, b, in[10] + 0xFFFF5BB1, 17);
	MD5STEP(F1, b, c, d, a, in[11] + 0x895CD7Be, 22);
	MD5STEP(F1, a, b, c, d, in[12] + 0x6B901122, 7);
	MD5STEP(F1, d, a, b, c, in[13] + 0xFD987193, 12);
	MD5STEP(F1, c, d, a, b, in[14] + 0xA679438e, 17);
	MD5STEP(F1, b, c, d, a, in[15] + 0x49B40821, 22);

	MD5STEP(F2, a, b, c, d, in[1]  + 0xF61E2562, 5);
	MD5STEP(F2, d, a, b, c, in[6]  + 0xC040B340, 9);
	MD5STEP(F2, c, d, a, b, in[11] + 0x265E5A51, 14);
	MD5STEP(F2, b, c, d, a, in[0]  + 0xE9B6C7AA, 20);
	MD5STEP(F2, a, b, c, d, in[5]  + 0xD62F105D, 5);
	MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
	MD5STEP(F2, c, d, a, b, in[15] + 0xD8A1E681, 14);
	MD5STEP(F2, b, c, d, a, in[4]  + 0xE7D3FBC8, 20);
	MD5STEP(F2, a, b, c, d, in[9]  + 0x21E1CDE6, 5);
	MD5STEP(F2, d, a, b, c, in[14] + 0xC33707D6, 9);
	MD5STEP(F2, c, d, a, b, in[3]  + 0xF4D50D87, 14);
	MD5STEP(F2, b, c, d, a, in[8]  + 0x455A14ED, 20);
	MD5STEP(F2, a, b, c, d, in[13] + 0xA9E3E905, 5);
	MD5STEP(F2, d, a, b, c, in[2]  + 0xFCEFA3F8, 9);
	MD5STEP(F2, c, d, a, b, in[7]  + 0x676F02D9, 14);
	MD5STEP(F2, b, c, d, a, in[12] + 0x8D2A4C8a, 20);

	MD5STEP(F3, a, b, c, d, in[5]  + 0xFFFA3942, 4);
	MD5STEP(F3, d, a, b, c, in[8]  + 0x8771F681, 11);
	MD5STEP(F3, c, d, a, b, in[11] + 0x6D9D6122, 16);
	MD5STEP(F3, b, c, d, a, in[14] + 0xFDE5380c, 23);
	MD5STEP(F3, a, b, c, d, in[1]  + 0xA4BEEA44, 4);
	MD5STEP(F3, d, a, b, c, in[4]  + 0x4BDECFA9, 11);
	MD5STEP(F3, c, d, a, b, in[7]  + 0xF6BB4B60, 16);
	MD5STEP(F3, b, c, d, a, in[10] + 0xBEBFBC70, 23);
	MD5STEP(F3, a, b, c, d, in[13] + 0x289B7EC6, 4);
	MD5STEP(F3, d, a, b, c, in[0]  + 0xEAA127FA, 11);
	MD5STEP(F3, c, d, a, b, in[3]  + 0xD4EF3085, 16);
	MD5STEP(F3, b, c, d, a, in[6]  + 0x04881D05, 23);
	MD5STEP(F3, a, b, c, d, in[9]  + 0xD9D4D039, 4);
	MD5STEP(F3, d, a, b, c, in[12] + 0xE6DB99E5, 11);
	MD5STEP(F3, c, d, a, b, in[15] + 0x1FA27CF8, 16);
	MD5STEP(F3, b, c, d, a, in[2]  + 0xC4AC5665, 23);

	MD5STEP(F4, a, b, c, d, in[0]  + 0xF4292244, 6);
	MD5STEP(F4, d, a, b, c, in[7]  + 0x432AFF97, 10);
	MD5STEP(F4, c, d, a, b, in[14] + 0xAB9423A7, 15);
	MD5STEP(F4, b, c, d, a, in[5]  + 0xFC93A039, 21);
	MD5STEP(F4, a, b, c, d, in[12] + 0x655B59C3, 6);
	MD5STEP(F4, d, a, b, c, in[3]  + 0x8F0CCC92, 10);
	MD5STEP(F4, c, d, a, b, in[10] + 0xFFEFF47d, 15);
	MD5STEP(F4, b, c, d, a, in[1]  + 0x85845DD1, 21);
	MD5STEP(F4, a, b, c, d, in[8]  + 0x6FA87E4F, 6);
	MD5STEP(F4, d, a, b, c, in[15] + 0xFE2CE6E0, 10);
	MD5STEP(F4, c, d, a, b, in[6]  + 0xA3014314, 15);
	MD5STEP(F4, b, c, d, a, in[13] + 0x4E0811A1, 21);
	MD5STEP(F4, a, b, c, d, in[4]  + 0xF7537E82, 6);
	MD5STEP(F4, d, a, b, c, in[11] + 0xBD3AF235, 10);
	MD5STEP(F4, c, d, a, b, in[2]  + 0x2AD7D2BB, 15);
	MD5STEP(F4, b, c, d, a, in[9]  + 0xEB86D391, 21);

	buf[0] += a;
	buf[1] += b;
	buf[2] += c;
	buf[3] += d;
}

@implementation OFMD5Hash
+ md5Hash
{
	return [[[self alloc] init] autorelease];
}

- init
{
	self = [super init];

	buf[0] = 0x67452301;
	buf[1] = 0xEFCDAB89;
	buf[2] = 0x98BADCFE;
	buf[3] = 0x10325476;

	return self;
}

- (void)updateWithBuffer: (const char*)buffer
		  ofSize: (size_t)size
{
	uint32_t t;

	if (size == 0)
		return;

	if (calculated)
		@throw [OFHashAlreadyCalculatedException newWithClass: isa];

	/* Update bitcount */
	t = bits[0];
	if ((bits[0] = t + ((uint32_t)size << 3)) < t)
		/* Carry from low to high */
		bits[1]++;
	bits[1] += size >> 29;

	/* Bytes already in shsInfo->data */
	t = (t >> 3) & 0x3F;

	/* Handle any leading odd-sized chunks */
	if (t) {
		uint8_t *p = in + t;

		t = 64 - t;

		if (size < t) {
			memcpy(p, buffer, size);
			return;
		}

		memcpy(p, buffer, t);
		OF_BSWAP32_V_IF_BE((uint32_t*)in, 16);
		md5_transform(buf, (uint32_t*)in);

		buffer += t;
		size -= t;
	}

	/* Process data in 64-byte chunks */
	while (size >= 64) {
		memcpy(in, buffer, 64);
		OF_BSWAP32_V_IF_BE((uint32_t*)in, 16);
		md5_transform(buf, (uint32_t*)in);

		buffer += 64;
		size -= 64;
	}

	/* Handle any remaining bytes of data. */
	memcpy(in, buffer, size);
}

- (uint8_t*)digest
{
	uint8_t	*p;
	size_t	count;

	if (calculated)
		return (uint8_t*)buf;

	/* Compute number of bytes mod 64 */
	count = (bits[0] >> 3) & 0x3F;

	/*
	 * Set the first char of padding to 0x80. This is safe since there is
	 * always at least one byte free
	 */
	p = in + count;
	*p++ = 0x80;

	/* Bytes of padding needed to make 64 bytes */
	count = 64 - 1 - count;

	/* Pad out to 56 mod 64 */
	if (count < 8) {
		/* Two lots of padding: Pad the first block to 64 bytes */
		memset(p, 0, count);
		OF_BSWAP32_V_IF_BE((uint32_t*)in, 16);
		md5_transform(buf, (uint32_t*)in);

		/* Now fill the next block with 56 bytes */
		memset(in, 0, 56);
	} else {
		/* Pad block to 56 bytes */
		memset(p, 0, count - 8);
	}
	OF_BSWAP32_V_IF_BE((uint32_t*)in, 14);

	/* Append length in bits and transform */
	((uint32_t*)in)[14] = bits[0];
	((uint32_t*)in)[15] = bits[1];

	md5_transform(buf, (uint32_t*)in);
	OF_BSWAP32_V_IF_BE(buf, 4);

	calculated = YES;

	return (uint8_t*)buf;
}
@end

Added src/OFSHA1Hash.h version [27f80634e2].































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008 - 2010
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE included in
 * the packaging of this file.
 */

#import "OFHash.h"

#define OF_SHA1_DIGEST_SIZE 20

/**
 * \brief A class which provides functions to create an SHA1 hash.
 */
@interface OFSHA1Hash: OFHash
{
	uint32_t state[5];
	uint64_t count;
	char	 buffer[64];
	uint8_t	 digest[OF_SHA1_DIGEST_SIZE];
}

/**
 * \return A new autoreleased SHA1 Hash
 */
+ sha1Hash;
@end

Added src/OFSHA1Hash.m version [20af66d343].



















































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008 - 2010
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE included in
 * the packaging of this file.
 */

#include "config.h"

#include <string.h>

#import "OFSHA1Hash.h"
#import "OFExceptions.h"
#import "macros.h"

/* blk0() and blk() perform the initial expand. */
#ifndef OF_BIG_ENDIAN
#define blk0(i)							\
	(block->l[i] = (OF_ROL(block->l[i], 24) & 0xFF00FF00) |	\
	    (OF_ROL(block->l[i], 8) & 0x00FF00FF))
#else
#define blk0(i) block->l[i]
#endif
#define blk(i) \
	(block->l[i & 15] = OF_ROL(block->l[(i + 13) & 15] ^	\
	    block->l[(i + 8) & 15] ^ block->l[(i + 2) & 15] ^	\
	    block->l[i & 15], 1))

/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
#define R0(v, w, x, y, z, i)						\
	z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + OF_ROL(v, 5);	\
	w = OF_ROL(w, 30);
#define R1(v, w, x, y, z, i)						\
	z += ((w & (x ^ y)) ^ y) + blk(i) +  0x5A827999 + OF_ROL(v, 5);	\
	w = OF_ROL(w, 30);
#define R2(v, w, x, y, z, i)						\
	z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + OF_ROL(v, 5);		\
	w = OF_ROL(w, 30);
#define R3(v, w, x, y, z, i)						     \
	z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + OF_ROL(v, 5); \
	w = OF_ROL(w, 30);
#define R4(v, w, x, y, z, i)						\
	z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + OF_ROL(v, 5);		\
	w = OF_ROL(w, 30);

/// \cond internal
typedef union {
	char	 c[64];
	uint32_t l[16];
} sha1_c64l16_t;
/// \endcond

static inline void
sha1_transform(uint32_t state[5], const char buffer[64])
{
	uint32_t      a, b, c, d, e;
	char	      workspace[64];
	sha1_c64l16_t *block;

	block = (sha1_c64l16_t*)workspace;
	memcpy(block, buffer, 64);

	/* Copy state[] to working vars */
	a = state[0];
	b = state[1];
	c = state[2];
	d = state[3];
	e = state[4];

	/* 4 rounds of 20 operations each. Loop unrolled. */
	R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
	R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
	R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
	R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
	R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
	R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
	R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
	R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
	R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
	R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
	R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
	R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
	R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
	R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
	R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
	R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
	R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
	R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
	R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
	R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);

	/* Add the working vars back into state[] */
	state[0] += a;
	state[1] += b;
	state[2] += c;
	state[3] += d;
	state[4] += e;
}

static inline void
sha1_update(uint32_t *state, uint64_t *count, char *buffer,
    const char *buf, size_t size)
{
	size_t i, j;

	j = (size_t)((*count >> 3) & 63);
	*count += (size << 3);

	if ((j + size) > 63) {
		memcpy(&buffer[j], buf, (i = 64 - j));

		sha1_transform(state, buffer);

		for (; i + 63 < size; i += 64)
			sha1_transform(state, &buf[i]);

		j = 0;
	} else
		i = 0;

	memcpy(&buffer[j], &buf[i], size - i);
}

@implementation OFSHA1Hash
+ sha1Hash
{
	return [[[self alloc] init] autorelease];
}

- init
{
	self = [super init];

	state[0] = 0x67452301;
	state[1] = 0xEFCDAB89;
	state[2] = 0x98BADCFE;
	state[3] = 0x10325476;
	state[4] = 0xC3D2E1F0;

	return self;
}

- (void)updateWithBuffer: (const char*)buf
		  ofSize: (size_t)size
{
	if (size == 0)
		return;

	if (calculated)
		@throw [OFHashAlreadyCalculatedException newWithClass: isa];

	sha1_update(state, &count, buffer, buf, size);
}

- (uint8_t*)digest
{
	size_t i;
	char   finalcount[8];

	if (calculated)
		return digest;

	for (i = 0; i < 8; i++)
		/* Endian independent */
		finalcount[i] = (char)((count >> ((7 - (i & 7)) * 8)) & 255);
	sha1_update(state, &count, buffer, "\200", 1);

	while ((count & 504) != 448)
		sha1_update(state, &count, buffer, "\0", 1);
	/* Should cause a sha1_transform() */
	sha1_update(state, &count, buffer, finalcount, 8);

	for (i = 0; i < OF_SHA1_DIGEST_SIZE; i++)
		digest[i] = (char)((state[i >> 2] >>
		    ((3 - (i & 3)) * 8)) & 255);

	calculated = YES;

	return digest;
}
@end

Added src/OFString+Hashing.h version [04e6b3c3c1].





























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008 - 2010
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE included in
 * the packaging of this file.
 */

#import "OFString.h"

extern int _OFString_Hashing_reference;

/**
 * The OFString (OFHashing) category provides methods to calculate hashes for
 * strings.
 */
@interface OFString (Hashing)
/**
 * \return The MD5 hash of the string as an autoreleased OFString
 */
- (OFString*)md5Hash;

/**
 * \return The SHA1 hash of the string as an autoreleased OFString
 */
- (OFString*)sha1Hash;
@end

Added src/OFString+Hashing.m version [55b99ed0be].































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008 - 2010
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE included in
 * the packaging of this file.
 */

#include "config.h"

#include <string.h>

#import "OFString.h"
#import "OFMD5Hash.h"
#import "OFSHA1Hash.h"
#import "OFAutoreleasePool.h"

int _OFString_Hashing_reference;

@implementation OFString (Hashing)
- (OFString*)md5Hash
{
	OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];
	OFMD5Hash *hash = [OFMD5Hash md5Hash];
	uint8_t *digest;
	char ret_c[32];
	size_t i;

	[hash updateWithBuffer: string
			ofSize: length];
	digest = [hash digest];

	for (i = 0; i < 16; i++) {
		uint8_t high, low;

		high = digest[i] >> 4;
		low  = digest[i] & 0x0F;

		ret_c[i * 2] = (high > 9 ? high - 10 + 'a' : high + '0');
		ret_c[i * 2 + 1] = (low > 9 ? low - 10 + 'a' : low + '0');
	}

	[pool release];

	return [OFString stringWithCString: ret_c
				    length: 32];
}

- (OFString*)sha1Hash
{
	OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];
	OFMD5Hash *hash = [OFSHA1Hash sha1Hash];
	uint8_t *digest;
	char ret_c[40];
	size_t i;

	[hash updateWithBuffer: string
			ofSize: length];
	digest = [hash digest];

	for (i = 0; i < 20; i++) {
		uint8_t high, low;

		high = digest[i] >> 4;
		low  = digest[i] & 0x0F;

		ret_c[i * 2] = (high > 9 ? high - 10 + 'a' : high + '0');
		ret_c[i * 2 + 1] = (low > 9 ? low - 10 + 'a' : low + '0');
	}

	[pool release];

	return [OFString stringWithCString: ret_c
				    length: 40];
}
@end

Added src/OFString+URLEncoding.h version [ad9c728b83].



































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008 - 2010
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE included in
 * the packaging of this file.
 */

#import "OFString.h"

extern int _OFString_URLEncoding_reference;

/**
 * \brief A category which provides URL encoding and decoding.
 */
@interface OFString (URLEncoding)
/**
 * Encodes a string for use in a URL.
 *
 * \return A new autoreleased string
 */
- (OFString*)stringByURLEncoding;

/**
 * Decodes a string used in a URL.
 *
 * \return A new autoreleased string
 */
- (OFString*)stringByURLDecoding;
@end

Added src/OFString+URLEncoding.m version [7718e4ffef].





































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008 - 2010
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE included in
 * the packaging of this file.
 */

#include "config.h"

#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#import "OFString+URLEncoding.h"
#import "OFExceptions.h"

/* Reference for static linking */
int _OFString_URLEncoding_reference;

@implementation OFString (URLEncoding)
- (OFString*)stringByURLEncoding
{
	const char *s;
	char *ret_c;
	size_t i;
	OFString *ret;

	s = string;

	/*
	 * Worst case: 3 times longer than before.
	 * Oh, and we can't use [self allocWithSize:] here as self might be a
	 * @"" literal.
	 */
	if ((ret_c = malloc((length * 3) + 1)) == NULL)
		@throw [OFOutOfMemoryException newWithClass: isa
						       size: (length * 3) + 1];

	for (i = 0; *s != '\0'; s++) {
		if (isalnum((int)*s) || *s == '-' || *s == '_' || *s == '.' ||
		    *s == '~')
			ret_c[i++] = *s;
		else {
			uint8_t high, low;

			high = *s >> 4;
			low = *s & 0x0F;

			ret_c[i++] = '%';
			ret_c[i++] = (high > 9 ? high - 10 + 'A' : high + '0');
			ret_c[i++] = (low  > 9 ? low  - 10 + 'A' : low  + '0');
		}
	}

	@try {
		ret = [OFString stringWithCString: ret_c
					   length: i];
	} @finally {
		free(ret_c);
	}

	return ret;
}

- (OFString*)stringByURLDecoding
{
	const char *s;
	char *ret_c, c;
	size_t i;
	int st;
	OFString *ret;

	s = string;

	if ((ret_c = malloc(length + 1)) == NULL)
		@throw [OFOutOfMemoryException newWithClass: isa
						       size: length + 1];

	for (st = 0, i = 0, c = 0; *s; s++) {
		switch (st) {
		case 0:
			if (*s == '%')
				st = 1;
			else if (*s == '+')
				ret_c[i++] = ' ';
			else
				ret_c[i++] = *s;
			break;
		case 1:
		case 2:
			if (*s >= '0' && *s <= '9')
				c += (*s - '0') << (st == 1 ? 4 : 0);
			else if (*s >= 'A' && *s <= 'F')
				c += (*s - 'A' + 10) << (st == 1 ? 4 : 0);
			else if (*s >= 'a' && *s <= 'f')
				c += (*s - 'a' + 10) << (st == 1 ? 4 : 0);
			else {
				free(ret_c);
				@throw [OFInvalidEncodingException
				    newWithClass: isa];
			}

			if (++st == 3) {
				ret_c[i++] = c;
				st = 0;
				c = 0;
			}

			break;
		}
	}
	ret_c[i] = '\0';

	if (st) {
		free(ret_c);
		@throw [OFInvalidEncodingException newWithClass: isa];
	}

	@try {
		ret = [OFString stringWithCString: ret_c];
	} @finally {
		free(ret_c);
	}
	return ret;
}
@end

Added src/OFString+XMLEscaping.h version [2db9d50f33].





















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008 - 2010
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE included in
 * the packaging of this file.
 */

#import "OFString.h"

extern int _OFString_XMLEscaping_reference;

/**
 * \brief A category to escape strings for use in an XML document.
 */
@interface OFString (XMLEscaping)
/**
 * Escapes a string for use in an XML document.
 *
 * \return A new autoreleased string
 */
- (OFString*)stringByXMLEscaping;
@end

Added src/OFString+XMLEscaping.m version [fa81256b88].





























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008 - 2010
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE included in
 * the packaging of this file.
 */

#include "config.h"

#include <assert.h>
#include <stdlib.h>
#include <string.h>

#import "OFString.h"
#import "OFExceptions.h"

int _OFString_XMLEscaping_reference;

@implementation OFString (XMLEscaping)
- (OFString*)stringByXMLEscaping
{
	char *str_c, *append, *tmp;
	size_t len, append_len;
	size_t i, j;
	OFString *ret;

	j = 0;
	len = length;

	/*
	 * We can't use allocMemoryWithSize: here as it might be a @"" literal
	 */
	if ((str_c = malloc(len)) == NULL)
		@throw [OFOutOfMemoryException newWithClass: isa
						       size: len];

	for (i = 0; i < length; i++) {
		switch (string[i]) {
			case '<':
				append = "&lt;";
				append_len = 4;
				break;
			case '>':
				append = "&gt;";
				append_len = 4;
				break;
			case '"':
				append = "&quot;";
				append_len = 6;
				break;
			case '\'':
				append = "&apos;";
				append_len = 6;
				break;
			case '&':
				append = "&amp;";
				append_len = 5;
				break;
			default:
				append = NULL;
				append_len = 0;
		}

		if (append != NULL) {
			if ((tmp = realloc(str_c, len + append_len)) == NULL) {
				free(str_c);
				@throw [OFOutOfMemoryException
				    newWithClass: isa
					    size: len + append_len];
			}
			str_c = tmp;
			len += append_len - 1;

			memcpy(str_c + j, append, append_len);
			j += append_len;
		} else
			str_c[j++] = string[i];
	}

	assert(j == len);

	@try {
		ret = [OFString stringWithCString: str_c
					   length: len];
	} @finally {
		free(str_c);
	}
	return ret;
}
@end

Added src/OFString+XMLUnescaping.h version [b597a59e83].





































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008 - 2010
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE included in
 * the packaging of this file.
 */

#import "OFString.h"

extern int _OFString_XMLUnescaping_reference;

/**
 * \brief A protocol that needs to be implemented by delegates for
 *	  -[stringByXMLUnescapingWithHandler:].
 */
@protocol OFStringXMLUnescapingDelegate
/**
 * This callback is called when an unknown entity was found while trying to
 * unescape XML. The callback is supposed to return a substitution for the
 * entity or nil if it is unknown to the callback as well, in which case an
 * exception will be thrown.
 *
 * \param entity The name of the entity that is unknown
 * \return A substitution for the entity or nil
 */
- (OFString*)didFindUnknownEntityNamed: (OFString*)entity;
@end

/**
 * \brief A category for unescaping XML in strings.
 */
@interface OFString (XMLUnescaping)
/**
 * Unescapes XML in the string.
 */
- (OFString*)stringByXMLUnescaping;

/**
 * Unescapes XML in the string and uses the specified handler for unknown
 * entities.
 *
 * \param h An OFXMLUnescapingDelegate as a handler for unknown entities
 */
- (OFString*)stringByXMLUnescapingWithHandler:
    (OFObject <OFStringXMLUnescapingDelegate>*)h;
@end

Added src/OFString+XMLUnescaping.m version [8b7255c2dd].

















































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008 - 2010
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE included in
 * the packaging of this file.
 */

#include "config.h"

#include <string.h>

#import "OFString.h"
#import "OFAutoreleasePool.h"
#import "OFExceptions.h"
#import "macros.h"

int _OFString_XMLUnescaping_reference;

static OF_INLINE OFString*
parse_numeric_entity(const char *entity, size_t length)
{
	of_unichar_t c;
	size_t i;
	char buf[5];

	if (length == 1 || *entity != '#')
		return nil;

	c = 0;
	entity++;
	length--;

	if (entity[0] == 'x') {
		if (length == 1)
			return nil;

		entity++;
		length--;

		for (i = 0; i < length; i++) {
			if (entity[i] >= '0' && entity[i] <= '9')
				c = (c << 4) + (entity[i] - '0');
			else if (entity[i] >= 'A' && entity[i] <= 'F')
				c = (c << 4) + (entity[i] - 'A' + 10);
			else if (entity[i] >= 'a' && entity[i] <= 'f')
				c = (c << 4) + (entity[i] - 'a' + 10);
			else
				return nil;
		}
	} else {
		for (i = 0; i < length; i++) {
			if (entity[i] >= '0' && entity[i] <= '9')
				c = (c * 10) + (entity[i] - '0');
			else
				return nil;
		}
	}

	if ((i = of_string_unicode_to_utf8(c, buf)) == 0)
		return nil;
	buf[i] = 0;

	return [OFString stringWithCString: buf
				    length: i];
}

@implementation OFString (XMLUnescaping)
- (OFString*)stringByXMLUnescaping
{
	return [self stringByXMLUnescapingWithHandler: nil];
}

- (OFString*)stringByXMLUnescapingWithHandler:
    (OFObject <OFStringXMLUnescapingDelegate>*)h
{
	size_t i, last;
	BOOL in_entity;
	OFMutableString *ret;

	last = 0;
	in_entity = NO;
	ret = [OFMutableString string];

	switch (of_string_check_utf8(string, length)) {
	case 1:
		((OFString*)ret)->isUTF8 = YES;
		break;
	case -1:
		@throw [OFInvalidEncodingException newWithClass: isa];
	}

	for (i = 0; i < length; i++) {
		if (!in_entity && string[i] == '&') {
			[ret appendCStringWithoutUTF8Checking: string + last
						       length: i - last];

			last = i + 1;
			in_entity = YES;
		} else if (in_entity && string[i] == ';') {
			char *entity = string + last;
			size_t len = i - last;

			if (len == 2 && !memcmp(entity, "lt", 2))
				[ret appendCStringWithoutUTF8Checking: "<"
							       length: 1];
			else if (len == 2 && !memcmp(entity, "gt", 2))
				[ret appendCStringWithoutUTF8Checking: ">"
							       length: 1];
			else if (len == 4 && !memcmp(entity, "quot", 4))
				[ret appendCStringWithoutUTF8Checking: "\""
							       length: 1];
			else if (len == 4 && !memcmp(entity, "apos", 4))
				[ret appendCStringWithoutUTF8Checking: "'"
							       length: 1];
			else if (len == 3 && !memcmp(entity, "amp", 3))
				[ret appendCStringWithoutUTF8Checking: "&"
							       length: 1];
			else if (entity[0] == '#') {
				OFAutoreleasePool *pool;
				OFString *tmp;

				pool = [[OFAutoreleasePool alloc] init];
				tmp = parse_numeric_entity(entity, len);

				if (tmp == nil)
					@throw [OFInvalidEncodingException
					    newWithClass: isa];

				[ret appendString: tmp];
				[pool release];
			} else if (h != nil) {
				OFAutoreleasePool *pool;
				OFString *n, *tmp;

				pool = [[OFAutoreleasePool alloc] init];

				n = [OFString stringWithCString: entity
							 length: len];
				tmp = [h didFindUnknownEntityNamed: n];

				if (tmp == nil)
					@throw [OFInvalidEncodingException
					    newWithClass: isa];

				[ret appendString: tmp];
				[pool release];
			} else
				@throw [OFInvalidEncodingException
				    newWithClass: isa];

			last = i + 1;
			in_entity = NO;
		}
	}

	if (in_entity)
		@throw [OFInvalidEncodingException newWithClass: isa];

	[ret appendCStringWithoutUTF8Checking: string + last
				       length: i - last];

	return ret;
}
@end

Modified src/OFString.h from [dc84da64f5] to [56876e2512].

366
367
368
369
370
371
372
373
374
375
376
 * \return An OFNumber
 */
- (uintmax_t)hexadecimalValueAsInteger;
@end

#import "OFConstString.h"
#import "OFMutableString.h"
#import "OFHash.h"
#import "OFURLEncoding.h"
#import "OFXMLElement.h"
#import "OFXMLParser.h"







|
|
|
|
366
367
368
369
370
371
372
373
374
375
376
 * \return An OFNumber
 */
- (uintmax_t)hexadecimalValueAsInteger;
@end

#import "OFConstString.h"
#import "OFMutableString.h"
#import "OFString+Hashing.h"
#import "OFString+URLEncoding.h"
#import "OFString+XMLEscaping.h"
#import "OFString+XMLUnescaping.h"

Modified src/OFString.m from [1d5af0ad42] to [19d4bb0975].

36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

extern const uint16_t of_iso_8859_15[256];
extern const uint16_t of_windows_1252[256];

/* References for static linking */
void _references_to_categories_of_OFString()
{
	_OFHashing_reference = 1;
	_OFURLEncoding_reference = 1;
	_OFXMLElement_reference = 1;
	_OFXMLParser_reference = 1;
};

int
of_string_check_utf8(const char *str, size_t len)
{
	size_t i;
	int utf8 = 0;







|
|
|
|







36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

extern const uint16_t of_iso_8859_15[256];
extern const uint16_t of_windows_1252[256];

/* References for static linking */
void _references_to_categories_of_OFString()
{
	_OFString_Hashing_reference = 1;
	_OFString_URLEncoding_reference = 1;
	_OFString_XMLEscaping_reference = 1;
	_OFString_XMLUnescaping_reference = 1;
};

int
of_string_check_utf8(const char *str, size_t len)
{
	size_t i;
	int utf8 = 0;

Deleted src/OFURLEncoding.h version [1262cd49d1].

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
/*
 * Copyright (c) 2008 - 2010
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE included in
 * the packaging of this file.
 */

#import "OFString.h"

extern int _OFURLEncoding_reference;

/**
 * \brief A category which provides URL encoding and decoding.
 */
@interface OFString (OFURLEncoding)
/**
 * Encodes a string for use in a URL.
 *
 * \return A new autoreleased string
 */
- (OFString*)stringByURLEncoding;

/**
 * Decodes a string used in a URL.
 *
 * \return A new autoreleased string
 */
- (OFString*)stringByURLDecoding;
@end
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


































































Deleted src/OFURLEncoding.m version [51165a76a2].

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
/*
 * Copyright (c) 2008 - 2010
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE included in
 * the packaging of this file.
 */

#include "config.h"

#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#import "OFURLEncoding.h"
#import "OFExceptions.h"

/* Reference for static linking */
int _OFURLEncoding_reference;

@implementation OFString (OFURLEncoding)
- (OFString*)stringByURLEncoding
{
	const char *s;
	char *ret_c;
	size_t i;
	OFString *ret;

	s = string;

	/*
	 * Worst case: 3 times longer than before.
	 * Oh, and we can't use [self allocWithSize:] here as self might be a
	 * @"" literal.
	 */
	if ((ret_c = malloc((length * 3) + 1)) == NULL)
		@throw [OFOutOfMemoryException newWithClass: isa
						       size: (length * 3) + 1];

	for (i = 0; *s != '\0'; s++) {
		if (isalnum((int)*s) || *s == '-' || *s == '_' || *s == '.' ||
		    *s == '~')
			ret_c[i++] = *s;
		else {
			uint8_t high, low;

			high = *s >> 4;
			low = *s & 0x0F;

			ret_c[i++] = '%';
			ret_c[i++] = (high > 9 ? high - 10 + 'A' : high + '0');
			ret_c[i++] = (low  > 9 ? low  - 10 + 'A' : low  + '0');
		}
	}

	@try {
		ret = [OFString stringWithCString: ret_c
					   length: i];
	} @finally {
		free(ret_c);
	}

	return ret;
}

- (OFString*)stringByURLDecoding
{
	const char *s;
	char *ret_c, c;
	size_t i;
	int st;
	OFString *ret;

	s = string;

	if ((ret_c = malloc(length + 1)) == NULL)
		@throw [OFOutOfMemoryException newWithClass: isa
						       size: length + 1];

	for (st = 0, i = 0, c = 0; *s; s++) {
		switch (st) {
		case 0:
			if (*s == '%')
				st = 1;
			else if (*s == '+')
				ret_c[i++] = ' ';
			else
				ret_c[i++] = *s;
			break;
		case 1:
		case 2:
			if (*s >= '0' && *s <= '9')
				c += (*s - '0') << (st == 1 ? 4 : 0);
			else if (*s >= 'A' && *s <= 'F')
				c += (*s - 'A' + 10) << (st == 1 ? 4 : 0);
			else if (*s >= 'a' && *s <= 'f')
				c += (*s - 'a' + 10) << (st == 1 ? 4 : 0);
			else {
				free(ret_c);
				@throw [OFInvalidEncodingException
				    newWithClass: isa];
			}

			if (++st == 3) {
				ret_c[i++] = c;
				st = 0;
				c = 0;
			}

			break;
		}
	}
	ret_c[i] = '\0';

	if (st) {
		free(ret_c);
		@throw [OFInvalidEncodingException newWithClass: isa];
	}

	@try {
		ret = [OFString stringWithCString: ret_c];
	} @finally {
		free(ret_c);
	}
	return ret;
}
@end
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




































































































































































































































































Added src/OFXMLAttribute.h version [7a67ed7d56].









































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008 - 2010
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE included in
 * the packaging of this file.
 */

#import "OFObject.h"

@class OFString;

/**
 * \brief A representation of an attribute of an XML element as an object.
 */
@interface OFXMLAttribute: OFObject
{
	OFString *name;
	OFString *namespace;
	OFString *stringValue;
}

#ifdef OF_HAVE_PROPERTIES
@property (readonly, retain) OFString *name;
@property (readonly, retain) OFString *namespace;
@property (readonly, retain) OFString *stringValue;
#endif

/**
 * \param name The name of the attribute
 * \param ns The namespace of the attribute
 * \param value The string value of the attribute
 * \return A new autoreleased OFXMLAttribute with the specified parameters
 */
+ attributeWithName: (OFString*)name
	  namespace: (OFString*)ns
	stringValue: (OFString*)value;

/**
 * Initializes an already allocated OFXMLAttribute.
 *
 * \param name The name of the attribute
 * \param ns The namespace of the attribute
 * \param value The string value of the attribute
 * \return An initialized OFXMLAttribute with the specified parameters
 */
- initWithName: (OFString*)name
     namespace: (OFString*)ns
   stringValue: (OFString*)value;

/**
 * \return The name of the attribute as an autoreleased OFString
 */
- (OFString*)name;

/**
 * \return The namespace of the attribute as an autoreleased OFString
 */
- (OFString*)namespace;

/**
 * \return The string value of the attribute as an autoreleased OFString
 */
- (OFString*)stringValue;
@end

Added src/OFXMLAttribute.m version [97f1780df3].

































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008 - 2010
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE included in
 * the packaging of this file.
 */

#include "config.h"

#import "OFXMLAttribute.h"
#import "OFString.h"
#import "OFAutoreleasePool.h"

@implementation OFXMLAttribute
+ attributeWithName: (OFString*)name
	  namespace: (OFString*)ns
	stringValue: (OFString*)value
{
	return [[[self alloc] initWithName: name
				 namespace: ns
			       stringValue: value] autorelease];
}

- initWithName: (OFString*)name_
     namespace: (OFString*)ns
   stringValue: (OFString*)value
{
	self = [super init];

	name = [name_ copy];
	namespace = [ns copy];
	stringValue = [value copy];

	return self;
}

- (void)dealloc
{
	[name release];
	[namespace release];
	[stringValue release];

	[super dealloc];
}

- (OFString*)name
{
	return [[name copy] autorelease];
}

- (OFString*)namespace
{
	return [[namespace copy] autorelease];
}

- (OFString*)stringValue
{
	return [[stringValue copy] autorelease];
}
@end

Modified src/OFXMLElement.h from [a44393b6ce] to [9c0874a8f4].

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
/*
 * Copyright (c) 2008 - 2010
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE included in
 * the packaging of this file.
 */

#import "OFObject.h"
#import "OFString.h"


@class OFMutableArray;
@class OFMutableDictionary;

extern int _OFXMLElement_reference;

/**
 * \brief A representation of an attribute of an XML element as an object.
 */
@interface OFXMLAttribute: OFObject
{
	OFString *name;
	OFString *namespace;
	OFString *stringValue;
}

#ifdef OF_HAVE_PROPERTIES
@property (readonly, retain) OFString *name;
@property (readonly, retain) OFString *namespace;
@property (readonly, retain) OFString *stringValue;
#endif

/**
 * \param name The name of the attribute
 * \param ns The namespace of the attribute
 * \param value The string value of the attribute
 * \return A new autoreleased OFXMLAttribute with the specified parameters
 */
+ attributeWithName: (OFString*)name
	  namespace: (OFString*)ns
	stringValue: (OFString*)value;

/**
 * Initializes an already allocated OFXMLAttribute.
 *
 * \param name The name of the attribute
 * \param ns The namespace of the attribute
 * \param value The string value of the attribute
 * \return An initialized OFXMLAttribute with the specified parameters
 */
- initWithName: (OFString*)name
     namespace: (OFString*)ns
   stringValue: (OFString*)value;

/**
 * \return The name of the attribute as an autoreleased OFString
 */
- (OFString*)name;

/**
 * \return The namespace of the attribute as an autoreleased OFString
 */
- (OFString*)namespace;

/**
 * \return The string value of the attribute as an autoreleased OFString
 */
- (OFString*)stringValue;
@end

/**
 * \brief A representation of an XML element as an object.
 *
 * The OFXMLElement represents an XML element as an object which can be
 * modified and converted back to XML again.
 */
@interface OFXMLElement: OFObject
{
	OFString *name;
	OFString *namespace;
	OFString *defaultNamespace;
	OFMutableArray *attributes;
	OFString *stringValue;












<

>


<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







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
/*
 * Copyright (c) 2008 - 2010
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE included in
 * the packaging of this file.
 */

#import "OFObject.h"


@class OFString;
@class OFMutableArray;
@class OFMutableDictionary;






@class OFXMLAttribute;
























































@interface OFXMLElement: OFObject
{
	OFString *name;
	OFString *namespace;
	OFString *defaultNamespace;
	OFMutableArray *attributes;
	OFString *stringValue;
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
/**
 * Adds a child to the OFXMLElement.
 *
 * \param child Another OFXMLElement which is added as a child
 */
- (void)addChild: (OFXMLElement*)child;
@end

/**
 * \brief A category to escape strings for use in an XML document.
 */
@interface OFString (OFXMLEscaping)
/**
 * Escapes a string for use in an XML document.
 *
 * \return A new autoreleased string
 */
- (OFString*)stringByXMLEscaping;
@end







<
<
<
<
<
<
<
<
<
<
<
<
161
162
163
164
165
166
167












/**
 * Adds a child to the OFXMLElement.
 *
 * \param child Another OFXMLElement which is added as a child
 */
- (void)addChild: (OFXMLElement*)child;
@end












Modified src/OFXMLElement.m from [62e141f922] to [2e589492fa].

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
 * Q Public License 1.0, which can be found in the file LICENSE included in
 * the packaging of this file.
 */

#include "config.h"

#include <assert.h>
#include <stdlib.h>
#include <string.h>

#import "OFXMLElement.h"
#import "OFString.h"
#import "OFArray.h"
#import "OFDictionary.h"

#import "OFAutoreleasePool.h"
#import "OFExceptions.h"

int _OFXMLElement_reference;

@implementation OFXMLAttribute
+ attributeWithName: (OFString*)name
	  namespace: (OFString*)ns
	stringValue: (OFString*)value
{
	return [[[self alloc] initWithName: name
				 namespace: ns
			       stringValue: value] autorelease];
}

- initWithName: (OFString*)name_
     namespace: (OFString*)ns
   stringValue: (OFString*)value
{
	self = [super init];

	name = [name_ copy];
	namespace = [ns copy];
	stringValue = [value copy];

	return self;
}

- (void)dealloc
{
	[name release];
	[namespace release];
	[stringValue release];

	[super dealloc];
}

- (OFString*)name
{
	return [[name copy] autorelease];
}

- (OFString*)namespace
{
	return [[namespace copy] autorelease];
}

- (OFString*)stringValue
{
	return [[stringValue copy] autorelease];
}
@end

@implementation OFXMLElement
+ elementWithName: (OFString*)name_
{
	return [[[self alloc] initWithName: name_] autorelease];
}

+ elementWithName: (OFString*)name







<






>



<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







8
9
10
11
12
13
14

15
16
17
18
19
20
21
22
23
24


















































25
26
27
28
29
30
31
 * Q Public License 1.0, which can be found in the file LICENSE included in
 * the packaging of this file.
 */

#include "config.h"

#include <assert.h>

#include <string.h>

#import "OFXMLElement.h"
#import "OFString.h"
#import "OFArray.h"
#import "OFDictionary.h"
#import "OFXMLAttribute.h"
#import "OFAutoreleasePool.h"
#import "OFExceptions.h"



















































@implementation OFXMLElement
+ elementWithName: (OFString*)name_
{
	return [[[self alloc] initWithName: name_] autorelease];
}

+ elementWithName: (OFString*)name
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
	[attributes release];
	[stringValue release];
	[namespaces release];
	[children release];

	[super dealloc];
}
@end

@implementation OFString (OFXMLEscaping)
- (OFString*)stringByXMLEscaping
{
	char *str_c, *append, *tmp;
	size_t len, append_len;
	size_t i, j;
	OFString *ret;

	j = 0;
	len = length;

	/*
	 * We can't use allocMemoryWithSize: here as it might be a @"" literal
	 */
	if ((str_c = malloc(len)) == NULL)
		@throw [OFOutOfMemoryException newWithClass: isa
						       size: len];

	for (i = 0; i < length; i++) {
		switch (string[i]) {
			case '<':
				append = "&lt;";
				append_len = 4;
				break;
			case '>':
				append = "&gt;";
				append_len = 4;
				break;
			case '"':
				append = "&quot;";
				append_len = 6;
				break;
			case '\'':
				append = "&apos;";
				append_len = 6;
				break;
			case '&':
				append = "&amp;";
				append_len = 5;
				break;
			default:
				append = NULL;
				append_len = 0;
		}

		if (append != NULL) {
			if ((tmp = realloc(str_c, len + append_len)) == NULL) {
				free(str_c);
				@throw [OFOutOfMemoryException
				    newWithClass: isa
					    size: len + append_len];
			}
			str_c = tmp;
			len += append_len - 1;

			memcpy(str_c + j, append, append_len);
			j += append_len;
		} else
			str_c[j++] = string[i];
	}

	assert(j == len);

	@try {
		ret = [OFString stringWithCString: str_c
					   length: len];
	} @finally {
		free(str_c);
	}
	return ret;
}
@end








<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
366
367
368
369
370
371
372
373









































































	[attributes release];
	[stringValue release];
	[namespaces release];
	[children release];

	[super dealloc];
}
@end









































































Modified src/OFXMLParser.h from [9635aaee4f] to [5b79a3d936].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/*
 * Copyright (c) 2008 - 2010
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE included in
 * the packaging of this file.
 */

#import "OFObject.h"
#import "OFString.h"

extern int _OFXMLParser_reference;

@class OFXMLParser;
@class OFArray;
@class OFMutableArray;

/**
 * \brief A protocol that needs to be implemented by delegates for OFXMLParser.













|
<







1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
/*
 * Copyright (c) 2008 - 2010
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE included in
 * the packaging of this file.
 */

#import "OFObject.h"
#import "OFString.h"
#import "OFXMLAttribute.h"


@class OFXMLParser;
@class OFArray;
@class OFMutableArray;

/**
 * \brief A protocol that needs to be implemented by delegates for OFXMLParser.
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
 * \param entity The name of the entity the XML parser didn't know
 * \return A substitution for the entity or nil
 */
-      (OFString*)xmlParser: (OFXMLParser*)parser
  didFindUnknownEntityNamed: (OFString*)entity;
@end

/**
 * \brief A protocol that needs to be implemented by delegates for
 *	  -[stringByXMLUnescapingWithHandler:].
 */
@protocol OFXMLUnescapingDelegate
/**
 * This callback is called when an unknown entity was found while trying to
 * unescape XML. The callback is supposed to return a substitution for the
 * entity or nil if it is unknown to the callback as well, in which case an
 * exception will be thrown.
 *
 * \param entity The name of the entity that is unknown
 * \return A substitution for the entity or nil
 */
- (OFString*)didFindUnknownEntityNamed: (OFString*)entity;
@end

/**
 * \brief An event-based XML parser.
 *
 * OFXMLParser is an event-based XML parser which calls the delegate's callbacks
 * as soon asit finds something, thus suitable for streams as well.
 */
@interface OFXMLParser: OFObject <OFXMLUnescapingDelegate>
{
	OFObject <OFXMLParserDelegate> *delegate;
	enum {
		OF_XMLPARSER_OUTSIDE_TAG,
		OF_XMLPARSER_TAG_OPENED,
		OF_XMLPARSER_IN_TAG_NAME,
		OF_XMLPARSER_IN_CLOSE_TAG_NAME,







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






|







80
81
82
83
84
85
86

















87
88
89
90
91
92
93
94
95
96
97
98
99
100
 * \param entity The name of the entity the XML parser didn't know
 * \return A substitution for the entity or nil
 */
-      (OFString*)xmlParser: (OFXMLParser*)parser
  didFindUnknownEntityNamed: (OFString*)entity;
@end


















/**
 * \brief An event-based XML parser.
 *
 * OFXMLParser is an event-based XML parser which calls the delegate's callbacks
 * as soon asit finds something, thus suitable for streams as well.
 */
@interface OFXMLParser: OFObject <OFStringXMLUnescapingDelegate>
{
	OFObject <OFXMLParserDelegate> *delegate;
	enum {
		OF_XMLPARSER_OUTSIDE_TAG,
		OF_XMLPARSER_TAG_OPENED,
		OF_XMLPARSER_IN_TAG_NAME,
		OF_XMLPARSER_IN_CLOSE_TAG_NAME,
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
 * \param buf The buffer to parse
 * \param size The size of the buffer
 */
- (void)parseBuffer: (const char*)buf
	   withSize: (size_t)size;
@end

/**
 * \brief A category for unescaping XML in strings.
 */
@interface OFString (OFXMLUnescaping)
/**
 * Unescapes XML in the string.
 */
- (OFString*)stringByXMLUnescaping;

/**
 * Unescapes XML in the string and uses the specified handler for unknown
 * entities.
 *
 * \param h An OFXMLUnescapingDelegate as a handler for unknown entities
 */
- (OFString*)stringByXMLUnescapingWithHandler:
    (OFObject <OFXMLUnescapingDelegate>*)h;
@end

@interface OFObject (OFXMLParserDelegate) <OFXMLParserDelegate>
@end







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


157
158
159
160
161
162
163



















164
165
 * \param buf The buffer to parse
 * \param size The size of the buffer
 */
- (void)parseBuffer: (const char*)buf
	   withSize: (size_t)size;
@end




















@interface OFObject (OFXMLParserDelegate) <OFXMLParserDelegate>
@end

Modified src/OFXMLParser.m from [379d043fd1] to [86523e53cd].

14
15
16
17
18
19
20

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <string.h>
#include <unistd.h>

#import "OFXMLParser.h"
#import "OFString.h"
#import "OFArray.h"
#import "OFDictionary.h"

#import "OFAutoreleasePool.h"
#import "OFExceptions.h"
#import "macros.h"

int _OFXMLParser_reference;

static OF_INLINE OFString*
transform_string(OFMutableString *cache,
    OFObject <OFXMLUnescapingDelegate> *handler)
{
	[cache replaceOccurrencesOfString: @"\r\n"
			       withString: @"\n"];
	[cache replaceOccurrencesOfString: @"\r"
			       withString: @"\n"];
	return [cache stringByXMLUnescapingWithHandler: handler];
}







>




<
<


|







14
15
16
17
18
19
20
21
22
23
24
25


26
27
28
29
30
31
32
33
34
35
#include <string.h>
#include <unistd.h>

#import "OFXMLParser.h"
#import "OFString.h"
#import "OFArray.h"
#import "OFDictionary.h"
#import "OFXMLAttribute.h"
#import "OFAutoreleasePool.h"
#import "OFExceptions.h"
#import "macros.h"



static OF_INLINE OFString*
transform_string(OFMutableString *cache,
    OFObject <OFStringXMLUnescapingDelegate> *handler)
{
	[cache replaceOccurrencesOfString: @"\r\n"
			       withString: @"\n"];
	[cache replaceOccurrencesOfString: @"\r"
			       withString: @"\n"];
	return [cache stringByXMLUnescapingWithHandler: handler];
}
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
		if ((tmp = [carray[i] objectForKey: prefix]) != nil)
			return tmp;
	}

	return nil;
}

static OF_INLINE OFString*
parse_numeric_entity(const char *entity, size_t length)
{
	of_unichar_t c;
	size_t i;
	char buf[5];

	if (length == 1 || *entity != '#')
		return nil;

	c = 0;
	entity++;
	length--;

	if (entity[0] == 'x') {
		if (length == 1)
			return nil;

		entity++;
		length--;

		for (i = 0; i < length; i++) {
			if (entity[i] >= '0' && entity[i] <= '9')
				c = (c << 4) + (entity[i] - '0');
			else if (entity[i] >= 'A' && entity[i] <= 'F')
				c = (c << 4) + (entity[i] - 'A' + 10);
			else if (entity[i] >= 'a' && entity[i] <= 'f')
				c = (c << 4) + (entity[i] - 'a' + 10);
			else
				return nil;
		}
	} else {
		for (i = 0; i < length; i++) {
			if (entity[i] >= '0' && entity[i] <= '9')
				c = (c * 10) + (entity[i] - '0');
			else
				return nil;
		}
	}

	if ((i = of_string_unicode_to_utf8(c, buf)) == 0)
		return nil;
	buf[i] = 0;

	return [OFString stringWithCString: buf
				    length: i];
}

@implementation OFXMLParser
+ xmlParser
{
	return [[[self alloc] init] autorelease];
}

- init







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







49
50
51
52
53
54
55
















































56
57
58
59
60
61
62
		if ((tmp = [carray[i] objectForKey: prefix]) != nil)
			return tmp;
	}

	return nil;
}

















































@implementation OFXMLParser
+ xmlParser
{
	return [[[self alloc] init] autorelease];
}

- init
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
}

- (OFString*)didFindUnknownEntityNamed: (OFString*)entity
{
	return [delegate xmlParser: self
	 didFindUnknownEntityNamed: entity];
}
@end

@implementation OFString (OFXMLUnescaping)
- (OFString*)stringByXMLUnescaping
{
	return [self stringByXMLUnescapingWithHandler: nil];
}

- (OFString*)stringByXMLUnescapingWithHandler:
    (OFObject <OFXMLUnescapingDelegate>*)h
{
	size_t i, last;
	BOOL in_entity;
	OFMutableString *ret;

	last = 0;
	in_entity = NO;
	ret = [OFMutableString string];

	switch (of_string_check_utf8(string, length)) {
	case 1:
		((OFString*)ret)->isUTF8 = YES;
		break;
	case -1:
		@throw [OFInvalidEncodingException newWithClass: isa];
	}

	for (i = 0; i < length; i++) {
		if (!in_entity && string[i] == '&') {
			[ret appendCStringWithoutUTF8Checking: string + last
						       length: i - last];

			last = i + 1;
			in_entity = YES;
		} else if (in_entity && string[i] == ';') {
			char *entity = string + last;
			size_t len = i - last;

			if (len == 2 && !memcmp(entity, "lt", 2))
				[ret appendCStringWithoutUTF8Checking: "<"
							       length: 1];
			else if (len == 2 && !memcmp(entity, "gt", 2))
				[ret appendCStringWithoutUTF8Checking: ">"
							       length: 1];
			else if (len == 4 && !memcmp(entity, "quot", 4))
				[ret appendCStringWithoutUTF8Checking: "\""
							       length: 1];
			else if (len == 4 && !memcmp(entity, "apos", 4))
				[ret appendCStringWithoutUTF8Checking: "'"
							       length: 1];
			else if (len == 3 && !memcmp(entity, "amp", 3))
				[ret appendCStringWithoutUTF8Checking: "&"
							       length: 1];
			else if (entity[0] == '#') {
				OFAutoreleasePool *pool;
				OFString *tmp;

				pool = [[OFAutoreleasePool alloc] init];
				tmp = parse_numeric_entity(entity, len);

				if (tmp == nil)
					@throw [OFInvalidEncodingException
					    newWithClass: isa];

				[ret appendString: tmp];
				[pool release];
			} else if (h != nil) {
				OFAutoreleasePool *pool;
				OFString *n, *tmp;

				pool = [[OFAutoreleasePool alloc] init];

				n = [OFString stringWithCString: entity
							 length: len];
				tmp = [h didFindUnknownEntityNamed: n];

				if (tmp == nil)
					@throw [OFInvalidEncodingException
					    newWithClass: isa];

				[ret appendString: tmp];
				[pool release];
			} else
				@throw [OFInvalidEncodingException
				    newWithClass: isa];

			last = i + 1;
			in_entity = NO;
		}
	}

	if (in_entity)
		@throw [OFInvalidEncodingException newWithClass: isa];

	[ret appendCStringWithoutUTF8Checking: string + last
				       length: i - last];

	return ret;
}
@end

@implementation OFObject (OFXMLParserDelegate)
-     (void)xmlParser: (OFXMLParser*)parser
  didStartTagWithName: (OFString*)name
	       prefix: (OFString*)prefix
	    namespace: (OFString*)ns







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







635
636
637
638
639
640
641



































































































642
643
644
645
646
647
648
}

- (OFString*)didFindUnknownEntityNamed: (OFString*)entity
{
	return [delegate xmlParser: self
	 didFindUnknownEntityNamed: entity];
}



































































































@end

@implementation OFObject (OFXMLParserDelegate)
-     (void)xmlParser: (OFXMLParser*)parser
  didStartTagWithName: (OFString*)name
	       prefix: (OFString*)prefix
	    namespace: (OFString*)ns

Modified tests/Makefile from [5eb1ee19f8] to [d7331cc9cf].

1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
include ../extra.mk

SUBDIRS = ${TESTPLUGIN}

PROG_NOINST = tests${PROG_SUFFIX}
SRCS = OFArrayTests.m		\
       OFDataArrayTests.m	\
       OFDictionaryTests.m	\
       OFFileTests.m		\
       OFHashTests.m		\
       OFListTests.m		\
       OFNumberTests.m		\
       OFObjectTests.m		\
       ${OFPLUGINTESTS_M}	\

       OFStreamTests.m		\
       OFStringTests.m		\
       OFTCPSocketTests.m	\
       ${OFTHREADTESTS_M}	\
       OFXMLElementTests.m	\
       OFXMLParserTests.m	\
       ${PROPERTIESTESTS_M}	\









|
|



>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
include ../extra.mk

SUBDIRS = ${TESTPLUGIN}

PROG_NOINST = tests${PROG_SUFFIX}
SRCS = OFArrayTests.m		\
       OFDataArrayTests.m	\
       OFDictionaryTests.m	\
       OFFileTests.m		\
       OFListTests.m		\
       OFMD5HashTests.m		\
       OFNumberTests.m		\
       OFObjectTests.m		\
       ${OFPLUGINTESTS_M}	\
       OFSHA1HashTests.m	\
       OFStreamTests.m		\
       OFStringTests.m		\
       OFTCPSocketTests.m	\
       ${OFTHREADTESTS_M}	\
       OFXMLElementTests.m	\
       OFXMLParserTests.m	\
       ${PROPERTIESTESTS_M}	\

Deleted tests/OFHashTests.m version [b953a9142a].

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
/*
 * Copyright (c) 2008 - 2010
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE included in
 * the packaging of this file.
 */

#include "config.h"

#include <string.h>

#import "OFHash.h"
#import "OFFile.h"
#import "OFAutoreleasePool.h"
#import "OFString.h"
#import "OFExceptions.h"

#import "TestsAppDelegate.h"

static OFString *module = @"OFHash";

const uint8_t testfile_md5[OF_MD5_DIGEST_SIZE] =
	"\x00\x8B\x9D\x1B\x58\xDF\xF8\xFE\xEE\xF3\xAE\x8D\xBB\x68\x2D\x38";
const uint8_t testfile_sha1[OF_SHA1_DIGEST_SIZE] =
	"\xC9\x9A\xB8\x7E\x1E\xC8\xEC\x65\xD5\xEB\xE4\x2E\x0D\xA6\x80\x96\xF5"
	"\x94\xE7\x17";

@implementation TestsAppDelegate (OFHashTests)
- (void)hashTests
{
	OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];
	OFMD5Hash *md5;
	OFSHA1Hash *sha1;
	OFFile *f = [OFFile fileWithPath: @"testfile.bin"
				    mode: @"rb"];

	TEST(@"+[md5Hash]", (md5 = [OFMD5Hash md5Hash]))

	TEST(@"+[sha1Hash]", (sha1 = [OFSHA1Hash sha1Hash]))

	while (![f atEndOfStream]) {
		char buf[64];
		size_t len = [f readNBytes: 64
				intoBuffer: buf];
		[md5 updateWithBuffer: buf
			       ofSize: len];
		[sha1 updateWithBuffer: buf
				ofSize: len];
	}
	[f close];

	TEST(@"-[digest]",
	    !memcmp([md5 digest], testfile_md5, OF_MD5_DIGEST_SIZE) &&
	    !memcmp([sha1 digest], testfile_sha1, OF_MD5_DIGEST_SIZE))

	EXPECT_EXCEPTION(@"Detect invalid call of -[updateWithBuffer] #1",
	    OFHashAlreadyCalculatedException, [md5 updateWithBuffer: ""
							     ofSize: 1])
	EXPECT_EXCEPTION(@"Detect invalid call of -[updateWithBuffer] #2",
	    OFHashAlreadyCalculatedException, [sha1 updateWithBuffer: ""
							      ofSize: 1])

	[pool drain];
}
@end
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<










































































































































Added tests/OFMD5HashTests.m version [2445ed3eca].





















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008 - 2010
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE included in
 * the packaging of this file.
 */

#include "config.h"

#include <string.h>

#import "OFMD5Hash.h"
#import "OFFile.h"
#import "OFAutoreleasePool.h"
#import "OFString.h"
#import "OFExceptions.h"

#import "TestsAppDelegate.h"

static OFString *module = @"OFMD5Hash";

const uint8_t testfile_md5[OF_MD5_DIGEST_SIZE] =
	"\x00\x8B\x9D\x1B\x58\xDF\xF8\xFE\xEE\xF3\xAE\x8D\xBB\x68\x2D\x38";

@implementation TestsAppDelegate (OFMD5HashTests)
- (void)MD5HashTests
{
	OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];
	OFMD5Hash *md5;
	OFFile *f = [OFFile fileWithPath: @"testfile.bin"
				    mode: @"rb"];

	TEST(@"+[md5Hash]", (md5 = [OFMD5Hash md5Hash]))


	while (![f atEndOfStream]) {
		char buf[64];
		size_t len = [f readNBytes: 64
				intoBuffer: buf];
		[md5 updateWithBuffer: buf
			       ofSize: len];
	}
	[f close];

	TEST(@"-[digest]",
	    !memcmp([md5 digest], testfile_md5, OF_MD5_DIGEST_SIZE))

	EXPECT_EXCEPTION(@"Detect invalid call of -[updateWithBuffer]",
	    OFHashAlreadyCalculatedException, [md5 updateWithBuffer: ""
							     ofSize: 1])

	[pool drain];
}
@end

Added tests/OFSHA1HashTests.m version [cd8e81d091].





















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008 - 2010
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE included in
 * the packaging of this file.
 */

#include "config.h"

#include <string.h>

#import "OFSHA1Hash.h"
#import "OFFile.h"
#import "OFAutoreleasePool.h"
#import "OFString.h"
#import "OFExceptions.h"

#import "TestsAppDelegate.h"

static OFString *module = @"OFHash";

const uint8_t testfile_sha1[OF_SHA1_DIGEST_SIZE] =
	"\xC9\x9A\xB8\x7E\x1E\xC8\xEC\x65\xD5\xEB\xE4\x2E\x0D\xA6\x80\x96\xF5"
	"\x94\xE7\x17";

@implementation TestsAppDelegate (SHA1HashTests)
- (void)SHA1HashTests
{
	OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];
	OFSHA1Hash *sha1;
	OFFile *f = [OFFile fileWithPath: @"testfile.bin"
				    mode: @"rb"];

	TEST(@"+[sha1Hash]", (sha1 = [OFSHA1Hash sha1Hash]))

	while (![f atEndOfStream]) {
		char buf[64];
		size_t len = [f readNBytes: 64
				intoBuffer: buf];
		[sha1 updateWithBuffer: buf
				ofSize: len];
	}
	[f close];

	TEST(@"-[digest]",
	    !memcmp([sha1 digest], testfile_sha1, OF_SHA1_DIGEST_SIZE))

	EXPECT_EXCEPTION(@"Detect invalid call of -[updateWithBuffer]",
	    OFHashAlreadyCalculatedException, [sha1 updateWithBuffer: ""
							      ofSize: 1])

	[pool drain];
}
@end

Modified tests/OFStringTests.m from [b8a81af19d] to [db370d10b8].

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

static OFString *module = @"OFString";
static OFString* whitespace[] = {
	@" \r \t\n\t \tasd  \t \t\t\r\n",
	@" \t\t  \t\t  \t \t"
};

@interface EntityHandler: OFObject <OFXMLUnescapingDelegate>
@end

@implementation EntityHandler
- (OFString*)didFindUnknownEntityNamed: (OFString*)entity
{
	if ([entity isEqual: @"foo"])
		return @"bar";







|







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

static OFString *module = @"OFString";
static OFString* whitespace[] = {
	@" \r \t\n\t \tasd  \t \t\t\r\n",
	@" \t\t  \t\t  \t \t"
};

@interface EntityHandler: OFObject <OFStringXMLUnescapingDelegate>
@end

@implementation EntityHandler
- (OFString*)didFindUnknownEntityNamed: (OFString*)entity
{
	if ([entity isEqual: @"foo"])
		return @"bar";

Modified tests/TestsAppDelegate.h from [acc81e847c] to [2d4213ddaa].

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
- (void)dictionaryTests;
@end

@interface TestsAppDelegate (OFFileTests)
- (void)fileTests;
@end

@interface TestsAppDelegate (OFHashTests)
- (void)hashTests;
@end

@interface TestsAppDelegate (OFListTests)
- (void)listTests;
@end





@interface TestsAppDelegate (OFNumberTests)
- (void)numberTests;
@end

@interface TestsAppDelegate (OFObjectTests)
- (void)objectTests;
@end

@interface TestsAppDelegate (OFPluginTests)
- (void)pluginTests;
@end

@interface TestsAppDelegate (PropertiesTests)
- (void)propertiesTests;
@end





@interface TestsAppDelegate (OFStreamTests)
- (void)streamTests;
@end

@interface TestsAppDelegate (OFStringTests)
- (void)stringTests;







<
<
<
<



>
>
>
>
















>
>
>
>







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
- (void)dictionaryTests;
@end

@interface TestsAppDelegate (OFFileTests)
- (void)fileTests;
@end





@interface TestsAppDelegate (OFListTests)
- (void)listTests;
@end

@interface TestsAppDelegate (OFMD5HashTests)
- (void)MD5HashTests;
@end

@interface TestsAppDelegate (OFNumberTests)
- (void)numberTests;
@end

@interface TestsAppDelegate (OFObjectTests)
- (void)objectTests;
@end

@interface TestsAppDelegate (OFPluginTests)
- (void)pluginTests;
@end

@interface TestsAppDelegate (PropertiesTests)
- (void)propertiesTests;
@end

@interface TestsAppDelegate (OFSHA1HashTests)
- (void)SHA1HashTests;
@end

@interface TestsAppDelegate (OFStreamTests)
- (void)streamTests;
@end

@interface TestsAppDelegate (OFStringTests)
- (void)stringTests;

Modified tests/TestsAppDelegate.m from [0d39b5669b] to [3a8f0dc730].

75
76
77
78
79
80
81
82

83
84
85
86
87
88
89
}

- (void)applicationDidFinishLaunching
{
	[self objectTests];
	[self stringTests];
	[self fileTests];
	[self hashTests];

	[self dataArrayTests];
	[self arrayTests];
	[self dictionaryTests];
	[self listTests];
	[self numberTests];
	[self streamTests];
	[self TCPSocketTests];







|
>







75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
}

- (void)applicationDidFinishLaunching
{
	[self objectTests];
	[self stringTests];
	[self fileTests];
	[self MD5HashTests];
	[self SHA1HashTests];
	[self dataArrayTests];
	[self arrayTests];
	[self dictionaryTests];
	[self listTests];
	[self numberTests];
	[self streamTests];
	[self TCPSocketTests];