本程序依赖 c99, 只支持终端“标准输入”,转换成的链接以”标准输出“而输出,错误以”标出错误输出“而输出。
md4 编码代码来自网络。
编译命令:gcc -std=c99 -o ed2k md4.c ed2k.c utils.c
用户命令:ed2k <File...>
产生的链是最简短的形式:ed2k://|file|<FileName>|<FileSize>|<FileHash>|/
c++版本:
编译命令:g++ -o ed2k ed2k.cpp utils.cpp MD4Hash.cpp ED2KHash.cpp
用户命令:ed2k <File...> (虽然--help可以看到其它选项,但都没实现)
defs.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
#ifndef MYCODE_DEFS_H #define MYCODE_DEFS_H #include <stdint.h> /* uint32_t ... */ #include <stddef.h> /* size_t, ssize_t */ #include <stdbool.h> #endif #if __cplusplus # define BEGIN_NAMESPACE_MYCODE namespace mc { # define END_NAMESPACE_MYCODE } # if __cplusplus < 201103L # define nullptr ((void*)0) # endif #endif /* __cplusplus */ #endif /* MYCODE_DEFS_H */ |
utils.h
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
|
#ifndef MYCODE_UTILS_H #define MYCODE_UTILS_H #include <stdio.h> #if __cplusplus # include <utility> # include <string> # include <fstream> #endif /* __cplusplus */ #include "defs.h" #if __cplusplus extern "C" { #endif #undef byteswap32 #define byteswap32(x) \ ( (((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24) ) #undef htobe32 #undef htole32 #if __BYTE_ORDER == __LITTLE_ENDIAN # define htobe32(x) byteswap32(x) # define htole32(x) (x) #else # define htobe32(x) (x) # define htole32(x) byteswap32(x) #endif enum { string_npos = ( size_t )-1 }; /* 查找字符串 str 中第一个与 c 匹配的字符,返回该字符在字符串中的下标, 失败返回 string_npos */ size_t string_find( const char *str, size_t size, char c); /* 逆向查找*/ size_t string_rfind( const char *str, size_t size, char c); void setBigEndian_uint32(uint32_t *data, size_t n); char * toHexString_uint32( char *buf, size_t bufSize, const uint32_t *data, size_t n); char * createShortFileName( char *buf, size_t bufSize, const char *fullName, size_t size); /* 成功时返回指针 fullName 某部分的地址, 失败时返回 NULL */ const char * getShortFileName( const char * fullName, size_t size); /* 当返回0大小时, 需要检查state, state == 0 表示失败 */ size_t getFileSize( FILE *in, int *state); #if __cplusplus } /* extern "C" */ #endif /****************************************************************************** * c++ *****************************************************************************/ #if __cplusplus BEGIN_NAMESPACE_MYCODE # if __cplusplus >= 201103L # define mc_move(x) std::move(x) # else # define mc_move(x) (x); # endif /////////////////////////////////////////////////////////////////////////////// template < class T> void setBigEndian(T*, size_t ); template <> inline void setBigEndian<uint32_t>(uint32_t *p, size_t n) { setBigEndian_uint32(p, n); } /////////////////////////////////////////////////////////////////////////////// template < class T> std::string toHexString(T*, size_t ); template <> inline std::string toHexString<uint32_t>(uint32_t *p, size_t n) { std::string strHex; char buf[9]; for ( size_t i = 0; i < n; ++i) { sprintf (buf, "%08X" , p[i]); strHex += buf; } return mc_move(strHex); } /////////////////////////////////////////////////////////////////////////////// std::string getShortFileName( const std::string& fullName); void getShortFileName(std::string *shortName, const std::string& fullName); size_t getFileSize(std::ifstream& f); END_NAMESPACE_MYCODE #endif /* __cplusplus */ #endif /* MYCODE_UTILS_H */ |
utils.c
1
|
#include "utils.cpp" |
utils.cpp
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
|
#include <string.h> #include "utils.h" #if __cplusplus extern "C" { #endif void setBigEndian_uint32(uint32_t *data, size_t n) { for ( size_t i = 0; i < n; ++i) data[i] = htobe32(data[i]); } char * toHexString_uint32( char *buf, size_t bufSize, const uint32_t *data, size_t n) { char *p = buf; size_t i = 0; size_t one_uint32_size = sizeof (uint32_t); if ( one_uint32_size * n < bufSize ) { while (i < n) { sprintf (p, "%08X" , data[i++]); p += 8; } } *p = '\0' ; return buf; } size_t string_find( const char *str, size_t size, char c) { size_t pos = 0; while (pos < size) { if (str[pos] == c) return pos; ++pos; } return string_npos; } size_t string_rfind( const char *str, size_t size, char c) { while (size) { if (str[--size] == c) return size; } return string_npos; } char * createShortFileName( char *buf, size_t bufSize, const char *fullName, size_t size) { const char * p = getShortFileName(fullName, size); buf[0] = '\0' ; if (p) { size_t len = strlen (p); if (bufSize > len) memcpy (buf, p, len + 1); } return buf; } const char * getShortFileName( const char *fileName, size_t size) { #if _WIN32 char c = '\\' ; #else char c = '/' ; #endif size_t pos = string_rfind(fileName, size, c); if (pos == string_npos) return NULL; else return fileName + (pos + 1); } size_t getFileSize( FILE *in, int *state) { *state = 0; if (!in) return 0; size_t curpos = ftell (in); if ( fseek (in, 0, SEEK_END) == -1) return 0; size_t fileSize = ftell (in); if ( fseek (in, curpos, SEEK_SET) == -1) return 0; *state = 1; return fileSize; } #if __cplusplus } /* extern "C" */ #endif /****************************************************************************** * c++ *****************************************************************************/ #if __cplusplus BEGIN_NAMESPACE_MYCODE void getShortFileName(std::string *shortName, const std::string& fullName) { # if _WIN32 char c = '\\' ; # else char c = '/' ; # endif size_t pos = fullName.rfind(c); if (pos == std::string::npos) shortName->assign(fullName); else shortName->assign(fullName.begin() + pos + 1, fullName.end()); } std::string getShortFileName( const std::string& fullName) { std::string shortName; getShortFileName(&shortName, fullName); return mc_move(shortName); } size_t getFileSize(std::ifstream& f) { f.seekg(0, f.end); size_t fileSize = f.tellg(); f.seekg(0); return fileSize; } END_NAMESPACE_MYCODE #endif /* __cplusplus */ |
md4.h
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
|
#ifndef MYCODE_MD4_H #define MYCODE_MD4_H #include "defs.h" #if __cplusplus extern "C" { #endif enum { MD4_COUNT_SIZE = 8, MD4_STATE_SIZE = 16, MD4_BUFFER_SIZE = 64 }; typedef struct { uint32_t count[2]; uint32_t state[4]; uint8_t buffer[MD4_BUFFER_SIZE]; } md4_t; #define md4_data(md4_ptr) ((char*)((md4_ptr)->state)) #define md4_cdata(md4_ptr) ((const char*)((md4_ptr)->state)) #define md4_dataSize() (MD4_STATE_SIZE) void md4_reset(md4_t *md4); void md4_update(md4_t *md4, const char *src, size_t srcSize); void md4_finish(md4_t *md4); void md4_setBigEndian(md4_t *md4); char * md4_toHashString( char dest[33], const md4_t *md4); #if __cplusplus } #endif #endif /* MYCODE_MD4_H */ |
md4.c
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
|
/* #include <endian.h> */ #include <stdio.h> #include <string.h> #include "utils.h" #include "md4.h" #if __cplusplus extern "C" { #endif #if __BYTE_ORDER == __LITTLE_ENDIAN # define md4_htole32_4(buf) /* empty */ # define md4_htole32_14(buf) /* empty */ # define md4_htole32_16(buf) /* empty */ #else # define md4_htole32_4(buf) \ (buf)[ 0] = htole32((buf)[ 0]); \ (buf)[ 1] = htole32((buf)[ 1]); \ (buf)[ 2] = htole32((buf)[ 2]); \ (buf)[ 3] = htole32((buf)[ 3]) # define md4_htole32_14(buf) \ (buf)[ 0] = htole32((buf)[ 0]); \ (buf)[ 1] = htole32((buf)[ 1]); \ (buf)[ 2] = htole32((buf)[ 2]); \ (buf)[ 3] = htole32((buf)[ 3]); \ (buf)[ 4] = htole32((buf)[ 4]); \ (buf)[ 5] = htole32((buf)[ 5]); \ (buf)[ 6] = htole32((buf)[ 6]); \ (buf)[ 7] = htole32((buf)[ 7]); \ (buf)[ 8] = htole32((buf)[ 8]); \ (buf)[ 9] = htole32((buf)[ 9]); \ (buf)[10] = htole32((buf)[10]); \ (buf)[11] = htole32((buf)[11]); \ (buf)[12] = htole32((buf)[12]); \ (buf)[13] = htole32((buf)[13]) # define md4_htole32_16(buf) \ (buf)[ 0] = htole32((buf)[ 0]); \ (buf)[ 1] = htole32((buf)[ 1]); \ (buf)[ 2] = htole32((buf)[ 2]); \ (buf)[ 3] = htole32((buf)[ 3]); \ (buf)[ 4] = htole32((buf)[ 4]); \ (buf)[ 5] = htole32((buf)[ 5]); \ (buf)[ 6] = htole32((buf)[ 6]); \ (buf)[ 7] = htole32((buf)[ 7]); \ (buf)[ 8] = htole32((buf)[ 8]); \ (buf)[ 9] = htole32((buf)[ 9]); \ (buf)[10] = htole32((buf)[10]); \ (buf)[11] = htole32((buf)[11]); \ (buf)[12] = htole32((buf)[12]); \ (buf)[13] = htole32((buf)[13]); \ (buf)[14] = htole32((buf)[14]); \ (buf)[15] = htole32((buf)[15]) #endif /* #define F1(x, y, z) (x & y | ~x & z) */ #define F1(x, y, z) (z ^ (x & (y ^ z))) #define F2(x, y, z) ((x & y) | (x & z) | (y & z)) #define F3(x, y, z) (x ^ y ^ z) /* This is the central step in the MD4 algorithm. */ #define MD4STEP(f, w, x, y, z, data, s) \ ( w += f(x, y, z) + data, w = w<<s | w>>(32-s) ) static void md4_transform(uint32_t *state, const uint8_t *buffer) { uint32_t a, b, c, d; const uint32_t *src = ( const uint32_t *)buffer; a = state[0]; b = state[1]; c = state[2]; d = state[3]; MD4STEP(F1, a, b, c, d, src[ 0], 3); MD4STEP(F1, d, a, b, c, src[ 1], 7); MD4STEP(F1, c, d, a, b, src[ 2], 11); MD4STEP(F1, b, c, d, a, src[ 3], 19); MD4STEP(F1, a, b, c, d, src[ 4], 3); MD4STEP(F1, d, a, b, c, src[ 5], 7); MD4STEP(F1, c, d, a, b, src[ 6], 11); MD4STEP(F1, b, c, d, a, src[ 7], 19); MD4STEP(F1, a, b, c, d, src[ 8], 3); MD4STEP(F1, d, a, b, c, src[ 9], 7); MD4STEP(F1, c, d, a, b, src[10], 11); MD4STEP(F1, b, c, d, a, src[11], 19); MD4STEP(F1, a, b, c, d, src[12], 3); MD4STEP(F1, d, a, b, c, src[13], 7); MD4STEP(F1, c, d, a, b, src[14], 11); MD4STEP(F1, b, c, d, a, src[15], 19); MD4STEP(F2, a, b, c, d, src[ 0] + 0x5a827999, 3); MD4STEP(F2, d, a, b, c, src[ 4] + 0x5a827999, 5); MD4STEP(F2, c, d, a, b, src[ 8] + 0x5a827999, 9); MD4STEP(F2, b, c, d, a, src[12] + 0x5a827999, 13); MD4STEP(F2, a, b, c, d, src[ 1] + 0x5a827999, 3); MD4STEP(F2, d, a, b, c, src[ 5] + 0x5a827999, 5); MD4STEP(F2, c, d, a, b, src[ 9] + 0x5a827999, 9); MD4STEP(F2, b, c, d, a, src[13] + 0x5a827999, 13); MD4STEP(F2, a, b, c, d, src[ 2] + 0x5a827999, 3); MD4STEP(F2, d, a, b, c, src[ 6] + 0x5a827999, 5); MD4STEP(F2, c, d, a, b, src[10] + 0x5a827999, 9); MD4STEP(F2, b, c, d, a, src[14] + 0x5a827999, 13); MD4STEP(F2, a, b, c, d, src[ 3] + 0x5a827999, 3); MD4STEP(F2, d, a, b, c, src[ 7] + 0x5a827999, 5); MD4STEP(F2, c, d, a, b, src[11] + 0x5a827999, 9); MD4STEP(F2, b, c, d, a, src[15] + 0x5a827999, 13); MD4STEP(F3, a, b, c, d, src[ 0] + 0x6ed9eba1, 3); MD4STEP(F3, d, a, b, c, src[ 8] + 0x6ed9eba1, 9); MD4STEP(F3, c, d, a, b, src[ 4] + 0x6ed9eba1, 11); MD4STEP(F3, b, c, d, a, src[12] + 0x6ed9eba1, 15); MD4STEP(F3, a, b, c, d, src[ 2] + 0x6ed9eba1, 3); MD4STEP(F3, d, a, b, c, src[10] + 0x6ed9eba1, 9); MD4STEP(F3, c, d, a, b, src[ 6] + 0x6ed9eba1, 11); MD4STEP(F3, b, c, d, a, src[14] + 0x6ed9eba1, 15); MD4STEP(F3, a, b, c, d, src[ 1] + 0x6ed9eba1, 3); MD4STEP(F3, d, a, b, c, src[ 9] + 0x6ed9eba1, 9); MD4STEP(F3, c, d, a, b, src[ 5] + 0x6ed9eba1, 11); MD4STEP(F3, b, c, d, a, src[13] + 0x6ed9eba1, 15); MD4STEP(F3, a, b, c, d, src[ 3] + 0x6ed9eba1, 3); MD4STEP(F3, d, a, b, c, src[11] + 0x6ed9eba1, 9); MD4STEP(F3, c, d, a, b, src[ 7] + 0x6ed9eba1, 11); MD4STEP(F3, b, c, d, a, src[15] + 0x6ed9eba1, 15); state[0] += a; state[1] += b; state[2] += c; state[3] += d; } void md4_reset(md4_t *md4) { md4->count[0] = 0; md4->count[1] = 0; md4->state[0] = 0x67452301; md4->state[1] = 0xEFCDAB89; md4->state[2] = 0x98BADCFE; md4->state[3] = 0x10325476; } void md4_update(md4_t *md4, const char *src, size_t srcSize) { uint32_t count = (uint32_t)((md4->count[0] >> 3) & 0x3f); if ((md4->count[0] += (srcSize << 3)) < (srcSize << 3)) ++(md4->count[1]); md4->count[1] += (srcSize >> 29); if (count > 0) { size_t partSize = MD4_BUFFER_SIZE - count; if (srcSize < partSize) { memcpy (md4->buffer + count, src, srcSize); return ; } memcpy (md4->buffer + count, src, partSize); md4_htole32_16((uint32_t*)md4->buffer); md4_transform(md4->state, md4->buffer); src += partSize; srcSize -= partSize; } while (srcSize >= MD4_BUFFER_SIZE) { memcpy (md4->buffer, src, MD4_BUFFER_SIZE); md4_transform(md4->state, md4->buffer); md4_htole32_16((uint32_t *)md4->buffer); src += MD4_BUFFER_SIZE; srcSize -= MD4_BUFFER_SIZE; } memcpy (md4->buffer, src, srcSize); } void md4_finish(md4_t *md4) { uint32_t count = (uint32_t)((md4->count[0] >> 3) & 0x3f); uint8_t *p = md4->buffer + count; *p++ = 0x80; count = MD4_BUFFER_SIZE - 1 - count; if (count < 8) { memset (p, 0, count); md4_htole32_16((uint32_t *)md4->buffer); md4_transform(md4->state, md4->buffer); memset (md4->buffer, 0, 56); } else { memset (p, 0, count - 8); } md4_htole32_14((uint32_t *)md4->buffer); /* Append bit count and transform */ ((uint32_t *)md4->buffer)[14] = md4->count[0]; ((uint32_t *)md4->buffer)[15] = md4->count[1]; md4_transform(md4->state, md4->buffer); md4_htole32_4(md4->state); memset (md4->buffer, 0, MD4_BUFFER_SIZE); } void md4_setBigEndian(md4_t *md4) { uint32_t *p = md4->state; p[0] = htobe32(p[0]); p[1] = htobe32(p[1]); p[2] = htobe32(p[2]); p[3] = htobe32(p[3]); } char * md4_toHashString( char dest[33], const md4_t *md4) { return toHexString_uint32(dest, 33, md4->state, 4); } #if __cplusplus } #endif |
ed2k.c
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
|
#include <stdlib.h> #include <stdio.h> #include <string.h> #include "defs.h" #include "utils.h" #include "md4.h" enum { CHUNK_SIZE = 9728000, BUFFER_MAX_SIZE = 256 }; bool printEd2kLink( const char *fileName) { FILE *in = fopen (fileName, "rb" ); if (!in) { fprintf (stderr, "error: Open file failed.\n" ); return false ; } size_t fileSize; { int state; if ((fileSize = getFileSize(in, &state)) == 0) { if (state == 0) fprintf (stderr, "error: get fileSize of \'%s\' failed\n" , fileName); else fprintf (stderr, "error: \'%s\' is empty.\n" , fileName); fclose (in); return false ; } } const char *shortFileName = getShortFileName(fileName, strlen (fileName)); if (shortFileName == NULL) { fprintf (stderr, "error: createNewFilename().\n" ); fclose (in); return false ; } static md4_t md4HashSet, md4FileHash; md4_reset(&md4FileHash); static char chunk[CHUNK_SIZE]; size_t readCount; bool bContinue = true ; int chunkCount = 0; while (bContinue) { readCount = fread (chunk, sizeof (chunk[0]), CHUNK_SIZE, in); if (readCount < CHUNK_SIZE) { if ( feof (in)) { if (0 == readCount) break ; bContinue = false ; /* memset(chunk + readCount, 0, CHUNK_SIZE - readCount); */ } else { fprintf (stderr, "error: Read file failed.\n" ); fclose (in); return false ; } } md4_reset(&md4HashSet); md4_update(&md4HashSet, chunk, readCount); md4_finish(&md4HashSet); md4_update(&md4FileHash, md4_data(&md4HashSet), md4_dataSize()); chunkCount++; } static char strHash[33]; if (chunkCount > 1) { md4_finish(&md4FileHash); md4_setBigEndian(&md4FileHash); md4_toHashString(strHash, &md4FileHash); } else { md4_setBigEndian(&md4HashSet); md4_toHashString(strHash, &md4HashSet); } fprintf (stdout, "ed2k://|file|%s|%ld|%s|/\n" , shortFileName, fileSize, strHash); md4_reset(&md4FileHash); fclose (in); return true ; } int main( int argc, const char *argv[]) { if (argc < 2) { fprintf (stderr, "error: argc < 2\n" ); exit (EXIT_FAILURE); } int linkCount = 0; for ( int i = 1; i < argc; ++i) { if (!printEd2kLink(argv[i])) { fprintf (stderr, "Created %d links.\n" ,linkCount); exit (EXIT_FAILURE); } linkCount++; } exit (EXIT_SUCCESS); } |
MD4Hash.h
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
|
#ifndef MYCODE_MD4HASH_H #define MYCODE_MD4HASH_H #include <string> #include <utility> #include "md4.h" #include "defs.h" BEGIN_NAMESPACE_MYCODE class MD4Hash { friend class MD4HashAlgo; struct Data{ uint32_t d[4]; }; public : MD4Hash(); MD4Hash( const MD4Hash& o); #if __cplusplus >= 201103L MD4Hash(MD4Hash&& o); MD4Hash& operator=(MD4Hash&& o); #endif ~MD4Hash(); MD4Hash& operator=( const MD4Hash& o); void setBigEndian(); std::string toString(); void swap(MD4Hash& o) { std::swap(m_data, o.m_data); } private : Data m_data; MD4Hash(uint32_t *data); }; class MD4HashAlgo { md4_t m_md4; public : MD4HashAlgo(); MD4HashAlgo( const MD4HashAlgo& o); #if __cplusplus >= 201103L MD4HashAlgo(MD4HashAlgo&& o); MD4HashAlgo& operator=(MD4HashAlgo&& o); #endif ~MD4HashAlgo(); MD4HashAlgo& operator=( const MD4HashAlgo& o); void reset() { md4_reset(&m_md4); } void update( const char *data, size_t size) { md4_update(&m_md4, data, size); } void update( const MD4Hash& hash) { md4_update(&m_md4, ( const char *)(hash.m_data.d), 16); } void finish() { md4_finish(&m_md4); } MD4Hash getHash() { return MD4Hash(m_md4.state); } size_t hashSize() { return md4_dataSize(); } void swap(MD4HashAlgo& o) { std::swap(m_md4, o.m_md4); } }; END_NAMESPACE_MYCODE #endif /* MYCODE_MD4HASH_H */ |
ED2KHash.h
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
|
#ifndef MYCODE_ED2KHASH_H #define MYCODE_ED2KHASH_H #include <string> #include <iostream> #include "defs.h" BEGIN_NAMESPACE_MYCODE class ED2KHash { public : enum mode { FileHash = 0x01, PartHash = 0x10, RootHash = 0x20, Default = FileHash }; ED2KHash( int mode = ED2KHash::Default); ED2KHash( const ED2KHash& o); ~ED2KHash(); ED2KHash& operator=( const ED2KHash& o); #if __cplusplus >= 201103L ED2KHash(ED2KHash&& o); ED2KHash& operator=(ED2KHash&& o); #endif void exec( const char * fileName); void swap(ED2KHash& o); std::string getFileHash(); friend std::ostream& operator<<(std::ostream& out, const ED2KHash& v); private : int m_mode; size_t m_fileSize; std::string m_fileName; std::string m_fileHash; void copy( const ED2KHash& o); #if __cplusplus >= 201103L void move(ED2KHash& o); #endif }; END_NAMESPACE_MYCODE #endif /* MYCODE_ED2KHASH_H */ |
ED2KHash.cpp
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
|
#include <cstring> #include <fstream> #include <utility> #include "utils.h" #include "MD4Hash.h" #include "ED2KHash.h" BEGIN_NAMESPACE_MYCODE /////////////////////////////////////////////////////////////////////////////// // ED2KHash // /////////////////////////////////////////////////////////////////////////////// ED2KHash::ED2KHash( int mode) : m_mode(mode), m_fileSize(0) { /* empty */ } void ED2KHash::copy( const ED2KHash& o) { m_mode = o.m_mode; m_fileSize = o.m_fileSize; m_fileName = o.m_fileName; m_fileHash = o.m_fileHash; } ED2KHash::ED2KHash( const ED2KHash& o) { copy(o); } ED2KHash& ED2KHash::operator=( const ED2KHash& o) { copy(o); return * this ; } #if __cplusplus >= 201103L void ED2KHash::move(ED2KHash& o) { m_mode = o.m_mode; m_fileSize = o.m_fileSize; m_fileName = std::move(o.m_fileName); m_fileHash = std::move(o.m_fileHash); } ED2KHash::ED2KHash(ED2KHash&& o) { this ->move(o); } ED2KHash& ED2KHash::operator=(ED2KHash&& o) { this ->move(o); return * this ; } #endif ED2KHash::~ED2KHash() { /* empty */ } void ED2KHash::swap(ED2KHash& o) { std::swap(* this , o); } std::string ED2KHash::getFileHash() { return m_fileHash; } enum { CHUNK_SIZE = 9728000 }; enum { BLOCK_180K = 184320, BLOCK_140K = 143360 }; void ED2KHash::exec( const char * fileName) { std::string msg( "error: " ); std::ifstream in(fileName, std::ios_base::binary | std::ios_base::in); if (!in.is_open()) throw msg = msg + "Open \'" + fileName + "\' failed." ; if ((m_fileSize = mc::getFileSize(in)) == 0) throw msg = msg + fileName + " is empty." ; mc::getShortFileName(&m_fileName, fileName); static mc::MD4Hash md4Hash; static mc::MD4HashAlgo partHashMD4Algo, fileHashMD4Algo; fileHashMD4Algo.reset(); static char chunk[CHUNK_SIZE]; size_t readCount; size_t chunkCount = 0; bool bContinue = true ; while (bContinue) { in.read(chunk, CHUNK_SIZE); if ((readCount = in.gcount()) < CHUNK_SIZE) { if (in.eof()) { if (0 == readCount) break ; bContinue = false ; memset (chunk + readCount, 0, CHUNK_SIZE - readCount); } else { throw msg += "Read file failed." ; } } partHashMD4Algo.reset(); partHashMD4Algo.update(chunk, readCount); partHashMD4Algo.finish(); md4Hash = mc_move(partHashMD4Algo.getHash()); fileHashMD4Algo.update(md4Hash); /*if (m_mode & PartHash) { if (bWriteToData) ;// else { md4Hash.setBigEndian(); m_listPartHash.push_back(md4Hash); } }*/ if (m_mode & RootHash) { // } chunkCount++; } if (chunkCount > 1) { fileHashMD4Algo.finish(); md4Hash = mc_move(fileHashMD4Algo.getHash()); md4Hash.setBigEndian(); m_fileHash = mc_move(md4Hash.toString()); } else { md4Hash = mc_move(partHashMD4Algo.getHash()); md4Hash.setBigEndian(); m_fileHash = mc_move(md4Hash.toString()); } } std::ostream& operator<<(std::ostream& out, const ED2KHash& v) { out << "ed2k://|file|" << v.m_fileName << '|' << v.m_fileSize << '|' << v.m_fileHash << '|' ; /*if (v.m_mode | ED2KHash::PartHash) { size_t n = m_listPartHash.size(); m_listPartHash.iterator it = m_listPartHash.begin(); if (n > 0) do { cout << it->getHash().toString(); if (--n == 0) break; ++it; cout << ':'; } while (1); out << '|'; }*/ //if (v.m_mode | ED2KHash::RootHash) // out << '|'; return out << '/' ; } END_NAMESPACE_MYCODE |
ed2k.cpp
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
|
#include <cstdlib> #include <cstring> #include <string> #include <iostream> #include <fstream> #include "utils.h" #include "ED2KHash.h" #include "defs.h" void usage( bool b) { std::cout << "command: ed2k [Option...] <File...>\n" << " ed2k <File...> (1)\n" << " ed2k -r <File...> (2)\n" << " ed2k -p <File...> (3)\n" << " ed2k -p -r <File...> (4)\n" << " ed2k -pr <File...> (4)\n\n" << "(1) ed2k://|file|<FileName>|<FileSize>|<FileHash>|/\n" << "(2) ed2k://|file|<FileName>|<FileSize>|<FileHash>|<h=RootHash>|/\n" << "(3) ed2k://|file|<FileName>|<FileSize>|<FileHash>|<p=PartHash>|/\n" << "(4) ed2k://|file|<FileName>|<FileSize>|<FileHash>|<p=PartHash>|<h=RootHash>|/" << std::endl; if (b) exit (EXIT_SUCCESS); } bool parsed( int argc, const char *argv[], int *opt, int *pos) { if (argc < 2) return false ; if ( strcmp ( "--help" , argv[1]) == 0) usage( true ); if ( strcmp ( "--version" , argv[1]) == 0) { std::cout << "0.1v" << std::endl; exit (EXIT_SUCCESS); } *opt = mc::ED2KHash::FileHash; *pos = 1; for (; *pos < argc; ++(*pos)) { if ( '-' != argv[*pos][0]) break ; int len = strlen (argv[*pos]); for ( int j = 1; j < len; ++j) { if ( 'p' == argv[*pos][j]) *opt |= mc::ED2KHash::PartHash; else if ( 'r' == argv[*pos][j]) *opt |= mc::ED2KHash::RootHash; else { std::cerr << "error: \'" << argv[*pos] << "\' is not a option." << " Enter '--help' veiw usage." << std::endl; return false ; } } } if (*pos == argc) { std::cerr << "error: no parameter." << " Enter '--help' veiw usage." << std::endl; return false ; } return true ; } int main( int argc, const char *argv[]) { int opt, pos; if (!parsed(argc, argv, &opt, &pos)) exit (EXIT_FAILURE); int linkCount = 0; mc::ED2KHash ed2k(opt); for (; pos < argc; ++pos) { try { ed2k.exec(argv[pos]); std::cout << ed2k << std::endl; } catch (std::string& e) { std::cerr << e << "\ncreated " << linkCount << " links." << std::endl; exit (EXIT_FAILURE); } linkCount++; } std::cerr << "\ncreated " << linkCount << " links." << std::endl; exit (EXIT_SUCCESS); } |
以上所述就是本文给大家分享的制作ed2k链的代码了,希望大家能够喜欢。