1 /**
2 	Helper functions.
3 
4 	`hmac_sha1` and `toRFC822DateTime` functions will become obsolete in future versions of Photos.
5 
6 	Copyright: © 2015 sigod
7 	License: Subject to the terms of the MIT license, as written in the included LICENSE file.
8 	Authors: sigod
9 */
10 module s3.internal.helpers;
11 
12 ubyte[20] hmac_sha1(const(ubyte)[] key, const(ubyte)[] message)
13 {
14 	import std.digest.sha : sha1Of;
15 
16 	enum block_size = 64;
17 
18 	if (key.length > block_size)
19 		key = sha1Of(key);
20 	if (key.length < block_size)
21 		key.length = block_size;
22 
23 	ubyte[] o_key_pad = key.dup;
24 	ubyte[] i_key_pad = key.dup;
25 
26 	o_key_pad[] ^= 0x5c;
27 	i_key_pad[] ^= 0x36;
28 
29 	return sha1Of(o_key_pad ~ sha1Of(i_key_pad ~ message));
30 }
31 
32 unittest {
33 	import std.digest.digest : toHexString;
34 
35 	auto value = hmac_sha1(cast(ubyte[])"", cast(ubyte[])"");
36 	assert(value.toHexString == "FBDB1D1B18AA6C08324B7D64B71FB76370690E1D");
37 
38 	value = hmac_sha1(cast(ubyte[])"key", cast(ubyte[])"The quick brown fox jumps over the lazy dog");
39 	assert(value.toHexString == "DE7C9B85B8B78AA6BC8A7A36F70A90701C9DB4D9");
40 }
41 
42 
43 private import std.datetime : SysTime;
44 
45 // example: Tue, 27 Mar 2007 21:06:08 +0000
46 
47 string toRFC822DateTime(in SysTime time) @safe
48 {
49 	import std.format : format;
50 	try
51 	{
52 		auto time_ = time.toUTC();
53 
54 		assert(time_.year >= 1900);
55 
56 		return format("%s, %02d %s %04d %02d:%02d:%02d +0000",
57 			dayToString(time_.dayOfWeek), time_.day, monthToString(time_.month), time_.year,
58 			time_.hour, time_.minute, time_.second
59 		);
60 	}
61 	catch(Exception e)
62 		assert(0, "format() threw.");
63 }
64 
65 private:
66 
67 // private members of std.datetime:
68 
69 import std.datetime;
70 
71 immutable string[12] _monthNames = ["Jan",
72 									"Feb",
73 									"Mar",
74 									"Apr",
75 									"May",
76 									"Jun",
77 									"Jul",
78 									"Aug",
79 									"Sep",
80 									"Oct",
81 									"Nov",
82 									"Dec"];
83 
84 string monthToString(Month month) @safe pure
85 {
86 	import std.format : format;
87 	assert(month >= Month.jan && month <= Month.dec, format("Invalid month: %s", month));
88 	return _monthNames[month - Month.jan];
89 }
90 
91 unittest
92 {
93 	assert(monthToString(Month.jan) == "Jan");
94 	assert(monthToString(Month.feb) == "Feb");
95 	assert(monthToString(Month.mar) == "Mar");
96 	assert(monthToString(Month.apr) == "Apr");
97 	assert(monthToString(Month.may) == "May");
98 	assert(monthToString(Month.jun) == "Jun");
99 	assert(monthToString(Month.jul) == "Jul");
100 	assert(monthToString(Month.aug) == "Aug");
101 	assert(monthToString(Month.sep) == "Sep");
102 	assert(monthToString(Month.oct) == "Oct");
103 	assert(monthToString(Month.nov) == "Nov");
104 	assert(monthToString(Month.dec) == "Dec");
105 }
106 
107 // custom
108 
109 immutable string[7] daysOfWeekNames = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
110 
111 string dayToString(DayOfWeek day) @safe pure
112 {
113 	return daysOfWeekNames[day - DayOfWeek.sun];
114 }
115 
116 unittest
117 {
118 	assert(dayToString(DayOfWeek.sun) == "Sun");
119 	assert(dayToString(DayOfWeek.mon) == "Mon");
120 	assert(dayToString(DayOfWeek.tue) == "Tue");
121 	assert(dayToString(DayOfWeek.wed) == "Wed");
122 	assert(dayToString(DayOfWeek.thu) == "Thu");
123 	assert(dayToString(DayOfWeek.fri) == "Fri");
124 	assert(dayToString(DayOfWeek.sat) == "Sat");
125 }