Skip to content

Commit cf6309d

Browse files
committed
Add MD5 computation with base64
1 parent ac64642 commit cf6309d

File tree

1 file changed

+88
-7
lines changed

1 file changed

+88
-7
lines changed

devserver/main.cc

Lines changed: 88 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
using bazel::tools::cpp::runfiles::Runfiles;
1616
using ::nlohmann::json;
1717

18+
using Path = std::string;
19+
using FileContents = std::string;
20+
1821
bool DEBUG = false;
1922

2023
#define DEBUG_LOG(msg) \
@@ -24,6 +27,70 @@ constexpr char kWorkspaceName[] = "rules_devserver";
2427
constexpr int kDefaultPort = 8080;
2528
constexpr char kHost[] = "localhost";
2629

30+
/*
31+
* Base64 encoding/decoding (RFC1341)
32+
* Copyright (c) 2005-2011, Jouni Malinen <[email protected]>
33+
*
34+
* This software may be distributed under the terms of the BSD license.
35+
* See README for more details.
36+
*/
37+
38+
// 2016-12-12 - Gaspard Petit : Slightly modified to return a std::string
39+
// instead of a buffer allocated with malloc.
40+
41+
#include <string>
42+
43+
static const unsigned char base64_table[65] =
44+
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
45+
46+
/**
47+
* base64_encode - Base64 encode
48+
* @src: Data to be encoded
49+
* @len: Length of the data to be encoded
50+
* @out_len: Pointer to output length variable, or %NULL if not used
51+
* Returns: Allocated buffer of out_len bytes of encoded data,
52+
* or empty string on failure
53+
*/
54+
std::string base64_encode(const unsigned char *src, size_t len) {
55+
unsigned char *out, *pos;
56+
const unsigned char *end, *in;
57+
58+
size_t olen;
59+
60+
olen = 4 * ((len + 2) / 3); /* 3-byte blocks to 4-byte */
61+
62+
if (olen < len) return std::string(); /* integer overflow */
63+
64+
std::string outStr;
65+
outStr.resize(olen);
66+
out = (unsigned char *)&outStr[0];
67+
68+
end = src + len;
69+
in = src;
70+
pos = out;
71+
while (end - in >= 3) {
72+
*pos++ = base64_table[in[0] >> 2];
73+
*pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)];
74+
*pos++ = base64_table[((in[1] & 0x0f) << 2) | (in[2] >> 6)];
75+
*pos++ = base64_table[in[2] & 0x3f];
76+
in += 3;
77+
}
78+
79+
if (end - in) {
80+
*pos++ = base64_table[in[0] >> 2];
81+
if (end - in == 1) {
82+
*pos++ = base64_table[(in[0] & 0x03) << 4];
83+
*pos++ = '=';
84+
} else {
85+
*pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)];
86+
*pos++ = base64_table[(in[1] & 0x0f) << 2];
87+
}
88+
*pos++ = '=';
89+
}
90+
91+
return outStr;
92+
}
93+
2794
struct Arguments {
2895
int32_t port;
2996
std::string static_file;
@@ -38,10 +105,22 @@ std::string GetFileContents(const std::string &path) {
38105
return content;
39106
}
40107

41-
json ComputeManifest() {
108+
json ComputeManifest(const std::map<Path, FileContents> &path_to_contents) {
42109
json manifest;
43110

44-
manifest["manifest"] = {{"/", "123"}};
111+
for (const auto &path_and_contents : path_to_contents) {
112+
Path path = path_and_contents.first;
113+
FileContents contents = path_and_contents.second;
114+
115+
picohash_ctx_t ctx;
116+
char digest[PICOHASH_MD5_DIGEST_LENGTH];
117+
118+
picohash_init_md5(&ctx);
119+
picohash_update(&ctx, &contents, contents.size());
120+
picohash_final(&ctx, digest);
121+
std::string digest_str(base64_encode(digest, PICOHASH_MD5_DIGEST_LENGTH));
122+
manifest[path] = digest_str;
123+
}
45124

46125
return manifest;
47126
}
@@ -93,7 +172,7 @@ Arguments ParseArguments(int argc, char **argv) {
93172
parser, "static_file", "Index file to serve from top-level / route",
94173
{"static_file"});
95174
args::ValueFlag<std::string> workspace_name_arg(
96-
parser, "workspace_name", "Calling Bazel workspace name",
175+
parser, "workspace_name", "Cgalling Bazel workspace name",
97176
{"workspace_name"});
98177
args::ValueFlag<std::string> package_name(parser, "package_name",
99178
"Package name", {"package_name"});
@@ -148,8 +227,10 @@ int main(int argc, char **argv) {
148227
static_file_contents =
149228
AddDevserverLoaderToStaticFileContents(static_file_contents);
150229

151-
const std::map<std::string, std::string> path_to_contents = {{"/", "123"}};
152-
const json manifest = ComputeManifest();
230+
const std::map<std::string, std::string> path_to_contents = {
231+
{"/", static_file_contents}};
232+
json manifest = ComputeManifest(path_to_contents);
233+
std::cout << "manifest: " << manifest.dump() << std::endl;
153234

154235
svr.Get("/", [&static_file_contents](const httplib::Request &req,
155236
httplib::Response &res) {
@@ -164,8 +245,8 @@ int main(int argc, char **argv) {
164245
});
165246

166247
svr.Get("/devserver/manifest",
167-
[](const httplib::Request &req, httplib::Response &res) {
168-
res.set_content(ComputeManifest().dump(), "application/json");
248+
[&manifest](const httplib::Request &req, httplib::Response &res) {
249+
res.set_content(manifest.dump(), "application/json");
169250
});
170251

171252
svr.listen(kHost, port);

0 commit comments

Comments
 (0)