2 9460dac0 2020-01-15 tracey * Copyright (c) 2019, 2020 Tracey Emery <tracey@traceyemery.net>
3 2c251c14 2020-01-15 tracey * Copyright (c) 2018, 2019 Stefan Sperling <stsp@openbsd.org>
5 2c251c14 2020-01-15 tracey * Permission to use, copy, modify, and distribute this software for any
6 2c251c14 2020-01-15 tracey * purpose with or without fee is hereby granted, provided that the above
7 2c251c14 2020-01-15 tracey * copyright notice and this permission notice appear in all copies.
9 2c251c14 2020-01-15 tracey * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 2c251c14 2020-01-15 tracey * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 2c251c14 2020-01-15 tracey * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 2c251c14 2020-01-15 tracey * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 2c251c14 2020-01-15 tracey * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 2c251c14 2020-01-15 tracey * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 2c251c14 2020-01-15 tracey * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 2c251c14 2020-01-15 tracey #include <sys/queue.h>
19 2c251c14 2020-01-15 tracey #include <sys/stat.h>
20 2c251c14 2020-01-15 tracey #include <sys/types.h>
22 2c251c14 2020-01-15 tracey #include <dirent.h>
23 2c251c14 2020-01-15 tracey #include <err.h>
24 c25c2314 2020-01-28 stsp #include <errno.h>
25 474370cb 2020-01-15 tracey #include <regex.h>
26 2c251c14 2020-01-15 tracey #include <stdarg.h>
27 2c251c14 2020-01-15 tracey #include <stdint.h>
28 2c251c14 2020-01-15 tracey #include <stdio.h>
29 2c251c14 2020-01-15 tracey #include <stdlib.h>
30 2c251c14 2020-01-15 tracey #include <string.h>
31 2c251c14 2020-01-15 tracey #include <unistd.h>
33 2c251c14 2020-01-15 tracey #include <got_object.h>
34 2c251c14 2020-01-15 tracey #include <got_reference.h>
35 2c251c14 2020-01-15 tracey #include <got_repository.h>
36 2c251c14 2020-01-15 tracey #include <got_path.h>
37 2c251c14 2020-01-15 tracey #include <got_cancel.h>
38 2c251c14 2020-01-15 tracey #include <got_worktree.h>
39 2c251c14 2020-01-15 tracey #include <got_diff.h>
40 2c251c14 2020-01-15 tracey #include <got_commit_graph.h>
41 2c251c14 2020-01-15 tracey #include <got_blame.h>
42 2c251c14 2020-01-15 tracey #include <got_privsep.h>
43 2c251c14 2020-01-15 tracey #include <got_opentemp.h>
45 2c251c14 2020-01-15 tracey #include <kcgi.h>
46 2c251c14 2020-01-15 tracey #include <kcgihtml.h>
48 474370cb 2020-01-15 tracey #include "buf.h"
49 2c251c14 2020-01-15 tracey #include "gotweb.h"
50 2c251c14 2020-01-15 tracey #include "gotweb_ui.h"
52 2c251c14 2020-01-15 tracey #ifndef nitems
53 2c251c14 2020-01-15 tracey #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
56 54415d85 2020-01-15 tracey struct gw_trans {
57 f2f46662 2020-01-23 tracey TAILQ_HEAD(headers, gw_header) gw_headers;
58 f2f46662 2020-01-23 tracey TAILQ_HEAD(dirs, gw_dir) gw_dirs;
59 46b9c89b 2020-01-15 tracey struct gw_dir *gw_dir;
60 2c251c14 2020-01-15 tracey struct gotweb_conf *gw_conf;
61 2c251c14 2020-01-15 tracey struct ktemplate *gw_tmpl;
62 2c251c14 2020-01-15 tracey struct khtmlreq *gw_html_req;
63 2c251c14 2020-01-15 tracey struct kreq *gw_req;
64 2c251c14 2020-01-15 tracey char *repo_name;
65 2c251c14 2020-01-15 tracey char *repo_path;
66 2c251c14 2020-01-15 tracey char *commit;
67 2c251c14 2020-01-15 tracey char *repo_file;
68 ec46ccd7 2020-01-15 tracey char *repo_folder;
69 2c251c14 2020-01-15 tracey char *action_name;
70 8087c3c5 2020-01-15 tracey char *headref;
71 2c251c14 2020-01-15 tracey unsigned int action;
72 2c251c14 2020-01-15 tracey unsigned int page;
73 2c251c14 2020-01-15 tracey unsigned int repos_total;
74 387a29ba 2020-01-15 tracey enum kmime mime;
77 f2f46662 2020-01-23 tracey struct gw_header {
78 f2f46662 2020-01-23 tracey TAILQ_ENTRY(gw_header) entry;
79 f2f46662 2020-01-23 tracey struct got_repository *repo;
80 f2f46662 2020-01-23 tracey struct got_reflist_head refs;
81 f2f46662 2020-01-23 tracey struct got_commit_object *commit;
82 f2f46662 2020-01-23 tracey struct got_object_id *id;
83 f2f46662 2020-01-23 tracey char *path;
85 f2f46662 2020-01-23 tracey char *refs_str;
86 f2f46662 2020-01-23 tracey char *commit_id; /* id_str1 */
87 f2f46662 2020-01-23 tracey char *parent_id; /* id_str2 */
88 f2f46662 2020-01-23 tracey char *tree_id;
89 f2f46662 2020-01-23 tracey char *author;
90 f2f46662 2020-01-23 tracey char *committer;
91 f2f46662 2020-01-23 tracey char *commit_msg;
92 f2f46662 2020-01-23 tracey time_t committer_time;
95 2c251c14 2020-01-15 tracey struct gw_dir {
96 2c251c14 2020-01-15 tracey TAILQ_ENTRY(gw_dir) entry;
97 2c251c14 2020-01-15 tracey char *name;
98 2c251c14 2020-01-15 tracey char *owner;
99 2c251c14 2020-01-15 tracey char *description;
100 2c251c14 2020-01-15 tracey char *url;
101 2c251c14 2020-01-15 tracey char *age;
102 2c251c14 2020-01-15 tracey char *path;
105 f2f46662 2020-01-23 tracey enum gw_key {
106 f2f46662 2020-01-23 tracey KEY_ACTION,
107 f2f46662 2020-01-23 tracey KEY_COMMIT_ID,
108 f2f46662 2020-01-23 tracey KEY_FILE,
109 f2f46662 2020-01-23 tracey KEY_FOLDER,
110 f2f46662 2020-01-23 tracey KEY_HEADREF,
111 f2f46662 2020-01-23 tracey KEY_PAGE,
112 f2f46662 2020-01-23 tracey KEY_PATH,
113 f2f46662 2020-01-23 tracey KEY__ZMAX
116 54415d85 2020-01-15 tracey enum gw_tmpl {
117 f2f46662 2020-01-23 tracey TEMPL_CONTENT,
118 2c251c14 2020-01-15 tracey TEMPL_HEAD,
119 2c251c14 2020-01-15 tracey TEMPL_HEADER,
120 f2f46662 2020-01-23 tracey TEMPL_SEARCH,
121 2c251c14 2020-01-15 tracey TEMPL_SITEPATH,
122 2c251c14 2020-01-15 tracey TEMPL_SITEOWNER,
123 2c251c14 2020-01-15 tracey TEMPL_TITLE,
124 2c251c14 2020-01-15 tracey TEMPL__MAX
127 54415d85 2020-01-15 tracey enum gw_ref_tm {
132 54415d85 2020-01-15 tracey enum gw_tags {
133 87f9ebf5 2020-01-15 tracey TAGBRIEF,
137 54415d85 2020-01-15 tracey static const char *const gw_templs[TEMPL__MAX] = {
138 f2f46662 2020-01-23 tracey "content",
140 2c251c14 2020-01-15 tracey "header",
141 f2f46662 2020-01-23 tracey "search",
142 2c251c14 2020-01-15 tracey "sitepath",
143 2c251c14 2020-01-15 tracey "siteowner",
147 ec46ccd7 2020-01-15 tracey static const struct kvalid gw_keys[KEY__ZMAX] = {
148 2c251c14 2020-01-15 tracey { kvalid_stringne, "action" },
149 2c251c14 2020-01-15 tracey { kvalid_stringne, "commit" },
150 2c251c14 2020-01-15 tracey { kvalid_stringne, "file" },
151 ec46ccd7 2020-01-15 tracey { kvalid_stringne, "folder" },
152 8087c3c5 2020-01-15 tracey { kvalid_stringne, "headref" },
153 ec46ccd7 2020-01-15 tracey { kvalid_int, "page" },
154 ec46ccd7 2020-01-15 tracey { kvalid_stringne, "path" },
157 2c251c14 2020-01-15 tracey static struct gw_dir *gw_init_gw_dir(char *);
158 f2f46662 2020-01-23 tracey static struct gw_header *gw_init_header(void);
160 54415d85 2020-01-15 tracey static char *gw_get_repo_description(struct gw_trans *,
162 54415d85 2020-01-15 tracey static char *gw_get_repo_owner(struct gw_trans *,
164 474370cb 2020-01-15 tracey static char *gw_get_time_str(time_t, int);
165 d126c1b7 2020-01-29 stsp static const struct got_error *gw_get_repo_age(char **, struct gw_trans *,
166 387a29ba 2020-01-15 tracey char *, char *, int);
167 e46f587c 2020-01-29 tracey static char *gw_get_file_blame_blob(struct gw_trans *);
168 f2f46662 2020-01-23 tracey static char *gw_get_repo_tree(struct gw_trans *);
169 f2f46662 2020-01-23 tracey static char *gw_get_diff(struct gw_trans *,
170 f2f46662 2020-01-23 tracey struct gw_header *);
171 4ff7391f 2020-01-28 tracey static char *gw_get_repo_tags(struct gw_trans *,
172 4ff7391f 2020-01-28 tracey struct gw_header *, int, int);
173 54415d85 2020-01-15 tracey static char *gw_get_repo_heads(struct gw_trans *);
174 54415d85 2020-01-15 tracey static char *gw_get_clone_url(struct gw_trans *, char *);
175 54415d85 2020-01-15 tracey static char *gw_get_got_link(struct gw_trans *);
176 54415d85 2020-01-15 tracey static char *gw_get_site_link(struct gw_trans *);
177 2c251c14 2020-01-15 tracey static char *gw_html_escape(const char *);
178 d0ea9c5b 2020-01-15 tracey static char *gw_colordiff_line(char *);
180 f2f46662 2020-01-23 tracey static char *gw_gen_commit_header(char *, char*);
181 f2f46662 2020-01-23 tracey static char *gw_gen_diff_header(char *, char*);
182 f2f46662 2020-01-23 tracey static char *gw_gen_author_header(char *);
183 f2f46662 2020-01-23 tracey static char *gw_gen_committer_header(char *);
184 f2f46662 2020-01-23 tracey static char *gw_gen_age_header(char *);
185 f2f46662 2020-01-23 tracey static char *gw_gen_commit_msg_header(char *);
186 f2f46662 2020-01-23 tracey static char *gw_gen_tree_header(char *);
188 f2f46662 2020-01-23 tracey static void gw_free_headers(struct gw_header *);
189 c25c2314 2020-01-28 stsp static const struct got_error* gw_display_open(struct gw_trans *, enum khttp,
190 2c251c14 2020-01-15 tracey enum kmime);
191 6d8d8a26 2020-01-29 stsp static const struct got_error* gw_display_index(struct gw_trans *);
192 6d8d8a26 2020-01-29 stsp static void gw_display_error(struct gw_trans *,
193 2c251c14 2020-01-15 tracey const struct got_error *);
195 2c251c14 2020-01-15 tracey static int gw_template(size_t, void *);
197 f2f46662 2020-01-23 tracey static const struct got_error* gw_get_header(struct gw_trans *,
198 f2f46662 2020-01-23 tracey struct gw_header *, int);
199 f2f46662 2020-01-23 tracey static const struct got_error* gw_get_commits(struct gw_trans *,
200 f2f46662 2020-01-23 tracey struct gw_header *, int);
201 f2f46662 2020-01-23 tracey static const struct got_error* gw_get_commit(struct gw_trans *,
202 f2f46662 2020-01-23 tracey struct gw_header *);
203 54415d85 2020-01-15 tracey static const struct got_error* gw_apply_unveil(const char *, const char *);
204 147269d5 2020-01-15 tracey static const struct got_error* gw_blame_cb(void *, int, int,
205 ec46ccd7 2020-01-15 tracey struct got_object_id *);
206 54415d85 2020-01-15 tracey static const struct got_error* gw_load_got_paths(struct gw_trans *);
207 54415d85 2020-01-15 tracey static const struct got_error* gw_load_got_path(struct gw_trans *,
208 2c251c14 2020-01-15 tracey struct gw_dir *);
209 54415d85 2020-01-15 tracey static const struct got_error* gw_parse_querystring(struct gw_trans *);
211 54415d85 2020-01-15 tracey static const struct got_error* gw_blame(struct gw_trans *);
212 e46f587c 2020-01-29 tracey static const struct got_error* gw_blob(struct gw_trans *);
213 f2f46662 2020-01-23 tracey static const struct got_error* gw_diff(struct gw_trans *);
214 54415d85 2020-01-15 tracey static const struct got_error* gw_index(struct gw_trans *);
215 f2f46662 2020-01-23 tracey static const struct got_error* gw_commits(struct gw_trans *);
216 f2f46662 2020-01-23 tracey static const struct got_error* gw_briefs(struct gw_trans *);
217 54415d85 2020-01-15 tracey static const struct got_error* gw_summary(struct gw_trans *);
218 54415d85 2020-01-15 tracey static const struct got_error* gw_tree(struct gw_trans *);
219 4ff7391f 2020-01-28 tracey static const struct got_error* gw_tag(struct gw_trans *);
221 2c251c14 2020-01-15 tracey struct gw_query_action {
222 2c251c14 2020-01-15 tracey unsigned int func_id;
223 2c251c14 2020-01-15 tracey const char *func_name;
224 54415d85 2020-01-15 tracey const struct got_error *(*func_main)(struct gw_trans *);
225 2c251c14 2020-01-15 tracey char *template;
228 2c251c14 2020-01-15 tracey enum gw_query_actions {
229 2c251c14 2020-01-15 tracey GW_BLAME,
231 f2f46662 2020-01-23 tracey GW_BRIEFS,
232 f2f46662 2020-01-23 tracey GW_COMMITS,
235 2c251c14 2020-01-15 tracey GW_INDEX,
236 2c251c14 2020-01-15 tracey GW_SUMMARY,
241 2c251c14 2020-01-15 tracey static struct gw_query_action gw_query_funcs[] = {
242 f2f46662 2020-01-23 tracey { GW_BLAME, "blame", gw_blame, "gw_tmpl/blame.tmpl" },
243 e46f587c 2020-01-29 tracey { GW_BLOB, "blob", gw_blob, "gw_tmpl/blob.tmpl" },
244 f2f46662 2020-01-23 tracey { GW_BRIEFS, "briefs", gw_briefs, "gw_tmpl/briefs.tmpl" },
245 f2f46662 2020-01-23 tracey { GW_COMMITS, "commits", gw_commits, "gw_tmpl/commit.tmpl" },
246 f2f46662 2020-01-23 tracey { GW_DIFF, "diff", gw_diff, "gw_tmpl/diff.tmpl" },
247 f2f46662 2020-01-23 tracey { GW_ERR, NULL, NULL, "gw_tmpl/err.tmpl" },
248 f2f46662 2020-01-23 tracey { GW_INDEX, "index", gw_index, "gw_tmpl/index.tmpl" },
249 f2f46662 2020-01-23 tracey { GW_SUMMARY, "summary", gw_summary, "gw_tmpl/summry.tmpl" },
250 4ff7391f 2020-01-28 tracey { GW_TAG, "tag", gw_tag, "gw_tmpl/tag.tmpl" },
251 f2f46662 2020-01-23 tracey { GW_TREE, "tree", gw_tree, "gw_tmpl/tree.tmpl" },
254 c25c2314 2020-01-28 stsp static const struct got_error *
255 c25c2314 2020-01-28 stsp gw_kcgi_error(enum kcgi_err kerr)
257 c25c2314 2020-01-28 stsp if (kerr == KCGI_OK)
258 c25c2314 2020-01-28 stsp return NULL;
260 c25c2314 2020-01-28 stsp if (kerr == KCGI_EXIT || kerr == KCGI_HUP)
261 c25c2314 2020-01-28 stsp return got_error(GOT_ERR_CANCELLED);
263 c25c2314 2020-01-28 stsp if (kerr == KCGI_ENOMEM)
264 c25c2314 2020-01-28 stsp return got_error_set_errno(ENOMEM, kcgi_strerror(kerr));
266 c25c2314 2020-01-28 stsp if (kerr == KCGI_ENFILE)
267 c25c2314 2020-01-28 stsp return got_error_set_errno(ENFILE, kcgi_strerror(kerr));
269 c25c2314 2020-01-28 stsp if (kerr == KCGI_EAGAIN)
270 c25c2314 2020-01-28 stsp return got_error_set_errno(EAGAIN, kcgi_strerror(kerr));
272 c25c2314 2020-01-28 stsp if (kerr == KCGI_FORM)
273 c25c2314 2020-01-28 stsp return got_error_msg(GOT_ERR_IO, kcgi_strerror(kerr));
275 c25c2314 2020-01-28 stsp return got_error_from_errno(kcgi_strerror(kerr));
278 2c251c14 2020-01-15 tracey static const struct got_error *
279 54415d85 2020-01-15 tracey gw_apply_unveil(const char *repo_path, const char *repo_file)
281 2c251c14 2020-01-15 tracey const struct got_error *err;
283 2c251c14 2020-01-15 tracey if (repo_path && repo_file) {
284 2c251c14 2020-01-15 tracey char *full_path;
285 88d59c36 2020-01-29 stsp if (asprintf(&full_path, "%s/%s", repo_path, repo_file) == -1)
286 2c251c14 2020-01-15 tracey return got_error_from_errno("asprintf unveil");
287 2c251c14 2020-01-15 tracey if (unveil(full_path, "r") != 0)
288 2c251c14 2020-01-15 tracey return got_error_from_errno2("unveil", full_path);
291 2c251c14 2020-01-15 tracey if (repo_path && unveil(repo_path, "r") != 0)
292 2c251c14 2020-01-15 tracey return got_error_from_errno2("unveil", repo_path);
294 2c251c14 2020-01-15 tracey if (unveil("/tmp", "rwc") != 0)
295 2c251c14 2020-01-15 tracey return got_error_from_errno2("unveil", "/tmp");
297 2c251c14 2020-01-15 tracey err = got_privsep_unveil_exec_helpers();
298 2c251c14 2020-01-15 tracey if (err != NULL)
299 2c251c14 2020-01-15 tracey return err;
301 2c251c14 2020-01-15 tracey if (unveil(NULL, NULL) != 0)
302 2c251c14 2020-01-15 tracey return got_error_from_errno("unveil");
304 2c251c14 2020-01-15 tracey return NULL;
307 2c251c14 2020-01-15 tracey static const struct got_error *
308 54415d85 2020-01-15 tracey gw_blame(struct gw_trans *gw_trans)
310 2c251c14 2020-01-15 tracey const struct got_error *error = NULL;
311 f2f46662 2020-01-23 tracey struct gw_header *header = NULL;
312 f2f46662 2020-01-23 tracey char *blame = NULL, *blame_html = NULL, *blame_html_disp = NULL;
313 c25c2314 2020-01-28 stsp enum kcgi_err kerr;
315 6bee13de 2020-01-16 tracey if (pledge("stdio rpath wpath cpath proc exec sendfd unveil",
316 f2f46662 2020-01-23 tracey NULL) == -1)
317 f2f46662 2020-01-23 tracey return got_error_from_errno("pledge");
319 f2f46662 2020-01-23 tracey if ((header = gw_init_header()) == NULL)
320 f2f46662 2020-01-23 tracey return got_error_from_errno("malloc");
322 54415d85 2020-01-15 tracey error = gw_apply_unveil(gw_trans->gw_dir->path, NULL);
323 ec46ccd7 2020-01-15 tracey if (error)
326 f2f46662 2020-01-23 tracey error = gw_get_header(gw_trans, header, 1);
327 f2f46662 2020-01-23 tracey if (error)
330 e46f587c 2020-01-29 tracey blame_html = gw_get_file_blame_blob(gw_trans);
332 6d9fc692 2020-01-28 stsp if (blame_html == NULL) {
333 f2f46662 2020-01-23 tracey blame_html = strdup("");
334 5ddf0079 2020-01-29 stsp if (blame_html == NULL) {
335 5ddf0079 2020-01-29 stsp error = got_error_from_errno("strdup");
340 88d59c36 2020-01-29 stsp if (asprintf(&blame_html_disp, blame_header,
341 f2f46662 2020-01-23 tracey gw_gen_age_header(gw_get_time_str(header->committer_time, TM_LONG)),
342 f2f46662 2020-01-23 tracey gw_gen_commit_msg_header(gw_html_escape(header->commit_msg)),
343 88d59c36 2020-01-29 stsp blame_html) == -1) {
344 6d9fc692 2020-01-28 stsp error = got_error_from_errno("asprintf");
348 6d9fc692 2020-01-28 stsp if (asprintf(&blame, blame_wrapper, blame_html_disp) == -1) {
349 6d9fc692 2020-01-28 stsp error = got_error_from_errno("asprintf");
353 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, blame);
354 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
355 c25c2314 2020-01-28 stsp error = gw_kcgi_error(kerr);
357 f2f46662 2020-01-23 tracey got_ref_list_free(&header->refs);
358 f2f46662 2020-01-23 tracey gw_free_headers(header);
359 f2f46662 2020-01-23 tracey free(blame_html_disp);
360 f2f46662 2020-01-23 tracey free(blame_html);
361 f2f46662 2020-01-23 tracey free(blame);
362 2c251c14 2020-01-15 tracey return error;
365 2c251c14 2020-01-15 tracey static const struct got_error *
366 e46f587c 2020-01-29 tracey gw_blob(struct gw_trans *gw_trans)
368 e46f587c 2020-01-29 tracey const struct got_error *error = NULL;
369 e46f587c 2020-01-29 tracey struct gw_header *header = NULL;
370 b27da801 2020-01-29 tracey char *blob = NULL;
371 e46f587c 2020-01-29 tracey enum kcgi_err kerr;
373 e46f587c 2020-01-29 tracey if (pledge("stdio rpath wpath cpath proc exec sendfd unveil",
374 e46f587c 2020-01-29 tracey NULL) == -1)
375 e46f587c 2020-01-29 tracey return got_error_from_errno("pledge");
377 e46f587c 2020-01-29 tracey if ((header = gw_init_header()) == NULL)
378 e46f587c 2020-01-29 tracey return got_error_from_errno("malloc");
380 e46f587c 2020-01-29 tracey error = gw_apply_unveil(gw_trans->gw_dir->path, NULL);
381 e46f587c 2020-01-29 tracey if (error)
382 e46f587c 2020-01-29 tracey goto done;
384 e46f587c 2020-01-29 tracey error = gw_get_header(gw_trans, header, 1);
385 e46f587c 2020-01-29 tracey if (error)
386 e46f587c 2020-01-29 tracey goto done;
388 b27da801 2020-01-29 tracey blob = gw_get_file_blame_blob(gw_trans);
390 b27da801 2020-01-29 tracey if (blob == NULL) {
391 b27da801 2020-01-29 tracey blob = strdup("");
392 b27da801 2020-01-29 tracey if (blob == NULL) {
393 e46f587c 2020-01-29 tracey error = got_error_from_errno("strdup");
394 e46f587c 2020-01-29 tracey goto done;
398 e46f587c 2020-01-29 tracey kerr = khttp_puts(gw_trans->gw_req, blob);
399 e46f587c 2020-01-29 tracey if (kerr != KCGI_OK)
400 e46f587c 2020-01-29 tracey error = gw_kcgi_error(kerr);
402 e46f587c 2020-01-29 tracey got_ref_list_free(&header->refs);
403 e46f587c 2020-01-29 tracey gw_free_headers(header);
404 e46f587c 2020-01-29 tracey free(blob);
405 e46f587c 2020-01-29 tracey return error;
408 e46f587c 2020-01-29 tracey static const struct got_error *
409 f2f46662 2020-01-23 tracey gw_diff(struct gw_trans *gw_trans)
411 2c251c14 2020-01-15 tracey const struct got_error *error = NULL;
412 f2f46662 2020-01-23 tracey struct gw_header *header = NULL;
413 f2f46662 2020-01-23 tracey char *diff = NULL, *diff_html = NULL, *diff_html_disp = NULL;
414 c25c2314 2020-01-28 stsp enum kcgi_err kerr;
416 f2f46662 2020-01-23 tracey if (pledge("stdio rpath wpath cpath proc exec sendfd unveil",
417 f2f46662 2020-01-23 tracey NULL) == -1)
418 f2f46662 2020-01-23 tracey return got_error_from_errno("pledge");
420 ae36ed87 2020-01-28 stsp if ((header = gw_init_header()) == NULL)
421 f2f46662 2020-01-23 tracey return got_error_from_errno("malloc");
423 54415d85 2020-01-15 tracey error = gw_apply_unveil(gw_trans->gw_dir->path, NULL);
424 8087c3c5 2020-01-15 tracey if (error)
427 f2f46662 2020-01-23 tracey error = gw_get_header(gw_trans, header, 1);
428 f2f46662 2020-01-23 tracey if (error)
431 f2f46662 2020-01-23 tracey diff_html = gw_get_diff(gw_trans, header);
433 390d412c 2020-01-28 stsp if (diff_html == NULL) {
434 f2f46662 2020-01-23 tracey diff_html = strdup("");
435 390d412c 2020-01-28 stsp if (diff_html == NULL) {
436 390d412c 2020-01-28 stsp error = got_error_from_errno("strdup");
441 390d412c 2020-01-28 stsp if (asprintf(&diff_html_disp, diff_header,
442 2ac037ec 2020-01-24 tracey gw_gen_diff_header(header->parent_id, header->commit_id),
443 f2f46662 2020-01-23 tracey gw_gen_commit_header(header->commit_id, header->refs_str),
444 f2f46662 2020-01-23 tracey gw_gen_tree_header(header->tree_id),
445 f2f46662 2020-01-23 tracey gw_gen_author_header(header->author),
446 f2f46662 2020-01-23 tracey gw_gen_committer_header(header->committer),
447 f2f46662 2020-01-23 tracey gw_gen_age_header(gw_get_time_str(header->committer_time, TM_LONG)),
448 f2f46662 2020-01-23 tracey gw_gen_commit_msg_header(gw_html_escape(header->commit_msg)),
449 390d412c 2020-01-28 stsp diff_html) == -1) {
450 390d412c 2020-01-28 stsp error = got_error_from_errno("asprintf");
454 390d412c 2020-01-28 stsp if (asprintf(&diff, diff_wrapper, diff_html_disp) == -1) {
455 390d412c 2020-01-28 stsp error = got_error_from_errno("asprintf");
459 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, diff);
460 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
461 c25c2314 2020-01-28 stsp error = gw_kcgi_error(kerr);
463 2dcb56a8 2020-01-28 stsp got_ref_list_free(&header->refs);
464 f2f46662 2020-01-23 tracey gw_free_headers(header);
465 f2f46662 2020-01-23 tracey free(diff_html_disp);
466 f2f46662 2020-01-23 tracey free(diff_html);
467 f2f46662 2020-01-23 tracey free(diff);
468 2204c934 2020-01-15 tracey return error;
471 2204c934 2020-01-15 tracey static const struct got_error *
472 54415d85 2020-01-15 tracey gw_index(struct gw_trans *gw_trans)
474 2c251c14 2020-01-15 tracey const struct got_error *error = NULL;
475 46b9c89b 2020-01-15 tracey struct gw_dir *gw_dir = NULL;
476 2c251c14 2020-01-15 tracey char *html, *navs, *next, *prev;
477 387a29ba 2020-01-15 tracey unsigned int prev_disp = 0, next_disp = 1, dir_c = 0;
478 c25c2314 2020-01-28 stsp enum kcgi_err kerr;
480 6bee13de 2020-01-16 tracey if (pledge("stdio rpath proc exec sendfd unveil",
481 6bee13de 2020-01-16 tracey NULL) == -1) {
482 6bee13de 2020-01-16 tracey error = got_error_from_errno("pledge");
483 6bee13de 2020-01-16 tracey return error;
486 54415d85 2020-01-15 tracey error = gw_apply_unveil(gw_trans->gw_conf->got_repos_path, NULL);
487 46b9c89b 2020-01-15 tracey if (error)
488 46b9c89b 2020-01-15 tracey return error;
490 2c251c14 2020-01-15 tracey error = gw_load_got_paths(gw_trans);
491 46b9c89b 2020-01-15 tracey if (error)
492 2c251c14 2020-01-15 tracey return error;
494 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, index_projects_header);
495 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
496 c25c2314 2020-01-28 stsp return gw_kcgi_error(kerr);
498 bce5dac1 2020-01-28 stsp if (TAILQ_EMPTY(&gw_trans->gw_dirs)) {
499 bce5dac1 2020-01-28 stsp if (asprintf(&html, index_projects_empty,
500 bce5dac1 2020-01-28 stsp gw_trans->gw_conf->got_repos_path) == -1)
501 bce5dac1 2020-01-28 stsp return got_error_from_errno("asprintf");
502 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, html);
503 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
504 c25c2314 2020-01-28 stsp error = gw_kcgi_error(kerr);
505 bce5dac1 2020-01-28 stsp free(html);
506 c25c2314 2020-01-28 stsp return error;
509 46b9c89b 2020-01-15 tracey TAILQ_FOREACH(gw_dir, &gw_trans->gw_dirs, entry)
512 46b9c89b 2020-01-15 tracey TAILQ_FOREACH(gw_dir, &gw_trans->gw_dirs, entry) {
513 2c251c14 2020-01-15 tracey if (gw_trans->page > 0 && (gw_trans->page *
514 2c251c14 2020-01-15 tracey gw_trans->gw_conf->got_max_repos_display) > prev_disp) {
515 2c251c14 2020-01-15 tracey prev_disp++;
516 2c251c14 2020-01-15 tracey continue;
519 2c251c14 2020-01-15 tracey prev_disp++;
521 f2f46662 2020-01-23 tracey if (error)
522 f2f46662 2020-01-23 tracey return error;
523 88d59c36 2020-01-29 stsp if(asprintf(&navs, index_navs, gw_dir->name, gw_dir->name,
524 88d59c36 2020-01-29 stsp gw_dir->name, gw_dir->name) == -1)
525 2c251c14 2020-01-15 tracey return got_error_from_errno("asprintf");
527 88d59c36 2020-01-29 stsp if (asprintf(&html, index_projects, gw_dir->name, gw_dir->name,
528 46b9c89b 2020-01-15 tracey gw_dir->description, gw_dir->owner, gw_dir->age,
529 88d59c36 2020-01-29 stsp navs) == -1)
530 2c251c14 2020-01-15 tracey return got_error_from_errno("asprintf");
532 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, html);
533 2c251c14 2020-01-15 tracey free(navs);
534 2c251c14 2020-01-15 tracey free(html);
535 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
536 c25c2314 2020-01-28 stsp return gw_kcgi_error(kerr);
538 2c251c14 2020-01-15 tracey if (gw_trans->gw_conf->got_max_repos_display == 0)
539 2c251c14 2020-01-15 tracey continue;
541 c25c2314 2020-01-28 stsp if (next_disp == gw_trans->gw_conf->got_max_repos_display) {
542 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, np_wrapper_start);
543 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
544 c25c2314 2020-01-28 stsp return gw_kcgi_error(kerr);
545 c25c2314 2020-01-28 stsp } else if ((gw_trans->gw_conf->got_max_repos_display > 0) &&
546 2c251c14 2020-01-15 tracey (gw_trans->page > 0) &&
547 2c251c14 2020-01-15 tracey (next_disp == gw_trans->gw_conf->got_max_repos_display ||
548 c25c2314 2020-01-28 stsp prev_disp == gw_trans->repos_total)) {
549 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, np_wrapper_start);
550 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
551 c25c2314 2020-01-28 stsp return gw_kcgi_error(kerr);
554 2c251c14 2020-01-15 tracey if ((gw_trans->gw_conf->got_max_repos_display > 0) &&
555 2c251c14 2020-01-15 tracey (gw_trans->page > 0) &&
556 2c251c14 2020-01-15 tracey (next_disp == gw_trans->gw_conf->got_max_repos_display ||
557 2c251c14 2020-01-15 tracey prev_disp == gw_trans->repos_total)) {
558 88d59c36 2020-01-29 stsp if (asprintf(&prev, nav_prev, gw_trans->page - 1) == -1)
559 2c251c14 2020-01-15 tracey return got_error_from_errno("asprintf");
560 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, prev);
561 2c251c14 2020-01-15 tracey free(prev);
562 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
563 c25c2314 2020-01-28 stsp return gw_kcgi_error(kerr);
566 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, div_end);
567 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
568 c25c2314 2020-01-28 stsp return gw_kcgi_error(kerr);
570 2c251c14 2020-01-15 tracey if (gw_trans->gw_conf->got_max_repos_display > 0 &&
571 2c251c14 2020-01-15 tracey next_disp == gw_trans->gw_conf->got_max_repos_display &&
572 2c251c14 2020-01-15 tracey dir_c != (gw_trans->page + 1) *
573 2c251c14 2020-01-15 tracey gw_trans->gw_conf->got_max_repos_display) {
574 88d59c36 2020-01-29 stsp if (asprintf(&next, nav_next, gw_trans->page + 1) == -1)
575 2c251c14 2020-01-15 tracey return got_error_from_errno("calloc");
576 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, next);
577 2c251c14 2020-01-15 tracey free(next);
578 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
579 c25c2314 2020-01-28 stsp return gw_kcgi_error(kerr);
580 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, div_end);
581 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
582 c25c2314 2020-01-28 stsp error = gw_kcgi_error(kerr);
583 2c251c14 2020-01-15 tracey next_disp = 0;
587 2c251c14 2020-01-15 tracey if ((gw_trans->gw_conf->got_max_repos_display > 0) &&
588 2c251c14 2020-01-15 tracey (gw_trans->page > 0) &&
589 2c251c14 2020-01-15 tracey (next_disp == gw_trans->gw_conf->got_max_repos_display ||
590 c25c2314 2020-01-28 stsp prev_disp == gw_trans->repos_total)) {
591 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, div_end);
592 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
593 c25c2314 2020-01-28 stsp return gw_kcgi_error(kerr);
596 2c251c14 2020-01-15 tracey next_disp++;
598 2c251c14 2020-01-15 tracey return error;
601 2c251c14 2020-01-15 tracey static const struct got_error *
602 f2f46662 2020-01-23 tracey gw_commits(struct gw_trans *gw_trans)
604 2c251c14 2020-01-15 tracey const struct got_error *error = NULL;
605 f2f46662 2020-01-23 tracey char *commits_html, *commits_navs_html;
606 f2f46662 2020-01-23 tracey struct gw_header *header = NULL, *n_header = NULL;
607 c25c2314 2020-01-28 stsp enum kcgi_err kerr;
609 ae36ed87 2020-01-28 stsp if ((header = gw_init_header()) == NULL)
610 f2f46662 2020-01-23 tracey return got_error_from_errno("malloc");
612 6bee13de 2020-01-16 tracey if (pledge("stdio rpath proc exec sendfd unveil",
613 6bee13de 2020-01-16 tracey NULL) == -1) {
614 6bee13de 2020-01-16 tracey error = got_error_from_errno("pledge");
618 54415d85 2020-01-15 tracey error = gw_apply_unveil(gw_trans->gw_dir->path, NULL);
619 8087c3c5 2020-01-15 tracey if (error)
622 f2f46662 2020-01-23 tracey error = gw_get_header(gw_trans, header,
623 f2f46662 2020-01-23 tracey gw_trans->gw_conf->got_max_commits_display);
627 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, commits_wrapper);
628 18da9978 2020-01-29 stsp if (kerr != KCGI_OK) {
629 18da9978 2020-01-29 stsp error = gw_kcgi_error(kerr);
632 f2f46662 2020-01-23 tracey TAILQ_FOREACH(n_header, &gw_trans->gw_headers, entry) {
633 88d59c36 2020-01-29 stsp if (asprintf(&commits_navs_html, commits_navs,
634 f2f46662 2020-01-23 tracey gw_trans->repo_name, n_header->commit_id,
635 f2f46662 2020-01-23 tracey gw_trans->repo_name, n_header->commit_id,
636 88d59c36 2020-01-29 stsp gw_trans->repo_name, n_header->commit_id) == -1) {
637 18da9978 2020-01-29 stsp error = got_error_from_errno("asprintf");
641 88d59c36 2020-01-29 stsp if (asprintf(&commits_html, commits_line,
642 e46f587c 2020-01-29 tracey gw_gen_commit_header(n_header->commit_id,
643 f2f46662 2020-01-23 tracey n_header->refs_str),
644 e46f587c 2020-01-29 tracey gw_gen_author_header(n_header->author),
645 e46f587c 2020-01-29 tracey gw_gen_committer_header(n_header->committer),
646 f2f46662 2020-01-23 tracey gw_gen_age_header(gw_get_time_str(n_header->committer_time,
647 f2f46662 2020-01-23 tracey TM_LONG)), gw_html_escape(n_header->commit_msg),
648 88d59c36 2020-01-29 stsp commits_navs_html) == -1) {
649 18da9978 2020-01-29 stsp error = got_error_from_errno("asprintf");
652 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, commits_html);
653 18da9978 2020-01-29 stsp if (kerr != KCGI_OK) {
654 18da9978 2020-01-29 stsp error = gw_kcgi_error(kerr);
658 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, div_end);
659 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
660 c25c2314 2020-01-28 stsp error = gw_kcgi_error(kerr);
662 2dcb56a8 2020-01-28 stsp got_ref_list_free(&header->refs);
663 f2f46662 2020-01-23 tracey gw_free_headers(header);
664 f2f46662 2020-01-23 tracey TAILQ_FOREACH(n_header, &gw_trans->gw_headers, entry)
665 f2f46662 2020-01-23 tracey gw_free_headers(n_header);
666 2c251c14 2020-01-15 tracey return error;
669 2c251c14 2020-01-15 tracey static const struct got_error *
670 f2f46662 2020-01-23 tracey gw_briefs(struct gw_trans *gw_trans)
672 2c251c14 2020-01-15 tracey const struct got_error *error = NULL;
673 f2f46662 2020-01-23 tracey char *briefs_html = NULL, *briefs_navs_html = NULL, *newline;
674 f2f46662 2020-01-23 tracey struct gw_header *header = NULL, *n_header = NULL;
675 c25c2314 2020-01-28 stsp enum kcgi_err kerr;
677 ae36ed87 2020-01-28 stsp if ((header = gw_init_header()) == NULL)
678 f2f46662 2020-01-23 tracey return got_error_from_errno("malloc");
680 6bee13de 2020-01-16 tracey if (pledge("stdio rpath proc exec sendfd unveil",
681 6bee13de 2020-01-16 tracey NULL) == -1) {
682 6bee13de 2020-01-16 tracey error = got_error_from_errno("pledge");
686 54415d85 2020-01-15 tracey error = gw_apply_unveil(gw_trans->gw_dir->path, NULL);
687 8087c3c5 2020-01-15 tracey if (error)
690 f2f46662 2020-01-23 tracey if (gw_trans->action == GW_SUMMARY)
691 f2f46662 2020-01-23 tracey error = gw_get_header(gw_trans, header, D_MAXSLCOMMDISP);
693 f2f46662 2020-01-23 tracey error = gw_get_header(gw_trans, header,
694 f2f46662 2020-01-23 tracey gw_trans->gw_conf->got_max_commits_display);
698 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, briefs_wrapper);
699 0e00e8f4 2020-01-29 stsp if (kerr != KCGI_OK) {
700 0e00e8f4 2020-01-29 stsp error = gw_kcgi_error(kerr);
704 f2f46662 2020-01-23 tracey TAILQ_FOREACH(n_header, &gw_trans->gw_headers, entry) {
705 88d59c36 2020-01-29 stsp if (asprintf(&briefs_navs_html, briefs_navs,
706 f2f46662 2020-01-23 tracey gw_trans->repo_name, n_header->commit_id,
707 f2f46662 2020-01-23 tracey gw_trans->repo_name, n_header->commit_id,
708 88d59c36 2020-01-29 stsp gw_trans->repo_name, n_header->commit_id) == -1) {
709 0e00e8f4 2020-01-29 stsp error = got_error_from_errno("asprintf");
712 f2f46662 2020-01-23 tracey newline = strchr(n_header->commit_msg, '\n');
713 f2f46662 2020-01-23 tracey if (newline)
714 f2f46662 2020-01-23 tracey *newline = '\0';
715 88d59c36 2020-01-29 stsp if (asprintf(&briefs_html, briefs_line,
716 f2f46662 2020-01-23 tracey gw_get_time_str(n_header->committer_time, TM_DIFF),
717 f2f46662 2020-01-23 tracey n_header->author, gw_html_escape(n_header->commit_msg),
718 88d59c36 2020-01-29 stsp briefs_navs_html) == -1) {
719 0e00e8f4 2020-01-29 stsp error = got_error_from_errno("asprintf");
722 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, briefs_html);
723 0e00e8f4 2020-01-29 stsp if (kerr != KCGI_OK) {
724 0e00e8f4 2020-01-29 stsp error = gw_kcgi_error(kerr);
728 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, div_end);
729 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
730 c25c2314 2020-01-28 stsp error = gw_kcgi_error(kerr);
732 2dcb56a8 2020-01-28 stsp got_ref_list_free(&header->refs);
733 f2f46662 2020-01-23 tracey gw_free_headers(header);
734 f2f46662 2020-01-23 tracey TAILQ_FOREACH(n_header, &gw_trans->gw_headers, entry)
735 f2f46662 2020-01-23 tracey gw_free_headers(n_header);
736 2c251c14 2020-01-15 tracey return error;
739 2c251c14 2020-01-15 tracey static const struct got_error *
740 54415d85 2020-01-15 tracey gw_summary(struct gw_trans *gw_trans)
742 387a29ba 2020-01-15 tracey const struct got_error *error = NULL;
743 20f34652 2020-01-29 stsp char *description_html = NULL, *repo_owner_html = NULL;
744 20f34652 2020-01-29 stsp char *age = NULL, *repo_age_html = NULL, *cloneurl_html = NULL;
745 20f34652 2020-01-29 stsp char *tags = NULL, *tags_html = NULL;
746 20f34652 2020-01-29 stsp char *heads = NULL, *heads_html = NULL;
747 c25c2314 2020-01-28 stsp enum kcgi_err kerr;
749 f4df82f9 2020-01-29 stsp if (pledge("stdio rpath proc exec sendfd unveil", NULL) == -1)
750 f4df82f9 2020-01-29 stsp return got_error_from_errno("pledge");
752 f2f46662 2020-01-23 tracey /* unveil is applied with gw_briefs below */
754 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, summary_wrapper);
755 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
756 c25c2314 2020-01-28 stsp return gw_kcgi_error(kerr);
758 46b9c89b 2020-01-15 tracey if (gw_trans->gw_conf->got_show_repo_description) {
759 46b9c89b 2020-01-15 tracey if (gw_trans->gw_dir->description != NULL &&
760 46b9c89b 2020-01-15 tracey (strcmp(gw_trans->gw_dir->description, "") != 0)) {
761 88d59c36 2020-01-29 stsp if (asprintf(&description_html, description,
762 20f34652 2020-01-29 stsp gw_trans->gw_dir->description) == -1) {
763 20f34652 2020-01-29 stsp error = got_error_from_errno("asprintf");
767 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, description_html);
768 20f34652 2020-01-29 stsp if (kerr != KCGI_OK) {
769 20f34652 2020-01-29 stsp error = gw_kcgi_error(kerr);
775 46b9c89b 2020-01-15 tracey if (gw_trans->gw_conf->got_show_repo_owner) {
776 46b9c89b 2020-01-15 tracey if (gw_trans->gw_dir->owner != NULL &&
777 46b9c89b 2020-01-15 tracey (strcmp(gw_trans->gw_dir->owner, "") != 0)) {
778 88d59c36 2020-01-29 stsp if (asprintf(&repo_owner_html, repo_owner,
779 20f34652 2020-01-29 stsp gw_trans->gw_dir->owner) == -1) {
780 20f34652 2020-01-29 stsp error = got_error_from_errno("asprintf");
784 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, repo_owner_html);
785 20f34652 2020-01-29 stsp if (kerr != KCGI_OK) {
786 20f34652 2020-01-29 stsp error = gw_kcgi_error(kerr);
792 46b9c89b 2020-01-15 tracey if (gw_trans->gw_conf->got_show_repo_age) {
793 d126c1b7 2020-01-29 stsp error = gw_get_repo_age(&age, gw_trans, gw_trans->gw_dir->path,
794 c6b62706 2020-01-15 tracey "refs/heads", TM_LONG);
797 d126c1b7 2020-01-29 stsp if (strcmp(age, "") != 0) {
798 20f34652 2020-01-29 stsp if (asprintf(&repo_age_html, last_change, age) == -1) {
799 20f34652 2020-01-29 stsp error = got_error_from_errno("asprintf");
803 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, repo_age_html);
804 20f34652 2020-01-29 stsp if (kerr != KCGI_OK) {
805 20f34652 2020-01-29 stsp error = gw_kcgi_error(kerr);
811 46b9c89b 2020-01-15 tracey if (gw_trans->gw_conf->got_show_repo_cloneurl) {
812 46b9c89b 2020-01-15 tracey if (gw_trans->gw_dir->url != NULL &&
813 46b9c89b 2020-01-15 tracey (strcmp(gw_trans->gw_dir->url, "") != 0)) {
814 88d59c36 2020-01-29 stsp if (asprintf(&cloneurl_html, cloneurl,
815 20f34652 2020-01-29 stsp gw_trans->gw_dir->url) == -1) {
816 20f34652 2020-01-29 stsp error = got_error_from_errno("asprintf");
820 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, cloneurl_html);
821 20f34652 2020-01-29 stsp if (kerr != KCGI_OK) {
822 20f34652 2020-01-29 stsp error = gw_kcgi_error(kerr);
827 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, div_end);
828 20f34652 2020-01-29 stsp if (kerr != KCGI_OK) {
829 20f34652 2020-01-29 stsp error = gw_kcgi_error(kerr);
833 f2f46662 2020-01-23 tracey error = gw_briefs(gw_trans);
834 f2f46662 2020-01-23 tracey if (error)
837 4ff7391f 2020-01-28 tracey tags = gw_get_repo_tags(gw_trans, NULL, D_MAXSLCOMMDISP, TAGBRIEF);
838 8d4d2453 2020-01-15 tracey heads = gw_get_repo_heads(gw_trans);
840 8d4d2453 2020-01-15 tracey if (tags != NULL && strcmp(tags, "") != 0) {
841 20f34652 2020-01-29 stsp if (asprintf(&tags_html, summary_tags, tags) == -1) {
842 20f34652 2020-01-29 stsp error = got_error_from_errno("asprintf");
845 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, tags_html);
846 20f34652 2020-01-29 stsp if (kerr != KCGI_OK) {
847 20f34652 2020-01-29 stsp error = gw_kcgi_error(kerr);
852 8d4d2453 2020-01-15 tracey if (heads != NULL && strcmp(heads, "") != 0) {
853 20f34652 2020-01-29 stsp if (asprintf(&heads_html, summary_heads, heads) == -1) {
854 20f34652 2020-01-29 stsp error = got_error_from_errno("asprintf");
857 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, heads_html);
858 20f34652 2020-01-29 stsp if (kerr != KCGI_OK) {
859 20f34652 2020-01-29 stsp error = gw_kcgi_error(kerr);
864 20f34652 2020-01-29 stsp free(description_html);
865 20f34652 2020-01-29 stsp free(repo_owner_html);
867 20f34652 2020-01-29 stsp free(repo_age_html);
868 20f34652 2020-01-29 stsp free(cloneurl_html);
869 20f34652 2020-01-29 stsp free(tags);
870 20f34652 2020-01-29 stsp free(tags_html);
871 20f34652 2020-01-29 stsp free(heads);
872 20f34652 2020-01-29 stsp free(heads_html);
873 2204c934 2020-01-15 tracey return error;
876 2204c934 2020-01-15 tracey static const struct got_error *
877 f2f46662 2020-01-23 tracey gw_tree(struct gw_trans *gw_trans)
879 b772de24 2020-01-15 tracey const struct got_error *error = NULL;
880 f2f46662 2020-01-23 tracey struct gw_header *header = NULL;
881 f2f46662 2020-01-23 tracey char *tree = NULL, *tree_html = NULL, *tree_html_disp = NULL;
882 c25c2314 2020-01-28 stsp enum kcgi_err kerr;
884 f2f46662 2020-01-23 tracey if (pledge("stdio rpath proc exec sendfd unveil", NULL) == -1)
885 f2f46662 2020-01-23 tracey return got_error_from_errno("pledge");
887 ae36ed87 2020-01-28 stsp if ((header = gw_init_header()) == NULL)
888 f2f46662 2020-01-23 tracey return got_error_from_errno("malloc");
890 54415d85 2020-01-15 tracey error = gw_apply_unveil(gw_trans->gw_dir->path, NULL);
891 b772de24 2020-01-15 tracey if (error)
894 f2f46662 2020-01-23 tracey error = gw_get_header(gw_trans, header, 1);
895 f2f46662 2020-01-23 tracey if (error)
898 f2f46662 2020-01-23 tracey tree_html = gw_get_repo_tree(gw_trans);
900 4ff7391f 2020-01-28 tracey if (tree_html == NULL) {
901 f2f46662 2020-01-23 tracey tree_html = strdup("");
902 4ff7391f 2020-01-28 tracey if (tree_html == NULL) {
903 4ff7391f 2020-01-28 tracey error = got_error_from_errno("strdup");
904 4ff7391f 2020-01-28 tracey goto done;
908 88d59c36 2020-01-29 stsp if (asprintf(&tree_html_disp, tree_header,
909 f2f46662 2020-01-23 tracey gw_gen_age_header(gw_get_time_str(header->committer_time, TM_LONG)),
910 f2f46662 2020-01-23 tracey gw_gen_commit_msg_header(gw_html_escape(header->commit_msg)),
911 88d59c36 2020-01-29 stsp tree_html) == -1) {
912 42281175 2020-01-29 stsp error = got_error_from_errno("asprintf");
916 42281175 2020-01-29 stsp if (asprintf(&tree, tree_wrapper, tree_html_disp) == -1) {
917 42281175 2020-01-29 stsp error = got_error_from_errno("asprintf");
921 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, tree);
922 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
923 c25c2314 2020-01-28 stsp error = gw_kcgi_error(kerr);
925 2dcb56a8 2020-01-28 stsp got_ref_list_free(&header->refs);
926 f2f46662 2020-01-23 tracey gw_free_headers(header);
927 f2f46662 2020-01-23 tracey free(tree_html_disp);
928 f2f46662 2020-01-23 tracey free(tree_html);
929 f2f46662 2020-01-23 tracey free(tree);
930 4ff7391f 2020-01-28 tracey return error;
933 4ff7391f 2020-01-28 tracey static const struct got_error *
934 4ff7391f 2020-01-28 tracey gw_tag(struct gw_trans *gw_trans)
936 4ff7391f 2020-01-28 tracey const struct got_error *error = NULL;
937 4ff7391f 2020-01-28 tracey struct gw_header *header = NULL;
938 4ff7391f 2020-01-28 tracey char *tag = NULL, *tag_html = NULL, *tag_html_disp = NULL;
939 4ff7391f 2020-01-28 tracey enum kcgi_err kerr;
941 4ff7391f 2020-01-28 tracey if (pledge("stdio rpath proc exec sendfd unveil", NULL) == -1)
942 4ff7391f 2020-01-28 tracey return got_error_from_errno("pledge");
944 4ff7391f 2020-01-28 tracey if ((header = gw_init_header()) == NULL)
945 4ff7391f 2020-01-28 tracey return got_error_from_errno("malloc");
947 4ff7391f 2020-01-28 tracey error = gw_apply_unveil(gw_trans->gw_dir->path, NULL);
948 4ff7391f 2020-01-28 tracey if (error)
951 4ff7391f 2020-01-28 tracey error = gw_get_header(gw_trans, header, 1);
952 4ff7391f 2020-01-28 tracey if (error)
955 4ff7391f 2020-01-28 tracey tag_html = gw_get_repo_tags(gw_trans, header, 1, TAGFULL);
956 4ff7391f 2020-01-28 tracey if (tag_html == NULL) {
957 4ff7391f 2020-01-28 tracey tag_html = strdup("");
958 4ff7391f 2020-01-28 tracey if (tag_html == NULL) {
959 4ff7391f 2020-01-28 tracey error = got_error_from_errno("strdup");
960 4ff7391f 2020-01-28 tracey goto done;
964 88d59c36 2020-01-29 stsp if (asprintf(&tag_html_disp, tag_header,
965 4ff7391f 2020-01-28 tracey gw_gen_commit_header(header->commit_id, header->refs_str),
966 4ff7391f 2020-01-28 tracey gw_gen_commit_msg_header(gw_html_escape(header->commit_msg)),
967 88d59c36 2020-01-29 stsp tag_html) == -1) {
968 470cd826 2020-01-29 stsp error = got_error_from_errno("asprintf");
972 470cd826 2020-01-29 stsp if (asprintf(&tag, tag_wrapper, tag_html_disp) == -1) {
973 470cd826 2020-01-29 stsp error = got_error_from_errno("asprintf");
977 4ff7391f 2020-01-28 tracey kerr = khttp_puts(gw_trans->gw_req, tag);
978 4ff7391f 2020-01-28 tracey if (kerr != KCGI_OK)
979 4ff7391f 2020-01-28 tracey error = gw_kcgi_error(kerr);
981 4ff7391f 2020-01-28 tracey got_ref_list_free(&header->refs);
982 4ff7391f 2020-01-28 tracey gw_free_headers(header);
983 4ff7391f 2020-01-28 tracey free(tag_html_disp);
984 4ff7391f 2020-01-28 tracey free(tag_html);
985 4ff7391f 2020-01-28 tracey free(tag);
986 2c251c14 2020-01-15 tracey return error;
989 2c251c14 2020-01-15 tracey static const struct got_error *
990 54415d85 2020-01-15 tracey gw_load_got_path(struct gw_trans *gw_trans, struct gw_dir *gw_dir)
992 2c251c14 2020-01-15 tracey const struct got_error *error = NULL;
994 2c251c14 2020-01-15 tracey char *dir_test;
995 4ceb8155 2020-01-15 tracey int opened = 0;
997 88d59c36 2020-01-29 stsp if (asprintf(&dir_test, "%s/%s/%s",
998 2c251c14 2020-01-15 tracey gw_trans->gw_conf->got_repos_path, gw_dir->name,
999 88d59c36 2020-01-29 stsp GOTWEB_GIT_DIR) == -1)
1000 2c251c14 2020-01-15 tracey return got_error_from_errno("asprintf");
1002 2c251c14 2020-01-15 tracey dt = opendir(dir_test);
1003 2c251c14 2020-01-15 tracey if (dt == NULL) {
1004 2c251c14 2020-01-15 tracey free(dir_test);
1005 2c251c14 2020-01-15 tracey } else {
1006 2c251c14 2020-01-15 tracey gw_dir->path = strdup(dir_test);
1007 4ceb8155 2020-01-15 tracey opened = 1;
1008 2c251c14 2020-01-15 tracey goto done;
1011 88d59c36 2020-01-29 stsp if (asprintf(&dir_test, "%s/%s/%s",
1012 2c251c14 2020-01-15 tracey gw_trans->gw_conf->got_repos_path, gw_dir->name,
1013 88d59c36 2020-01-29 stsp GOTWEB_GOT_DIR) == -1)
1014 2c251c14 2020-01-15 tracey return got_error_from_errno("asprintf");
1016 2c251c14 2020-01-15 tracey dt = opendir(dir_test);
1017 2c251c14 2020-01-15 tracey if (dt == NULL)
1018 2c251c14 2020-01-15 tracey free(dir_test);
1020 4ceb8155 2020-01-15 tracey opened = 1;
1021 2c251c14 2020-01-15 tracey error = got_error(GOT_ERR_NOT_GIT_REPO);
1022 2c251c14 2020-01-15 tracey goto errored;
1025 88d59c36 2020-01-29 stsp if (asprintf(&dir_test, "%s/%s",
1026 88d59c36 2020-01-29 stsp gw_trans->gw_conf->got_repos_path, gw_dir->name) == -1)
1027 2c251c14 2020-01-15 tracey return got_error_from_errno("asprintf");
1029 2c251c14 2020-01-15 tracey gw_dir->path = strdup(dir_test);
1032 2c251c14 2020-01-15 tracey gw_dir->description = gw_get_repo_description(gw_trans,
1033 2c251c14 2020-01-15 tracey gw_dir->path);
1034 2c251c14 2020-01-15 tracey gw_dir->owner = gw_get_repo_owner(gw_trans, gw_dir->path);
1035 d126c1b7 2020-01-29 stsp error = gw_get_repo_age(&gw_dir->age, gw_trans, gw_dir->path,
1036 d126c1b7 2020-01-29 stsp "refs/heads", TM_DIFF);
1037 d126c1b7 2020-01-29 stsp if (error)
1038 d126c1b7 2020-01-29 stsp goto errored;
1039 2c251c14 2020-01-15 tracey gw_dir->url = gw_get_clone_url(gw_trans, gw_dir->path);
1041 2c251c14 2020-01-15 tracey errored:
1042 2c251c14 2020-01-15 tracey free(dir_test);
1043 2c251c14 2020-01-15 tracey if (opened)
1044 2c251c14 2020-01-15 tracey closedir(dt);
1045 2c251c14 2020-01-15 tracey return error;
1048 2c251c14 2020-01-15 tracey static const struct got_error *
1049 54415d85 2020-01-15 tracey gw_load_got_paths(struct gw_trans *gw_trans)
1051 2c251c14 2020-01-15 tracey const struct got_error *error = NULL;
1053 2c251c14 2020-01-15 tracey struct dirent **sd_dent;
1054 2c251c14 2020-01-15 tracey struct gw_dir *gw_dir;
1055 2c251c14 2020-01-15 tracey struct stat st;
1056 2c251c14 2020-01-15 tracey unsigned int d_cnt, d_i;
1058 2c251c14 2020-01-15 tracey d = opendir(gw_trans->gw_conf->got_repos_path);
1059 2c251c14 2020-01-15 tracey if (d == NULL) {
1060 2c251c14 2020-01-15 tracey error = got_error_from_errno2("opendir",
1061 2c251c14 2020-01-15 tracey gw_trans->gw_conf->got_repos_path);
1062 2c251c14 2020-01-15 tracey return error;
1065 2c251c14 2020-01-15 tracey d_cnt = scandir(gw_trans->gw_conf->got_repos_path, &sd_dent, NULL,
1066 2c251c14 2020-01-15 tracey alphasort);
1067 2c251c14 2020-01-15 tracey if (d_cnt == -1) {
1068 2c251c14 2020-01-15 tracey error = got_error_from_errno2("scandir",
1069 2c251c14 2020-01-15 tracey gw_trans->gw_conf->got_repos_path);
1070 2c251c14 2020-01-15 tracey return error;
1073 2c251c14 2020-01-15 tracey for (d_i = 0; d_i < d_cnt; d_i++) {
1074 2c251c14 2020-01-15 tracey if (gw_trans->gw_conf->got_max_repos > 0 &&
1075 2c251c14 2020-01-15 tracey (d_i - 2) == gw_trans->gw_conf->got_max_repos)
1076 2c251c14 2020-01-15 tracey break; /* account for parent and self */
1078 2c251c14 2020-01-15 tracey if (strcmp(sd_dent[d_i]->d_name, ".") == 0 ||
1079 2c251c14 2020-01-15 tracey strcmp(sd_dent[d_i]->d_name, "..") == 0)
1080 2c251c14 2020-01-15 tracey continue;
1082 2c251c14 2020-01-15 tracey if ((gw_dir = gw_init_gw_dir(sd_dent[d_i]->d_name)) == NULL)
1083 2c251c14 2020-01-15 tracey return got_error_from_errno("gw_dir malloc");
1085 2c251c14 2020-01-15 tracey error = gw_load_got_path(gw_trans, gw_dir);
1086 2c251c14 2020-01-15 tracey if (error && error->code == GOT_ERR_NOT_GIT_REPO)
1087 2c251c14 2020-01-15 tracey continue;
1088 2c251c14 2020-01-15 tracey else if (error)
1089 2c251c14 2020-01-15 tracey return error;
1091 2c251c14 2020-01-15 tracey if (lstat(gw_dir->path, &st) == 0 && S_ISDIR(st.st_mode) &&
1092 2c251c14 2020-01-15 tracey !got_path_dir_is_empty(gw_dir->path)) {
1093 2c251c14 2020-01-15 tracey TAILQ_INSERT_TAIL(&gw_trans->gw_dirs, gw_dir,
1095 2c251c14 2020-01-15 tracey gw_trans->repos_total++;
1099 2c251c14 2020-01-15 tracey closedir(d);
1100 2c251c14 2020-01-15 tracey return error;
1103 2c251c14 2020-01-15 tracey static const struct got_error *
1104 54415d85 2020-01-15 tracey gw_parse_querystring(struct gw_trans *gw_trans)
1106 2c251c14 2020-01-15 tracey const struct got_error *error = NULL;
1107 2c251c14 2020-01-15 tracey struct kpair *p;
1108 2c251c14 2020-01-15 tracey struct gw_query_action *action = NULL;
1109 2c251c14 2020-01-15 tracey unsigned int i;
1111 2c251c14 2020-01-15 tracey if (gw_trans->gw_req->fieldnmap[0]) {
1112 2c251c14 2020-01-15 tracey error = got_error_from_errno("bad parse");
1113 2c251c14 2020-01-15 tracey return error;
1114 2c251c14 2020-01-15 tracey } else if ((p = gw_trans->gw_req->fieldmap[KEY_PATH])) {
1115 2c251c14 2020-01-15 tracey /* define gw_trans->repo_path */
1116 88d59c36 2020-01-29 stsp if (asprintf(&gw_trans->repo_name, "%s", p->parsed.s) == -1)
1117 2c251c14 2020-01-15 tracey return got_error_from_errno("asprintf");
1119 88d59c36 2020-01-29 stsp if (asprintf(&gw_trans->repo_path, "%s/%s",
1120 88d59c36 2020-01-29 stsp gw_trans->gw_conf->got_repos_path, p->parsed.s) == -1)
1121 2c251c14 2020-01-15 tracey return got_error_from_errno("asprintf");
1123 2c251c14 2020-01-15 tracey /* get action and set function */
1124 2c251c14 2020-01-15 tracey if ((p = gw_trans->gw_req->fieldmap[KEY_ACTION]))
1125 2c251c14 2020-01-15 tracey for (i = 0; i < nitems(gw_query_funcs); i++) {
1126 2c251c14 2020-01-15 tracey action = &gw_query_funcs[i];
1127 2c251c14 2020-01-15 tracey if (action->func_name == NULL)
1128 2c251c14 2020-01-15 tracey continue;
1130 2c251c14 2020-01-15 tracey if (strcmp(action->func_name,
1131 2c251c14 2020-01-15 tracey p->parsed.s) == 0) {
1132 2c251c14 2020-01-15 tracey gw_trans->action = i;
1133 88d59c36 2020-01-29 stsp if (asprintf(&gw_trans->action_name,
1134 88d59c36 2020-01-29 stsp "%s", action->func_name) == -1)
1136 b772de24 2020-01-15 tracey got_error_from_errno(
1137 2c251c14 2020-01-15 tracey "asprintf");
1142 2c251c14 2020-01-15 tracey action = NULL;
1145 ec46ccd7 2020-01-15 tracey if ((p = gw_trans->gw_req->fieldmap[KEY_COMMIT_ID]))
1146 88d59c36 2020-01-29 stsp if (asprintf(&gw_trans->commit, "%s",
1147 88d59c36 2020-01-29 stsp p->parsed.s) == -1)
1148 ec46ccd7 2020-01-15 tracey return got_error_from_errno("asprintf");
1150 2c251c14 2020-01-15 tracey if ((p = gw_trans->gw_req->fieldmap[KEY_FILE]))
1151 88d59c36 2020-01-29 stsp if (asprintf(&gw_trans->repo_file, "%s",
1152 88d59c36 2020-01-29 stsp p->parsed.s) == -1)
1153 8087c3c5 2020-01-15 tracey return got_error_from_errno("asprintf");
1155 ec46ccd7 2020-01-15 tracey if ((p = gw_trans->gw_req->fieldmap[KEY_FOLDER]))
1156 88d59c36 2020-01-29 stsp if (asprintf(&gw_trans->repo_folder, "%s",
1157 88d59c36 2020-01-29 stsp p->parsed.s) == -1)
1158 ec46ccd7 2020-01-15 tracey return got_error_from_errno("asprintf");
1160 8087c3c5 2020-01-15 tracey if ((p = gw_trans->gw_req->fieldmap[KEY_HEADREF]))
1161 88d59c36 2020-01-29 stsp if (asprintf(&gw_trans->headref, "%s",
1162 88d59c36 2020-01-29 stsp p->parsed.s) == -1)
1163 2c251c14 2020-01-15 tracey return got_error_from_errno("asprintf");
1165 2c251c14 2020-01-15 tracey if (action == NULL) {
1166 2c251c14 2020-01-15 tracey error = got_error_from_errno("invalid action");
1167 2c251c14 2020-01-15 tracey return error;
1169 46b9c89b 2020-01-15 tracey if ((gw_trans->gw_dir =
1170 46b9c89b 2020-01-15 tracey gw_init_gw_dir(gw_trans->repo_name)) == NULL)
1171 46b9c89b 2020-01-15 tracey return got_error_from_errno("gw_dir malloc");
1173 46b9c89b 2020-01-15 tracey error = gw_load_got_path(gw_trans, gw_trans->gw_dir);
1174 46b9c89b 2020-01-15 tracey if (error)
1175 46b9c89b 2020-01-15 tracey return error;
1177 2c251c14 2020-01-15 tracey gw_trans->action = GW_INDEX;
1179 2c251c14 2020-01-15 tracey if ((p = gw_trans->gw_req->fieldmap[KEY_PAGE]))
1180 2c251c14 2020-01-15 tracey gw_trans->page = p->parsed.i;
1182 b27da801 2020-01-29 tracey if (gw_trans->action == GW_BLOB)
1183 b27da801 2020-01-29 tracey gw_trans->mime = KMIME_TEXT_PLAIN;
1185 2c251c14 2020-01-15 tracey return error;
1188 2c251c14 2020-01-15 tracey static struct gw_dir *
1189 2c251c14 2020-01-15 tracey gw_init_gw_dir(char *dir)
1191 2c251c14 2020-01-15 tracey struct gw_dir *gw_dir;
1193 2c251c14 2020-01-15 tracey if ((gw_dir = malloc(sizeof(*gw_dir))) == NULL)
1194 2c251c14 2020-01-15 tracey return NULL;
1196 88d59c36 2020-01-29 stsp if (asprintf(&gw_dir->name, "%s", dir) == -1)
1197 2c251c14 2020-01-15 tracey return NULL;
1199 2c251c14 2020-01-15 tracey return gw_dir;
1202 c25c2314 2020-01-28 stsp static const struct got_error *
1203 54415d85 2020-01-15 tracey gw_display_open(struct gw_trans *gw_trans, enum khttp code, enum kmime mime)
1205 c25c2314 2020-01-28 stsp enum kcgi_err kerr;
1207 c25c2314 2020-01-28 stsp kerr = khttp_head(gw_trans->gw_req, kresps[KRESP_ALLOW], "GET");
1208 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
1209 c25c2314 2020-01-28 stsp return gw_kcgi_error(kerr);
1210 c25c2314 2020-01-28 stsp kerr = khttp_head(gw_trans->gw_req, kresps[KRESP_STATUS], "%s",
1211 2c251c14 2020-01-15 tracey khttps[code]);
1212 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
1213 c25c2314 2020-01-28 stsp return gw_kcgi_error(kerr);
1214 c25c2314 2020-01-28 stsp kerr = khttp_head(gw_trans->gw_req, kresps[KRESP_CONTENT_TYPE], "%s",
1215 2c251c14 2020-01-15 tracey kmimetypes[mime]);
1216 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
1217 c25c2314 2020-01-28 stsp return gw_kcgi_error(kerr);
1218 c25c2314 2020-01-28 stsp kerr = khttp_head(gw_trans->gw_req, "X-Content-Type-Options", "nosniff");
1219 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
1220 c25c2314 2020-01-28 stsp return gw_kcgi_error(kerr);
1221 c25c2314 2020-01-28 stsp kerr = khttp_head(gw_trans->gw_req, "X-Frame-Options", "DENY");
1222 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
1223 c25c2314 2020-01-28 stsp return gw_kcgi_error(kerr);
1224 c25c2314 2020-01-28 stsp kerr = khttp_head(gw_trans->gw_req, "X-XSS-Protection", "1; mode=block");
1225 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
1226 c25c2314 2020-01-28 stsp return gw_kcgi_error(kerr);
1228 c25c2314 2020-01-28 stsp kerr = khttp_body(gw_trans->gw_req);
1229 c25c2314 2020-01-28 stsp return gw_kcgi_error(kerr);
1232 c25c2314 2020-01-28 stsp static const struct got_error *
1233 6d8d8a26 2020-01-29 stsp gw_display_index(struct gw_trans *gw_trans)
1235 4bec7539 2020-01-29 stsp const struct got_error *error;
1236 c25c2314 2020-01-28 stsp enum kcgi_err kerr;
1238 4bec7539 2020-01-29 stsp error = gw_display_open(gw_trans, KHTTP_200, gw_trans->mime);
1239 4bec7539 2020-01-29 stsp if (error)
1240 4bec7539 2020-01-29 stsp return error;
1242 c25c2314 2020-01-28 stsp kerr = khtml_open(gw_trans->gw_html_req, gw_trans->gw_req, 0);
1244 6d8d8a26 2020-01-29 stsp return gw_kcgi_error(kerr);
1246 6d8d8a26 2020-01-29 stsp kerr = khttp_template(gw_trans->gw_req, gw_trans->gw_tmpl,
1247 6d8d8a26 2020-01-29 stsp gw_query_funcs[gw_trans->action].template);
1248 7a9bfbff 2020-01-29 stsp if (kerr != KCGI_OK) {
1249 7a9bfbff 2020-01-29 stsp khtml_close(gw_trans->gw_html_req);
1250 c25c2314 2020-01-28 stsp return gw_kcgi_error(kerr);
1253 7a9bfbff 2020-01-29 stsp return gw_kcgi_error(khtml_close(gw_trans->gw_html_req));
1256 6d8d8a26 2020-01-29 stsp static void
1257 6d8d8a26 2020-01-29 stsp gw_display_error(struct gw_trans *gw_trans, const struct got_error *err)
1259 6d8d8a26 2020-01-29 stsp if (gw_display_open(gw_trans, KHTTP_200, gw_trans->mime) != NULL)
1262 6d8d8a26 2020-01-29 stsp if (khtml_open(gw_trans->gw_html_req, gw_trans->gw_req, 0) != KCGI_OK)
1265 6d8d8a26 2020-01-29 stsp khttp_puts(gw_trans->gw_req, err->msg);
1266 6d8d8a26 2020-01-29 stsp khtml_close(gw_trans->gw_html_req);
1269 2c251c14 2020-01-15 tracey static int
1270 2c251c14 2020-01-15 tracey gw_template(size_t key, void *arg)
1272 2c251c14 2020-01-15 tracey const struct got_error *error = NULL;
1273 54415d85 2020-01-15 tracey struct gw_trans *gw_trans = arg;
1274 2c251c14 2020-01-15 tracey char *gw_got_link, *gw_site_link;
1275 2c251c14 2020-01-15 tracey char *site_owner_name, *site_owner_name_h;
1277 2c251c14 2020-01-15 tracey switch (key) {
1278 2c251c14 2020-01-15 tracey case (TEMPL_HEAD):
1279 2c251c14 2020-01-15 tracey khttp_puts(gw_trans->gw_req, head);
1281 2c251c14 2020-01-15 tracey case(TEMPL_HEADER):
1282 2c251c14 2020-01-15 tracey gw_got_link = gw_get_got_link(gw_trans);
1283 2c251c14 2020-01-15 tracey if (gw_got_link != NULL)
1284 2c251c14 2020-01-15 tracey khttp_puts(gw_trans->gw_req, gw_got_link);
1286 2c251c14 2020-01-15 tracey free(gw_got_link);
1288 2c251c14 2020-01-15 tracey case (TEMPL_SITEPATH):
1289 2c251c14 2020-01-15 tracey gw_site_link = gw_get_site_link(gw_trans);
1290 2c251c14 2020-01-15 tracey if (gw_site_link != NULL)
1291 2c251c14 2020-01-15 tracey khttp_puts(gw_trans->gw_req, gw_site_link);
1293 2c251c14 2020-01-15 tracey free(gw_site_link);
1295 2c251c14 2020-01-15 tracey case(TEMPL_TITLE):
1296 2c251c14 2020-01-15 tracey if (gw_trans->gw_conf->got_site_name != NULL)
1297 2c251c14 2020-01-15 tracey khtml_puts(gw_trans->gw_html_req,
1298 2c251c14 2020-01-15 tracey gw_trans->gw_conf->got_site_name);
1301 2c251c14 2020-01-15 tracey case (TEMPL_SEARCH):
1302 2c251c14 2020-01-15 tracey khttp_puts(gw_trans->gw_req, search);
1304 2c251c14 2020-01-15 tracey case(TEMPL_SITEOWNER):
1305 2c251c14 2020-01-15 tracey if (gw_trans->gw_conf->got_site_owner != NULL &&
1306 2c251c14 2020-01-15 tracey gw_trans->gw_conf->got_show_site_owner) {
1307 2c251c14 2020-01-15 tracey site_owner_name =
1308 2c251c14 2020-01-15 tracey gw_html_escape(gw_trans->gw_conf->got_site_owner);
1309 88d59c36 2020-01-29 stsp if (asprintf(&site_owner_name_h, site_owner,
1310 88d59c36 2020-01-29 stsp site_owner_name) == -1)
1311 2c251c14 2020-01-15 tracey return 0;
1313 2c251c14 2020-01-15 tracey khttp_puts(gw_trans->gw_req, site_owner_name_h);
1314 2c251c14 2020-01-15 tracey free(site_owner_name);
1315 2c251c14 2020-01-15 tracey free(site_owner_name_h);
1318 2c251c14 2020-01-15 tracey case(TEMPL_CONTENT):
1319 2c251c14 2020-01-15 tracey error = gw_query_funcs[gw_trans->action].func_main(gw_trans);
1320 2c251c14 2020-01-15 tracey if (error)
1321 2c251c14 2020-01-15 tracey khttp_puts(gw_trans->gw_req, error->msg);
1323 2c251c14 2020-01-15 tracey default:
1324 2c251c14 2020-01-15 tracey return 0;
1326 2c251c14 2020-01-15 tracey return 1;
1329 2c251c14 2020-01-15 tracey static char *
1330 f2f46662 2020-01-23 tracey gw_gen_commit_header(char *str1, char *str2)
1332 f2f46662 2020-01-23 tracey char *return_html = NULL, *ref_str = NULL;
1334 f2f46662 2020-01-23 tracey if (strcmp(str2, "") != 0) {
1335 88d59c36 2020-01-29 stsp if (asprintf(&ref_str, "(%s)", str2) == -1) {
1336 f2f46662 2020-01-23 tracey return_html = strdup("");
1337 f2f46662 2020-01-23 tracey return return_html;
1340 f2f46662 2020-01-23 tracey ref_str = strdup("");
1343 88d59c36 2020-01-29 stsp if (asprintf(&return_html, header_commit_html, str1, ref_str) == -1)
1344 f2f46662 2020-01-23 tracey return_html = strdup("");
1346 f2f46662 2020-01-23 tracey free(ref_str);
1347 f2f46662 2020-01-23 tracey return return_html;
1350 f2f46662 2020-01-23 tracey static char *
1351 f2f46662 2020-01-23 tracey gw_gen_diff_header(char *str1, char *str2)
1353 f2f46662 2020-01-23 tracey char *return_html = NULL;
1355 88d59c36 2020-01-29 stsp if (asprintf(&return_html, header_diff_html, str1, str2) == -1)
1356 f2f46662 2020-01-23 tracey return_html = strdup("");
1358 f2f46662 2020-01-23 tracey return return_html;
1361 f2f46662 2020-01-23 tracey static char *
1362 f2f46662 2020-01-23 tracey gw_gen_author_header(char *str)
1364 f2f46662 2020-01-23 tracey char *return_html = NULL;
1366 88d59c36 2020-01-29 stsp if (asprintf(&return_html, header_author_html, str) == -1)
1367 f2f46662 2020-01-23 tracey return_html = strdup("");
1369 f2f46662 2020-01-23 tracey return return_html;
1372 f2f46662 2020-01-23 tracey static char *
1373 f2f46662 2020-01-23 tracey gw_gen_committer_header(char *str)
1375 f2f46662 2020-01-23 tracey char *return_html = NULL;
1377 88d59c36 2020-01-29 stsp if (asprintf(&return_html, header_committer_html, str) == -1)
1378 f2f46662 2020-01-23 tracey return_html = strdup("");
1380 f2f46662 2020-01-23 tracey return return_html;
1383 f2f46662 2020-01-23 tracey static char *
1384 f2f46662 2020-01-23 tracey gw_gen_age_header(char *str)
1386 f2f46662 2020-01-23 tracey char *return_html = NULL;
1388 88d59c36 2020-01-29 stsp if (asprintf(&return_html, header_age_html, str) == -1)
1389 f2f46662 2020-01-23 tracey return_html = strdup("");
1391 f2f46662 2020-01-23 tracey return return_html;
1394 f2f46662 2020-01-23 tracey static char *
1395 f2f46662 2020-01-23 tracey gw_gen_commit_msg_header(char *str)
1397 f2f46662 2020-01-23 tracey char *return_html = NULL;
1399 88d59c36 2020-01-29 stsp if (asprintf(&return_html, header_commit_msg_html, str) == -1)
1400 f2f46662 2020-01-23 tracey return_html = strdup("");
1402 f2f46662 2020-01-23 tracey return return_html;
1405 f2f46662 2020-01-23 tracey static char *
1406 f2f46662 2020-01-23 tracey gw_gen_tree_header(char *str)
1408 f2f46662 2020-01-23 tracey char *return_html = NULL;
1410 88d59c36 2020-01-29 stsp if (asprintf(&return_html, header_tree_html, str) == -1)
1411 f2f46662 2020-01-23 tracey return_html = strdup("");
1413 f2f46662 2020-01-23 tracey return return_html;
1416 f2f46662 2020-01-23 tracey static char *
1417 54415d85 2020-01-15 tracey gw_get_repo_description(struct gw_trans *gw_trans, char *dir)
1419 2c251c14 2020-01-15 tracey FILE *f;
1420 2c251c14 2020-01-15 tracey char *description = NULL, *d_file = NULL;
1421 2c251c14 2020-01-15 tracey unsigned int len;
1423 0b20762b 2020-01-29 stsp if (gw_trans->gw_conf->got_show_repo_description == 0)
1424 2c251c14 2020-01-15 tracey goto err;
1426 88d59c36 2020-01-29 stsp if (asprintf(&d_file, "%s/description", dir) == -1)
1427 2c251c14 2020-01-15 tracey goto err;
1429 2c251c14 2020-01-15 tracey if ((f = fopen(d_file, "r")) == NULL)
1430 2c251c14 2020-01-15 tracey goto err;
1432 2c251c14 2020-01-15 tracey fseek(f, 0, SEEK_END);
1433 2c251c14 2020-01-15 tracey len = ftell(f) + 1;
1434 2c251c14 2020-01-15 tracey fseek(f, 0, SEEK_SET);
1435 2c251c14 2020-01-15 tracey if ((description = calloc(len, sizeof(char *))) == NULL)
1436 2c251c14 2020-01-15 tracey goto err;
1438 2c251c14 2020-01-15 tracey fread(description, 1, len, f);
1439 2c251c14 2020-01-15 tracey fclose(f);
1440 2c251c14 2020-01-15 tracey free(d_file);
1441 2c251c14 2020-01-15 tracey return description;
1443 4b60fece 2020-01-29 stsp return strdup("");
1446 2c251c14 2020-01-15 tracey static char *
1447 474370cb 2020-01-15 tracey gw_get_time_str(time_t committer_time, int ref_tm)
1449 474370cb 2020-01-15 tracey struct tm tm;
1450 474370cb 2020-01-15 tracey time_t diff_time;
1451 474370cb 2020-01-15 tracey char *years = "years ago", *months = "months ago";
1452 474370cb 2020-01-15 tracey char *weeks = "weeks ago", *days = "days ago", *hours = "hours ago";
1453 474370cb 2020-01-15 tracey char *minutes = "minutes ago", *seconds = "seconds ago";
1454 474370cb 2020-01-15 tracey char *now = "right now";
1455 474370cb 2020-01-15 tracey char *repo_age, *s;
1456 6c6c85af 2020-01-15 tracey char datebuf[29];
1458 474370cb 2020-01-15 tracey switch (ref_tm) {
1459 474370cb 2020-01-15 tracey case TM_DIFF:
1460 474370cb 2020-01-15 tracey diff_time = time(NULL) - committer_time;
1461 474370cb 2020-01-15 tracey if (diff_time > 60 * 60 * 24 * 365 * 2) {
1462 88d59c36 2020-01-29 stsp if (asprintf(&repo_age, "%lld %s",
1463 88d59c36 2020-01-29 stsp (diff_time / 60 / 60 / 24 / 365), years) == -1)
1464 474370cb 2020-01-15 tracey return NULL;
1465 474370cb 2020-01-15 tracey } else if (diff_time > 60 * 60 * 24 * (365 / 12) * 2) {
1466 88d59c36 2020-01-29 stsp if (asprintf(&repo_age, "%lld %s",
1467 474370cb 2020-01-15 tracey (diff_time / 60 / 60 / 24 / (365 / 12)),
1468 88d59c36 2020-01-29 stsp months) == -1)
1469 474370cb 2020-01-15 tracey return NULL;
1470 474370cb 2020-01-15 tracey } else if (diff_time > 60 * 60 * 24 * 7 * 2) {
1471 88d59c36 2020-01-29 stsp if (asprintf(&repo_age, "%lld %s",
1472 88d59c36 2020-01-29 stsp (diff_time / 60 / 60 / 24 / 7), weeks) == -1)
1473 474370cb 2020-01-15 tracey return NULL;
1474 474370cb 2020-01-15 tracey } else if (diff_time > 60 * 60 * 24 * 2) {
1475 88d59c36 2020-01-29 stsp if (asprintf(&repo_age, "%lld %s",
1476 88d59c36 2020-01-29 stsp (diff_time / 60 / 60 / 24), days) == -1)
1477 474370cb 2020-01-15 tracey return NULL;
1478 474370cb 2020-01-15 tracey } else if (diff_time > 60 * 60 * 2) {
1479 88d59c36 2020-01-29 stsp if (asprintf(&repo_age, "%lld %s",
1480 88d59c36 2020-01-29 stsp (diff_time / 60 / 60), hours) == -1)
1481 474370cb 2020-01-15 tracey return NULL;
1482 474370cb 2020-01-15 tracey } else if (diff_time > 60 * 2) {
1483 88d59c36 2020-01-29 stsp if (asprintf(&repo_age, "%lld %s", (diff_time / 60),
1484 88d59c36 2020-01-29 stsp minutes) == -1)
1485 474370cb 2020-01-15 tracey return NULL;
1486 474370cb 2020-01-15 tracey } else if (diff_time > 2) {
1487 88d59c36 2020-01-29 stsp if (asprintf(&repo_age, "%lld %s", diff_time,
1488 88d59c36 2020-01-29 stsp seconds) == -1)
1489 474370cb 2020-01-15 tracey return NULL;
1490 474370cb 2020-01-15 tracey } else {
1491 88d59c36 2020-01-29 stsp if (asprintf(&repo_age, "%s", now) == -1)
1492 474370cb 2020-01-15 tracey return NULL;
1495 474370cb 2020-01-15 tracey case TM_LONG:
1496 474370cb 2020-01-15 tracey if (gmtime_r(&committer_time, &tm) == NULL)
1497 474370cb 2020-01-15 tracey return NULL;
1499 474370cb 2020-01-15 tracey s = asctime_r(&tm, datebuf);
1500 474370cb 2020-01-15 tracey if (s == NULL)
1501 474370cb 2020-01-15 tracey return NULL;
1503 88d59c36 2020-01-29 stsp if (asprintf(&repo_age, "%s UTC", datebuf) == -1)
1504 474370cb 2020-01-15 tracey return NULL;
1507 474370cb 2020-01-15 tracey return repo_age;
1510 d126c1b7 2020-01-29 stsp static const struct got_error *
1511 d126c1b7 2020-01-29 stsp gw_get_repo_age(char **repo_age, struct gw_trans *gw_trans, char *dir,
1512 d126c1b7 2020-01-29 stsp char *repo_ref, int ref_tm)
1514 2c251c14 2020-01-15 tracey const struct got_error *error = NULL;
1515 2c251c14 2020-01-15 tracey struct got_object_id *id = NULL;
1516 2c251c14 2020-01-15 tracey struct got_repository *repo = NULL;
1517 2c251c14 2020-01-15 tracey struct got_commit_object *commit = NULL;
1518 2c251c14 2020-01-15 tracey struct got_reflist_head refs;
1519 2c251c14 2020-01-15 tracey struct got_reflist_entry *re;
1520 2c251c14 2020-01-15 tracey struct got_reference *head_ref;
1521 87f9ebf5 2020-01-15 tracey int is_head = 0;
1522 474370cb 2020-01-15 tracey time_t committer_time = 0, cmp_time = 0;
1523 87f9ebf5 2020-01-15 tracey const char *refname;
1525 d126c1b7 2020-01-29 stsp *repo_age = NULL;
1526 a0f36e03 2020-01-28 stsp SIMPLEQ_INIT(&refs);
1528 387a29ba 2020-01-15 tracey if (repo_ref == NULL)
1529 387a29ba 2020-01-15 tracey return NULL;
1531 87f9ebf5 2020-01-15 tracey if (strncmp(repo_ref, "refs/heads/", 11) == 0)
1532 87f9ebf5 2020-01-15 tracey is_head = 1;
1534 d126c1b7 2020-01-29 stsp if (gw_trans->gw_conf->got_show_repo_age == 0) {
1535 d126c1b7 2020-01-29 stsp *repo_age = strdup("");
1536 d126c1b7 2020-01-29 stsp if (*repo_age == NULL)
1537 d126c1b7 2020-01-29 stsp return got_error_from_errno("strdup");
1538 d126c1b7 2020-01-29 stsp return NULL;
1541 2c251c14 2020-01-15 tracey error = got_repo_open(&repo, dir, NULL);
1542 ec46ccd7 2020-01-15 tracey if (error)
1543 d126c1b7 2020-01-29 stsp goto done;
1545 87f9ebf5 2020-01-15 tracey if (is_head)
1546 87f9ebf5 2020-01-15 tracey error = got_ref_list(&refs, repo, "refs/heads",
1547 87f9ebf5 2020-01-15 tracey got_ref_cmp_by_name, NULL);
1549 87f9ebf5 2020-01-15 tracey error = got_ref_list(&refs, repo, repo_ref,
1550 87f9ebf5 2020-01-15 tracey got_ref_cmp_by_name, NULL);
1551 ec46ccd7 2020-01-15 tracey if (error)
1552 d126c1b7 2020-01-29 stsp goto done;
1554 2c251c14 2020-01-15 tracey SIMPLEQ_FOREACH(re, &refs, entry) {
1555 87f9ebf5 2020-01-15 tracey if (is_head)
1556 87f9ebf5 2020-01-15 tracey refname = strdup(repo_ref);
1558 87f9ebf5 2020-01-15 tracey refname = got_ref_get_name(re->ref);
1559 2c251c14 2020-01-15 tracey error = got_ref_open(&head_ref, repo, refname, 0);
1560 ec46ccd7 2020-01-15 tracey if (error)
1561 d126c1b7 2020-01-29 stsp goto done;
1563 2c251c14 2020-01-15 tracey error = got_ref_resolve(&id, repo, head_ref);
1564 2c251c14 2020-01-15 tracey got_ref_close(head_ref);
1565 ec46ccd7 2020-01-15 tracey if (error)
1566 d126c1b7 2020-01-29 stsp goto done;
1568 2c251c14 2020-01-15 tracey error = got_object_open_as_commit(&commit, repo, id);
1569 ec46ccd7 2020-01-15 tracey if (error)
1570 d126c1b7 2020-01-29 stsp goto done;
1572 2c251c14 2020-01-15 tracey committer_time =
1573 2c251c14 2020-01-15 tracey got_object_commit_get_committer_time(commit);
1575 387a29ba 2020-01-15 tracey if (cmp_time < committer_time)
1576 2c251c14 2020-01-15 tracey cmp_time = committer_time;
1579 474370cb 2020-01-15 tracey if (cmp_time != 0) {
1580 2c251c14 2020-01-15 tracey committer_time = cmp_time;
1581 d126c1b7 2020-01-29 stsp *repo_age = gw_get_time_str(committer_time, ref_tm);
1583 d126c1b7 2020-01-29 stsp *repo_age = strdup("");
1584 d126c1b7 2020-01-29 stsp if (*repo_age == NULL)
1585 d126c1b7 2020-01-29 stsp error = got_error_from_errno("strdup");
1588 2c251c14 2020-01-15 tracey got_ref_list_free(&refs);
1589 2c251c14 2020-01-15 tracey free(id);
1590 d126c1b7 2020-01-29 stsp return error;
1593 ec46ccd7 2020-01-15 tracey static char *
1594 f2f46662 2020-01-23 tracey gw_get_diff(struct gw_trans *gw_trans, struct gw_header *header)
1596 ec46ccd7 2020-01-15 tracey const struct got_error *error;
1597 ec46ccd7 2020-01-15 tracey FILE *f = NULL;
1598 ec46ccd7 2020-01-15 tracey struct got_object_id *id1 = NULL, *id2 = NULL;
1599 ec46ccd7 2020-01-15 tracey struct buf *diffbuf = NULL;
1600 e46f587c 2020-01-29 tracey char *label1 = NULL, *label2 = NULL, *diff_html = NULL, *buf = NULL;
1601 e46f587c 2020-01-29 tracey char *buf_color = NULL, *n_buf = NULL, *newline = NULL;
1602 05ce9a79 2020-01-24 tracey int obj_type;
1603 ec46ccd7 2020-01-15 tracey size_t newsize;
1605 ec46ccd7 2020-01-15 tracey f = got_opentemp();
1606 ec46ccd7 2020-01-15 tracey if (f == NULL)
1607 ec46ccd7 2020-01-15 tracey return NULL;
1609 ec46ccd7 2020-01-15 tracey error = buf_alloc(&diffbuf, 0);
1610 ec46ccd7 2020-01-15 tracey if (error)
1611 ec46ccd7 2020-01-15 tracey return NULL;
1613 90f16cb8 2020-01-24 tracey error = got_repo_open(&header->repo, gw_trans->repo_path, NULL);
1614 ec46ccd7 2020-01-15 tracey if (error)
1615 ec46ccd7 2020-01-15 tracey goto done;
1617 05ce9a79 2020-01-24 tracey if (strncmp(header->parent_id, "/dev/null", 9) != 0) {
1618 05ce9a79 2020-01-24 tracey error = got_repo_match_object_id(&id1, &label1,
1619 05ce9a79 2020-01-24 tracey header->parent_id, GOT_OBJ_TYPE_ANY, 1, header->repo);
1620 05ce9a79 2020-01-24 tracey if (error)
1621 05ce9a79 2020-01-24 tracey goto done;
1624 90f16cb8 2020-01-24 tracey error = got_repo_match_object_id(&id2, &label2,
1625 2ac037ec 2020-01-24 tracey header->commit_id, GOT_OBJ_TYPE_ANY, 1, header->repo);
1626 90f16cb8 2020-01-24 tracey if (error)
1627 90f16cb8 2020-01-24 tracey goto done;
1629 05ce9a79 2020-01-24 tracey error = got_object_get_type(&obj_type, header->repo, id2);
1630 90f16cb8 2020-01-24 tracey if (error)
1631 90f16cb8 2020-01-24 tracey goto done;
1632 05ce9a79 2020-01-24 tracey switch (obj_type) {
1633 ec46ccd7 2020-01-15 tracey case GOT_OBJ_TYPE_BLOB:
1634 90f16cb8 2020-01-24 tracey error = got_diff_objects_as_blobs(id1, id2, NULL, NULL, 3, 0,
1635 90f16cb8 2020-01-24 tracey header->repo, f);
1637 ec46ccd7 2020-01-15 tracey case GOT_OBJ_TYPE_TREE:
1638 90f16cb8 2020-01-24 tracey error = got_diff_objects_as_trees(id1, id2, "", "", 3, 0,
1639 90f16cb8 2020-01-24 tracey header->repo, f);
1641 ec46ccd7 2020-01-15 tracey case GOT_OBJ_TYPE_COMMIT:
1642 90f16cb8 2020-01-24 tracey error = got_diff_objects_as_commits(id1, id2, 3, 0,
1643 90f16cb8 2020-01-24 tracey header->repo, f);
1645 ec46ccd7 2020-01-15 tracey default:
1646 ec46ccd7 2020-01-15 tracey error = got_error(GOT_ERR_OBJ_TYPE);
1649 ec46ccd7 2020-01-15 tracey if ((buf = calloc(128, sizeof(char *))) == NULL)
1650 ec46ccd7 2020-01-15 tracey goto done;
1652 ec46ccd7 2020-01-15 tracey fseek(f, 0, SEEK_SET);
1654 bfd30182 2020-01-24 tracey while ((fgets(buf, 2048, f)) != NULL) {
1655 65559f29 2020-01-24 tracey n_buf = buf;
1656 65559f29 2020-01-24 tracey while (*n_buf == '\n')
1657 65559f29 2020-01-24 tracey n_buf++;
1658 65559f29 2020-01-24 tracey newline = strchr(n_buf, '\n');
1659 65559f29 2020-01-24 tracey if (newline)
1660 65559f29 2020-01-24 tracey *newline = ' ';
1662 65559f29 2020-01-24 tracey buf_color = gw_colordiff_line(gw_html_escape(n_buf));
1663 bfd30182 2020-01-24 tracey if (buf_color == NULL)
1664 bfd30182 2020-01-24 tracey continue;
1666 ec46ccd7 2020-01-15 tracey error = buf_puts(&newsize, diffbuf, buf_color);
1667 ec46ccd7 2020-01-15 tracey if (error)
1668 ec46ccd7 2020-01-15 tracey return NULL;
1670 ec46ccd7 2020-01-15 tracey error = buf_puts(&newsize, diffbuf, div_end);
1671 ec46ccd7 2020-01-15 tracey if (error)
1672 ec46ccd7 2020-01-15 tracey return NULL;
1675 ec46ccd7 2020-01-15 tracey if (buf_len(diffbuf) > 0) {
1676 ec46ccd7 2020-01-15 tracey error = buf_putc(diffbuf, '\0');
1677 ec46ccd7 2020-01-15 tracey diff_html = strdup(buf_get(diffbuf));
1680 ec46ccd7 2020-01-15 tracey fclose(f);
1681 ec46ccd7 2020-01-15 tracey free(buf_color);
1682 ec46ccd7 2020-01-15 tracey free(buf);
1683 ec46ccd7 2020-01-15 tracey free(diffbuf);
1684 ec46ccd7 2020-01-15 tracey free(label1);
1685 ec46ccd7 2020-01-15 tracey free(label2);
1686 ec46ccd7 2020-01-15 tracey free(id1);
1687 ec46ccd7 2020-01-15 tracey free(id2);
1689 ec46ccd7 2020-01-15 tracey if (error)
1690 ec46ccd7 2020-01-15 tracey return NULL;
1692 ec46ccd7 2020-01-15 tracey return diff_html;
1695 2c251c14 2020-01-15 tracey static char *
1696 54415d85 2020-01-15 tracey gw_get_repo_owner(struct gw_trans *gw_trans, char *dir)
1698 2c251c14 2020-01-15 tracey FILE *f;
1699 2c251c14 2020-01-15 tracey char *owner = NULL, *d_file = NULL;
1700 2c251c14 2020-01-15 tracey char *gotweb = "[gotweb]", *gitweb = "[gitweb]", *gw_owner = "owner";
1701 2c251c14 2020-01-15 tracey char *comp, *pos, *buf;
1702 2c251c14 2020-01-15 tracey unsigned int i;
1704 0b20762b 2020-01-29 stsp if (gw_trans->gw_conf->got_show_repo_owner == 0)
1705 2c251c14 2020-01-15 tracey goto err;
1707 88d59c36 2020-01-29 stsp if (asprintf(&d_file, "%s/config", dir) == -1)
1708 2c251c14 2020-01-15 tracey goto err;
1710 2c251c14 2020-01-15 tracey if ((f = fopen(d_file, "r")) == NULL)
1711 2c251c14 2020-01-15 tracey goto err;
1713 6c6c85af 2020-01-15 tracey if ((buf = calloc(128, sizeof(char *))) == NULL)
1714 2c251c14 2020-01-15 tracey goto err;
1716 6c6c85af 2020-01-15 tracey while ((fgets(buf, 128, f)) != NULL) {
1717 2c251c14 2020-01-15 tracey if ((pos = strstr(buf, gotweb)) != NULL)
1720 2c251c14 2020-01-15 tracey if ((pos = strstr(buf, gitweb)) != NULL)
1724 2c251c14 2020-01-15 tracey if (pos == NULL)
1725 2c251c14 2020-01-15 tracey goto err;
1728 6c6c85af 2020-01-15 tracey fgets(buf, 128, f);
1729 2c251c14 2020-01-15 tracey } while ((comp = strcasestr(buf, gw_owner)) == NULL);
1731 2c251c14 2020-01-15 tracey if (comp == NULL)
1732 2c251c14 2020-01-15 tracey goto err;
1734 2c251c14 2020-01-15 tracey if (strncmp(gw_owner, comp, strlen(gw_owner)) != 0)
1735 2c251c14 2020-01-15 tracey goto err;
1737 2c251c14 2020-01-15 tracey for (i = 0; i < 2; i++) {
1738 2c251c14 2020-01-15 tracey owner = strsep(&buf, "\"");
1741 2c251c14 2020-01-15 tracey if (owner == NULL)
1742 2c251c14 2020-01-15 tracey goto err;
1744 2c251c14 2020-01-15 tracey fclose(f);
1745 2c251c14 2020-01-15 tracey free(d_file);
1746 2c251c14 2020-01-15 tracey return owner;
1748 4b60fece 2020-01-29 stsp return strdup("");
1751 2c251c14 2020-01-15 tracey static char *
1752 54415d85 2020-01-15 tracey gw_get_clone_url(struct gw_trans *gw_trans, char *dir)
1754 2c251c14 2020-01-15 tracey FILE *f;
1755 2c251c14 2020-01-15 tracey char *url = NULL, *d_file = NULL;
1756 2c251c14 2020-01-15 tracey unsigned int len;
1758 88d59c36 2020-01-29 stsp if (asprintf(&d_file, "%s/cloneurl", dir) == -1)
1759 2c251c14 2020-01-15 tracey return NULL;
1761 2c251c14 2020-01-15 tracey if ((f = fopen(d_file, "r")) == NULL)
1762 2c251c14 2020-01-15 tracey return NULL;
1764 2c251c14 2020-01-15 tracey fseek(f, 0, SEEK_END);
1765 2c251c14 2020-01-15 tracey len = ftell(f) + 1;
1766 2c251c14 2020-01-15 tracey fseek(f, 0, SEEK_SET);
1768 2c251c14 2020-01-15 tracey if ((url = calloc(len, sizeof(char *))) == NULL)
1769 2c251c14 2020-01-15 tracey return NULL;
1771 2c251c14 2020-01-15 tracey fread(url, 1, len, f);
1772 2c251c14 2020-01-15 tracey fclose(f);
1773 2c251c14 2020-01-15 tracey free(d_file);
1774 2c251c14 2020-01-15 tracey return url;
1777 8d4d2453 2020-01-15 tracey static char *
1778 4ff7391f 2020-01-28 tracey gw_get_repo_tags(struct gw_trans *gw_trans, struct gw_header *header, int limit,
1779 4ff7391f 2020-01-28 tracey int tag_type)
1781 87f9ebf5 2020-01-15 tracey const struct got_error *error = NULL;
1782 87f9ebf5 2020-01-15 tracey struct got_repository *repo = NULL;
1783 87f9ebf5 2020-01-15 tracey struct got_reflist_head refs;
1784 87f9ebf5 2020-01-15 tracey struct got_reflist_entry *re;
1785 e46f587c 2020-01-29 tracey char *tags = NULL, *tag_row = NULL, *tags_navs_disp = NULL;
1786 e46f587c 2020-01-29 tracey char *age = NULL, *newline;
1787 87f9ebf5 2020-01-15 tracey struct buf *diffbuf = NULL;
1788 87f9ebf5 2020-01-15 tracey size_t newsize;
1790 a0f36e03 2020-01-28 stsp SIMPLEQ_INIT(&refs);
1792 6c6c85af 2020-01-15 tracey error = buf_alloc(&diffbuf, 0);
1793 ec46ccd7 2020-01-15 tracey if (error)
1794 6c6c85af 2020-01-15 tracey return NULL;
1796 87f9ebf5 2020-01-15 tracey error = got_repo_open(&repo, gw_trans->repo_path, NULL);
1797 ec46ccd7 2020-01-15 tracey if (error)
1798 87f9ebf5 2020-01-15 tracey goto done;
1800 add40c4f 2020-01-15 tracey error = got_ref_list(&refs, repo, "refs/tags", got_ref_cmp_tags, repo);
1801 87f9ebf5 2020-01-15 tracey if (error)
1802 87f9ebf5 2020-01-15 tracey goto done;
1804 87f9ebf5 2020-01-15 tracey SIMPLEQ_FOREACH(re, &refs, entry) {
1805 87f9ebf5 2020-01-15 tracey const char *refname;
1806 f2f46662 2020-01-23 tracey char *refstr, *tag_commit0, *tag_commit, *id_str;
1807 4ff7391f 2020-01-28 tracey const char *tagger;
1808 87f9ebf5 2020-01-15 tracey time_t tagger_time;
1809 87f9ebf5 2020-01-15 tracey struct got_object_id *id;
1810 87f9ebf5 2020-01-15 tracey struct got_tag_object *tag;
1812 87f9ebf5 2020-01-15 tracey refname = got_ref_get_name(re->ref);
1813 87f9ebf5 2020-01-15 tracey if (strncmp(refname, "refs/tags/", 10) != 0)
1814 87f9ebf5 2020-01-15 tracey continue;
1815 87f9ebf5 2020-01-15 tracey refname += 10;
1816 87f9ebf5 2020-01-15 tracey refstr = got_ref_to_str(re->ref);
1817 87f9ebf5 2020-01-15 tracey if (refstr == NULL) {
1818 87f9ebf5 2020-01-15 tracey error = got_error_from_errno("got_ref_to_str");
1819 87f9ebf5 2020-01-15 tracey goto done;
1822 87f9ebf5 2020-01-15 tracey error = got_ref_resolve(&id, repo, re->ref);
1823 87f9ebf5 2020-01-15 tracey if (error)
1824 87f9ebf5 2020-01-15 tracey goto done;
1825 87f9ebf5 2020-01-15 tracey error = got_object_open_as_tag(&tag, repo, id);
1826 87f9ebf5 2020-01-15 tracey free(id);
1827 87f9ebf5 2020-01-15 tracey if (error)
1828 87f9ebf5 2020-01-15 tracey goto done;
1830 4ff7391f 2020-01-28 tracey tagger = got_object_tag_get_tagger(tag);
1831 87f9ebf5 2020-01-15 tracey tagger_time = got_object_tag_get_tagger_time(tag);
1833 87f9ebf5 2020-01-15 tracey error = got_object_id_str(&id_str,
1834 87f9ebf5 2020-01-15 tracey got_object_tag_get_object_id(tag));
1835 87f9ebf5 2020-01-15 tracey if (error)
1836 87f9ebf5 2020-01-15 tracey goto done;
1838 f2f46662 2020-01-23 tracey tag_commit0 = strdup(got_object_tag_get_message(tag));
1840 f2f46662 2020-01-23 tracey if (tag_commit0 == NULL) {
1841 87f9ebf5 2020-01-15 tracey error = got_error_from_errno("strdup");
1842 87f9ebf5 2020-01-15 tracey goto done;
1845 f2f46662 2020-01-23 tracey tag_commit = tag_commit0;
1846 f2f46662 2020-01-23 tracey while (*tag_commit == '\n')
1847 f2f46662 2020-01-23 tracey tag_commit++;
1849 87f9ebf5 2020-01-15 tracey switch (tag_type) {
1850 87f9ebf5 2020-01-15 tracey case TAGBRIEF:
1851 f2f46662 2020-01-23 tracey newline = strchr(tag_commit, '\n');
1852 87f9ebf5 2020-01-15 tracey if (newline)
1853 87f9ebf5 2020-01-15 tracey *newline = '\0';
1855 88d59c36 2020-01-29 stsp if (asprintf(&age, "%s", gw_get_time_str(tagger_time,
1856 88d59c36 2020-01-29 stsp TM_DIFF)) == -1) {
1857 87f9ebf5 2020-01-15 tracey error = got_error_from_errno("asprintf");
1858 87f9ebf5 2020-01-15 tracey goto done;
1861 88d59c36 2020-01-29 stsp if (asprintf(&tags_navs_disp, tags_navs,
1862 87f9ebf5 2020-01-15 tracey gw_trans->repo_name, id_str, gw_trans->repo_name,
1863 87f9ebf5 2020-01-15 tracey id_str, gw_trans->repo_name, id_str,
1864 88d59c36 2020-01-29 stsp gw_trans->repo_name, id_str) == -1) {
1865 87f9ebf5 2020-01-15 tracey error = got_error_from_errno("asprintf");
1866 87f9ebf5 2020-01-15 tracey goto done;
1869 88d59c36 2020-01-29 stsp if (asprintf(&tag_row, tags_row, age, refname,
1870 88d59c36 2020-01-29 stsp tag_commit, tags_navs_disp) == -1) {
1871 87f9ebf5 2020-01-15 tracey error = got_error_from_errno("asprintf");
1872 87f9ebf5 2020-01-15 tracey goto done;
1875 87f9ebf5 2020-01-15 tracey free(tags_navs_disp);
1877 87f9ebf5 2020-01-15 tracey case TAGFULL:
1878 88d59c36 2020-01-29 stsp if (asprintf(&age, "%s", gw_get_time_str(tagger_time,
1879 88d59c36 2020-01-29 stsp TM_LONG)) == -1) {
1880 4ff7391f 2020-01-28 tracey error = got_error_from_errno("asprintf");
1881 4ff7391f 2020-01-28 tracey goto done;
1883 88d59c36 2020-01-29 stsp if (asprintf(&tag_row, tag_info, age,
1884 4ff7391f 2020-01-28 tracey gw_html_escape(tagger),
1885 88d59c36 2020-01-29 stsp gw_html_escape(tag_commit)) == -1) {
1886 4ff7391f 2020-01-28 tracey error = got_error_from_errno("asprintf");
1887 4ff7391f 2020-01-28 tracey goto done;
1890 87f9ebf5 2020-01-15 tracey default:
1894 6c6c85af 2020-01-15 tracey got_object_tag_close(tag);
1896 6c6c85af 2020-01-15 tracey error = buf_puts(&newsize, diffbuf, tag_row);
1898 6c6c85af 2020-01-15 tracey free(id_str);
1899 6c6c85af 2020-01-15 tracey free(refstr);
1900 6c6c85af 2020-01-15 tracey free(age);
1901 f2f46662 2020-01-23 tracey free(tag_commit0);
1902 87f9ebf5 2020-01-15 tracey free(tag_row);
1904 87f9ebf5 2020-01-15 tracey if (error || (limit && --limit == 0))
1908 6c6c85af 2020-01-15 tracey if (buf_len(diffbuf) > 0) {
1909 6c6c85af 2020-01-15 tracey error = buf_putc(diffbuf, '\0');
1910 6c6c85af 2020-01-15 tracey tags = strdup(buf_get(diffbuf));
1913 87f9ebf5 2020-01-15 tracey buf_free(diffbuf);
1914 87f9ebf5 2020-01-15 tracey got_ref_list_free(&refs);
1915 87f9ebf5 2020-01-15 tracey if (repo)
1916 87f9ebf5 2020-01-15 tracey got_repo_close(repo);
1917 87f9ebf5 2020-01-15 tracey if (error)
1918 87f9ebf5 2020-01-15 tracey return NULL;
1920 87f9ebf5 2020-01-15 tracey return tags;
1923 f2f46662 2020-01-23 tracey static void
1924 f2f46662 2020-01-23 tracey gw_free_headers(struct gw_header *header)
1926 f2f46662 2020-01-23 tracey free(header->id);
1927 f2f46662 2020-01-23 tracey free(header->path);
1928 f2f46662 2020-01-23 tracey if (header->commit != NULL)
1929 f2f46662 2020-01-23 tracey got_object_commit_close(header->commit);
1930 f2f46662 2020-01-23 tracey if (header->repo)
1931 f2f46662 2020-01-23 tracey got_repo_close(header->repo);
1932 f2f46662 2020-01-23 tracey free(header->refs_str);
1933 f2f46662 2020-01-23 tracey free(header->commit_id);
1934 f2f46662 2020-01-23 tracey free(header->parent_id);
1935 f2f46662 2020-01-23 tracey free(header->tree_id);
1936 f2f46662 2020-01-23 tracey free(header->author);
1937 f2f46662 2020-01-23 tracey free(header->committer);
1938 f2f46662 2020-01-23 tracey free(header->commit_msg);
1941 f2f46662 2020-01-23 tracey static struct gw_header *
1942 f2f46662 2020-01-23 tracey gw_init_header()
1944 f2f46662 2020-01-23 tracey struct gw_header *header;
1946 ae36ed87 2020-01-28 stsp header = malloc(sizeof(*header));
1947 ae36ed87 2020-01-28 stsp if (header == NULL)
1948 f2f46662 2020-01-23 tracey return NULL;
1950 f2f46662 2020-01-23 tracey header->repo = NULL;
1951 f2f46662 2020-01-23 tracey header->commit = NULL;
1952 f2f46662 2020-01-23 tracey header->id = NULL;
1953 f2f46662 2020-01-23 tracey header->path = NULL;
1954 ae36ed87 2020-01-28 stsp SIMPLEQ_INIT(&header->refs);
1956 f2f46662 2020-01-23 tracey return header;
1959 f2f46662 2020-01-23 tracey static const struct got_error *
1960 f2f46662 2020-01-23 tracey gw_get_commits(struct gw_trans * gw_trans, struct gw_header *header,
1961 f2f46662 2020-01-23 tracey int limit)
1963 f2f46662 2020-01-23 tracey const struct got_error *error = NULL;
1964 f2f46662 2020-01-23 tracey struct got_commit_graph *graph = NULL;
1966 f2f46662 2020-01-23 tracey error = got_commit_graph_open(&graph, header->path, 0);
1967 f2f46662 2020-01-23 tracey if (error)
1968 f2f46662 2020-01-23 tracey goto done;
1970 f2f46662 2020-01-23 tracey error = got_commit_graph_iter_start(graph, header->id, header->repo,
1971 f2f46662 2020-01-23 tracey NULL, NULL);
1972 f2f46662 2020-01-23 tracey if (error)
1973 f2f46662 2020-01-23 tracey goto done;
1975 f2f46662 2020-01-23 tracey for (;;) {
1976 f2f46662 2020-01-23 tracey error = got_commit_graph_iter_next(&header->id, graph,
1977 f2f46662 2020-01-23 tracey header->repo, NULL, NULL);
1978 f2f46662 2020-01-23 tracey if (error) {
1979 f2f46662 2020-01-23 tracey if (error->code == GOT_ERR_ITER_COMPLETED)
1980 f2f46662 2020-01-23 tracey error = NULL;
1981 f2f46662 2020-01-23 tracey goto done;
1983 f2f46662 2020-01-23 tracey if (header->id == NULL)
1984 f2f46662 2020-01-23 tracey goto done;
1986 f2f46662 2020-01-23 tracey error = got_object_open_as_commit(&header->commit, header->repo,
1987 f2f46662 2020-01-23 tracey header->id);
1988 f2f46662 2020-01-23 tracey if (error)
1989 f2f46662 2020-01-23 tracey goto done;
1991 f2f46662 2020-01-23 tracey error = gw_get_commit(gw_trans, header);
1992 f2f46662 2020-01-23 tracey if (limit > 1) {
1993 f2f46662 2020-01-23 tracey struct gw_header *n_header = NULL;
1994 5147ab56 2020-01-29 stsp if ((n_header = gw_init_header()) == NULL) {
1995 f2f46662 2020-01-23 tracey error = got_error_from_errno("malloc");
1996 5147ab56 2020-01-29 stsp goto done;
1999 f2f46662 2020-01-23 tracey n_header->refs_str = strdup(header->refs_str);
2000 f2f46662 2020-01-23 tracey n_header->commit_id = strdup(header->commit_id);
2001 f2f46662 2020-01-23 tracey n_header->parent_id = strdup(header->parent_id);
2002 f2f46662 2020-01-23 tracey n_header->tree_id = strdup(header->tree_id);
2003 f2f46662 2020-01-23 tracey n_header->author = strdup(header->author);
2004 f2f46662 2020-01-23 tracey n_header->committer = strdup(header->committer);
2005 f2f46662 2020-01-23 tracey n_header->commit_msg = strdup(header->commit_msg);
2006 f2f46662 2020-01-23 tracey n_header->committer_time = header->committer_time;
2007 f2f46662 2020-01-23 tracey TAILQ_INSERT_TAIL(&gw_trans->gw_headers, n_header,
2010 f2f46662 2020-01-23 tracey if (error || (limit && --limit == 0))
2014 f2f46662 2020-01-23 tracey if (graph)
2015 f2f46662 2020-01-23 tracey got_commit_graph_close(graph);
2016 f2f46662 2020-01-23 tracey return error;
2019 f2f46662 2020-01-23 tracey static const struct got_error *
2020 f2f46662 2020-01-23 tracey gw_get_commit(struct gw_trans *gw_trans, struct gw_header *header)
2022 f2f46662 2020-01-23 tracey const struct got_error *error = NULL;
2023 f2f46662 2020-01-23 tracey struct got_reflist_entry *re;
2024 f2f46662 2020-01-23 tracey struct got_object_id *id2 = NULL;
2025 f2f46662 2020-01-23 tracey struct got_object_qid *parent_id;
2026 e46f587c 2020-01-29 tracey char *refs_str = NULL, *commit_msg = NULL, *commit_msg0;
2028 f2f46662 2020-01-23 tracey /*print commit*/
2029 f2f46662 2020-01-23 tracey SIMPLEQ_FOREACH(re, &header->refs, entry) {
2030 f2f46662 2020-01-23 tracey char *s;
2031 f2f46662 2020-01-23 tracey const char *name;
2032 f2f46662 2020-01-23 tracey struct got_tag_object *tag = NULL;
2033 f2f46662 2020-01-23 tracey int cmp;
2035 f2f46662 2020-01-23 tracey name = got_ref_get_name(re->ref);
2036 f2f46662 2020-01-23 tracey if (strcmp(name, GOT_REF_HEAD) == 0)
2037 f2f46662 2020-01-23 tracey continue;
2038 f2f46662 2020-01-23 tracey if (strncmp(name, "refs/", 5) == 0)
2039 f2f46662 2020-01-23 tracey name += 5;
2040 f2f46662 2020-01-23 tracey if (strncmp(name, "got/", 4) == 0)
2041 f2f46662 2020-01-23 tracey continue;
2042 f2f46662 2020-01-23 tracey if (strncmp(name, "heads/", 6) == 0)
2043 f2f46662 2020-01-23 tracey name += 6;
2044 f2f46662 2020-01-23 tracey if (strncmp(name, "remotes/", 8) == 0)
2045 f2f46662 2020-01-23 tracey name += 8;
2046 f2f46662 2020-01-23 tracey if (strncmp(name, "tags/", 5) == 0) {
2047 f2f46662 2020-01-23 tracey error = got_object_open_as_tag(&tag, header->repo,
2048 f2f46662 2020-01-23 tracey re->id);
2049 f2f46662 2020-01-23 tracey if (error) {
2050 f2f46662 2020-01-23 tracey if (error->code != GOT_ERR_OBJ_TYPE)
2051 f2f46662 2020-01-23 tracey continue;
2053 f2f46662 2020-01-23 tracey * Ref points at something other
2054 f2f46662 2020-01-23 tracey * than a tag.
2056 f2f46662 2020-01-23 tracey error = NULL;
2057 f2f46662 2020-01-23 tracey tag = NULL;
2060 f2f46662 2020-01-23 tracey cmp = got_object_id_cmp(tag ?
2061 f2f46662 2020-01-23 tracey got_object_tag_get_object_id(tag) : re->id, header->id);
2062 f2f46662 2020-01-23 tracey if (tag)
2063 f2f46662 2020-01-23 tracey got_object_tag_close(tag);
2064 f2f46662 2020-01-23 tracey if (cmp != 0)
2065 f2f46662 2020-01-23 tracey continue;
2066 f2f46662 2020-01-23 tracey s = refs_str;
2067 88d59c36 2020-01-29 stsp if (asprintf(&refs_str, "%s%s%s", s ? s : "",
2068 88d59c36 2020-01-29 stsp s ? ", " : "", name) == -1) {
2069 f2f46662 2020-01-23 tracey error = got_error_from_errno("asprintf");
2070 f2f46662 2020-01-23 tracey free(s);
2071 f2f46662 2020-01-23 tracey return error;
2073 f2f46662 2020-01-23 tracey header->refs_str = strdup(refs_str);
2074 f2f46662 2020-01-23 tracey free(s);
2077 f2f46662 2020-01-23 tracey if (refs_str == NULL)
2078 f2f46662 2020-01-23 tracey header->refs_str = strdup("");
2079 f2f46662 2020-01-23 tracey free(refs_str);
2081 f2f46662 2020-01-23 tracey error = got_object_id_str(&header->commit_id, header->id);
2082 f2f46662 2020-01-23 tracey if (error)
2083 f2f46662 2020-01-23 tracey return error;
2085 f2f46662 2020-01-23 tracey error = got_object_id_str(&header->tree_id,
2086 f2f46662 2020-01-23 tracey got_object_commit_get_tree_id(header->commit));
2087 f2f46662 2020-01-23 tracey if (error)
2088 f2f46662 2020-01-23 tracey return error;
2090 f2f46662 2020-01-23 tracey if (gw_trans->action == GW_DIFF) {
2091 f2f46662 2020-01-23 tracey parent_id = SIMPLEQ_FIRST(
2092 f2f46662 2020-01-23 tracey got_object_commit_get_parent_ids(header->commit));
2093 f2f46662 2020-01-23 tracey if (parent_id != NULL) {
2094 f2f46662 2020-01-23 tracey id2 = got_object_id_dup(parent_id->id);
2095 f2f46662 2020-01-23 tracey free (parent_id);
2096 f2f46662 2020-01-23 tracey error = got_object_id_str(&header->parent_id, id2);
2097 f2f46662 2020-01-23 tracey if (error)
2098 f2f46662 2020-01-23 tracey return error;
2099 f2f46662 2020-01-23 tracey free(id2);
2101 f2f46662 2020-01-23 tracey header->parent_id = strdup("/dev/null");
2103 f2f46662 2020-01-23 tracey header->parent_id = strdup("");
2105 f2f46662 2020-01-23 tracey header->committer_time =
2106 f2f46662 2020-01-23 tracey got_object_commit_get_committer_time(header->commit);
2108 1177268c 2020-01-28 tracey if (gw_trans->action != GW_BRIEFS && gw_trans->action != GW_SUMMARY) {
2109 1177268c 2020-01-28 tracey header->author = strdup(
2110 1177268c 2020-01-28 tracey gw_html_escape(got_object_commit_get_author(header->commit))
2112 1177268c 2020-01-28 tracey } else {
2113 1177268c 2020-01-28 tracey header->author = strdup(
2114 1177268c 2020-01-28 tracey got_object_commit_get_author(header->commit)
2118 4ff7391f 2020-01-28 tracey header->committer = strdup(
2119 4ff7391f 2020-01-28 tracey gw_html_escape(got_object_commit_get_committer(header->commit))
2122 f2f46662 2020-01-23 tracey error = got_object_commit_get_logmsg(&commit_msg0, header->commit);
2123 f2f46662 2020-01-23 tracey if (error)
2124 f2f46662 2020-01-23 tracey return error;
2126 f2f46662 2020-01-23 tracey commit_msg = commit_msg0;
2127 f2f46662 2020-01-23 tracey while (*commit_msg == '\n')
2128 f2f46662 2020-01-23 tracey commit_msg++;
2130 f2f46662 2020-01-23 tracey header->commit_msg = strdup(commit_msg);
2131 f2f46662 2020-01-23 tracey free(commit_msg0);
2132 f2f46662 2020-01-23 tracey return error;
2135 f2f46662 2020-01-23 tracey static const struct got_error *
2136 f2f46662 2020-01-23 tracey gw_get_header(struct gw_trans *gw_trans, struct gw_header *header, int limit)
2138 f2f46662 2020-01-23 tracey const struct got_error *error = NULL;
2139 f2f46662 2020-01-23 tracey char *in_repo_path = NULL;
2141 f2f46662 2020-01-23 tracey error = got_repo_open(&header->repo, gw_trans->repo_path, NULL);
2142 f2f46662 2020-01-23 tracey if (error)
2143 f2f46662 2020-01-23 tracey return error;
2145 f2f46662 2020-01-23 tracey if (gw_trans->commit == NULL) {
2146 f2f46662 2020-01-23 tracey struct got_reference *head_ref;
2147 f2f46662 2020-01-23 tracey error = got_ref_open(&head_ref, header->repo,
2148 f2f46662 2020-01-23 tracey gw_trans->headref, 0);
2149 f2f46662 2020-01-23 tracey if (error)
2150 f2f46662 2020-01-23 tracey return error;
2152 f2f46662 2020-01-23 tracey error = got_ref_resolve(&header->id, header->repo, head_ref);
2153 f2f46662 2020-01-23 tracey got_ref_close(head_ref);
2154 f2f46662 2020-01-23 tracey if (error)
2155 f2f46662 2020-01-23 tracey return error;
2157 f2f46662 2020-01-23 tracey error = got_object_open_as_commit(&header->commit,
2158 f2f46662 2020-01-23 tracey header->repo, header->id);
2159 f2f46662 2020-01-23 tracey } else {
2160 f2f46662 2020-01-23 tracey struct got_reference *ref;
2161 f2f46662 2020-01-23 tracey error = got_ref_open(&ref, header->repo, gw_trans->commit, 0);
2162 f2f46662 2020-01-23 tracey if (error == NULL) {
2163 f2f46662 2020-01-23 tracey int obj_type;
2164 f2f46662 2020-01-23 tracey error = got_ref_resolve(&header->id, header->repo, ref);
2165 f2f46662 2020-01-23 tracey got_ref_close(ref);
2166 f2f46662 2020-01-23 tracey if (error)
2167 f2f46662 2020-01-23 tracey return error;
2168 f2f46662 2020-01-23 tracey error = got_object_get_type(&obj_type, header->repo,
2169 f2f46662 2020-01-23 tracey header->id);
2170 f2f46662 2020-01-23 tracey if (error)
2171 f2f46662 2020-01-23 tracey return error;
2172 f2f46662 2020-01-23 tracey if (obj_type == GOT_OBJ_TYPE_TAG) {
2173 f2f46662 2020-01-23 tracey struct got_tag_object *tag;
2174 f2f46662 2020-01-23 tracey error = got_object_open_as_tag(&tag,
2175 f2f46662 2020-01-23 tracey header->repo, header->id);
2176 f2f46662 2020-01-23 tracey if (error)
2177 f2f46662 2020-01-23 tracey return error;
2178 f2f46662 2020-01-23 tracey if (got_object_tag_get_object_type(tag) !=
2179 f2f46662 2020-01-23 tracey GOT_OBJ_TYPE_COMMIT) {
2180 f2f46662 2020-01-23 tracey got_object_tag_close(tag);
2181 f2f46662 2020-01-23 tracey error = got_error(GOT_ERR_OBJ_TYPE);
2182 f2f46662 2020-01-23 tracey return error;
2184 f2f46662 2020-01-23 tracey free(header->id);
2185 f2f46662 2020-01-23 tracey header->id = got_object_id_dup(
2186 f2f46662 2020-01-23 tracey got_object_tag_get_object_id(tag));
2187 f2f46662 2020-01-23 tracey if (header->id == NULL)
2188 f2f46662 2020-01-23 tracey error = got_error_from_errno(
2189 f2f46662 2020-01-23 tracey "got_object_id_dup");
2190 f2f46662 2020-01-23 tracey got_object_tag_close(tag);
2191 f2f46662 2020-01-23 tracey if (error)
2192 f2f46662 2020-01-23 tracey return error;
2193 f2f46662 2020-01-23 tracey } else if (obj_type != GOT_OBJ_TYPE_COMMIT) {
2194 f2f46662 2020-01-23 tracey error = got_error(GOT_ERR_OBJ_TYPE);
2195 f2f46662 2020-01-23 tracey return error;
2197 f2f46662 2020-01-23 tracey error = got_object_open_as_commit(&header->commit,
2198 f2f46662 2020-01-23 tracey header->repo, header->id);
2199 f2f46662 2020-01-23 tracey if (error)
2200 f2f46662 2020-01-23 tracey return error;
2202 f2f46662 2020-01-23 tracey if (header->commit == NULL) {
2203 f2f46662 2020-01-23 tracey error = got_repo_match_object_id_prefix(&header->id,
2204 f2f46662 2020-01-23 tracey gw_trans->commit, GOT_OBJ_TYPE_COMMIT,
2205 f2f46662 2020-01-23 tracey header->repo);
2206 f2f46662 2020-01-23 tracey if (error)
2207 f2f46662 2020-01-23 tracey return error;
2209 f2f46662 2020-01-23 tracey error = got_repo_match_object_id_prefix(&header->id,
2210 f2f46662 2020-01-23 tracey gw_trans->commit, GOT_OBJ_TYPE_COMMIT,
2211 f2f46662 2020-01-23 tracey header->repo);
2214 f2f46662 2020-01-23 tracey error = got_repo_map_path(&in_repo_path, header->repo,
2215 f2f46662 2020-01-23 tracey gw_trans->repo_path, 1);
2216 f2f46662 2020-01-23 tracey if (error)
2217 f2f46662 2020-01-23 tracey return error;
2219 f2f46662 2020-01-23 tracey if (in_repo_path) {
2220 f2f46662 2020-01-23 tracey header->path = strdup(in_repo_path);
2222 f2f46662 2020-01-23 tracey free(in_repo_path);
2224 f2f46662 2020-01-23 tracey error = got_ref_list(&header->refs, header->repo, NULL,
2225 f2f46662 2020-01-23 tracey got_ref_cmp_by_name, NULL);
2226 f2f46662 2020-01-23 tracey if (error)
2227 f2f46662 2020-01-23 tracey return error;
2229 f2f46662 2020-01-23 tracey error = gw_get_commits(gw_trans, header, limit);
2230 f2f46662 2020-01-23 tracey return error;
2233 ec46ccd7 2020-01-15 tracey struct blame_line {
2234 ec46ccd7 2020-01-15 tracey int annotated;
2235 ec46ccd7 2020-01-15 tracey char *id_str;
2236 ec46ccd7 2020-01-15 tracey char *committer;
2237 ec46ccd7 2020-01-15 tracey char datebuf[11]; /* YYYY-MM-DD + NUL */
2240 147269d5 2020-01-15 tracey struct gw_blame_cb_args {
2241 ec46ccd7 2020-01-15 tracey struct blame_line *lines;
2242 ec46ccd7 2020-01-15 tracey int nlines;
2243 ec46ccd7 2020-01-15 tracey int nlines_prec;
2244 ec46ccd7 2020-01-15 tracey int lineno_cur;
2245 ec46ccd7 2020-01-15 tracey off_t *line_offsets;
2246 ec46ccd7 2020-01-15 tracey FILE *f;
2247 ec46ccd7 2020-01-15 tracey struct got_repository *repo;
2248 54415d85 2020-01-15 tracey struct gw_trans *gw_trans;
2249 2e676fc5 2020-01-15 tracey struct buf *blamebuf;
2252 ec46ccd7 2020-01-15 tracey static const struct got_error *
2253 147269d5 2020-01-15 tracey gw_blame_cb(void *arg, int nlines, int lineno, struct got_object_id *id)
2255 ec46ccd7 2020-01-15 tracey const struct got_error *err = NULL;
2256 147269d5 2020-01-15 tracey struct gw_blame_cb_args *a = arg;
2257 ec46ccd7 2020-01-15 tracey struct blame_line *bline;
2258 ec46ccd7 2020-01-15 tracey char *line = NULL;
2259 2e676fc5 2020-01-15 tracey size_t linesize = 0, newsize;
2260 ec46ccd7 2020-01-15 tracey struct got_commit_object *commit = NULL;
2261 ec46ccd7 2020-01-15 tracey off_t offset;
2262 ec46ccd7 2020-01-15 tracey struct tm tm;
2263 ec46ccd7 2020-01-15 tracey time_t committer_time;
2265 ec46ccd7 2020-01-15 tracey if (nlines != a->nlines ||
2266 ec46ccd7 2020-01-15 tracey (lineno != -1 && lineno < 1) || lineno > a->nlines)
2267 ec46ccd7 2020-01-15 tracey return got_error(GOT_ERR_RANGE);
2269 ec46ccd7 2020-01-15 tracey if (lineno == -1)
2270 ec46ccd7 2020-01-15 tracey return NULL; /* no change in this commit */
2272 ec46ccd7 2020-01-15 tracey /* Annotate this line. */
2273 ec46ccd7 2020-01-15 tracey bline = &a->lines[lineno - 1];
2274 ec46ccd7 2020-01-15 tracey if (bline->annotated)
2275 ec46ccd7 2020-01-15 tracey return NULL;
2276 ec46ccd7 2020-01-15 tracey err = got_object_id_str(&bline->id_str, id);
2277 ec46ccd7 2020-01-15 tracey if (err)
2278 ec46ccd7 2020-01-15 tracey return err;
2280 ec46ccd7 2020-01-15 tracey err = got_object_open_as_commit(&commit, a->repo, id);
2281 ec46ccd7 2020-01-15 tracey if (err)
2282 ec46ccd7 2020-01-15 tracey goto done;
2284 ec46ccd7 2020-01-15 tracey bline->committer = strdup(got_object_commit_get_committer(commit));
2285 ec46ccd7 2020-01-15 tracey if (bline->committer == NULL) {
2286 ec46ccd7 2020-01-15 tracey err = got_error_from_errno("strdup");
2287 ec46ccd7 2020-01-15 tracey goto done;
2290 ec46ccd7 2020-01-15 tracey committer_time = got_object_commit_get_committer_time(commit);
2291 ec46ccd7 2020-01-15 tracey if (localtime_r(&committer_time, &tm) == NULL)
2292 ec46ccd7 2020-01-15 tracey return got_error_from_errno("localtime_r");
2293 ec46ccd7 2020-01-15 tracey if (strftime(bline->datebuf, sizeof(bline->datebuf), "%G-%m-%d",
2294 ec46ccd7 2020-01-15 tracey &tm) >= sizeof(bline->datebuf)) {
2295 ec46ccd7 2020-01-15 tracey err = got_error(GOT_ERR_NO_SPACE);
2296 ec46ccd7 2020-01-15 tracey goto done;
2298 ec46ccd7 2020-01-15 tracey bline->annotated = 1;
2300 ec46ccd7 2020-01-15 tracey /* Print lines annotated so far. */
2301 ec46ccd7 2020-01-15 tracey bline = &a->lines[a->lineno_cur - 1];
2302 ec46ccd7 2020-01-15 tracey if (!bline->annotated)
2303 ec46ccd7 2020-01-15 tracey goto done;
2305 ec46ccd7 2020-01-15 tracey offset = a->line_offsets[a->lineno_cur - 1];
2306 ec46ccd7 2020-01-15 tracey if (fseeko(a->f, offset, SEEK_SET) == -1) {
2307 ec46ccd7 2020-01-15 tracey err = got_error_from_errno("fseeko");
2308 ec46ccd7 2020-01-15 tracey goto done;
2311 ec46ccd7 2020-01-15 tracey while (bline->annotated) {
2312 0311ce2d 2020-01-15 tracey char *smallerthan, *at, *nl, *committer, *blame_row = NULL,
2313 0311ce2d 2020-01-15 tracey *line_escape = NULL;
2314 ec46ccd7 2020-01-15 tracey size_t len;
2316 ec46ccd7 2020-01-15 tracey if (getline(&line, &linesize, a->f) == -1) {
2317 ec46ccd7 2020-01-15 tracey if (ferror(a->f))
2318 ec46ccd7 2020-01-15 tracey err = got_error_from_errno("getline");
2322 ec46ccd7 2020-01-15 tracey committer = bline->committer;
2323 ec46ccd7 2020-01-15 tracey smallerthan = strchr(committer, '<');
2324 ec46ccd7 2020-01-15 tracey if (smallerthan && smallerthan[1] != '\0')
2325 ec46ccd7 2020-01-15 tracey committer = smallerthan + 1;
2326 ec46ccd7 2020-01-15 tracey at = strchr(committer, '@');
2328 ec46ccd7 2020-01-15 tracey *at = '\0';
2329 ec46ccd7 2020-01-15 tracey len = strlen(committer);
2330 ec46ccd7 2020-01-15 tracey if (len >= 9)
2331 ec46ccd7 2020-01-15 tracey committer[8] = '\0';
2333 ec46ccd7 2020-01-15 tracey nl = strchr(line, '\n');
2335 ec46ccd7 2020-01-15 tracey *nl = '\0';
2337 0311ce2d 2020-01-15 tracey if (strcmp(line, "") != 0)
2338 0311ce2d 2020-01-15 tracey line_escape = strdup(gw_html_escape(line));
2340 0311ce2d 2020-01-15 tracey line_escape = strdup("");
2342 f2f46662 2020-01-23 tracey asprintf(&blame_row, blame_line, a->nlines_prec,
2343 2e676fc5 2020-01-15 tracey a->lineno_cur, bline->id_str, bline->datebuf, committer,
2344 0311ce2d 2020-01-15 tracey line_escape);
2345 ec46ccd7 2020-01-15 tracey a->lineno_cur++;
2346 2e676fc5 2020-01-15 tracey err = buf_puts(&newsize, a->blamebuf, blame_row);
2347 2e676fc5 2020-01-15 tracey if (err)
2348 2e676fc5 2020-01-15 tracey return err;
2350 ec46ccd7 2020-01-15 tracey bline = &a->lines[a->lineno_cur - 1];
2351 0311ce2d 2020-01-15 tracey free(line_escape);
2352 2e676fc5 2020-01-15 tracey free(blame_row);
2355 ec46ccd7 2020-01-15 tracey if (commit)
2356 ec46ccd7 2020-01-15 tracey got_object_commit_close(commit);
2357 ec46ccd7 2020-01-15 tracey free(line);
2358 ec46ccd7 2020-01-15 tracey return err;
2361 bcbc97d8 2020-01-15 tracey static char*
2362 e46f587c 2020-01-29 tracey gw_get_file_blame_blob(struct gw_trans *gw_trans)
2364 bcbc97d8 2020-01-15 tracey const struct got_error *error = NULL;
2365 bcbc97d8 2020-01-15 tracey struct got_repository *repo = NULL;
2366 ec46ccd7 2020-01-15 tracey struct got_object_id *obj_id = NULL;
2367 ec46ccd7 2020-01-15 tracey struct got_object_id *commit_id = NULL;
2368 ec46ccd7 2020-01-15 tracey struct got_blob_object *blob = NULL;
2369 e46f587c 2020-01-29 tracey char *blame_html = NULL, *path = NULL, *in_repo_path = NULL;
2370 e46f587c 2020-01-29 tracey char *folder = NULL;
2371 147269d5 2020-01-15 tracey struct gw_blame_cb_args bca;
2372 119bf4ed 2020-01-15 tracey int i, obj_type;
2373 ec46ccd7 2020-01-15 tracey size_t filesize;
2375 ec46ccd7 2020-01-15 tracey error = got_repo_open(&repo, gw_trans->repo_path, NULL);
2376 ec46ccd7 2020-01-15 tracey if (error)
2377 ec46ccd7 2020-01-15 tracey goto done;
2379 2e676fc5 2020-01-15 tracey if (gw_trans->repo_folder != NULL) {
2380 88d59c36 2020-01-29 stsp if (asprintf(&folder, "%s/", gw_trans->repo_folder) == -1) {
2381 2e676fc5 2020-01-15 tracey error = got_error_from_errno("asprintf");
2382 2e676fc5 2020-01-15 tracey goto done;
2385 2e676fc5 2020-01-15 tracey folder = strdup("");
2387 88d59c36 2020-01-29 stsp if (asprintf(&path, "%s%s", folder, gw_trans->repo_file) == -1) {
2388 2e676fc5 2020-01-15 tracey error = got_error_from_errno("asprintf");
2389 2e676fc5 2020-01-15 tracey goto done;
2391 2e676fc5 2020-01-15 tracey free(folder);
2393 2e676fc5 2020-01-15 tracey error = got_repo_map_path(&in_repo_path, repo, path, 1);
2394 ec46ccd7 2020-01-15 tracey if (error)
2395 ec46ccd7 2020-01-15 tracey goto done;
2397 f2f46662 2020-01-23 tracey error = got_repo_match_object_id(&commit_id, NULL, gw_trans->commit,
2398 147269d5 2020-01-15 tracey GOT_OBJ_TYPE_COMMIT, 1, repo);
2399 ec46ccd7 2020-01-15 tracey if (error)
2400 ec46ccd7 2020-01-15 tracey goto done;
2402 ec46ccd7 2020-01-15 tracey error = got_object_id_by_path(&obj_id, repo, commit_id, in_repo_path);
2403 ec46ccd7 2020-01-15 tracey if (error)
2404 ec46ccd7 2020-01-15 tracey goto done;
2406 ec46ccd7 2020-01-15 tracey if (obj_id == NULL) {
2407 ec46ccd7 2020-01-15 tracey error = got_error(GOT_ERR_NO_OBJ);
2408 ec46ccd7 2020-01-15 tracey goto done;
2411 ec46ccd7 2020-01-15 tracey error = got_object_get_type(&obj_type, repo, obj_id);
2412 ec46ccd7 2020-01-15 tracey if (error)
2413 ec46ccd7 2020-01-15 tracey goto done;
2415 ec46ccd7 2020-01-15 tracey if (obj_type != GOT_OBJ_TYPE_BLOB) {
2416 ec46ccd7 2020-01-15 tracey error = got_error(GOT_ERR_OBJ_TYPE);
2417 ec46ccd7 2020-01-15 tracey goto done;
2420 ec46ccd7 2020-01-15 tracey error = got_object_open_as_blob(&blob, repo, obj_id, 8192);
2421 ec46ccd7 2020-01-15 tracey if (error)
2422 ec46ccd7 2020-01-15 tracey goto done;
2424 2e676fc5 2020-01-15 tracey error = buf_alloc(&bca.blamebuf, 0);
2425 2e676fc5 2020-01-15 tracey if (error)
2426 2e676fc5 2020-01-15 tracey goto done;
2428 ec46ccd7 2020-01-15 tracey bca.f = got_opentemp();
2429 ec46ccd7 2020-01-15 tracey if (bca.f == NULL) {
2430 ec46ccd7 2020-01-15 tracey error = got_error_from_errno("got_opentemp");
2431 ec46ccd7 2020-01-15 tracey goto done;
2433 ec46ccd7 2020-01-15 tracey error = got_object_blob_dump_to_file(&filesize, &bca.nlines,
2434 ec46ccd7 2020-01-15 tracey &bca.line_offsets, bca.f, blob);
2435 ec46ccd7 2020-01-15 tracey if (error || bca.nlines == 0)
2436 ec46ccd7 2020-01-15 tracey goto done;
2438 e46f587c 2020-01-29 tracey if (gw_trans->action == GW_BLOB) {
2439 e46f587c 2020-01-29 tracey int len;
2440 e46f587c 2020-01-29 tracey fseek(bca.f, 0, SEEK_END);
2441 e46f587c 2020-01-29 tracey len = ftell(bca.f) + 1;
2442 e46f587c 2020-01-29 tracey fseek(bca.f, 0, SEEK_SET);
2443 e46f587c 2020-01-29 tracey if ((blame_html = calloc(len, sizeof(char *))) == NULL)
2444 e46f587c 2020-01-29 tracey goto done;
2445 e46f587c 2020-01-29 tracey fread(blame_html, 1, len, bca.f);
2446 e46f587c 2020-01-29 tracey goto done;
2449 ec46ccd7 2020-01-15 tracey /* Don't include \n at EOF in the blame line count. */
2450 ec46ccd7 2020-01-15 tracey if (bca.line_offsets[bca.nlines - 1] == filesize)
2451 ec46ccd7 2020-01-15 tracey bca.nlines--;
2453 ec46ccd7 2020-01-15 tracey bca.lines = calloc(bca.nlines, sizeof(*bca.lines));
2454 ec46ccd7 2020-01-15 tracey if (bca.lines == NULL) {
2455 ec46ccd7 2020-01-15 tracey error = got_error_from_errno("calloc");
2456 ec46ccd7 2020-01-15 tracey goto done;
2458 ec46ccd7 2020-01-15 tracey bca.lineno_cur = 1;
2459 ec46ccd7 2020-01-15 tracey bca.nlines_prec = 0;
2460 ec46ccd7 2020-01-15 tracey i = bca.nlines;
2461 ec46ccd7 2020-01-15 tracey while (i > 0) {
2462 ec46ccd7 2020-01-15 tracey i /= 10;
2463 ec46ccd7 2020-01-15 tracey bca.nlines_prec++;
2465 ec46ccd7 2020-01-15 tracey bca.repo = repo;
2466 2e676fc5 2020-01-15 tracey bca.gw_trans = gw_trans;
2468 147269d5 2020-01-15 tracey error = got_blame(in_repo_path, commit_id, repo, gw_blame_cb, &bca,
2469 147269d5 2020-01-15 tracey NULL, NULL);
2470 e46f587c 2020-01-29 tracey if (error)
2471 e46f587c 2020-01-29 tracey goto done;
2472 2e676fc5 2020-01-15 tracey if (buf_len(bca.blamebuf) > 0) {
2473 2e676fc5 2020-01-15 tracey error = buf_putc(bca.blamebuf, '\0');
2474 2e676fc5 2020-01-15 tracey blame_html = strdup(buf_get(bca.blamebuf));
2477 e46f587c 2020-01-29 tracey free(bca.line_offsets);
2478 2e676fc5 2020-01-15 tracey free(bca.blamebuf);
2479 2e676fc5 2020-01-15 tracey free(in_repo_path);
2480 2e676fc5 2020-01-15 tracey free(commit_id);
2481 2e676fc5 2020-01-15 tracey free(obj_id);
2482 2e676fc5 2020-01-15 tracey free(path);
2484 e46f587c 2020-01-29 tracey if (gw_trans->action != GW_BLOB && bca.lines) {
2485 2e676fc5 2020-01-15 tracey for (i = 0; i < bca.nlines; i++) {
2486 2e676fc5 2020-01-15 tracey struct blame_line *bline = &bca.lines[i];
2487 2e676fc5 2020-01-15 tracey free(bline->id_str);
2488 2e676fc5 2020-01-15 tracey free(bline->committer);
2490 2e676fc5 2020-01-15 tracey free(bca.lines);
2492 e46f587c 2020-01-29 tracey if (error)
2493 e46f587c 2020-01-29 tracey return NULL;
2494 2e676fc5 2020-01-15 tracey if (bca.f && fclose(bca.f) == EOF && error == NULL)
2495 e46f587c 2020-01-29 tracey return NULL;
2496 e46f587c 2020-01-29 tracey if (blob)
2497 e46f587c 2020-01-29 tracey error = got_object_blob_close(blob);
2498 2e676fc5 2020-01-15 tracey if (error)
2499 2e676fc5 2020-01-15 tracey return NULL;
2500 e46f587c 2020-01-29 tracey if (repo)
2501 e46f587c 2020-01-29 tracey error = got_repo_close(repo);
2502 e46f587c 2020-01-29 tracey if (error)
2503 e46f587c 2020-01-29 tracey return NULL;
2505 ec46ccd7 2020-01-15 tracey return blame_html;
2508 ec46ccd7 2020-01-15 tracey static char*
2509 f2f46662 2020-01-23 tracey gw_get_repo_tree(struct gw_trans *gw_trans)
2511 ec46ccd7 2020-01-15 tracey const struct got_error *error = NULL;
2512 ec46ccd7 2020-01-15 tracey struct got_repository *repo = NULL;
2513 bcbc97d8 2020-01-15 tracey struct got_object_id *tree_id = NULL, *commit_id = NULL;
2514 bcbc97d8 2020-01-15 tracey struct got_tree_object *tree = NULL;
2515 bcbc97d8 2020-01-15 tracey struct buf *diffbuf = NULL;
2516 bcbc97d8 2020-01-15 tracey size_t newsize;
2517 bcbc97d8 2020-01-15 tracey char *tree_html = NULL, *path = NULL, *in_repo_path = NULL,
2518 c3bcdfd5 2020-01-29 tracey *tree_row = NULL, *id_str, *class = NULL;
2519 c3bcdfd5 2020-01-29 tracey int nentries, i, class_flip = 0;
2521 bcbc97d8 2020-01-15 tracey error = buf_alloc(&diffbuf, 0);
2522 ec46ccd7 2020-01-15 tracey if (error)
2523 bcbc97d8 2020-01-15 tracey return NULL;
2525 bcbc97d8 2020-01-15 tracey error = got_repo_open(&repo, gw_trans->repo_path, NULL);
2526 ec46ccd7 2020-01-15 tracey if (error)
2527 bcbc97d8 2020-01-15 tracey goto done;
2529 bcbc97d8 2020-01-15 tracey error = got_repo_map_path(&in_repo_path, repo, gw_trans->repo_path, 1);
2530 ec46ccd7 2020-01-15 tracey if (error)
2531 bcbc97d8 2020-01-15 tracey goto done;
2533 ec46ccd7 2020-01-15 tracey if (gw_trans->repo_folder != NULL)
2534 ec46ccd7 2020-01-15 tracey path = strdup(gw_trans->repo_folder);
2535 ec46ccd7 2020-01-15 tracey else if (in_repo_path) {
2536 bcbc97d8 2020-01-15 tracey free(path);
2537 bcbc97d8 2020-01-15 tracey path = in_repo_path;
2540 f2f46662 2020-01-23 tracey if (gw_trans->commit == NULL) {
2541 ec46ccd7 2020-01-15 tracey struct got_reference *head_ref;
2542 ec46ccd7 2020-01-15 tracey error = got_ref_open(&head_ref, repo, gw_trans->headref, 0);
2543 ec46ccd7 2020-01-15 tracey if (error)
2544 ec46ccd7 2020-01-15 tracey goto done;
2546 ec46ccd7 2020-01-15 tracey error = got_ref_resolve(&commit_id, repo, head_ref);
2547 ec46ccd7 2020-01-15 tracey got_ref_close(head_ref);
2550 f2f46662 2020-01-23 tracey error = got_repo_match_object_id(&commit_id, NULL,
2551 f2f46662 2020-01-23 tracey gw_trans->commit, GOT_OBJ_TYPE_COMMIT, 1, repo);
2552 f2f46662 2020-01-23 tracey if (error)
2553 f2f46662 2020-01-23 tracey goto done;
2555 f2f46662 2020-01-23 tracey error = got_object_id_str(&gw_trans->commit, commit_id);
2556 bcbc97d8 2020-01-15 tracey if (error)
2557 bcbc97d8 2020-01-15 tracey goto done;
2559 ec46ccd7 2020-01-15 tracey error = got_object_id_by_path(&tree_id, repo, commit_id, path);
2560 bcbc97d8 2020-01-15 tracey if (error)
2561 bcbc97d8 2020-01-15 tracey goto done;
2563 bcbc97d8 2020-01-15 tracey error = got_object_open_as_tree(&tree, repo, tree_id);
2564 bcbc97d8 2020-01-15 tracey if (error)
2565 bcbc97d8 2020-01-15 tracey goto done;
2567 bcbc97d8 2020-01-15 tracey nentries = got_object_tree_get_nentries(tree);
2569 bcbc97d8 2020-01-15 tracey for (i = 0; i < nentries; i++) {
2570 bcbc97d8 2020-01-15 tracey struct got_tree_entry *te;
2571 ec46ccd7 2020-01-15 tracey const char *modestr = "";
2572 ec46ccd7 2020-01-15 tracey char *id = NULL, *url_html = NULL;
2574 bcbc97d8 2020-01-15 tracey te = got_object_tree_get_entry(tree, i);
2576 bcbc97d8 2020-01-15 tracey error = got_object_id_str(&id_str, got_tree_entry_get_id(te));
2577 bcbc97d8 2020-01-15 tracey if (error)
2578 bcbc97d8 2020-01-15 tracey goto done;
2580 88d59c36 2020-01-29 stsp if (asprintf(&id, "%s", id_str) == -1) {
2581 bcbc97d8 2020-01-15 tracey error = got_error_from_errno("asprintf");
2582 bcbc97d8 2020-01-15 tracey free(id_str);
2583 bcbc97d8 2020-01-15 tracey goto done;
2586 bcbc97d8 2020-01-15 tracey mode_t mode = got_tree_entry_get_mode(te);
2588 bcbc97d8 2020-01-15 tracey if (got_object_tree_entry_is_submodule(te))
2589 bcbc97d8 2020-01-15 tracey modestr = "$";
2590 bcbc97d8 2020-01-15 tracey else if (S_ISLNK(mode))
2591 bcbc97d8 2020-01-15 tracey modestr = "@";
2592 bcbc97d8 2020-01-15 tracey else if (S_ISDIR(mode))
2593 bcbc97d8 2020-01-15 tracey modestr = "/";
2594 bcbc97d8 2020-01-15 tracey else if (mode & S_IXUSR)
2595 bcbc97d8 2020-01-15 tracey modestr = "*";
2597 c3bcdfd5 2020-01-29 tracey if (class_flip == 0) {
2598 c3bcdfd5 2020-01-29 tracey class = strdup("back_lightgray");
2599 c3bcdfd5 2020-01-29 tracey class_flip = 1;
2600 c3bcdfd5 2020-01-29 tracey } else {
2601 c3bcdfd5 2020-01-29 tracey class = strdup("back_white");
2602 c3bcdfd5 2020-01-29 tracey class_flip = 0;
2605 ec46ccd7 2020-01-15 tracey char *build_folder = NULL;
2606 ec46ccd7 2020-01-15 tracey if (S_ISDIR(got_tree_entry_get_mode(te))) {
2607 ec46ccd7 2020-01-15 tracey if (gw_trans->repo_folder != NULL) {
2608 88d59c36 2020-01-29 stsp if (asprintf(&build_folder, "%s/%s",
2609 ec46ccd7 2020-01-15 tracey gw_trans->repo_folder,
2610 88d59c36 2020-01-29 stsp got_tree_entry_get_name(te)) == -1) {
2612 ec46ccd7 2020-01-15 tracey got_error_from_errno("asprintf");
2613 ec46ccd7 2020-01-15 tracey goto done;
2615 ec46ccd7 2020-01-15 tracey } else {
2616 ec46ccd7 2020-01-15 tracey if (asprintf(&build_folder, "%s",
2617 ec46ccd7 2020-01-15 tracey got_tree_entry_get_name(te)) == -1)
2618 ec46ccd7 2020-01-15 tracey goto done;
2621 88d59c36 2020-01-29 stsp if (asprintf(&url_html, folder_html,
2622 ec46ccd7 2020-01-15 tracey gw_trans->repo_name, gw_trans->action_name,
2623 ec46ccd7 2020-01-15 tracey gw_trans->commit, build_folder,
2624 88d59c36 2020-01-29 stsp got_tree_entry_get_name(te), modestr) == -1) {
2625 ec46ccd7 2020-01-15 tracey error = got_error_from_errno("asprintf");
2626 ec46ccd7 2020-01-15 tracey goto done;
2628 e46f587c 2020-01-29 tracey if (asprintf(&tree_row, tree_line, class, url_html,
2629 e46f587c 2020-01-29 tracey class) == -1) {
2630 e46f587c 2020-01-29 tracey error = got_error_from_errno("asprintf");
2631 e46f587c 2020-01-29 tracey goto done;
2634 ec46ccd7 2020-01-15 tracey } else {
2635 ec46ccd7 2020-01-15 tracey if (gw_trans->repo_folder != NULL) {
2636 88d59c36 2020-01-29 stsp if (asprintf(&build_folder, "%s",
2637 88d59c36 2020-01-29 stsp gw_trans->repo_folder) == -1) {
2639 ec46ccd7 2020-01-15 tracey got_error_from_errno("asprintf");
2640 ec46ccd7 2020-01-15 tracey goto done;
2643 ec46ccd7 2020-01-15 tracey build_folder = strdup("");
2645 88d59c36 2020-01-29 stsp if (asprintf(&url_html, file_html, gw_trans->repo_name,
2646 e46f587c 2020-01-29 tracey "blob", gw_trans->commit,
2647 ec46ccd7 2020-01-15 tracey got_tree_entry_get_name(te), build_folder,
2648 88d59c36 2020-01-29 stsp got_tree_entry_get_name(te), modestr) == -1) {
2649 ec46ccd7 2020-01-15 tracey error = got_error_from_errno("asprintf");
2650 ec46ccd7 2020-01-15 tracey goto done;
2653 e46f587c 2020-01-29 tracey if (asprintf(&tree_row, tree_line_with_navs, class,
2654 e46f587c 2020-01-29 tracey url_html, class, gw_trans->repo_name, "blob",
2655 e46f587c 2020-01-29 tracey gw_trans->commit, got_tree_entry_get_name(te),
2656 e46f587c 2020-01-29 tracey build_folder, "blob", gw_trans->repo_name,
2657 e46f587c 2020-01-29 tracey "blame", gw_trans->commit,
2658 e46f587c 2020-01-29 tracey got_tree_entry_get_name(te), build_folder,
2659 e46f587c 2020-01-29 tracey "blame") == -1) {
2660 e46f587c 2020-01-29 tracey error = got_error_from_errno("asprintf");
2661 e46f587c 2020-01-29 tracey goto done;
2664 ec46ccd7 2020-01-15 tracey free(build_folder);
2666 ec46ccd7 2020-01-15 tracey if (error)
2667 ec46ccd7 2020-01-15 tracey goto done;
2669 bcbc97d8 2020-01-15 tracey error = buf_puts(&newsize, diffbuf, tree_row);
2670 ec46ccd7 2020-01-15 tracey if (error)
2671 ec46ccd7 2020-01-15 tracey goto done;
2673 bcbc97d8 2020-01-15 tracey free(id);
2674 bcbc97d8 2020-01-15 tracey free(id_str);
2675 ec46ccd7 2020-01-15 tracey free(url_html);
2676 ec46ccd7 2020-01-15 tracey free(tree_row);
2679 bcbc97d8 2020-01-15 tracey if (buf_len(diffbuf) > 0) {
2680 bcbc97d8 2020-01-15 tracey error = buf_putc(diffbuf, '\0');
2681 bcbc97d8 2020-01-15 tracey tree_html = strdup(buf_get(diffbuf));
2684 bcbc97d8 2020-01-15 tracey if (tree)
2685 bcbc97d8 2020-01-15 tracey got_object_tree_close(tree);
2686 2e676fc5 2020-01-15 tracey if (repo)
2687 2e676fc5 2020-01-15 tracey got_repo_close(repo);
2689 2e676fc5 2020-01-15 tracey free(in_repo_path);
2690 bcbc97d8 2020-01-15 tracey free(tree_id);
2691 bcbc97d8 2020-01-15 tracey free(diffbuf);
2692 bcbc97d8 2020-01-15 tracey if (error)
2693 bcbc97d8 2020-01-15 tracey return NULL;
2695 bcbc97d8 2020-01-15 tracey return tree_html;
2698 8d4d2453 2020-01-15 tracey static char *
2699 54415d85 2020-01-15 tracey gw_get_repo_heads(struct gw_trans *gw_trans)
2701 87f9ebf5 2020-01-15 tracey const struct got_error *error = NULL;
2702 87f9ebf5 2020-01-15 tracey struct got_repository *repo = NULL;
2703 87f9ebf5 2020-01-15 tracey struct got_reflist_head refs;
2704 87f9ebf5 2020-01-15 tracey struct got_reflist_entry *re;
2705 87f9ebf5 2020-01-15 tracey char *heads, *head_row = NULL, *head_navs_disp = NULL, *age = NULL;
2706 87f9ebf5 2020-01-15 tracey struct buf *diffbuf = NULL;
2707 87f9ebf5 2020-01-15 tracey size_t newsize;
2709 a0f36e03 2020-01-28 stsp SIMPLEQ_INIT(&refs);
2711 6c6c85af 2020-01-15 tracey error = buf_alloc(&diffbuf, 0);
2712 ec46ccd7 2020-01-15 tracey if (error)
2713 6c6c85af 2020-01-15 tracey return NULL;
2715 87f9ebf5 2020-01-15 tracey error = got_repo_open(&repo, gw_trans->repo_path, NULL);
2716 ec46ccd7 2020-01-15 tracey if (error)
2717 87f9ebf5 2020-01-15 tracey goto done;
2719 87f9ebf5 2020-01-15 tracey error = got_ref_list(&refs, repo, "refs/heads", got_ref_cmp_by_name,
2721 87f9ebf5 2020-01-15 tracey if (error)
2722 87f9ebf5 2020-01-15 tracey goto done;
2724 87f9ebf5 2020-01-15 tracey SIMPLEQ_FOREACH(re, &refs, entry) {
2725 87f9ebf5 2020-01-15 tracey char *refname;
2727 87f9ebf5 2020-01-15 tracey refname = strdup(got_ref_get_name(re->ref));
2728 87f9ebf5 2020-01-15 tracey if (refname == NULL) {
2729 87f9ebf5 2020-01-15 tracey error = got_error_from_errno("got_ref_to_str");
2730 87f9ebf5 2020-01-15 tracey goto done;
2733 87f9ebf5 2020-01-15 tracey if (strncmp(refname, "refs/heads/", 11) != 0) {
2734 87f9ebf5 2020-01-15 tracey free(refname);
2735 87f9ebf5 2020-01-15 tracey continue;
2738 d126c1b7 2020-01-29 stsp error = gw_get_repo_age(&age, gw_trans, gw_trans->gw_dir->path, refname,
2739 87f9ebf5 2020-01-15 tracey TM_DIFF);
2740 d126c1b7 2020-01-29 stsp if (error)
2741 d126c1b7 2020-01-29 stsp goto done;
2743 88d59c36 2020-01-29 stsp if (asprintf(&head_navs_disp, heads_navs, gw_trans->repo_name,
2744 87f9ebf5 2020-01-15 tracey refname, gw_trans->repo_name, refname,
2745 87f9ebf5 2020-01-15 tracey gw_trans->repo_name, refname, gw_trans->repo_name,
2746 88d59c36 2020-01-29 stsp refname) == -1) {
2747 87f9ebf5 2020-01-15 tracey error = got_error_from_errno("asprintf");
2748 87f9ebf5 2020-01-15 tracey goto done;
2751 87f9ebf5 2020-01-15 tracey if (strncmp(refname, "refs/heads/", 11) == 0)
2752 87f9ebf5 2020-01-15 tracey refname += 11;
2754 88d59c36 2020-01-29 stsp if (asprintf(&head_row, heads_row, age, refname,
2755 88d59c36 2020-01-29 stsp head_navs_disp) == -1) {
2756 87f9ebf5 2020-01-15 tracey error = got_error_from_errno("asprintf");
2757 87f9ebf5 2020-01-15 tracey goto done;
2760 6c6c85af 2020-01-15 tracey error = buf_puts(&newsize, diffbuf, head_row);
2762 87f9ebf5 2020-01-15 tracey free(head_navs_disp);
2763 87f9ebf5 2020-01-15 tracey free(head_row);
2766 6c6c85af 2020-01-15 tracey if (buf_len(diffbuf) > 0) {
2767 6c6c85af 2020-01-15 tracey error = buf_putc(diffbuf, '\0');
2768 6c6c85af 2020-01-15 tracey heads = strdup(buf_get(diffbuf));
2771 87f9ebf5 2020-01-15 tracey buf_free(diffbuf);
2772 87f9ebf5 2020-01-15 tracey got_ref_list_free(&refs);
2773 87f9ebf5 2020-01-15 tracey if (repo)
2774 87f9ebf5 2020-01-15 tracey got_repo_close(repo);
2775 87f9ebf5 2020-01-15 tracey if (error)
2776 87f9ebf5 2020-01-15 tracey return NULL;
2778 87f9ebf5 2020-01-15 tracey return heads;
2781 8d4d2453 2020-01-15 tracey static char *
2782 54415d85 2020-01-15 tracey gw_get_got_link(struct gw_trans *gw_trans)
2784 2c251c14 2020-01-15 tracey char *link;
2786 88d59c36 2020-01-29 stsp if (asprintf(&link, got_link, gw_trans->gw_conf->got_logo_url,
2787 88d59c36 2020-01-29 stsp gw_trans->gw_conf->got_logo) == -1)
2788 2c251c14 2020-01-15 tracey return NULL;
2790 2c251c14 2020-01-15 tracey return link;
2793 2c251c14 2020-01-15 tracey static char *
2794 54415d85 2020-01-15 tracey gw_get_site_link(struct gw_trans *gw_trans)
2796 2c251c14 2020-01-15 tracey char *link, *repo = "", *action = "";
2798 2c251c14 2020-01-15 tracey if (gw_trans->repo_name != NULL)
2799 88d59c36 2020-01-29 stsp if (asprintf(&repo, " / <a href='?path=%s&action=summary'>%s" \
2800 88d59c36 2020-01-29 stsp "</a>", gw_trans->repo_name, gw_trans->repo_name) == -1)
2801 2c251c14 2020-01-15 tracey return NULL;
2803 2c251c14 2020-01-15 tracey if (gw_trans->action_name != NULL)
2804 88d59c36 2020-01-29 stsp if (asprintf(&action, " / %s", gw_trans->action_name) == -1)
2805 2c251c14 2020-01-15 tracey return NULL;
2807 88d59c36 2020-01-29 stsp if (asprintf(&link, site_link, GOTWEB,
2808 88d59c36 2020-01-29 stsp gw_trans->gw_conf->got_site_link, repo, action) == -1)
2809 2c251c14 2020-01-15 tracey return NULL;
2811 2c251c14 2020-01-15 tracey return link;
2814 2c251c14 2020-01-15 tracey static char *
2815 d0ea9c5b 2020-01-15 tracey gw_colordiff_line(char *buf)
2817 ec46ccd7 2020-01-15 tracey const struct got_error *error = NULL;
2818 ec46ccd7 2020-01-15 tracey char *colorized_line = NULL, *div_diff_line_div = NULL, *color = NULL;
2819 ec46ccd7 2020-01-15 tracey struct buf *diffbuf = NULL;
2820 ec46ccd7 2020-01-15 tracey size_t newsize;
2822 ec46ccd7 2020-01-15 tracey error = buf_alloc(&diffbuf, 0);
2823 ec46ccd7 2020-01-15 tracey if (error)
2824 ec46ccd7 2020-01-15 tracey return NULL;
2826 bfd30182 2020-01-24 tracey if (buf == NULL)
2827 bfd30182 2020-01-24 tracey return NULL;
2828 ec46ccd7 2020-01-15 tracey if (strncmp(buf, "-", 1) == 0)
2829 ec46ccd7 2020-01-15 tracey color = "diff_minus";
2830 ec46ccd7 2020-01-15 tracey if (strncmp(buf, "+", 1) == 0)
2831 ec46ccd7 2020-01-15 tracey color = "diff_plus";
2832 ec46ccd7 2020-01-15 tracey if (strncmp(buf, "@@", 2) == 0)
2833 ec46ccd7 2020-01-15 tracey color = "diff_chunk_header";
2834 ec46ccd7 2020-01-15 tracey if (strncmp(buf, "@@", 2) == 0)
2835 ec46ccd7 2020-01-15 tracey color = "diff_chunk_header";
2836 ec46ccd7 2020-01-15 tracey if (strncmp(buf, "commit +", 8) == 0)
2837 ec46ccd7 2020-01-15 tracey color = "diff_meta";
2838 ec46ccd7 2020-01-15 tracey if (strncmp(buf, "commit -", 8) == 0)
2839 ec46ccd7 2020-01-15 tracey color = "diff_meta";
2840 ec46ccd7 2020-01-15 tracey if (strncmp(buf, "blob +", 6) == 0)
2841 ec46ccd7 2020-01-15 tracey color = "diff_meta";
2842 ec46ccd7 2020-01-15 tracey if (strncmp(buf, "blob -", 6) == 0)
2843 ec46ccd7 2020-01-15 tracey color = "diff_meta";
2844 ec46ccd7 2020-01-15 tracey if (strncmp(buf, "file +", 6) == 0)
2845 ec46ccd7 2020-01-15 tracey color = "diff_meta";
2846 ec46ccd7 2020-01-15 tracey if (strncmp(buf, "file -", 6) == 0)
2847 ec46ccd7 2020-01-15 tracey color = "diff_meta";
2848 ec46ccd7 2020-01-15 tracey if (strncmp(buf, "from:", 5) == 0)
2849 ec46ccd7 2020-01-15 tracey color = "diff_author";
2850 ec46ccd7 2020-01-15 tracey if (strncmp(buf, "via:", 4) == 0)
2851 ec46ccd7 2020-01-15 tracey color = "diff_author";
2852 ec46ccd7 2020-01-15 tracey if (strncmp(buf, "date:", 5) == 0)
2853 ec46ccd7 2020-01-15 tracey color = "diff_date";
2855 88d59c36 2020-01-29 stsp if (asprintf(&div_diff_line_div, div_diff_line, color) == -1)
2856 ec46ccd7 2020-01-15 tracey return NULL;
2858 ec46ccd7 2020-01-15 tracey error = buf_puts(&newsize, diffbuf, div_diff_line_div);
2859 ec46ccd7 2020-01-15 tracey if (error)
2860 ec46ccd7 2020-01-15 tracey return NULL;
2862 ec46ccd7 2020-01-15 tracey error = buf_puts(&newsize, diffbuf, buf);
2863 ec46ccd7 2020-01-15 tracey if (error)
2864 ec46ccd7 2020-01-15 tracey return NULL;
2866 ec46ccd7 2020-01-15 tracey if (buf_len(diffbuf) > 0) {
2867 ec46ccd7 2020-01-15 tracey error = buf_putc(diffbuf, '\0');
2868 ec46ccd7 2020-01-15 tracey colorized_line = strdup(buf_get(diffbuf));
2871 ec46ccd7 2020-01-15 tracey free(diffbuf);
2872 ec46ccd7 2020-01-15 tracey free(div_diff_line_div);
2873 ec46ccd7 2020-01-15 tracey return colorized_line;
2876 ec46ccd7 2020-01-15 tracey static char *
2877 2c251c14 2020-01-15 tracey gw_html_escape(const char *html)
2879 2c251c14 2020-01-15 tracey char *escaped_str = NULL, *buf;
2880 2c251c14 2020-01-15 tracey char c[1];
2881 6c6c85af 2020-01-15 tracey size_t sz, i, buff_sz = 2048;
2883 6c6c85af 2020-01-15 tracey if ((buf = calloc(buff_sz, sizeof(char *))) == NULL)
2884 2c251c14 2020-01-15 tracey return NULL;
2886 2c251c14 2020-01-15 tracey if (html == NULL)
2887 2c251c14 2020-01-15 tracey return NULL;
2889 2c251c14 2020-01-15 tracey if ((sz = strlen(html)) == 0)
2890 2c251c14 2020-01-15 tracey return NULL;
2892 6c6c85af 2020-01-15 tracey /* only work with buff_sz */
2893 6c6c85af 2020-01-15 tracey if (buff_sz < sz)
2894 6c6c85af 2020-01-15 tracey sz = buff_sz;
2896 2c251c14 2020-01-15 tracey for (i = 0; i < sz; i++) {
2897 2c251c14 2020-01-15 tracey c[0] = html[i];
2898 2c251c14 2020-01-15 tracey switch (c[0]) {
2899 2c251c14 2020-01-15 tracey case ('>'):
2900 2c251c14 2020-01-15 tracey strcat(buf, ">");
2902 2c251c14 2020-01-15 tracey case ('&'):
2903 2c251c14 2020-01-15 tracey strcat(buf, "&");
2905 2c251c14 2020-01-15 tracey case ('<'):
2906 2c251c14 2020-01-15 tracey strcat(buf, "<");
2908 2c251c14 2020-01-15 tracey case ('"'):
2909 2c251c14 2020-01-15 tracey strcat(buf, """);
2911 2c251c14 2020-01-15 tracey case ('\''):
2912 2c251c14 2020-01-15 tracey strcat(buf, "'");
2914 2c251c14 2020-01-15 tracey case ('\n'):
2915 2c251c14 2020-01-15 tracey strcat(buf, "<br />");
2916 2c251c14 2020-01-15 tracey default:
2917 2c251c14 2020-01-15 tracey strcat(buf, &c[0]);
2921 2c251c14 2020-01-15 tracey asprintf(&escaped_str, "%s", buf);
2922 2c251c14 2020-01-15 tracey free(buf);
2923 2c251c14 2020-01-15 tracey return escaped_str;
2927 c08369d7 2020-01-15 tracey main(int argc, char *argv[])
2929 2c251c14 2020-01-15 tracey const struct got_error *error = NULL;
2930 54415d85 2020-01-15 tracey struct gw_trans *gw_trans;
2931 2c251c14 2020-01-15 tracey struct gw_dir *dir = NULL, *tdir;
2932 2c251c14 2020-01-15 tracey const char *page = "index";
2933 4ceb8155 2020-01-15 tracey int gw_malloc = 1;
2934 c25c2314 2020-01-28 stsp enum kcgi_err kerr;
2936 54415d85 2020-01-15 tracey if ((gw_trans = malloc(sizeof(struct gw_trans))) == NULL)
2937 2c251c14 2020-01-15 tracey errx(1, "malloc");
2939 2c251c14 2020-01-15 tracey if ((gw_trans->gw_req = malloc(sizeof(struct kreq))) == NULL)
2940 2c251c14 2020-01-15 tracey errx(1, "malloc");
2942 2c251c14 2020-01-15 tracey if ((gw_trans->gw_html_req = malloc(sizeof(struct khtmlreq))) == NULL)
2943 2c251c14 2020-01-15 tracey errx(1, "malloc");
2945 2c251c14 2020-01-15 tracey if ((gw_trans->gw_tmpl = malloc(sizeof(struct ktemplate))) == NULL)
2946 2c251c14 2020-01-15 tracey errx(1, "malloc");
2948 c25c2314 2020-01-28 stsp kerr = khttp_parse(gw_trans->gw_req, gw_keys, KEY__ZMAX, &page, 1, 0);
2949 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK) {
2950 c25c2314 2020-01-28 stsp error = gw_kcgi_error(kerr);
2951 c119608e 2020-01-28 stsp goto done;
2954 2c251c14 2020-01-15 tracey if ((gw_trans->gw_conf =
2955 2c251c14 2020-01-15 tracey malloc(sizeof(struct gotweb_conf))) == NULL) {
2956 4ceb8155 2020-01-15 tracey gw_malloc = 0;
2957 387a29ba 2020-01-15 tracey error = got_error_from_errno("malloc");
2958 c119608e 2020-01-28 stsp goto done;
2961 2c251c14 2020-01-15 tracey TAILQ_INIT(&gw_trans->gw_dirs);
2962 f2f46662 2020-01-23 tracey TAILQ_INIT(&gw_trans->gw_headers);
2964 2c251c14 2020-01-15 tracey gw_trans->page = 0;
2965 2c251c14 2020-01-15 tracey gw_trans->repos_total = 0;
2966 2c251c14 2020-01-15 tracey gw_trans->repo_path = NULL;
2967 2c251c14 2020-01-15 tracey gw_trans->commit = NULL;
2968 8087c3c5 2020-01-15 tracey gw_trans->headref = strdup(GOT_REF_HEAD);
2969 2c251c14 2020-01-15 tracey gw_trans->mime = KMIME_TEXT_HTML;
2970 54415d85 2020-01-15 tracey gw_trans->gw_tmpl->key = gw_templs;
2971 2c251c14 2020-01-15 tracey gw_trans->gw_tmpl->keysz = TEMPL__MAX;
2972 2c251c14 2020-01-15 tracey gw_trans->gw_tmpl->arg = gw_trans;
2973 2c251c14 2020-01-15 tracey gw_trans->gw_tmpl->cb = gw_template;
2974 2c251c14 2020-01-15 tracey error = parse_conf(GOTWEB_CONF, gw_trans->gw_conf);
2975 c119608e 2020-01-28 stsp if (error)
2976 2c251c14 2020-01-15 tracey goto done;
2978 2c251c14 2020-01-15 tracey error = gw_parse_querystring(gw_trans);
2979 2c251c14 2020-01-15 tracey if (error)
2980 c119608e 2020-01-28 stsp goto done;
2982 6d8d8a26 2020-01-29 stsp error = gw_display_index(gw_trans);
2984 c119608e 2020-01-28 stsp if (error) {
2985 c119608e 2020-01-28 stsp gw_trans->mime = KMIME_TEXT_PLAIN;
2986 c119608e 2020-01-28 stsp gw_trans->action = GW_ERR;
2987 6d8d8a26 2020-01-29 stsp gw_display_error(gw_trans, error);
2989 2c251c14 2020-01-15 tracey if (gw_malloc) {
2990 2c251c14 2020-01-15 tracey free(gw_trans->gw_conf->got_repos_path);
2991 2c251c14 2020-01-15 tracey free(gw_trans->gw_conf->got_site_name);
2992 2c251c14 2020-01-15 tracey free(gw_trans->gw_conf->got_site_owner);
2993 2c251c14 2020-01-15 tracey free(gw_trans->gw_conf->got_site_link);
2994 2c251c14 2020-01-15 tracey free(gw_trans->gw_conf->got_logo);
2995 2c251c14 2020-01-15 tracey free(gw_trans->gw_conf->got_logo_url);
2996 2c251c14 2020-01-15 tracey free(gw_trans->gw_conf);
2997 2c251c14 2020-01-15 tracey free(gw_trans->commit);
2998 2c251c14 2020-01-15 tracey free(gw_trans->repo_path);
2999 2c251c14 2020-01-15 tracey free(gw_trans->repo_name);
3000 2c251c14 2020-01-15 tracey free(gw_trans->repo_file);
3001 2c251c14 2020-01-15 tracey free(gw_trans->action_name);
3002 8087c3c5 2020-01-15 tracey free(gw_trans->headref);
3004 2c251c14 2020-01-15 tracey TAILQ_FOREACH_SAFE(dir, &gw_trans->gw_dirs, entry, tdir) {
3005 2c251c14 2020-01-15 tracey free(dir->name);
3006 2c251c14 2020-01-15 tracey free(dir->description);
3007 2c251c14 2020-01-15 tracey free(dir->age);
3008 2c251c14 2020-01-15 tracey free(dir->url);
3009 2c251c14 2020-01-15 tracey free(dir->path);
3010 2c251c14 2020-01-15 tracey free(dir);
3015 2c251c14 2020-01-15 tracey khttp_free(gw_trans->gw_req);