Blame


1 2c251c14 2020-01-15 tracey /*
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>
4 2c251c14 2020-01-15 tracey *
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.
8 2c251c14 2020-01-15 tracey *
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.
16 2c251c14 2020-01-15 tracey */
17 2c251c14 2020-01-15 tracey
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>
21 2c251c14 2020-01-15 tracey
22 017d6da3 2020-01-29 tracey #include <ctype.h>
23 2c251c14 2020-01-15 tracey #include <dirent.h>
24 2c251c14 2020-01-15 tracey #include <err.h>
25 c25c2314 2020-01-28 stsp #include <errno.h>
26 474370cb 2020-01-15 tracey #include <regex.h>
27 2c251c14 2020-01-15 tracey #include <stdarg.h>
28 2c251c14 2020-01-15 tracey #include <stdint.h>
29 2c251c14 2020-01-15 tracey #include <stdio.h>
30 2c251c14 2020-01-15 tracey #include <stdlib.h>
31 2c251c14 2020-01-15 tracey #include <string.h>
32 2c251c14 2020-01-15 tracey #include <unistd.h>
33 2c251c14 2020-01-15 tracey
34 2c251c14 2020-01-15 tracey #include <got_object.h>
35 2c251c14 2020-01-15 tracey #include <got_reference.h>
36 2c251c14 2020-01-15 tracey #include <got_repository.h>
37 2c251c14 2020-01-15 tracey #include <got_path.h>
38 2c251c14 2020-01-15 tracey #include <got_cancel.h>
39 2c251c14 2020-01-15 tracey #include <got_worktree.h>
40 2c251c14 2020-01-15 tracey #include <got_diff.h>
41 2c251c14 2020-01-15 tracey #include <got_commit_graph.h>
42 2c251c14 2020-01-15 tracey #include <got_blame.h>
43 2c251c14 2020-01-15 tracey #include <got_privsep.h>
44 2c251c14 2020-01-15 tracey #include <got_opentemp.h>
45 2c251c14 2020-01-15 tracey
46 2c251c14 2020-01-15 tracey #include <kcgi.h>
47 2c251c14 2020-01-15 tracey #include <kcgihtml.h>
48 2c251c14 2020-01-15 tracey
49 474370cb 2020-01-15 tracey #include "buf.h"
50 2c251c14 2020-01-15 tracey #include "gotweb.h"
51 2c251c14 2020-01-15 tracey #include "gotweb_ui.h"
52 2c251c14 2020-01-15 tracey
53 2c251c14 2020-01-15 tracey #ifndef nitems
54 2c251c14 2020-01-15 tracey #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
55 2c251c14 2020-01-15 tracey #endif
56 2c251c14 2020-01-15 tracey
57 54415d85 2020-01-15 tracey struct gw_trans {
58 f2f46662 2020-01-23 tracey TAILQ_HEAD(headers, gw_header) gw_headers;
59 f2f46662 2020-01-23 tracey TAILQ_HEAD(dirs, gw_dir) gw_dirs;
60 46b9c89b 2020-01-15 tracey struct gw_dir *gw_dir;
61 2c251c14 2020-01-15 tracey struct gotweb_conf *gw_conf;
62 2c251c14 2020-01-15 tracey struct ktemplate *gw_tmpl;
63 2c251c14 2020-01-15 tracey struct khtmlreq *gw_html_req;
64 2c251c14 2020-01-15 tracey struct kreq *gw_req;
65 2c251c14 2020-01-15 tracey char *repo_name;
66 2c251c14 2020-01-15 tracey char *repo_path;
67 2c251c14 2020-01-15 tracey char *commit;
68 2c251c14 2020-01-15 tracey char *repo_file;
69 ec46ccd7 2020-01-15 tracey char *repo_folder;
70 2c251c14 2020-01-15 tracey char *action_name;
71 8087c3c5 2020-01-15 tracey char *headref;
72 2c251c14 2020-01-15 tracey unsigned int action;
73 2c251c14 2020-01-15 tracey unsigned int page;
74 2c251c14 2020-01-15 tracey unsigned int repos_total;
75 387a29ba 2020-01-15 tracey enum kmime mime;
76 2c251c14 2020-01-15 tracey };
77 2c251c14 2020-01-15 tracey
78 f2f46662 2020-01-23 tracey struct gw_header {
79 f2f46662 2020-01-23 tracey TAILQ_ENTRY(gw_header) entry;
80 f2f46662 2020-01-23 tracey struct got_repository *repo;
81 f2f46662 2020-01-23 tracey struct got_reflist_head refs;
82 f2f46662 2020-01-23 tracey struct got_commit_object *commit;
83 f2f46662 2020-01-23 tracey struct got_object_id *id;
84 f2f46662 2020-01-23 tracey char *path;
85 f2f46662 2020-01-23 tracey
86 f2f46662 2020-01-23 tracey char *refs_str;
87 f2f46662 2020-01-23 tracey char *commit_id; /* id_str1 */
88 f2f46662 2020-01-23 tracey char *parent_id; /* id_str2 */
89 f2f46662 2020-01-23 tracey char *tree_id;
90 bd275801 2020-02-03 tracey const char *author;
91 27192be7 2020-02-04 tracey const char *committer;
92 f2f46662 2020-01-23 tracey char *commit_msg;
93 f2f46662 2020-01-23 tracey time_t committer_time;
94 2c251c14 2020-01-15 tracey };
95 2c251c14 2020-01-15 tracey
96 2c251c14 2020-01-15 tracey struct gw_dir {
97 2c251c14 2020-01-15 tracey TAILQ_ENTRY(gw_dir) entry;
98 2c251c14 2020-01-15 tracey char *name;
99 2c251c14 2020-01-15 tracey char *owner;
100 2c251c14 2020-01-15 tracey char *description;
101 2c251c14 2020-01-15 tracey char *url;
102 2c251c14 2020-01-15 tracey char *age;
103 2c251c14 2020-01-15 tracey char *path;
104 2c251c14 2020-01-15 tracey };
105 2c251c14 2020-01-15 tracey
106 f2f46662 2020-01-23 tracey enum gw_key {
107 f2f46662 2020-01-23 tracey KEY_ACTION,
108 f2f46662 2020-01-23 tracey KEY_COMMIT_ID,
109 f2f46662 2020-01-23 tracey KEY_FILE,
110 f2f46662 2020-01-23 tracey KEY_FOLDER,
111 f2f46662 2020-01-23 tracey KEY_HEADREF,
112 f2f46662 2020-01-23 tracey KEY_PAGE,
113 f2f46662 2020-01-23 tracey KEY_PATH,
114 f2f46662 2020-01-23 tracey KEY__ZMAX
115 f2f46662 2020-01-23 tracey };
116 f2f46662 2020-01-23 tracey
117 54415d85 2020-01-15 tracey enum gw_tmpl {
118 f2f46662 2020-01-23 tracey TEMPL_CONTENT,
119 2c251c14 2020-01-15 tracey TEMPL_HEAD,
120 2c251c14 2020-01-15 tracey TEMPL_HEADER,
121 f2f46662 2020-01-23 tracey TEMPL_SEARCH,
122 2c251c14 2020-01-15 tracey TEMPL_SITEPATH,
123 2c251c14 2020-01-15 tracey TEMPL_SITEOWNER,
124 2c251c14 2020-01-15 tracey TEMPL_TITLE,
125 2c251c14 2020-01-15 tracey TEMPL__MAX
126 2c251c14 2020-01-15 tracey };
127 2c251c14 2020-01-15 tracey
128 54415d85 2020-01-15 tracey enum gw_ref_tm {
129 387a29ba 2020-01-15 tracey TM_DIFF,
130 387a29ba 2020-01-15 tracey TM_LONG,
131 387a29ba 2020-01-15 tracey };
132 387a29ba 2020-01-15 tracey
133 54415d85 2020-01-15 tracey enum gw_tags {
134 87f9ebf5 2020-01-15 tracey TAGBRIEF,
135 87f9ebf5 2020-01-15 tracey TAGFULL,
136 87f9ebf5 2020-01-15 tracey };
137 87f9ebf5 2020-01-15 tracey
138 54415d85 2020-01-15 tracey static const char *const gw_templs[TEMPL__MAX] = {
139 f2f46662 2020-01-23 tracey "content",
140 2c251c14 2020-01-15 tracey "head",
141 2c251c14 2020-01-15 tracey "header",
142 f2f46662 2020-01-23 tracey "search",
143 2c251c14 2020-01-15 tracey "sitepath",
144 2c251c14 2020-01-15 tracey "siteowner",
145 2c251c14 2020-01-15 tracey "title",
146 2c251c14 2020-01-15 tracey };
147 2c251c14 2020-01-15 tracey
148 ec46ccd7 2020-01-15 tracey static const struct kvalid gw_keys[KEY__ZMAX] = {
149 2c251c14 2020-01-15 tracey { kvalid_stringne, "action" },
150 2c251c14 2020-01-15 tracey { kvalid_stringne, "commit" },
151 2c251c14 2020-01-15 tracey { kvalid_stringne, "file" },
152 ec46ccd7 2020-01-15 tracey { kvalid_stringne, "folder" },
153 8087c3c5 2020-01-15 tracey { kvalid_stringne, "headref" },
154 ec46ccd7 2020-01-15 tracey { kvalid_int, "page" },
155 ec46ccd7 2020-01-15 tracey { kvalid_stringne, "path" },
156 2c251c14 2020-01-15 tracey };
157 2c251c14 2020-01-15 tracey
158 2c251c14 2020-01-15 tracey static struct gw_dir *gw_init_gw_dir(char *);
159 f2f46662 2020-01-23 tracey static struct gw_header *gw_init_header(void);
160 2c251c14 2020-01-15 tracey
161 185ba3ba 2020-02-04 tracey static const struct got_error *gw_get_repo_description(char **,
162 185ba3ba 2020-02-04 tracey struct gw_trans *, char *);
163 9a1cc63f 2020-02-03 stsp static const struct got_error *gw_get_repo_owner(char **, struct gw_trans *,
164 2c251c14 2020-01-15 tracey char *);
165 55ccf528 2020-02-03 stsp static const struct got_error *gw_get_time_str(char **, time_t, int);
166 d126c1b7 2020-01-29 stsp static const struct got_error *gw_get_repo_age(char **, struct gw_trans *,
167 387a29ba 2020-01-15 tracey char *, char *, int);
168 9a9d12ca 2020-02-06 tracey static const struct got_error *gw_output_file_blame(struct gw_trans *);
169 e0857cfe 2020-02-06 tracey static const struct got_error *gw_output_blob_buf(struct gw_trans *);
170 626b25b6 2020-02-06 tracey static const struct got_error *gw_output_repo_tree(struct gw_trans *);
171 38b240fb 2020-02-06 tracey static const struct got_error *gw_output_diff(struct gw_trans *,
172 f2f46662 2020-01-23 tracey struct gw_header *);
173 38b240fb 2020-02-06 tracey static const struct got_error *gw_output_repo_tags(struct gw_trans *,
174 4ff7391f 2020-01-28 tracey struct gw_header *, int, int);
175 51d4a92d 2020-02-03 tracey static const struct got_error *gw_get_repo_heads(char **, struct gw_trans *);
176 185ba3ba 2020-02-04 tracey static const struct got_error *gw_get_clone_url(char **, struct gw_trans *,
177 185ba3ba 2020-02-04 tracey char *);
178 54415d85 2020-01-15 tracey static char *gw_get_site_link(struct gw_trans *);
179 070fee27 2020-02-03 stsp static const struct got_error *gw_html_escape(char **, const char *);
180 f7cc9480 2020-02-05 tracey static const struct got_error *gw_colordiff_line(struct gw_trans *, char *);
181 2c251c14 2020-01-15 tracey
182 21a55cc7 2020-02-04 tracey static const struct got_error *gw_gen_commit_header(struct gw_trans *, char *,
183 21a55cc7 2020-02-04 tracey char*);
184 f7cc9480 2020-02-05 tracey static const struct got_error *gw_gen_diff_header(struct gw_trans *, char *,
185 f7cc9480 2020-02-05 tracey char*);
186 21a55cc7 2020-02-04 tracey static const struct got_error *gw_gen_author_header(struct gw_trans *,
187 21a55cc7 2020-02-04 tracey const char *);
188 21a55cc7 2020-02-04 tracey static const struct got_error *gw_gen_age_header(struct gw_trans *,
189 21a55cc7 2020-02-04 tracey const char *);
190 21a55cc7 2020-02-04 tracey static const struct got_error *gw_gen_committer_header(struct gw_trans *,
191 21a55cc7 2020-02-04 tracey const char *);
192 f7cc9480 2020-02-05 tracey static const struct got_error *gw_gen_commit_msg_header(struct gw_trans*,
193 f7cc9480 2020-02-05 tracey char *);
194 f7cc9480 2020-02-05 tracey static const struct got_error *gw_gen_tree_header(struct gw_trans *, char *);
195 f2f46662 2020-01-23 tracey
196 f2f46662 2020-01-23 tracey static void gw_free_headers(struct gw_header *);
197 c25c2314 2020-01-28 stsp static const struct got_error* gw_display_open(struct gw_trans *, enum khttp,
198 2c251c14 2020-01-15 tracey enum kmime);
199 6d8d8a26 2020-01-29 stsp static const struct got_error* gw_display_index(struct gw_trans *);
200 6d8d8a26 2020-01-29 stsp static void gw_display_error(struct gw_trans *,
201 2c251c14 2020-01-15 tracey const struct got_error *);
202 2c251c14 2020-01-15 tracey
203 2c251c14 2020-01-15 tracey static int gw_template(size_t, void *);
204 2c251c14 2020-01-15 tracey
205 f2f46662 2020-01-23 tracey static const struct got_error* gw_get_header(struct gw_trans *,
206 f2f46662 2020-01-23 tracey struct gw_header *, int);
207 f2f46662 2020-01-23 tracey static const struct got_error* gw_get_commits(struct gw_trans *,
208 f2f46662 2020-01-23 tracey struct gw_header *, int);
209 f2f46662 2020-01-23 tracey static const struct got_error* gw_get_commit(struct gw_trans *,
210 f2f46662 2020-01-23 tracey struct gw_header *);
211 54415d85 2020-01-15 tracey static const struct got_error* gw_apply_unveil(const char *, const char *);
212 147269d5 2020-01-15 tracey static const struct got_error* gw_blame_cb(void *, int, int,
213 ec46ccd7 2020-01-15 tracey struct got_object_id *);
214 54415d85 2020-01-15 tracey static const struct got_error* gw_load_got_paths(struct gw_trans *);
215 54415d85 2020-01-15 tracey static const struct got_error* gw_load_got_path(struct gw_trans *,
216 2c251c14 2020-01-15 tracey struct gw_dir *);
217 54415d85 2020-01-15 tracey static const struct got_error* gw_parse_querystring(struct gw_trans *);
218 2c251c14 2020-01-15 tracey
219 54415d85 2020-01-15 tracey static const struct got_error* gw_blame(struct gw_trans *);
220 e46f587c 2020-01-29 tracey static const struct got_error* gw_blob(struct gw_trans *);
221 f2f46662 2020-01-23 tracey static const struct got_error* gw_diff(struct gw_trans *);
222 54415d85 2020-01-15 tracey static const struct got_error* gw_index(struct gw_trans *);
223 f2f46662 2020-01-23 tracey static const struct got_error* gw_commits(struct gw_trans *);
224 f2f46662 2020-01-23 tracey static const struct got_error* gw_briefs(struct gw_trans *);
225 54415d85 2020-01-15 tracey static const struct got_error* gw_summary(struct gw_trans *);
226 54415d85 2020-01-15 tracey static const struct got_error* gw_tree(struct gw_trans *);
227 4ff7391f 2020-01-28 tracey static const struct got_error* gw_tag(struct gw_trans *);
228 2c251c14 2020-01-15 tracey
229 2c251c14 2020-01-15 tracey struct gw_query_action {
230 2c251c14 2020-01-15 tracey unsigned int func_id;
231 2c251c14 2020-01-15 tracey const char *func_name;
232 54415d85 2020-01-15 tracey const struct got_error *(*func_main)(struct gw_trans *);
233 2c251c14 2020-01-15 tracey char *template;
234 2c251c14 2020-01-15 tracey };
235 2c251c14 2020-01-15 tracey
236 2c251c14 2020-01-15 tracey enum gw_query_actions {
237 2c251c14 2020-01-15 tracey GW_BLAME,
238 e46f587c 2020-01-29 tracey GW_BLOB,
239 f2f46662 2020-01-23 tracey GW_BRIEFS,
240 f2f46662 2020-01-23 tracey GW_COMMITS,
241 f2f46662 2020-01-23 tracey GW_DIFF,
242 2c251c14 2020-01-15 tracey GW_ERR,
243 2c251c14 2020-01-15 tracey GW_INDEX,
244 2c251c14 2020-01-15 tracey GW_SUMMARY,
245 4ff7391f 2020-01-28 tracey GW_TAG,
246 b772de24 2020-01-15 tracey GW_TREE,
247 2c251c14 2020-01-15 tracey };
248 2c251c14 2020-01-15 tracey
249 2c251c14 2020-01-15 tracey static struct gw_query_action gw_query_funcs[] = {
250 f2f46662 2020-01-23 tracey { GW_BLAME, "blame", gw_blame, "gw_tmpl/blame.tmpl" },
251 017d6da3 2020-01-29 tracey { GW_BLOB, "blob", NULL, NULL },
252 f2f46662 2020-01-23 tracey { GW_BRIEFS, "briefs", gw_briefs, "gw_tmpl/briefs.tmpl" },
253 f2f46662 2020-01-23 tracey { GW_COMMITS, "commits", gw_commits, "gw_tmpl/commit.tmpl" },
254 f2f46662 2020-01-23 tracey { GW_DIFF, "diff", gw_diff, "gw_tmpl/diff.tmpl" },
255 f2f46662 2020-01-23 tracey { GW_ERR, NULL, NULL, "gw_tmpl/err.tmpl" },
256 f2f46662 2020-01-23 tracey { GW_INDEX, "index", gw_index, "gw_tmpl/index.tmpl" },
257 f2f46662 2020-01-23 tracey { GW_SUMMARY, "summary", gw_summary, "gw_tmpl/summry.tmpl" },
258 4ff7391f 2020-01-28 tracey { GW_TAG, "tag", gw_tag, "gw_tmpl/tag.tmpl" },
259 f2f46662 2020-01-23 tracey { GW_TREE, "tree", gw_tree, "gw_tmpl/tree.tmpl" },
260 2c251c14 2020-01-15 tracey };
261 c25c2314 2020-01-28 stsp
262 c25c2314 2020-01-28 stsp static const struct got_error *
263 c25c2314 2020-01-28 stsp gw_kcgi_error(enum kcgi_err kerr)
264 c25c2314 2020-01-28 stsp {
265 c25c2314 2020-01-28 stsp if (kerr == KCGI_OK)
266 c25c2314 2020-01-28 stsp return NULL;
267 c25c2314 2020-01-28 stsp
268 c25c2314 2020-01-28 stsp if (kerr == KCGI_EXIT || kerr == KCGI_HUP)
269 c25c2314 2020-01-28 stsp return got_error(GOT_ERR_CANCELLED);
270 c25c2314 2020-01-28 stsp
271 c25c2314 2020-01-28 stsp if (kerr == KCGI_ENOMEM)
272 f7cc9480 2020-02-05 tracey return got_error_set_errno(ENOMEM,
273 7afec891 2020-02-06 stsp kcgi_strerror(kerr));
274 2c251c14 2020-01-15 tracey
275 c25c2314 2020-01-28 stsp if (kerr == KCGI_ENFILE)
276 f7cc9480 2020-02-05 tracey return got_error_set_errno(ENFILE,
277 7afec891 2020-02-06 stsp kcgi_strerror(kerr));
278 c25c2314 2020-01-28 stsp
279 c25c2314 2020-01-28 stsp if (kerr == KCGI_EAGAIN)
280 f7cc9480 2020-02-05 tracey return got_error_set_errno(EAGAIN,
281 7afec891 2020-02-06 stsp kcgi_strerror(kerr));
282 c25c2314 2020-01-28 stsp
283 c25c2314 2020-01-28 stsp if (kerr == KCGI_FORM)
284 f7cc9480 2020-02-05 tracey return got_error_msg(GOT_ERR_IO,
285 7afec891 2020-02-06 stsp kcgi_strerror(kerr));
286 c25c2314 2020-01-28 stsp
287 7afec891 2020-02-06 stsp return got_error_from_errno(kcgi_strerror(kerr));
288 c25c2314 2020-01-28 stsp }
289 c25c2314 2020-01-28 stsp
290 2c251c14 2020-01-15 tracey static const struct got_error *
291 54415d85 2020-01-15 tracey gw_apply_unveil(const char *repo_path, const char *repo_file)
292 2c251c14 2020-01-15 tracey {
293 2c251c14 2020-01-15 tracey const struct got_error *err;
294 2c251c14 2020-01-15 tracey
295 2c251c14 2020-01-15 tracey if (repo_path && repo_file) {
296 2c251c14 2020-01-15 tracey char *full_path;
297 88d59c36 2020-01-29 stsp if (asprintf(&full_path, "%s/%s", repo_path, repo_file) == -1)
298 2c251c14 2020-01-15 tracey return got_error_from_errno("asprintf unveil");
299 2c251c14 2020-01-15 tracey if (unveil(full_path, "r") != 0)
300 2c251c14 2020-01-15 tracey return got_error_from_errno2("unveil", full_path);
301 2c251c14 2020-01-15 tracey }
302 2c251c14 2020-01-15 tracey
303 2c251c14 2020-01-15 tracey if (repo_path && unveil(repo_path, "r") != 0)
304 2c251c14 2020-01-15 tracey return got_error_from_errno2("unveil", repo_path);
305 2c251c14 2020-01-15 tracey
306 2c251c14 2020-01-15 tracey if (unveil("/tmp", "rwc") != 0)
307 2c251c14 2020-01-15 tracey return got_error_from_errno2("unveil", "/tmp");
308 2c251c14 2020-01-15 tracey
309 2c251c14 2020-01-15 tracey err = got_privsep_unveil_exec_helpers();
310 2c251c14 2020-01-15 tracey if (err != NULL)
311 2c251c14 2020-01-15 tracey return err;
312 2c251c14 2020-01-15 tracey
313 2c251c14 2020-01-15 tracey if (unveil(NULL, NULL) != 0)
314 2c251c14 2020-01-15 tracey return got_error_from_errno("unveil");
315 2c251c14 2020-01-15 tracey
316 2c251c14 2020-01-15 tracey return NULL;
317 87f9ebf5 2020-01-15 tracey }
318 65b95fb2 2020-01-15 tracey
319 2c251c14 2020-01-15 tracey static const struct got_error *
320 32cd4d18 2020-02-03 stsp gw_empty_string(char **s)
321 32cd4d18 2020-02-03 stsp {
322 32cd4d18 2020-02-03 stsp *s = strdup("");
323 32cd4d18 2020-02-03 stsp if (*s == NULL)
324 32cd4d18 2020-02-03 stsp return got_error_from_errno("strdup");
325 32cd4d18 2020-02-03 stsp return NULL;
326 5894d523 2020-02-03 stsp }
327 5894d523 2020-02-03 stsp
328 5894d523 2020-02-03 stsp static int
329 e0857cfe 2020-02-06 tracey isbinary(const uint8_t *buf, size_t n)
330 5894d523 2020-02-03 stsp {
331 e0857cfe 2020-02-06 tracey size_t i;
332 e0857cfe 2020-02-06 tracey
333 e0857cfe 2020-02-06 tracey for (i = 0; i < n; i++)
334 e0857cfe 2020-02-06 tracey if (buf[i] == 0)
335 e0857cfe 2020-02-06 tracey return 1;
336 e0857cfe 2020-02-06 tracey return 0;
337 32cd4d18 2020-02-03 stsp }
338 5894d523 2020-02-03 stsp
339 32cd4d18 2020-02-03 stsp static const struct got_error *
340 54415d85 2020-01-15 tracey gw_blame(struct gw_trans *gw_trans)
341 2c251c14 2020-01-15 tracey {
342 2c251c14 2020-01-15 tracey const struct got_error *error = NULL;
343 f2f46662 2020-01-23 tracey struct gw_header *header = NULL;
344 9a9d12ca 2020-02-06 tracey char *age = NULL, *escaped_commit_msg = NULL;
345 c25c2314 2020-01-28 stsp enum kcgi_err kerr;
346 2c251c14 2020-01-15 tracey
347 6bee13de 2020-01-16 tracey if (pledge("stdio rpath wpath cpath proc exec sendfd unveil",
348 f2f46662 2020-01-23 tracey NULL) == -1)
349 f2f46662 2020-01-23 tracey return got_error_from_errno("pledge");
350 6bee13de 2020-01-16 tracey
351 f2f46662 2020-01-23 tracey if ((header = gw_init_header()) == NULL)
352 f2f46662 2020-01-23 tracey return got_error_from_errno("malloc");
353 f2f46662 2020-01-23 tracey
354 54415d85 2020-01-15 tracey error = gw_apply_unveil(gw_trans->gw_dir->path, NULL);
355 ec46ccd7 2020-01-15 tracey if (error)
356 5ddf0079 2020-01-29 stsp goto done;
357 ec46ccd7 2020-01-15 tracey
358 f2f46662 2020-01-23 tracey error = gw_get_header(gw_trans, header, 1);
359 f2f46662 2020-01-23 tracey if (error)
360 5ddf0079 2020-01-29 stsp goto done;
361 ec46ccd7 2020-01-15 tracey
362 9a9d12ca 2020-02-06 tracey /* blame header */
363 9a9d12ca 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
364 9a9d12ca 2020-02-06 tracey "blame_header_wrapper", KATTR__MAX);
365 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
366 9a9d12ca 2020-02-06 tracey goto done;
367 9a9d12ca 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
368 9a9d12ca 2020-02-06 tracey "blame_header", KATTR__MAX);
369 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
370 9a9d12ca 2020-02-06 tracey goto done;
371 9a9d12ca 2020-02-06 tracey error = gw_get_time_str(&age, header->committer_time,
372 9a9d12ca 2020-02-06 tracey TM_LONG);
373 a81f3554 2020-02-03 stsp if (error)
374 a81f3554 2020-02-03 stsp goto done;
375 9a9d12ca 2020-02-06 tracey error = gw_gen_age_header(gw_trans, age ?age : "");
376 55ccf528 2020-02-03 stsp if (error)
377 55ccf528 2020-02-03 stsp goto done;
378 9a9d12ca 2020-02-06 tracey /*
379 9a9d12ca 2020-02-06 tracey * XXX: keeping this for now, since kcgihtml does not convert
380 9a9d12ca 2020-02-06 tracey * \n into <br /> yet.
381 9a9d12ca 2020-02-06 tracey */
382 070fee27 2020-02-03 stsp error = gw_html_escape(&escaped_commit_msg, header->commit_msg);
383 070fee27 2020-02-03 stsp if (error)
384 070fee27 2020-02-03 stsp goto done;
385 9a9d12ca 2020-02-06 tracey error = gw_gen_commit_msg_header(gw_trans, header->commit_msg);
386 9a9d12ca 2020-02-06 tracey if (error)
387 6d9fc692 2020-01-28 stsp goto done;
388 9a9d12ca 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
389 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
390 6d9fc692 2020-01-28 stsp goto done;
391 9a9d12ca 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
392 9a9d12ca 2020-02-06 tracey "dotted_line", KATTR__MAX);
393 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
394 9a9d12ca 2020-02-06 tracey goto done;
395 9a9d12ca 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
396 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
397 9a9d12ca 2020-02-06 tracey goto done;
398 9a9d12ca 2020-02-06 tracey
399 9a9d12ca 2020-02-06 tracey /* blame */
400 9a9d12ca 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
401 9a9d12ca 2020-02-06 tracey "blame", KATTR__MAX);
402 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
403 9a9d12ca 2020-02-06 tracey goto done;
404 9a9d12ca 2020-02-06 tracey error = gw_output_file_blame(gw_trans);
405 9a9d12ca 2020-02-06 tracey if (error)
406 9a9d12ca 2020-02-06 tracey goto done;
407 9a9d12ca 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
408 6d9fc692 2020-01-28 stsp done:
409 f2f46662 2020-01-23 tracey got_ref_list_free(&header->refs);
410 f2f46662 2020-01-23 tracey gw_free_headers(header);
411 9a9d12ca 2020-02-06 tracey free(escaped_commit_msg);
412 9a9d12ca 2020-02-06 tracey if (error == NULL && kerr != KCGI_OK)
413 9a9d12ca 2020-02-06 tracey error = gw_kcgi_error(kerr);
414 2c251c14 2020-01-15 tracey return error;
415 2c251c14 2020-01-15 tracey }
416 2c251c14 2020-01-15 tracey
417 2c251c14 2020-01-15 tracey static const struct got_error *
418 e46f587c 2020-01-29 tracey gw_blob(struct gw_trans *gw_trans)
419 e46f587c 2020-01-29 tracey {
420 e46f587c 2020-01-29 tracey const struct got_error *error = NULL;
421 e46f587c 2020-01-29 tracey struct gw_header *header = NULL;
422 e46f587c 2020-01-29 tracey
423 e46f587c 2020-01-29 tracey if (pledge("stdio rpath wpath cpath proc exec sendfd unveil",
424 e46f587c 2020-01-29 tracey NULL) == -1)
425 e46f587c 2020-01-29 tracey return got_error_from_errno("pledge");
426 e46f587c 2020-01-29 tracey
427 e46f587c 2020-01-29 tracey if ((header = gw_init_header()) == NULL)
428 e46f587c 2020-01-29 tracey return got_error_from_errno("malloc");
429 e46f587c 2020-01-29 tracey
430 e46f587c 2020-01-29 tracey error = gw_apply_unveil(gw_trans->gw_dir->path, NULL);
431 e46f587c 2020-01-29 tracey if (error)
432 e46f587c 2020-01-29 tracey goto done;
433 e46f587c 2020-01-29 tracey
434 e46f587c 2020-01-29 tracey error = gw_get_header(gw_trans, header, 1);
435 e46f587c 2020-01-29 tracey if (error)
436 e46f587c 2020-01-29 tracey goto done;
437 e46f587c 2020-01-29 tracey
438 e0857cfe 2020-02-06 tracey error = gw_output_blob_buf(gw_trans);
439 e46f587c 2020-01-29 tracey done:
440 e46f587c 2020-01-29 tracey got_ref_list_free(&header->refs);
441 e46f587c 2020-01-29 tracey gw_free_headers(header);
442 e46f587c 2020-01-29 tracey return error;
443 e46f587c 2020-01-29 tracey }
444 e46f587c 2020-01-29 tracey
445 e46f587c 2020-01-29 tracey static const struct got_error *
446 f2f46662 2020-01-23 tracey gw_diff(struct gw_trans *gw_trans)
447 2c251c14 2020-01-15 tracey {
448 2c251c14 2020-01-15 tracey const struct got_error *error = NULL;
449 f2f46662 2020-01-23 tracey struct gw_header *header = NULL;
450 f7cc9480 2020-02-05 tracey char *age = NULL, *escaped_commit_msg = NULL;
451 f7cc9480 2020-02-05 tracey enum kcgi_err kerr = KCGI_OK;
452 2c251c14 2020-01-15 tracey
453 f2f46662 2020-01-23 tracey if (pledge("stdio rpath wpath cpath proc exec sendfd unveil",
454 f2f46662 2020-01-23 tracey NULL) == -1)
455 f2f46662 2020-01-23 tracey return got_error_from_errno("pledge");
456 6bee13de 2020-01-16 tracey
457 ae36ed87 2020-01-28 stsp if ((header = gw_init_header()) == NULL)
458 f2f46662 2020-01-23 tracey return got_error_from_errno("malloc");
459 f2f46662 2020-01-23 tracey
460 54415d85 2020-01-15 tracey error = gw_apply_unveil(gw_trans->gw_dir->path, NULL);
461 8087c3c5 2020-01-15 tracey if (error)
462 390d412c 2020-01-28 stsp goto done;
463 8087c3c5 2020-01-15 tracey
464 f2f46662 2020-01-23 tracey error = gw_get_header(gw_trans, header, 1);
465 f2f46662 2020-01-23 tracey if (error)
466 55ccf528 2020-02-03 stsp goto done;
467 f7cc9480 2020-02-05 tracey
468 f7cc9480 2020-02-05 tracey /* diff header */
469 f7cc9480 2020-02-05 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
470 f7cc9480 2020-02-05 tracey "diff_header_wrapper", KATTR__MAX);
471 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
472 f7cc9480 2020-02-05 tracey goto done;
473 f7cc9480 2020-02-05 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
474 f7cc9480 2020-02-05 tracey "diff_header", KATTR__MAX);
475 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
476 f7cc9480 2020-02-05 tracey goto done;
477 f7cc9480 2020-02-05 tracey error = gw_gen_diff_header(gw_trans, header->parent_id,
478 f7cc9480 2020-02-05 tracey header->commit_id);
479 f7cc9480 2020-02-05 tracey if (error)
480 f7cc9480 2020-02-05 tracey goto done;
481 f7cc9480 2020-02-05 tracey error = gw_gen_commit_header(gw_trans, header->commit_id,
482 f7cc9480 2020-02-05 tracey header->refs_str);
483 f7cc9480 2020-02-05 tracey if (error)
484 f7cc9480 2020-02-05 tracey goto done;
485 f7cc9480 2020-02-05 tracey error = gw_gen_tree_header(gw_trans, header->tree_id);
486 f7cc9480 2020-02-05 tracey if (error)
487 f7cc9480 2020-02-05 tracey goto done;
488 f7cc9480 2020-02-05 tracey error = gw_gen_author_header(gw_trans, header->author);
489 f7cc9480 2020-02-05 tracey if (error)
490 f7cc9480 2020-02-05 tracey goto done;
491 f7cc9480 2020-02-05 tracey error = gw_gen_committer_header(gw_trans, header->author);
492 f7cc9480 2020-02-05 tracey if (error)
493 f7cc9480 2020-02-05 tracey goto done;
494 f7cc9480 2020-02-05 tracey error = gw_get_time_str(&age, header->committer_time,
495 f7cc9480 2020-02-05 tracey TM_LONG);
496 f7cc9480 2020-02-05 tracey if (error)
497 f7cc9480 2020-02-05 tracey goto done;
498 f7cc9480 2020-02-05 tracey error = gw_gen_age_header(gw_trans, age ?age : "");
499 f7cc9480 2020-02-05 tracey if (error)
500 f7cc9480 2020-02-05 tracey goto done;
501 f7cc9480 2020-02-05 tracey /*
502 f7cc9480 2020-02-05 tracey * XXX: keeping this for now, since kcgihtml does not convert
503 f7cc9480 2020-02-05 tracey * \n into <br /> yet.
504 f7cc9480 2020-02-05 tracey */
505 070fee27 2020-02-03 stsp error = gw_html_escape(&escaped_commit_msg, header->commit_msg);
506 070fee27 2020-02-03 stsp if (error)
507 070fee27 2020-02-03 stsp goto done;
508 f7cc9480 2020-02-05 tracey error = gw_gen_commit_msg_header(gw_trans, header->commit_msg);
509 f7cc9480 2020-02-05 tracey if (error)
510 390d412c 2020-01-28 stsp goto done;
511 f7cc9480 2020-02-05 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
512 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
513 390d412c 2020-01-28 stsp goto done;
514 f7cc9480 2020-02-05 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
515 f7cc9480 2020-02-05 tracey "dotted_line", KATTR__MAX);
516 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
517 f7cc9480 2020-02-05 tracey goto done;
518 f7cc9480 2020-02-05 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
519 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
520 f7cc9480 2020-02-05 tracey goto done;
521 87f9ebf5 2020-01-15 tracey
522 f7cc9480 2020-02-05 tracey /* diff */
523 f7cc9480 2020-02-05 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
524 f7cc9480 2020-02-05 tracey "diff", KATTR__MAX);
525 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
526 f7cc9480 2020-02-05 tracey goto done;
527 38b240fb 2020-02-06 tracey error = gw_output_diff(gw_trans, header);
528 f7cc9480 2020-02-05 tracey if (error)
529 f7cc9480 2020-02-05 tracey goto done;
530 f7cc9480 2020-02-05 tracey
531 f7cc9480 2020-02-05 tracey /* diff content close */
532 b4fba448 2020-02-05 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
533 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
534 f7cc9480 2020-02-05 tracey goto done;
535 390d412c 2020-01-28 stsp done:
536 2dcb56a8 2020-01-28 stsp got_ref_list_free(&header->refs);
537 f2f46662 2020-01-23 tracey gw_free_headers(header);
538 55ccf528 2020-02-03 stsp free(age);
539 070fee27 2020-02-03 stsp free(escaped_commit_msg);
540 f7cc9480 2020-02-05 tracey if (error == NULL && kerr != KCGI_OK)
541 2447adad 2020-02-06 stsp error = gw_kcgi_error(kerr);
542 2204c934 2020-01-15 tracey return error;
543 2204c934 2020-01-15 tracey }
544 2204c934 2020-01-15 tracey
545 2204c934 2020-01-15 tracey static const struct got_error *
546 54415d85 2020-01-15 tracey gw_index(struct gw_trans *gw_trans)
547 2c251c14 2020-01-15 tracey {
548 2c251c14 2020-01-15 tracey const struct got_error *error = NULL;
549 46b9c89b 2020-01-15 tracey struct gw_dir *gw_dir = NULL;
550 2c251c14 2020-01-15 tracey char *html, *navs, *next, *prev;
551 387a29ba 2020-01-15 tracey unsigned int prev_disp = 0, next_disp = 1, dir_c = 0;
552 c25c2314 2020-01-28 stsp enum kcgi_err kerr;
553 2c251c14 2020-01-15 tracey
554 6bee13de 2020-01-16 tracey if (pledge("stdio rpath proc exec sendfd unveil",
555 6bee13de 2020-01-16 tracey NULL) == -1) {
556 6bee13de 2020-01-16 tracey error = got_error_from_errno("pledge");
557 6bee13de 2020-01-16 tracey return error;
558 6bee13de 2020-01-16 tracey }
559 6bee13de 2020-01-16 tracey
560 54415d85 2020-01-15 tracey error = gw_apply_unveil(gw_trans->gw_conf->got_repos_path, NULL);
561 46b9c89b 2020-01-15 tracey if (error)
562 46b9c89b 2020-01-15 tracey return error;
563 46b9c89b 2020-01-15 tracey
564 2c251c14 2020-01-15 tracey error = gw_load_got_paths(gw_trans);
565 46b9c89b 2020-01-15 tracey if (error)
566 2c251c14 2020-01-15 tracey return error;
567 2c251c14 2020-01-15 tracey
568 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, index_projects_header);
569 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
570 2447adad 2020-02-06 stsp return gw_kcgi_error(kerr);
571 2c251c14 2020-01-15 tracey
572 bce5dac1 2020-01-28 stsp if (TAILQ_EMPTY(&gw_trans->gw_dirs)) {
573 bce5dac1 2020-01-28 stsp if (asprintf(&html, index_projects_empty,
574 bce5dac1 2020-01-28 stsp gw_trans->gw_conf->got_repos_path) == -1)
575 bce5dac1 2020-01-28 stsp return got_error_from_errno("asprintf");
576 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, html);
577 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
578 2447adad 2020-02-06 stsp error = gw_kcgi_error(kerr);
579 bce5dac1 2020-01-28 stsp free(html);
580 c25c2314 2020-01-28 stsp return error;
581 bce5dac1 2020-01-28 stsp }
582 bce5dac1 2020-01-28 stsp
583 46b9c89b 2020-01-15 tracey TAILQ_FOREACH(gw_dir, &gw_trans->gw_dirs, entry)
584 2c251c14 2020-01-15 tracey dir_c++;
585 2c251c14 2020-01-15 tracey
586 46b9c89b 2020-01-15 tracey TAILQ_FOREACH(gw_dir, &gw_trans->gw_dirs, entry) {
587 2c251c14 2020-01-15 tracey if (gw_trans->page > 0 && (gw_trans->page *
588 2c251c14 2020-01-15 tracey gw_trans->gw_conf->got_max_repos_display) > prev_disp) {
589 2c251c14 2020-01-15 tracey prev_disp++;
590 2c251c14 2020-01-15 tracey continue;
591 2c251c14 2020-01-15 tracey }
592 2c251c14 2020-01-15 tracey
593 2c251c14 2020-01-15 tracey prev_disp++;
594 f2f46662 2020-01-23 tracey
595 f2f46662 2020-01-23 tracey if (error)
596 f2f46662 2020-01-23 tracey return error;
597 88d59c36 2020-01-29 stsp if(asprintf(&navs, index_navs, gw_dir->name, gw_dir->name,
598 88d59c36 2020-01-29 stsp gw_dir->name, gw_dir->name) == -1)
599 2c251c14 2020-01-15 tracey return got_error_from_errno("asprintf");
600 2c251c14 2020-01-15 tracey
601 88d59c36 2020-01-29 stsp if (asprintf(&html, index_projects, gw_dir->name, gw_dir->name,
602 9a1cc63f 2020-02-03 stsp gw_dir->description, gw_dir->owner ? gw_dir->owner : "",
603 9a1cc63f 2020-02-03 stsp gw_dir->age,
604 88d59c36 2020-01-29 stsp navs) == -1)
605 2c251c14 2020-01-15 tracey return got_error_from_errno("asprintf");
606 2c251c14 2020-01-15 tracey
607 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, html);
608 2c251c14 2020-01-15 tracey free(navs);
609 2c251c14 2020-01-15 tracey free(html);
610 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
611 2447adad 2020-02-06 stsp return gw_kcgi_error(kerr);
612 2c251c14 2020-01-15 tracey
613 2c251c14 2020-01-15 tracey if (gw_trans->gw_conf->got_max_repos_display == 0)
614 2c251c14 2020-01-15 tracey continue;
615 2c251c14 2020-01-15 tracey
616 c25c2314 2020-01-28 stsp if (next_disp == gw_trans->gw_conf->got_max_repos_display) {
617 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, np_wrapper_start);
618 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
619 2447adad 2020-02-06 stsp return gw_kcgi_error(kerr);
620 c25c2314 2020-01-28 stsp } else if ((gw_trans->gw_conf->got_max_repos_display > 0) &&
621 2c251c14 2020-01-15 tracey (gw_trans->page > 0) &&
622 2c251c14 2020-01-15 tracey (next_disp == gw_trans->gw_conf->got_max_repos_display ||
623 c25c2314 2020-01-28 stsp prev_disp == gw_trans->repos_total)) {
624 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, np_wrapper_start);
625 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
626 2447adad 2020-02-06 stsp return gw_kcgi_error(kerr);
627 c25c2314 2020-01-28 stsp }
628 2c251c14 2020-01-15 tracey
629 2c251c14 2020-01-15 tracey if ((gw_trans->gw_conf->got_max_repos_display > 0) &&
630 2c251c14 2020-01-15 tracey (gw_trans->page > 0) &&
631 2c251c14 2020-01-15 tracey (next_disp == gw_trans->gw_conf->got_max_repos_display ||
632 2c251c14 2020-01-15 tracey prev_disp == gw_trans->repos_total)) {
633 88d59c36 2020-01-29 stsp if (asprintf(&prev, nav_prev, gw_trans->page - 1) == -1)
634 2c251c14 2020-01-15 tracey return got_error_from_errno("asprintf");
635 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, prev);
636 2c251c14 2020-01-15 tracey free(prev);
637 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
638 2447adad 2020-02-06 stsp return gw_kcgi_error(kerr);
639 2c251c14 2020-01-15 tracey }
640 2c251c14 2020-01-15 tracey
641 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, div_end);
642 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
643 2447adad 2020-02-06 stsp return gw_kcgi_error(kerr);
644 2c251c14 2020-01-15 tracey
645 2c251c14 2020-01-15 tracey if (gw_trans->gw_conf->got_max_repos_display > 0 &&
646 2c251c14 2020-01-15 tracey next_disp == gw_trans->gw_conf->got_max_repos_display &&
647 2c251c14 2020-01-15 tracey dir_c != (gw_trans->page + 1) *
648 2c251c14 2020-01-15 tracey gw_trans->gw_conf->got_max_repos_display) {
649 88d59c36 2020-01-29 stsp if (asprintf(&next, nav_next, gw_trans->page + 1) == -1)
650 2c251c14 2020-01-15 tracey return got_error_from_errno("calloc");
651 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, next);
652 2c251c14 2020-01-15 tracey free(next);
653 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
654 2447adad 2020-02-06 stsp return gw_kcgi_error(kerr);
655 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, div_end);
656 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
657 2447adad 2020-02-06 stsp error = gw_kcgi_error(kerr);
658 2c251c14 2020-01-15 tracey next_disp = 0;
659 2c251c14 2020-01-15 tracey break;
660 2c251c14 2020-01-15 tracey }
661 2c251c14 2020-01-15 tracey
662 2c251c14 2020-01-15 tracey if ((gw_trans->gw_conf->got_max_repos_display > 0) &&
663 2c251c14 2020-01-15 tracey (gw_trans->page > 0) &&
664 2c251c14 2020-01-15 tracey (next_disp == gw_trans->gw_conf->got_max_repos_display ||
665 c25c2314 2020-01-28 stsp prev_disp == gw_trans->repos_total)) {
666 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, div_end);
667 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
668 2447adad 2020-02-06 stsp return gw_kcgi_error(kerr);
669 c25c2314 2020-01-28 stsp }
670 2c251c14 2020-01-15 tracey
671 2c251c14 2020-01-15 tracey next_disp++;
672 2c251c14 2020-01-15 tracey }
673 2c251c14 2020-01-15 tracey return error;
674 2c251c14 2020-01-15 tracey }
675 2c251c14 2020-01-15 tracey
676 2c251c14 2020-01-15 tracey static const struct got_error *
677 f2f46662 2020-01-23 tracey gw_commits(struct gw_trans *gw_trans)
678 2c251c14 2020-01-15 tracey {
679 2c251c14 2020-01-15 tracey const struct got_error *error = NULL;
680 f2f46662 2020-01-23 tracey struct gw_header *header = NULL, *n_header = NULL;
681 f7cc9480 2020-02-05 tracey char *age = NULL, *escaped_commit_msg = NULL;
682 626b25b6 2020-02-06 tracey char *href_diff = NULL, *href_blob = NULL;
683 21a55cc7 2020-02-04 tracey enum kcgi_err kerr = KCGI_OK;
684 6bee13de 2020-01-16 tracey
685 ae36ed87 2020-01-28 stsp if ((header = gw_init_header()) == NULL)
686 f2f46662 2020-01-23 tracey return got_error_from_errno("malloc");
687 f2f46662 2020-01-23 tracey
688 6bee13de 2020-01-16 tracey if (pledge("stdio rpath proc exec sendfd unveil",
689 6bee13de 2020-01-16 tracey NULL) == -1) {
690 6bee13de 2020-01-16 tracey error = got_error_from_errno("pledge");
691 5ddf0079 2020-01-29 stsp goto done;
692 6bee13de 2020-01-16 tracey }
693 8087c3c5 2020-01-15 tracey
694 54415d85 2020-01-15 tracey error = gw_apply_unveil(gw_trans->gw_dir->path, NULL);
695 8087c3c5 2020-01-15 tracey if (error)
696 5ddf0079 2020-01-29 stsp goto done;
697 2c251c14 2020-01-15 tracey
698 f2f46662 2020-01-23 tracey error = gw_get_header(gw_trans, header,
699 f2f46662 2020-01-23 tracey gw_trans->gw_conf->got_max_commits_display);
700 18da9978 2020-01-29 stsp if (error)
701 18da9978 2020-01-29 stsp goto done;
702 4ceb8155 2020-01-15 tracey
703 21a55cc7 2020-02-04 tracey /* commit content */
704 f2f46662 2020-01-23 tracey TAILQ_FOREACH(n_header, &gw_trans->gw_headers, entry) {
705 21a55cc7 2020-02-04 tracey /* commit line */
706 21a55cc7 2020-02-04 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
707 21a55cc7 2020-02-04 tracey "commits_line_wrapper", KATTR__MAX);
708 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
709 18da9978 2020-01-29 stsp goto done;
710 21a55cc7 2020-02-04 tracey error = gw_gen_commit_header(gw_trans, n_header->commit_id,
711 21a55cc7 2020-02-04 tracey n_header->refs_str);
712 f7cc9480 2020-02-05 tracey if (error)
713 f7cc9480 2020-02-05 tracey goto done;
714 21a55cc7 2020-02-04 tracey error = gw_gen_author_header(gw_trans, n_header->author);
715 21a55cc7 2020-02-04 tracey if (error)
716 21a55cc7 2020-02-04 tracey goto done;
717 21a55cc7 2020-02-04 tracey error = gw_gen_committer_header(gw_trans, n_header->author);
718 21a55cc7 2020-02-04 tracey if (error)
719 21a55cc7 2020-02-04 tracey goto done;
720 55ccf528 2020-02-03 stsp error = gw_get_time_str(&age, n_header->committer_time,
721 55ccf528 2020-02-03 stsp TM_LONG);
722 55ccf528 2020-02-03 stsp if (error)
723 55ccf528 2020-02-03 stsp goto done;
724 21a55cc7 2020-02-04 tracey error = gw_gen_age_header(gw_trans, age ?age : "");
725 21a55cc7 2020-02-04 tracey if (error)
726 55ccf528 2020-02-03 stsp goto done;
727 21a55cc7 2020-02-04 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
728 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
729 21a55cc7 2020-02-04 tracey goto done;
730 21a55cc7 2020-02-04 tracey
731 21a55cc7 2020-02-04 tracey /* dotted line */
732 21a55cc7 2020-02-04 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
733 21a55cc7 2020-02-04 tracey "dotted_line", KATTR__MAX);
734 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
735 21a55cc7 2020-02-04 tracey goto done;
736 21a55cc7 2020-02-04 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
737 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
738 21a55cc7 2020-02-04 tracey goto done;
739 21a55cc7 2020-02-04 tracey
740 21a55cc7 2020-02-04 tracey /* commit */
741 21a55cc7 2020-02-04 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
742 21a55cc7 2020-02-04 tracey "commit", KATTR__MAX);
743 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
744 21a55cc7 2020-02-04 tracey goto done;
745 21a55cc7 2020-02-04 tracey /*
746 21a55cc7 2020-02-04 tracey * XXX: keeping this for now, since kcgihtml does not convert
747 21a55cc7 2020-02-04 tracey * \n into <br /> yet.
748 21a55cc7 2020-02-04 tracey */
749 070fee27 2020-02-03 stsp error = gw_html_escape(&escaped_commit_msg,
750 070fee27 2020-02-03 stsp n_header->commit_msg);
751 070fee27 2020-02-03 stsp if (error)
752 070fee27 2020-02-03 stsp goto done;
753 21a55cc7 2020-02-04 tracey kerr = khttp_puts(gw_trans->gw_req, escaped_commit_msg);
754 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
755 21a55cc7 2020-02-04 tracey goto done;
756 21a55cc7 2020-02-04 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
757 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
758 21a55cc7 2020-02-04 tracey goto done;
759 21a55cc7 2020-02-04 tracey
760 21a55cc7 2020-02-04 tracey /* navs */
761 21a55cc7 2020-02-04 tracey
762 21a55cc7 2020-02-04 tracey /* XXX: create gen code for this */
763 21a55cc7 2020-02-04 tracey /* build diff nav */
764 21a55cc7 2020-02-04 tracey if (asprintf(&href_diff, "?path=%s&action=diff&commit=%s",
765 21a55cc7 2020-02-04 tracey gw_trans->repo_name, n_header->commit_id) == -1) {
766 18da9978 2020-01-29 stsp error = got_error_from_errno("asprintf");
767 18da9978 2020-01-29 stsp goto done;
768 18da9978 2020-01-29 stsp }
769 21a55cc7 2020-02-04 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
770 21a55cc7 2020-02-04 tracey KATTR_ID, "navs_wrapper", KATTR__MAX);
771 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
772 21a55cc7 2020-02-04 tracey goto done;
773 21a55cc7 2020-02-04 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
774 21a55cc7 2020-02-04 tracey KATTR_ID, "navs", KATTR__MAX);
775 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
776 21a55cc7 2020-02-04 tracey goto done;
777 21a55cc7 2020-02-04 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
778 21a55cc7 2020-02-04 tracey KATTR_HREF, href_diff, KATTR__MAX);
779 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
780 21a55cc7 2020-02-04 tracey goto done;
781 21a55cc7 2020-02-04 tracey kerr = khtml_puts(gw_trans->gw_html_req, "diff");
782 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
783 21a55cc7 2020-02-04 tracey goto done;
784 21a55cc7 2020-02-04 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
785 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
786 21a55cc7 2020-02-04 tracey goto done;
787 21a55cc7 2020-02-04 tracey
788 21a55cc7 2020-02-04 tracey kerr = khtml_puts(gw_trans->gw_html_req, " | ");
789 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
790 21a55cc7 2020-02-04 tracey goto done;
791 21a55cc7 2020-02-04 tracey
792 21a55cc7 2020-02-04 tracey /* XXX: create gen code for this */
793 21a55cc7 2020-02-04 tracey /* build tree nav */
794 626b25b6 2020-02-06 tracey if (asprintf(&href_blob, "?path=%s&action=tree&commit=%s",
795 21a55cc7 2020-02-04 tracey gw_trans->repo_name, n_header->commit_id) == -1) {
796 21a55cc7 2020-02-04 tracey error = got_error_from_errno("asprintf");
797 21a55cc7 2020-02-04 tracey goto done;
798 21a55cc7 2020-02-04 tracey }
799 21a55cc7 2020-02-04 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
800 626b25b6 2020-02-06 tracey KATTR_HREF, href_blob, KATTR__MAX);
801 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
802 21a55cc7 2020-02-04 tracey goto done;
803 21a55cc7 2020-02-04 tracey khtml_puts(gw_trans->gw_html_req, "tree");
804 21a55cc7 2020-02-04 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
805 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
806 21a55cc7 2020-02-04 tracey goto done;
807 21a55cc7 2020-02-04 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
808 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
809 21a55cc7 2020-02-04 tracey goto done;
810 21a55cc7 2020-02-04 tracey
811 21a55cc7 2020-02-04 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
812 21a55cc7 2020-02-04 tracey "solid_line", KATTR__MAX);
813 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
814 21a55cc7 2020-02-04 tracey goto done;
815 b4fba448 2020-02-05 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
816 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
817 21a55cc7 2020-02-04 tracey goto done;
818 21a55cc7 2020-02-04 tracey
819 55ccf528 2020-02-03 stsp free(age);
820 55ccf528 2020-02-03 stsp age = NULL;
821 070fee27 2020-02-03 stsp free(escaped_commit_msg);
822 070fee27 2020-02-03 stsp escaped_commit_msg = NULL;
823 f2f46662 2020-01-23 tracey }
824 18da9978 2020-01-29 stsp done:
825 2dcb56a8 2020-01-28 stsp got_ref_list_free(&header->refs);
826 f2f46662 2020-01-23 tracey gw_free_headers(header);
827 f2f46662 2020-01-23 tracey TAILQ_FOREACH(n_header, &gw_trans->gw_headers, entry)
828 f2f46662 2020-01-23 tracey gw_free_headers(n_header);
829 55ccf528 2020-02-03 stsp free(age);
830 21a55cc7 2020-02-04 tracey free(href_diff);
831 626b25b6 2020-02-06 tracey free(href_blob);
832 070fee27 2020-02-03 stsp free(escaped_commit_msg);
833 21a55cc7 2020-02-04 tracey if (error == NULL && kerr != KCGI_OK)
834 2447adad 2020-02-06 stsp error = gw_kcgi_error(kerr);
835 2c251c14 2020-01-15 tracey return error;
836 2c251c14 2020-01-15 tracey }
837 2c251c14 2020-01-15 tracey
838 2c251c14 2020-01-15 tracey static const struct got_error *
839 f2f46662 2020-01-23 tracey gw_briefs(struct gw_trans *gw_trans)
840 2c251c14 2020-01-15 tracey {
841 2c251c14 2020-01-15 tracey const struct got_error *error = NULL;
842 bd275801 2020-02-03 tracey struct gw_header *header = NULL, *n_header = NULL;
843 bd275801 2020-02-03 tracey char *age = NULL, *age_html = NULL;
844 626b25b6 2020-02-06 tracey char *href_diff = NULL, *href_blob = NULL;
845 bd275801 2020-02-03 tracey char *newline, *smallerthan;
846 ef72fe2c 2020-02-04 stsp enum kcgi_err kerr = KCGI_OK;
847 17a96b9f 2020-01-15 tracey
848 ae36ed87 2020-01-28 stsp if ((header = gw_init_header()) == NULL)
849 f2f46662 2020-01-23 tracey return got_error_from_errno("malloc");
850 f2f46662 2020-01-23 tracey
851 6bee13de 2020-01-16 tracey if (pledge("stdio rpath proc exec sendfd unveil",
852 6bee13de 2020-01-16 tracey NULL) == -1) {
853 6bee13de 2020-01-16 tracey error = got_error_from_errno("pledge");
854 5ddf0079 2020-01-29 stsp goto done;
855 6bee13de 2020-01-16 tracey }
856 6bee13de 2020-01-16 tracey
857 54415d85 2020-01-15 tracey error = gw_apply_unveil(gw_trans->gw_dir->path, NULL);
858 8087c3c5 2020-01-15 tracey if (error)
859 5ddf0079 2020-01-29 stsp goto done;
860 9d84e7dd 2020-01-15 tracey
861 f2f46662 2020-01-23 tracey if (gw_trans->action == GW_SUMMARY)
862 f2f46662 2020-01-23 tracey error = gw_get_header(gw_trans, header, D_MAXSLCOMMDISP);
863 f2f46662 2020-01-23 tracey else
864 f2f46662 2020-01-23 tracey error = gw_get_header(gw_trans, header,
865 f2f46662 2020-01-23 tracey gw_trans->gw_conf->got_max_commits_display);
866 c25c2314 2020-01-28 stsp if (error)
867 0e00e8f4 2020-01-29 stsp goto done;
868 c25c2314 2020-01-28 stsp
869 f2f46662 2020-01-23 tracey TAILQ_FOREACH(n_header, &gw_trans->gw_headers, entry) {
870 bd275801 2020-02-03 tracey error = gw_get_time_str(&age, n_header->committer_time,
871 bd275801 2020-02-03 tracey TM_DIFF);
872 bd275801 2020-02-03 tracey if (error)
873 bd275801 2020-02-03 tracey goto done;
874 bd275801 2020-02-03 tracey
875 bd275801 2020-02-03 tracey /* briefs wrapper */
876 bd275801 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
877 bd275801 2020-02-03 tracey KATTR_ID, "briefs_wrapper", KATTR__MAX);
878 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
879 bd275801 2020-02-03 tracey goto done;
880 bd275801 2020-02-03 tracey
881 bd275801 2020-02-03 tracey /* briefs age */
882 bd275801 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
883 bd275801 2020-02-03 tracey KATTR_ID, "briefs_age", KATTR__MAX);
884 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
885 bd275801 2020-02-03 tracey goto done;
886 bd275801 2020-02-03 tracey if (asprintf(&age_html, "%s", age ? age : "") == -1) {
887 0e00e8f4 2020-01-29 stsp error = got_error_from_errno("asprintf");
888 0e00e8f4 2020-01-29 stsp goto done;
889 0e00e8f4 2020-01-29 stsp }
890 bd275801 2020-02-03 tracey kerr = khtml_puts(gw_trans->gw_html_req, age_html);
891 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
892 bd275801 2020-02-03 tracey goto done;
893 bd275801 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
894 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
895 bd275801 2020-02-03 tracey goto done;
896 bd275801 2020-02-03 tracey
897 bd275801 2020-02-03 tracey /* briefs author */
898 bd275801 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
899 bd275801 2020-02-03 tracey KATTR_ID, "briefs_author", KATTR__MAX);
900 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
901 bd275801 2020-02-03 tracey goto done;
902 bd275801 2020-02-03 tracey smallerthan = strchr(n_header->author, '<');
903 bd275801 2020-02-03 tracey if (smallerthan)
904 bd275801 2020-02-03 tracey *smallerthan = '\0';
905 bd275801 2020-02-03 tracey kerr = khtml_puts(gw_trans->gw_html_req, n_header->author);
906 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
907 bd275801 2020-02-03 tracey goto done;
908 bd275801 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
909 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
910 bd275801 2020-02-03 tracey goto done;
911 bd275801 2020-02-03 tracey
912 bd275801 2020-02-03 tracey /* briefs log */
913 52f8346c 2020-02-03 tracey if (asprintf(&href_diff, "?path=%s&action=diff&commit=%s",
914 52f8346c 2020-02-03 tracey gw_trans->repo_name, n_header->commit_id) == -1) {
915 52f8346c 2020-02-03 tracey error = got_error_from_errno("asprintf");
916 52f8346c 2020-02-03 tracey goto done;
917 52f8346c 2020-02-03 tracey }
918 bd275801 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
919 bd275801 2020-02-03 tracey KATTR_ID, "briefs_log", KATTR__MAX);
920 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
921 bd275801 2020-02-03 tracey goto done;
922 f2f46662 2020-01-23 tracey newline = strchr(n_header->commit_msg, '\n');
923 f2f46662 2020-01-23 tracey if (newline)
924 f2f46662 2020-01-23 tracey *newline = '\0';
925 52f8346c 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
926 52f8346c 2020-02-03 tracey KATTR_HREF, href_diff, KATTR__MAX);
927 52f8346c 2020-02-03 tracey if (kerr != KCGI_OK)
928 52f8346c 2020-02-03 tracey goto done;
929 bd275801 2020-02-03 tracey kerr = khtml_puts(gw_trans->gw_html_req, n_header->commit_msg);
930 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
931 55ccf528 2020-02-03 stsp goto done;
932 52f8346c 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
933 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
934 bd275801 2020-02-03 tracey goto done;
935 bd275801 2020-02-03 tracey
936 bd275801 2020-02-03 tracey /* build diff nav */
937 bd275801 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
938 bd275801 2020-02-03 tracey KATTR_ID, "navs_wrapper", KATTR__MAX);
939 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
940 bd275801 2020-02-03 tracey goto done;
941 bd275801 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
942 bd275801 2020-02-03 tracey KATTR_ID, "navs", KATTR__MAX);
943 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
944 bd275801 2020-02-03 tracey goto done;
945 bd275801 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
946 bd275801 2020-02-03 tracey KATTR_HREF, href_diff, KATTR__MAX);
947 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
948 070fee27 2020-02-03 stsp goto done;
949 bd275801 2020-02-03 tracey kerr = khtml_puts(gw_trans->gw_html_req, "diff");
950 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
951 bd275801 2020-02-03 tracey goto done;
952 bd275801 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
953 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
954 bd275801 2020-02-03 tracey goto done;
955 bd275801 2020-02-03 tracey
956 bd275801 2020-02-03 tracey kerr = khtml_puts(gw_trans->gw_html_req, " | ");
957 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
958 bd275801 2020-02-03 tracey goto done;
959 bd275801 2020-02-03 tracey
960 bd275801 2020-02-03 tracey /* build tree nav */
961 626b25b6 2020-02-06 tracey if (asprintf(&href_blob, "?path=%s&action=tree&commit=%s",
962 bd275801 2020-02-03 tracey gw_trans->repo_name, n_header->commit_id) == -1) {
963 0e00e8f4 2020-01-29 stsp error = got_error_from_errno("asprintf");
964 0e00e8f4 2020-01-29 stsp goto done;
965 0e00e8f4 2020-01-29 stsp }
966 bd275801 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
967 626b25b6 2020-02-06 tracey KATTR_HREF, href_blob, KATTR__MAX);
968 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
969 bd275801 2020-02-03 tracey goto done;
970 bd275801 2020-02-03 tracey khtml_puts(gw_trans->gw_html_req, "tree");
971 bd275801 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
972 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
973 bd275801 2020-02-03 tracey goto done;
974 bd275801 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
975 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
976 bd275801 2020-02-03 tracey goto done;
977 bd275801 2020-02-03 tracey
978 bd275801 2020-02-03 tracey /* dotted line */
979 bd275801 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
980 bd275801 2020-02-03 tracey KATTR_ID, "dotted_line", KATTR__MAX);
981 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
982 bd275801 2020-02-03 tracey goto done;
983 bd275801 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 3);
984 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
985 bd275801 2020-02-03 tracey goto done;
986 bd275801 2020-02-03 tracey
987 55ccf528 2020-02-03 stsp free(age);
988 55ccf528 2020-02-03 stsp age = NULL;
989 55ccf528 2020-02-03 stsp free(age_html);
990 55ccf528 2020-02-03 stsp age_html = NULL;
991 bd275801 2020-02-03 tracey free(href_diff);
992 bd275801 2020-02-03 tracey href_diff = NULL;
993 626b25b6 2020-02-06 tracey free(href_blob);
994 626b25b6 2020-02-06 tracey href_blob = NULL;
995 9d84e7dd 2020-01-15 tracey }
996 0e00e8f4 2020-01-29 stsp done:
997 2dcb56a8 2020-01-28 stsp got_ref_list_free(&header->refs);
998 f2f46662 2020-01-23 tracey gw_free_headers(header);
999 f2f46662 2020-01-23 tracey TAILQ_FOREACH(n_header, &gw_trans->gw_headers, entry)
1000 f2f46662 2020-01-23 tracey gw_free_headers(n_header);
1001 55ccf528 2020-02-03 stsp free(age);
1002 55ccf528 2020-02-03 stsp free(age_html);
1003 bd275801 2020-02-03 tracey free(href_diff);
1004 626b25b6 2020-02-06 tracey free(href_blob);
1005 ef72fe2c 2020-02-04 stsp if (error == NULL && kerr != KCGI_OK)
1006 2447adad 2020-02-06 stsp error = gw_kcgi_error(kerr);
1007 2c251c14 2020-01-15 tracey return error;
1008 2c251c14 2020-01-15 tracey }
1009 2c251c14 2020-01-15 tracey
1010 2c251c14 2020-01-15 tracey static const struct got_error *
1011 54415d85 2020-01-15 tracey gw_summary(struct gw_trans *gw_trans)
1012 387a29ba 2020-01-15 tracey {
1013 387a29ba 2020-01-15 tracey const struct got_error *error = NULL;
1014 783ec107 2020-02-03 tracey char *age = NULL, *tags = NULL, *heads = NULL;
1015 21a55cc7 2020-02-04 tracey enum kcgi_err kerr = KCGI_OK;
1016 387a29ba 2020-01-15 tracey
1017 f4df82f9 2020-01-29 stsp if (pledge("stdio rpath proc exec sendfd unveil", NULL) == -1)
1018 f4df82f9 2020-01-29 stsp return got_error_from_errno("pledge");
1019 6bee13de 2020-01-16 tracey
1020 f2f46662 2020-01-23 tracey /* unveil is applied with gw_briefs below */
1021 46b9c89b 2020-01-15 tracey
1022 783ec107 2020-02-03 tracey /* summary wrapper */
1023 783ec107 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
1024 783ec107 2020-02-03 tracey "summary_wrapper", KATTR__MAX);
1025 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
1026 2447adad 2020-02-06 stsp return gw_kcgi_error(kerr);
1027 c25c2314 2020-01-28 stsp
1028 783ec107 2020-02-03 tracey /* description */
1029 783ec107 2020-02-03 tracey if (gw_trans->gw_conf->got_show_repo_description &&
1030 783ec107 2020-02-03 tracey gw_trans->gw_dir->description != NULL &&
1031 783ec107 2020-02-03 tracey (strcmp(gw_trans->gw_dir->description, "") != 0)) {
1032 783ec107 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1033 783ec107 2020-02-03 tracey KATTR_ID, "description_title", KATTR__MAX);
1034 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1035 783ec107 2020-02-03 tracey goto done;
1036 783ec107 2020-02-03 tracey kerr = khtml_puts(gw_trans->gw_html_req, "Description: ");
1037 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1038 783ec107 2020-02-03 tracey goto done;
1039 783ec107 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1040 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1041 783ec107 2020-02-03 tracey goto done;
1042 783ec107 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1043 783ec107 2020-02-03 tracey KATTR_ID, "description", KATTR__MAX);
1044 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1045 783ec107 2020-02-03 tracey goto done;
1046 783ec107 2020-02-03 tracey kerr = khtml_puts(gw_trans->gw_html_req,
1047 783ec107 2020-02-03 tracey gw_trans->gw_dir->description);
1048 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1049 783ec107 2020-02-03 tracey goto done;
1050 783ec107 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1051 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1052 783ec107 2020-02-03 tracey goto done;
1053 46b9c89b 2020-01-15 tracey }
1054 46b9c89b 2020-01-15 tracey
1055 783ec107 2020-02-03 tracey /* repo owner */
1056 9a1cc63f 2020-02-03 stsp if (gw_trans->gw_conf->got_show_repo_owner &&
1057 9a1cc63f 2020-02-03 stsp gw_trans->gw_dir->owner != NULL) {
1058 783ec107 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1059 783ec107 2020-02-03 tracey KATTR_ID, "repo_owner_title", KATTR__MAX);
1060 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1061 9a1cc63f 2020-02-03 stsp goto done;
1062 783ec107 2020-02-03 tracey kerr = khtml_puts(gw_trans->gw_html_req, "Owner: ");
1063 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1064 9a1cc63f 2020-02-03 stsp goto done;
1065 783ec107 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1066 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1067 783ec107 2020-02-03 tracey goto done;
1068 783ec107 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1069 783ec107 2020-02-03 tracey KATTR_ID, "repo_owner", KATTR__MAX);
1070 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1071 783ec107 2020-02-03 tracey goto done;
1072 783ec107 2020-02-03 tracey kerr = khtml_puts(gw_trans->gw_html_req,
1073 783ec107 2020-02-03 tracey gw_trans->gw_dir->owner);
1074 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1075 783ec107 2020-02-03 tracey goto done;
1076 783ec107 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1077 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1078 783ec107 2020-02-03 tracey goto done;
1079 46b9c89b 2020-01-15 tracey }
1080 46b9c89b 2020-01-15 tracey
1081 783ec107 2020-02-03 tracey /* last change */
1082 46b9c89b 2020-01-15 tracey if (gw_trans->gw_conf->got_show_repo_age) {
1083 d126c1b7 2020-01-29 stsp error = gw_get_repo_age(&age, gw_trans, gw_trans->gw_dir->path,
1084 c6b62706 2020-01-15 tracey "refs/heads", TM_LONG);
1085 d126c1b7 2020-01-29 stsp if (error)
1086 20f34652 2020-01-29 stsp goto done;
1087 55ccf528 2020-02-03 stsp if (age != NULL) {
1088 783ec107 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1089 783ec107 2020-02-03 tracey KATTR_ID, "last_change_title", KATTR__MAX);
1090 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1091 20f34652 2020-01-29 stsp goto done;
1092 783ec107 2020-02-03 tracey kerr = khtml_puts(gw_trans->gw_html_req,
1093 783ec107 2020-02-03 tracey "Last Change: ");
1094 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1095 20f34652 2020-01-29 stsp goto done;
1096 783ec107 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1097 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1098 20f34652 2020-01-29 stsp goto done;
1099 783ec107 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1100 783ec107 2020-02-03 tracey KATTR_ID, "last_change", KATTR__MAX);
1101 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1102 20f34652 2020-01-29 stsp goto done;
1103 783ec107 2020-02-03 tracey kerr = khtml_puts(gw_trans->gw_html_req, age);
1104 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1105 783ec107 2020-02-03 tracey goto done;
1106 783ec107 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1107 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1108 783ec107 2020-02-03 tracey goto done;
1109 46b9c89b 2020-01-15 tracey }
1110 46b9c89b 2020-01-15 tracey }
1111 783ec107 2020-02-03 tracey
1112 783ec107 2020-02-03 tracey /* cloneurl */
1113 783ec107 2020-02-03 tracey if (gw_trans->gw_conf->got_show_repo_cloneurl &&
1114 783ec107 2020-02-03 tracey gw_trans->gw_dir->url != NULL &&
1115 783ec107 2020-02-03 tracey (strcmp(gw_trans->gw_dir->url, "") != 0)) {
1116 783ec107 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1117 783ec107 2020-02-03 tracey KATTR_ID, "cloneurl_title", KATTR__MAX);
1118 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1119 783ec107 2020-02-03 tracey goto done;
1120 783ec107 2020-02-03 tracey kerr = khtml_puts(gw_trans->gw_html_req, "Clone URL: ");
1121 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1122 783ec107 2020-02-03 tracey goto done;
1123 783ec107 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1124 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1125 783ec107 2020-02-03 tracey goto done;
1126 783ec107 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1127 783ec107 2020-02-03 tracey KATTR_ID, "cloneurl", KATTR__MAX);
1128 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1129 783ec107 2020-02-03 tracey goto done;
1130 783ec107 2020-02-03 tracey kerr = khtml_puts(gw_trans->gw_html_req, gw_trans->gw_dir->url);
1131 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1132 21a55cc7 2020-02-04 tracey goto done;
1133 783ec107 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1134 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1135 783ec107 2020-02-03 tracey goto done;
1136 783ec107 2020-02-03 tracey }
1137 783ec107 2020-02-03 tracey
1138 783ec107 2020-02-03 tracey /* close summary wrapper */
1139 783ec107 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1140 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1141 bd275801 2020-02-03 tracey goto done;
1142 bd275801 2020-02-03 tracey
1143 bd275801 2020-02-03 tracey /* commit briefs header */
1144 bd275801 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
1145 bd275801 2020-02-03 tracey "briefs_title_wrapper", KATTR__MAX);
1146 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1147 bd275801 2020-02-03 tracey goto done;
1148 bd275801 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
1149 bd275801 2020-02-03 tracey "briefs_title", KATTR__MAX);
1150 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1151 20f34652 2020-01-29 stsp goto done;
1152 bd275801 2020-02-03 tracey kerr = khtml_puts(gw_trans->gw_html_req, "Commit Briefs");
1153 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1154 bd275801 2020-02-03 tracey goto done;
1155 bd275801 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
1156 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1157 bd275801 2020-02-03 tracey goto done;
1158 f2f46662 2020-01-23 tracey error = gw_briefs(gw_trans);
1159 f2f46662 2020-01-23 tracey if (error)
1160 20f34652 2020-01-29 stsp goto done;
1161 f2f46662 2020-01-23 tracey
1162 783ec107 2020-02-03 tracey /* tags */
1163 38b240fb 2020-02-06 tracey error = gw_output_repo_tags(gw_trans, NULL, D_MAXSLCOMMDISP,
1164 6eccd105 2020-02-03 stsp TAGBRIEF);
1165 6eccd105 2020-02-03 stsp if (error)
1166 6eccd105 2020-02-03 stsp goto done;
1167 8d4d2453 2020-01-15 tracey
1168 783ec107 2020-02-03 tracey /* heads */
1169 51d4a92d 2020-02-03 tracey error = gw_get_repo_heads(&heads, gw_trans);
1170 51d4a92d 2020-02-03 tracey if (error)
1171 51d4a92d 2020-02-03 tracey goto done;
1172 8d4d2453 2020-01-15 tracey if (heads != NULL && strcmp(heads, "") != 0) {
1173 783ec107 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1174 783ec107 2020-02-03 tracey KATTR_ID, "summary_heads_title_wrapper", KATTR__MAX);
1175 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1176 20f34652 2020-01-29 stsp goto done;
1177 783ec107 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1178 783ec107 2020-02-03 tracey KATTR_ID, "summary_heads_title", KATTR__MAX);
1179 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1180 783ec107 2020-02-03 tracey goto done;
1181 783ec107 2020-02-03 tracey kerr = khtml_puts(gw_trans->gw_html_req, "Heads");
1182 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1183 783ec107 2020-02-03 tracey goto done;
1184 783ec107 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
1185 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1186 783ec107 2020-02-03 tracey goto done;
1187 783ec107 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1188 783ec107 2020-02-03 tracey KATTR_ID, "summary_heads_content", KATTR__MAX);
1189 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1190 783ec107 2020-02-03 tracey goto done;
1191 783ec107 2020-02-03 tracey kerr = khttp_puts(gw_trans->gw_req, heads);
1192 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1193 783ec107 2020-02-03 tracey goto done;
1194 783ec107 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1195 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1196 20f34652 2020-01-29 stsp goto done;
1197 8d4d2453 2020-01-15 tracey }
1198 20f34652 2020-01-29 stsp done:
1199 20f34652 2020-01-29 stsp free(age);
1200 20f34652 2020-01-29 stsp free(tags);
1201 20f34652 2020-01-29 stsp free(heads);
1202 f7cc9480 2020-02-05 tracey if (error == NULL && kerr != KCGI_OK)
1203 2447adad 2020-02-06 stsp error = gw_kcgi_error(kerr);
1204 2204c934 2020-01-15 tracey return error;
1205 2204c934 2020-01-15 tracey }
1206 2204c934 2020-01-15 tracey
1207 2204c934 2020-01-15 tracey static const struct got_error *
1208 f2f46662 2020-01-23 tracey gw_tree(struct gw_trans *gw_trans)
1209 b772de24 2020-01-15 tracey {
1210 b772de24 2020-01-15 tracey const struct got_error *error = NULL;
1211 f2f46662 2020-01-23 tracey struct gw_header *header = NULL;
1212 f2f46662 2020-01-23 tracey char *tree = NULL, *tree_html = NULL, *tree_html_disp = NULL;
1213 070fee27 2020-02-03 stsp char *age = NULL, *age_html = NULL, *escaped_commit_msg = NULL;
1214 c25c2314 2020-01-28 stsp enum kcgi_err kerr;
1215 6bee13de 2020-01-16 tracey
1216 f2f46662 2020-01-23 tracey if (pledge("stdio rpath proc exec sendfd unveil", NULL) == -1)
1217 f2f46662 2020-01-23 tracey return got_error_from_errno("pledge");
1218 b772de24 2020-01-15 tracey
1219 ae36ed87 2020-01-28 stsp if ((header = gw_init_header()) == NULL)
1220 f2f46662 2020-01-23 tracey return got_error_from_errno("malloc");
1221 f2f46662 2020-01-23 tracey
1222 54415d85 2020-01-15 tracey error = gw_apply_unveil(gw_trans->gw_dir->path, NULL);
1223 b772de24 2020-01-15 tracey if (error)
1224 5ddf0079 2020-01-29 stsp goto done;
1225 b772de24 2020-01-15 tracey
1226 f2f46662 2020-01-23 tracey error = gw_get_header(gw_trans, header, 1);
1227 f2f46662 2020-01-23 tracey if (error)
1228 42281175 2020-01-29 stsp goto done;
1229 b772de24 2020-01-15 tracey
1230 626b25b6 2020-02-06 tracey /* tree header */
1231 626b25b6 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
1232 626b25b6 2020-02-06 tracey "tree_header_wrapper", KATTR__MAX);
1233 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
1234 55ccf528 2020-02-03 stsp goto done;
1235 626b25b6 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
1236 626b25b6 2020-02-06 tracey "tree_header", KATTR__MAX);
1237 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
1238 55ccf528 2020-02-03 stsp goto done;
1239 626b25b6 2020-02-06 tracey error = gw_gen_tree_header(gw_trans, header->tree_id);
1240 626b25b6 2020-02-06 tracey if (error)
1241 626b25b6 2020-02-06 tracey goto done;
1242 626b25b6 2020-02-06 tracey error = gw_get_time_str(&age, header->committer_time,
1243 626b25b6 2020-02-06 tracey TM_LONG);
1244 626b25b6 2020-02-06 tracey if (error)
1245 626b25b6 2020-02-06 tracey goto done;
1246 626b25b6 2020-02-06 tracey error = gw_gen_age_header(gw_trans, age ?age : "");
1247 626b25b6 2020-02-06 tracey if (error)
1248 626b25b6 2020-02-06 tracey goto done;
1249 626b25b6 2020-02-06 tracey /*
1250 626b25b6 2020-02-06 tracey * XXX: keeping this for now, since kcgihtml does not convert
1251 626b25b6 2020-02-06 tracey * \n into <br /> yet.
1252 626b25b6 2020-02-06 tracey */
1253 070fee27 2020-02-03 stsp error = gw_html_escape(&escaped_commit_msg, header->commit_msg);
1254 070fee27 2020-02-03 stsp if (error)
1255 070fee27 2020-02-03 stsp goto done;
1256 626b25b6 2020-02-06 tracey error = gw_gen_commit_msg_header(gw_trans, header->commit_msg);
1257 626b25b6 2020-02-06 tracey if (error)
1258 42281175 2020-01-29 stsp goto done;
1259 626b25b6 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
1260 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
1261 42281175 2020-01-29 stsp goto done;
1262 626b25b6 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
1263 626b25b6 2020-02-06 tracey "dotted_line", KATTR__MAX);
1264 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
1265 626b25b6 2020-02-06 tracey goto done;
1266 626b25b6 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1267 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
1268 626b25b6 2020-02-06 tracey goto done;
1269 626b25b6 2020-02-06 tracey
1270 626b25b6 2020-02-06 tracey /* tree */
1271 626b25b6 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
1272 626b25b6 2020-02-06 tracey "tree", KATTR__MAX);
1273 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
1274 626b25b6 2020-02-06 tracey goto done;
1275 626b25b6 2020-02-06 tracey error = gw_output_repo_tree(gw_trans);
1276 626b25b6 2020-02-06 tracey if (error)
1277 626b25b6 2020-02-06 tracey goto done;
1278 626b25b6 2020-02-06 tracey
1279 626b25b6 2020-02-06 tracey /* tree content close */
1280 626b25b6 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1281 4ff7391f 2020-01-28 tracey done:
1282 2dcb56a8 2020-01-28 stsp got_ref_list_free(&header->refs);
1283 f2f46662 2020-01-23 tracey gw_free_headers(header);
1284 f2f46662 2020-01-23 tracey free(tree_html_disp);
1285 f2f46662 2020-01-23 tracey free(tree_html);
1286 f2f46662 2020-01-23 tracey free(tree);
1287 55ccf528 2020-02-03 stsp free(age);
1288 55ccf528 2020-02-03 stsp free(age_html);
1289 070fee27 2020-02-03 stsp free(escaped_commit_msg);
1290 626b25b6 2020-02-06 tracey if (error == NULL && kerr != KCGI_OK)
1291 626b25b6 2020-02-06 tracey error = gw_kcgi_error(kerr);
1292 4ff7391f 2020-01-28 tracey return error;
1293 4ff7391f 2020-01-28 tracey }
1294 4ff7391f 2020-01-28 tracey
1295 4ff7391f 2020-01-28 tracey static const struct got_error *
1296 4ff7391f 2020-01-28 tracey gw_tag(struct gw_trans *gw_trans)
1297 4ff7391f 2020-01-28 tracey {
1298 4ff7391f 2020-01-28 tracey const struct got_error *error = NULL;
1299 4ff7391f 2020-01-28 tracey struct gw_header *header = NULL;
1300 070fee27 2020-02-03 stsp char *escaped_commit_msg = NULL;
1301 4ff7391f 2020-01-28 tracey enum kcgi_err kerr;
1302 4ff7391f 2020-01-28 tracey
1303 4ff7391f 2020-01-28 tracey if (pledge("stdio rpath proc exec sendfd unveil", NULL) == -1)
1304 4ff7391f 2020-01-28 tracey return got_error_from_errno("pledge");
1305 4ff7391f 2020-01-28 tracey
1306 4ff7391f 2020-01-28 tracey if ((header = gw_init_header()) == NULL)
1307 4ff7391f 2020-01-28 tracey return got_error_from_errno("malloc");
1308 4ff7391f 2020-01-28 tracey
1309 4ff7391f 2020-01-28 tracey error = gw_apply_unveil(gw_trans->gw_dir->path, NULL);
1310 4ff7391f 2020-01-28 tracey if (error)
1311 5ddf0079 2020-01-29 stsp goto done;
1312 4ff7391f 2020-01-28 tracey
1313 4ff7391f 2020-01-28 tracey error = gw_get_header(gw_trans, header, 1);
1314 4ff7391f 2020-01-28 tracey if (error)
1315 470cd826 2020-01-29 stsp goto done;
1316 4ff7391f 2020-01-28 tracey
1317 38b240fb 2020-02-06 tracey /* tag header */
1318 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
1319 38b240fb 2020-02-06 tracey "tag_header_wrapper", KATTR__MAX);
1320 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
1321 38b240fb 2020-02-06 tracey goto done;
1322 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
1323 38b240fb 2020-02-06 tracey "tag_header", KATTR__MAX);
1324 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
1325 38b240fb 2020-02-06 tracey goto done;
1326 38b240fb 2020-02-06 tracey error = gw_gen_commit_header(gw_trans, header->commit_id,
1327 38b240fb 2020-02-06 tracey header->refs_str);
1328 6eccd105 2020-02-03 stsp if (error)
1329 6eccd105 2020-02-03 stsp goto done;
1330 38b240fb 2020-02-06 tracey /*
1331 38b240fb 2020-02-06 tracey * XXX: keeping this for now, since kcgihtml does not convert
1332 38b240fb 2020-02-06 tracey * \n into <br /> yet.
1333 38b240fb 2020-02-06 tracey */
1334 070fee27 2020-02-03 stsp error = gw_html_escape(&escaped_commit_msg, header->commit_msg);
1335 070fee27 2020-02-03 stsp if (error)
1336 070fee27 2020-02-03 stsp goto done;
1337 38b240fb 2020-02-06 tracey error = gw_gen_commit_msg_header(gw_trans, header->commit_msg);
1338 38b240fb 2020-02-06 tracey if (error)
1339 470cd826 2020-01-29 stsp goto done;
1340 38b240fb 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
1341 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
1342 470cd826 2020-01-29 stsp goto done;
1343 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
1344 38b240fb 2020-02-06 tracey "dotted_line", KATTR__MAX);
1345 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
1346 38b240fb 2020-02-06 tracey goto done;
1347 38b240fb 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1348 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
1349 38b240fb 2020-02-06 tracey goto done;
1350 4ff7391f 2020-01-28 tracey
1351 38b240fb 2020-02-06 tracey /* tag */
1352 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
1353 38b240fb 2020-02-06 tracey "tree", KATTR__MAX);
1354 4ff7391f 2020-01-28 tracey if (kerr != KCGI_OK)
1355 38b240fb 2020-02-06 tracey goto done;
1356 38b240fb 2020-02-06 tracey
1357 38b240fb 2020-02-06 tracey error = gw_output_repo_tags(gw_trans, header, 1, TAGFULL);
1358 38b240fb 2020-02-06 tracey if (error)
1359 38b240fb 2020-02-06 tracey goto done;
1360 38b240fb 2020-02-06 tracey
1361 38b240fb 2020-02-06 tracey /* tag content close */
1362 38b240fb 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1363 4ff7391f 2020-01-28 tracey done:
1364 4ff7391f 2020-01-28 tracey got_ref_list_free(&header->refs);
1365 4ff7391f 2020-01-28 tracey gw_free_headers(header);
1366 070fee27 2020-02-03 stsp free(escaped_commit_msg);
1367 38b240fb 2020-02-06 tracey if (error == NULL && kerr != KCGI_OK)
1368 38b240fb 2020-02-06 tracey error = gw_kcgi_error(kerr);
1369 2c251c14 2020-01-15 tracey return error;
1370 2c251c14 2020-01-15 tracey }
1371 2c251c14 2020-01-15 tracey
1372 2c251c14 2020-01-15 tracey static const struct got_error *
1373 54415d85 2020-01-15 tracey gw_load_got_path(struct gw_trans *gw_trans, struct gw_dir *gw_dir)
1374 2c251c14 2020-01-15 tracey {
1375 2c251c14 2020-01-15 tracey const struct got_error *error = NULL;
1376 2c251c14 2020-01-15 tracey DIR *dt;
1377 2c251c14 2020-01-15 tracey char *dir_test;
1378 4ceb8155 2020-01-15 tracey int opened = 0;
1379 2c251c14 2020-01-15 tracey
1380 88d59c36 2020-01-29 stsp if (asprintf(&dir_test, "%s/%s/%s",
1381 2c251c14 2020-01-15 tracey gw_trans->gw_conf->got_repos_path, gw_dir->name,
1382 88d59c36 2020-01-29 stsp GOTWEB_GIT_DIR) == -1)
1383 2c251c14 2020-01-15 tracey return got_error_from_errno("asprintf");
1384 2c251c14 2020-01-15 tracey
1385 2c251c14 2020-01-15 tracey dt = opendir(dir_test);
1386 2c251c14 2020-01-15 tracey if (dt == NULL) {
1387 2c251c14 2020-01-15 tracey free(dir_test);
1388 2c251c14 2020-01-15 tracey } else {
1389 2c251c14 2020-01-15 tracey gw_dir->path = strdup(dir_test);
1390 4ceb8155 2020-01-15 tracey opened = 1;
1391 2c251c14 2020-01-15 tracey goto done;
1392 2c251c14 2020-01-15 tracey }
1393 2c251c14 2020-01-15 tracey
1394 88d59c36 2020-01-29 stsp if (asprintf(&dir_test, "%s/%s/%s",
1395 2c251c14 2020-01-15 tracey gw_trans->gw_conf->got_repos_path, gw_dir->name,
1396 88d59c36 2020-01-29 stsp GOTWEB_GOT_DIR) == -1)
1397 2c251c14 2020-01-15 tracey return got_error_from_errno("asprintf");
1398 2c251c14 2020-01-15 tracey
1399 2c251c14 2020-01-15 tracey dt = opendir(dir_test);
1400 2c251c14 2020-01-15 tracey if (dt == NULL)
1401 2c251c14 2020-01-15 tracey free(dir_test);
1402 2c251c14 2020-01-15 tracey else {
1403 4ceb8155 2020-01-15 tracey opened = 1;
1404 2c251c14 2020-01-15 tracey error = got_error(GOT_ERR_NOT_GIT_REPO);
1405 2c251c14 2020-01-15 tracey goto errored;
1406 2c251c14 2020-01-15 tracey }
1407 2c251c14 2020-01-15 tracey
1408 88d59c36 2020-01-29 stsp if (asprintf(&dir_test, "%s/%s",
1409 88d59c36 2020-01-29 stsp gw_trans->gw_conf->got_repos_path, gw_dir->name) == -1)
1410 2c251c14 2020-01-15 tracey return got_error_from_errno("asprintf");
1411 2c251c14 2020-01-15 tracey
1412 2c251c14 2020-01-15 tracey gw_dir->path = strdup(dir_test);
1413 2c251c14 2020-01-15 tracey done:
1414 32cd4d18 2020-02-03 stsp error = gw_get_repo_description(&gw_dir->description, gw_trans,
1415 2c251c14 2020-01-15 tracey gw_dir->path);
1416 32cd4d18 2020-02-03 stsp if (error)
1417 32cd4d18 2020-02-03 stsp goto errored;
1418 9a1cc63f 2020-02-03 stsp error = gw_get_repo_owner(&gw_dir->owner, gw_trans, gw_dir->path);
1419 9a1cc63f 2020-02-03 stsp if (error)
1420 9a1cc63f 2020-02-03 stsp goto errored;
1421 d126c1b7 2020-01-29 stsp error = gw_get_repo_age(&gw_dir->age, gw_trans, gw_dir->path,
1422 d126c1b7 2020-01-29 stsp "refs/heads", TM_DIFF);
1423 d126c1b7 2020-01-29 stsp if (error)
1424 d126c1b7 2020-01-29 stsp goto errored;
1425 59d3c40e 2020-02-03 stsp error = gw_get_clone_url(&gw_dir->url, gw_trans, gw_dir->path);
1426 2c251c14 2020-01-15 tracey errored:
1427 2c251c14 2020-01-15 tracey free(dir_test);
1428 2c251c14 2020-01-15 tracey if (opened)
1429 2c251c14 2020-01-15 tracey closedir(dt);
1430 2c251c14 2020-01-15 tracey return error;
1431 2c251c14 2020-01-15 tracey }
1432 2c251c14 2020-01-15 tracey
1433 2c251c14 2020-01-15 tracey static const struct got_error *
1434 54415d85 2020-01-15 tracey gw_load_got_paths(struct gw_trans *gw_trans)
1435 2c251c14 2020-01-15 tracey {
1436 2c251c14 2020-01-15 tracey const struct got_error *error = NULL;
1437 2c251c14 2020-01-15 tracey DIR *d;
1438 2c251c14 2020-01-15 tracey struct dirent **sd_dent;
1439 2c251c14 2020-01-15 tracey struct gw_dir *gw_dir;
1440 2c251c14 2020-01-15 tracey struct stat st;
1441 2c251c14 2020-01-15 tracey unsigned int d_cnt, d_i;
1442 2c251c14 2020-01-15 tracey
1443 2c251c14 2020-01-15 tracey d = opendir(gw_trans->gw_conf->got_repos_path);
1444 2c251c14 2020-01-15 tracey if (d == NULL) {
1445 2c251c14 2020-01-15 tracey error = got_error_from_errno2("opendir",
1446 2c251c14 2020-01-15 tracey gw_trans->gw_conf->got_repos_path);
1447 2c251c14 2020-01-15 tracey return error;
1448 2c251c14 2020-01-15 tracey }
1449 2c251c14 2020-01-15 tracey
1450 2c251c14 2020-01-15 tracey d_cnt = scandir(gw_trans->gw_conf->got_repos_path, &sd_dent, NULL,
1451 2c251c14 2020-01-15 tracey alphasort);
1452 2c251c14 2020-01-15 tracey if (d_cnt == -1) {
1453 2c251c14 2020-01-15 tracey error = got_error_from_errno2("scandir",
1454 2c251c14 2020-01-15 tracey gw_trans->gw_conf->got_repos_path);
1455 2c251c14 2020-01-15 tracey return error;
1456 2c251c14 2020-01-15 tracey }
1457 2c251c14 2020-01-15 tracey
1458 2c251c14 2020-01-15 tracey for (d_i = 0; d_i < d_cnt; d_i++) {
1459 2c251c14 2020-01-15 tracey if (gw_trans->gw_conf->got_max_repos > 0 &&
1460 2c251c14 2020-01-15 tracey (d_i - 2) == gw_trans->gw_conf->got_max_repos)
1461 2c251c14 2020-01-15 tracey break; /* account for parent and self */
1462 2c251c14 2020-01-15 tracey
1463 2c251c14 2020-01-15 tracey if (strcmp(sd_dent[d_i]->d_name, ".") == 0 ||
1464 2c251c14 2020-01-15 tracey strcmp(sd_dent[d_i]->d_name, "..") == 0)
1465 2c251c14 2020-01-15 tracey continue;
1466 2c251c14 2020-01-15 tracey
1467 2c251c14 2020-01-15 tracey if ((gw_dir = gw_init_gw_dir(sd_dent[d_i]->d_name)) == NULL)
1468 2c251c14 2020-01-15 tracey return got_error_from_errno("gw_dir malloc");
1469 2c251c14 2020-01-15 tracey
1470 2c251c14 2020-01-15 tracey error = gw_load_got_path(gw_trans, gw_dir);
1471 7bf16821 2020-02-07 stsp if (error && error->code == GOT_ERR_NOT_GIT_REPO) {
1472 7bf16821 2020-02-07 stsp error = NULL;
1473 2c251c14 2020-01-15 tracey continue;
1474 7bf16821 2020-02-07 stsp }
1475 2c251c14 2020-01-15 tracey else if (error)
1476 2c251c14 2020-01-15 tracey return error;
1477 2c251c14 2020-01-15 tracey
1478 2c251c14 2020-01-15 tracey if (lstat(gw_dir->path, &st) == 0 && S_ISDIR(st.st_mode) &&
1479 2c251c14 2020-01-15 tracey !got_path_dir_is_empty(gw_dir->path)) {
1480 2c251c14 2020-01-15 tracey TAILQ_INSERT_TAIL(&gw_trans->gw_dirs, gw_dir,
1481 2c251c14 2020-01-15 tracey entry);
1482 2c251c14 2020-01-15 tracey gw_trans->repos_total++;
1483 2c251c14 2020-01-15 tracey }
1484 2c251c14 2020-01-15 tracey }
1485 2c251c14 2020-01-15 tracey
1486 2c251c14 2020-01-15 tracey closedir(d);
1487 2c251c14 2020-01-15 tracey return error;
1488 2c251c14 2020-01-15 tracey }
1489 2c251c14 2020-01-15 tracey
1490 2c251c14 2020-01-15 tracey static const struct got_error *
1491 54415d85 2020-01-15 tracey gw_parse_querystring(struct gw_trans *gw_trans)
1492 2c251c14 2020-01-15 tracey {
1493 2c251c14 2020-01-15 tracey const struct got_error *error = NULL;
1494 2c251c14 2020-01-15 tracey struct kpair *p;
1495 2c251c14 2020-01-15 tracey struct gw_query_action *action = NULL;
1496 2c251c14 2020-01-15 tracey unsigned int i;
1497 2c251c14 2020-01-15 tracey
1498 2c251c14 2020-01-15 tracey if (gw_trans->gw_req->fieldnmap[0]) {
1499 2c251c14 2020-01-15 tracey error = got_error_from_errno("bad parse");
1500 2c251c14 2020-01-15 tracey return error;
1501 2c251c14 2020-01-15 tracey } else if ((p = gw_trans->gw_req->fieldmap[KEY_PATH])) {
1502 2c251c14 2020-01-15 tracey /* define gw_trans->repo_path */
1503 88d59c36 2020-01-29 stsp if (asprintf(&gw_trans->repo_name, "%s", p->parsed.s) == -1)
1504 2c251c14 2020-01-15 tracey return got_error_from_errno("asprintf");
1505 2c251c14 2020-01-15 tracey
1506 88d59c36 2020-01-29 stsp if (asprintf(&gw_trans->repo_path, "%s/%s",
1507 88d59c36 2020-01-29 stsp gw_trans->gw_conf->got_repos_path, p->parsed.s) == -1)
1508 2c251c14 2020-01-15 tracey return got_error_from_errno("asprintf");
1509 2c251c14 2020-01-15 tracey
1510 2c251c14 2020-01-15 tracey /* get action and set function */
1511 2c251c14 2020-01-15 tracey if ((p = gw_trans->gw_req->fieldmap[KEY_ACTION]))
1512 2c251c14 2020-01-15 tracey for (i = 0; i < nitems(gw_query_funcs); i++) {
1513 2c251c14 2020-01-15 tracey action = &gw_query_funcs[i];
1514 2c251c14 2020-01-15 tracey if (action->func_name == NULL)
1515 2c251c14 2020-01-15 tracey continue;
1516 077f6c5a 2020-01-15 tracey
1517 2c251c14 2020-01-15 tracey if (strcmp(action->func_name,
1518 2c251c14 2020-01-15 tracey p->parsed.s) == 0) {
1519 2c251c14 2020-01-15 tracey gw_trans->action = i;
1520 88d59c36 2020-01-29 stsp if (asprintf(&gw_trans->action_name,
1521 88d59c36 2020-01-29 stsp "%s", action->func_name) == -1)
1522 2c251c14 2020-01-15 tracey return
1523 b772de24 2020-01-15 tracey got_error_from_errno(
1524 2c251c14 2020-01-15 tracey "asprintf");
1525 2c251c14 2020-01-15 tracey
1526 2c251c14 2020-01-15 tracey break;
1527 2c251c14 2020-01-15 tracey }
1528 2c251c14 2020-01-15 tracey
1529 2c251c14 2020-01-15 tracey action = NULL;
1530 2c251c14 2020-01-15 tracey }
1531 ec46ccd7 2020-01-15 tracey
1532 ec46ccd7 2020-01-15 tracey if ((p = gw_trans->gw_req->fieldmap[KEY_COMMIT_ID]))
1533 88d59c36 2020-01-29 stsp if (asprintf(&gw_trans->commit, "%s",
1534 88d59c36 2020-01-29 stsp p->parsed.s) == -1)
1535 ec46ccd7 2020-01-15 tracey return got_error_from_errno("asprintf");
1536 2c251c14 2020-01-15 tracey
1537 2c251c14 2020-01-15 tracey if ((p = gw_trans->gw_req->fieldmap[KEY_FILE]))
1538 88d59c36 2020-01-29 stsp if (asprintf(&gw_trans->repo_file, "%s",
1539 88d59c36 2020-01-29 stsp p->parsed.s) == -1)
1540 8087c3c5 2020-01-15 tracey return got_error_from_errno("asprintf");
1541 8087c3c5 2020-01-15 tracey
1542 ec46ccd7 2020-01-15 tracey if ((p = gw_trans->gw_req->fieldmap[KEY_FOLDER]))
1543 88d59c36 2020-01-29 stsp if (asprintf(&gw_trans->repo_folder, "%s",
1544 88d59c36 2020-01-29 stsp p->parsed.s) == -1)
1545 ec46ccd7 2020-01-15 tracey return got_error_from_errno("asprintf");
1546 ec46ccd7 2020-01-15 tracey
1547 8087c3c5 2020-01-15 tracey if ((p = gw_trans->gw_req->fieldmap[KEY_HEADREF]))
1548 88d59c36 2020-01-29 stsp if (asprintf(&gw_trans->headref, "%s",
1549 88d59c36 2020-01-29 stsp p->parsed.s) == -1)
1550 2c251c14 2020-01-15 tracey return got_error_from_errno("asprintf");
1551 2c251c14 2020-01-15 tracey
1552 2c251c14 2020-01-15 tracey if (action == NULL) {
1553 2c251c14 2020-01-15 tracey error = got_error_from_errno("invalid action");
1554 2c251c14 2020-01-15 tracey return error;
1555 2c251c14 2020-01-15 tracey }
1556 46b9c89b 2020-01-15 tracey if ((gw_trans->gw_dir =
1557 46b9c89b 2020-01-15 tracey gw_init_gw_dir(gw_trans->repo_name)) == NULL)
1558 46b9c89b 2020-01-15 tracey return got_error_from_errno("gw_dir malloc");
1559 46b9c89b 2020-01-15 tracey
1560 46b9c89b 2020-01-15 tracey error = gw_load_got_path(gw_trans, gw_trans->gw_dir);
1561 46b9c89b 2020-01-15 tracey if (error)
1562 46b9c89b 2020-01-15 tracey return error;
1563 2c251c14 2020-01-15 tracey } else
1564 2c251c14 2020-01-15 tracey gw_trans->action = GW_INDEX;
1565 2c251c14 2020-01-15 tracey
1566 2c251c14 2020-01-15 tracey if ((p = gw_trans->gw_req->fieldmap[KEY_PAGE]))
1567 2c251c14 2020-01-15 tracey gw_trans->page = p->parsed.i;
1568 2c251c14 2020-01-15 tracey
1569 2c251c14 2020-01-15 tracey return error;
1570 2c251c14 2020-01-15 tracey }
1571 2c251c14 2020-01-15 tracey
1572 2c251c14 2020-01-15 tracey static struct gw_dir *
1573 2c251c14 2020-01-15 tracey gw_init_gw_dir(char *dir)
1574 2c251c14 2020-01-15 tracey {
1575 2c251c14 2020-01-15 tracey struct gw_dir *gw_dir;
1576 2c251c14 2020-01-15 tracey
1577 2c251c14 2020-01-15 tracey if ((gw_dir = malloc(sizeof(*gw_dir))) == NULL)
1578 2c251c14 2020-01-15 tracey return NULL;
1579 2c251c14 2020-01-15 tracey
1580 88d59c36 2020-01-29 stsp if (asprintf(&gw_dir->name, "%s", dir) == -1)
1581 2c251c14 2020-01-15 tracey return NULL;
1582 2c251c14 2020-01-15 tracey
1583 2c251c14 2020-01-15 tracey return gw_dir;
1584 474370cb 2020-01-15 tracey }
1585 474370cb 2020-01-15 tracey
1586 c25c2314 2020-01-28 stsp static const struct got_error *
1587 54415d85 2020-01-15 tracey gw_display_open(struct gw_trans *gw_trans, enum khttp code, enum kmime mime)
1588 2c251c14 2020-01-15 tracey {
1589 c25c2314 2020-01-28 stsp enum kcgi_err kerr;
1590 c25c2314 2020-01-28 stsp
1591 c25c2314 2020-01-28 stsp kerr = khttp_head(gw_trans->gw_req, kresps[KRESP_ALLOW], "GET");
1592 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
1593 2447adad 2020-02-06 stsp return gw_kcgi_error(kerr);
1594 c25c2314 2020-01-28 stsp kerr = khttp_head(gw_trans->gw_req, kresps[KRESP_STATUS], "%s",
1595 2c251c14 2020-01-15 tracey khttps[code]);
1596 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
1597 2447adad 2020-02-06 stsp return gw_kcgi_error(kerr);
1598 c25c2314 2020-01-28 stsp kerr = khttp_head(gw_trans->gw_req, kresps[KRESP_CONTENT_TYPE], "%s",
1599 2c251c14 2020-01-15 tracey kmimetypes[mime]);
1600 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
1601 2447adad 2020-02-06 stsp return gw_kcgi_error(kerr);
1602 017d6da3 2020-01-29 tracey kerr = khttp_head(gw_trans->gw_req, "X-Content-Type-Options",
1603 017d6da3 2020-01-29 tracey "nosniff");
1604 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
1605 2447adad 2020-02-06 stsp return gw_kcgi_error(kerr);
1606 c25c2314 2020-01-28 stsp kerr = khttp_head(gw_trans->gw_req, "X-Frame-Options", "DENY");
1607 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
1608 2447adad 2020-02-06 stsp return gw_kcgi_error(kerr);
1609 017d6da3 2020-01-29 tracey kerr = khttp_head(gw_trans->gw_req, "X-XSS-Protection",
1610 017d6da3 2020-01-29 tracey "1; mode=block");
1611 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
1612 2447adad 2020-02-06 stsp return gw_kcgi_error(kerr);
1613 c25c2314 2020-01-28 stsp
1614 017d6da3 2020-01-29 tracey if (gw_trans->mime == KMIME_APP_OCTET_STREAM) {
1615 017d6da3 2020-01-29 tracey kerr = khttp_head(gw_trans->gw_req,
1616 017d6da3 2020-01-29 tracey kresps[KRESP_CONTENT_DISPOSITION],
1617 017d6da3 2020-01-29 tracey "attachment; filename=%s", gw_trans->repo_file);
1618 017d6da3 2020-01-29 tracey if (kerr != KCGI_OK)
1619 2447adad 2020-02-06 stsp return gw_kcgi_error(kerr);
1620 017d6da3 2020-01-29 tracey }
1621 017d6da3 2020-01-29 tracey
1622 c25c2314 2020-01-28 stsp kerr = khttp_body(gw_trans->gw_req);
1623 2447adad 2020-02-06 stsp return gw_kcgi_error(kerr);
1624 2c251c14 2020-01-15 tracey }
1625 2c251c14 2020-01-15 tracey
1626 c25c2314 2020-01-28 stsp static const struct got_error *
1627 6d8d8a26 2020-01-29 stsp gw_display_index(struct gw_trans *gw_trans)
1628 2c251c14 2020-01-15 tracey {
1629 4bec7539 2020-01-29 stsp const struct got_error *error;
1630 c25c2314 2020-01-28 stsp enum kcgi_err kerr;
1631 c25c2314 2020-01-28 stsp
1632 4bec7539 2020-01-29 stsp error = gw_display_open(gw_trans, KHTTP_200, gw_trans->mime);
1633 4bec7539 2020-01-29 stsp if (error)
1634 4bec7539 2020-01-29 stsp return error;
1635 4bec7539 2020-01-29 stsp
1636 f7cc9480 2020-02-05 tracey kerr = khtml_open(gw_trans->gw_html_req, gw_trans->gw_req, 0);
1637 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
1638 2447adad 2020-02-06 stsp return gw_kcgi_error(kerr);
1639 2c251c14 2020-01-15 tracey
1640 017d6da3 2020-01-29 tracey if (gw_trans->action != GW_BLOB) {
1641 017d6da3 2020-01-29 tracey kerr = khttp_template(gw_trans->gw_req, gw_trans->gw_tmpl,
1642 017d6da3 2020-01-29 tracey gw_query_funcs[gw_trans->action].template);
1643 017d6da3 2020-01-29 tracey if (kerr != KCGI_OK) {
1644 017d6da3 2020-01-29 tracey khtml_close(gw_trans->gw_html_req);
1645 2447adad 2020-02-06 stsp return gw_kcgi_error(kerr);
1646 017d6da3 2020-01-29 tracey }
1647 7a9bfbff 2020-01-29 stsp }
1648 2c251c14 2020-01-15 tracey
1649 7a9bfbff 2020-01-29 stsp return gw_kcgi_error(khtml_close(gw_trans->gw_html_req));
1650 2c251c14 2020-01-15 tracey }
1651 2c251c14 2020-01-15 tracey
1652 6d8d8a26 2020-01-29 stsp static void
1653 6d8d8a26 2020-01-29 stsp gw_display_error(struct gw_trans *gw_trans, const struct got_error *err)
1654 6d8d8a26 2020-01-29 stsp {
1655 6d8d8a26 2020-01-29 stsp if (gw_display_open(gw_trans, KHTTP_200, gw_trans->mime) != NULL)
1656 6d8d8a26 2020-01-29 stsp return;
1657 6d8d8a26 2020-01-29 stsp
1658 6d8d8a26 2020-01-29 stsp if (khtml_open(gw_trans->gw_html_req, gw_trans->gw_req, 0) != KCGI_OK)
1659 6d8d8a26 2020-01-29 stsp return;
1660 33dc7bd2 2020-02-03 stsp khtml_puts(gw_trans->gw_html_req, err->msg);
1661 6d8d8a26 2020-01-29 stsp khtml_close(gw_trans->gw_html_req);
1662 6d8d8a26 2020-01-29 stsp }
1663 6d8d8a26 2020-01-29 stsp
1664 2c251c14 2020-01-15 tracey static int
1665 2c251c14 2020-01-15 tracey gw_template(size_t key, void *arg)
1666 2c251c14 2020-01-15 tracey {
1667 2c251c14 2020-01-15 tracey const struct got_error *error = NULL;
1668 bd275801 2020-02-03 tracey enum kcgi_err kerr;
1669 54415d85 2020-01-15 tracey struct gw_trans *gw_trans = arg;
1670 185ba3ba 2020-02-04 tracey char *gw_site_link, *img_src = NULL;
1671 2c251c14 2020-01-15 tracey
1672 2c251c14 2020-01-15 tracey switch (key) {
1673 2c251c14 2020-01-15 tracey case (TEMPL_HEAD):
1674 bd275801 2020-02-03 tracey kerr = khttp_puts(gw_trans->gw_req, head);
1675 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
1676 bd275801 2020-02-03 tracey return 0;
1677 2c251c14 2020-01-15 tracey break;
1678 2c251c14 2020-01-15 tracey case(TEMPL_HEADER):
1679 185ba3ba 2020-02-04 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1680 185ba3ba 2020-02-04 tracey KATTR_ID, "got_link", KATTR__MAX);
1681 185ba3ba 2020-02-04 tracey if (kerr != KCGI_OK)
1682 185ba3ba 2020-02-04 tracey return 0;
1683 185ba3ba 2020-02-04 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
1684 185ba3ba 2020-02-04 tracey KATTR_HREF, gw_trans->gw_conf->got_logo_url,
1685 185ba3ba 2020-02-04 tracey KATTR_TARGET, "_sotd", KATTR__MAX);
1686 185ba3ba 2020-02-04 tracey if (kerr != KCGI_OK)
1687 185ba3ba 2020-02-04 tracey return 0;
1688 185ba3ba 2020-02-04 tracey if (asprintf(&img_src, "/%s",
1689 185ba3ba 2020-02-04 tracey gw_trans->gw_conf->got_logo) == -1)
1690 185ba3ba 2020-02-04 tracey return 0;
1691 185ba3ba 2020-02-04 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_IMG,
1692 185ba3ba 2020-02-04 tracey KATTR_SRC, img_src, KATTR__MAX);
1693 185ba3ba 2020-02-04 tracey if (kerr != KCGI_OK) {
1694 185ba3ba 2020-02-04 tracey free(img_src);
1695 185ba3ba 2020-02-04 tracey return 0;
1696 bd275801 2020-02-03 tracey }
1697 185ba3ba 2020-02-04 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 3);
1698 185ba3ba 2020-02-04 tracey if (kerr != KCGI_OK) {
1699 185ba3ba 2020-02-04 tracey free(img_src);
1700 185ba3ba 2020-02-04 tracey return 0;
1701 185ba3ba 2020-02-04 tracey }
1702 2c251c14 2020-01-15 tracey break;
1703 2c251c14 2020-01-15 tracey case (TEMPL_SITEPATH):
1704 2c251c14 2020-01-15 tracey gw_site_link = gw_get_site_link(gw_trans);
1705 bd275801 2020-02-03 tracey if (gw_site_link != NULL) {
1706 bd275801 2020-02-03 tracey kerr = khttp_puts(gw_trans->gw_req, gw_site_link);
1707 bd275801 2020-02-03 tracey if (kerr != KCGI_OK) {
1708 bd275801 2020-02-03 tracey free(gw_site_link);
1709 bd275801 2020-02-03 tracey return 0;
1710 bd275801 2020-02-03 tracey }
1711 bd275801 2020-02-03 tracey }
1712 2c251c14 2020-01-15 tracey free(gw_site_link);
1713 2c251c14 2020-01-15 tracey break;
1714 2c251c14 2020-01-15 tracey case(TEMPL_TITLE):
1715 bd275801 2020-02-03 tracey if (gw_trans->gw_conf->got_site_name != NULL) {
1716 bd275801 2020-02-03 tracey kerr = khtml_puts(gw_trans->gw_html_req,
1717 2c251c14 2020-01-15 tracey gw_trans->gw_conf->got_site_name);
1718 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
1719 bd275801 2020-02-03 tracey return 0;
1720 bd275801 2020-02-03 tracey }
1721 2c251c14 2020-01-15 tracey break;
1722 2c251c14 2020-01-15 tracey case (TEMPL_SEARCH):
1723 bd275801 2020-02-03 tracey kerr = khttp_puts(gw_trans->gw_req, search);
1724 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
1725 bd275801 2020-02-03 tracey return 0;
1726 2c251c14 2020-01-15 tracey break;
1727 2c251c14 2020-01-15 tracey case(TEMPL_SITEOWNER):
1728 2c251c14 2020-01-15 tracey if (gw_trans->gw_conf->got_site_owner != NULL &&
1729 2c251c14 2020-01-15 tracey gw_trans->gw_conf->got_show_site_owner) {
1730 bd275801 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1731 bd275801 2020-02-03 tracey KATTR_ID, "site_owner_wrapper", KATTR__MAX);
1732 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
1733 070fee27 2020-02-03 stsp return 0;
1734 bd275801 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1735 bd275801 2020-02-03 tracey KATTR_ID, "site_owner", KATTR__MAX);
1736 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
1737 2c251c14 2020-01-15 tracey return 0;
1738 bd275801 2020-02-03 tracey kerr = khtml_puts(gw_trans->gw_html_req,
1739 bd275801 2020-02-03 tracey gw_trans->gw_conf->got_site_owner);
1740 bd275801 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
1741 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
1742 bd275801 2020-02-03 tracey return 0;
1743 2c251c14 2020-01-15 tracey }
1744 2c251c14 2020-01-15 tracey break;
1745 2c251c14 2020-01-15 tracey case(TEMPL_CONTENT):
1746 2c251c14 2020-01-15 tracey error = gw_query_funcs[gw_trans->action].func_main(gw_trans);
1747 bd275801 2020-02-03 tracey if (error) {
1748 bd275801 2020-02-03 tracey kerr = khttp_puts(gw_trans->gw_req, error->msg);
1749 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
1750 bd275801 2020-02-03 tracey return 0;
1751 bd275801 2020-02-03 tracey }
1752 2c251c14 2020-01-15 tracey break;
1753 2c251c14 2020-01-15 tracey default:
1754 2c251c14 2020-01-15 tracey return 0;
1755 2c251c14 2020-01-15 tracey }
1756 2c251c14 2020-01-15 tracey return 1;
1757 f2f46662 2020-01-23 tracey }
1758 21a55cc7 2020-02-04 tracey
1759 21a55cc7 2020-02-04 tracey static const struct got_error *
1760 21a55cc7 2020-02-04 tracey gw_gen_commit_header(struct gw_trans *gw_trans, char *str1, char *str2)
1761 21a55cc7 2020-02-04 tracey {
1762 21a55cc7 2020-02-04 tracey const struct got_error *error = NULL;
1763 21a55cc7 2020-02-04 tracey char *ref_str = NULL;
1764 21a55cc7 2020-02-04 tracey enum kcgi_err kerr = KCGI_OK;
1765 f2f46662 2020-01-23 tracey
1766 21a55cc7 2020-02-04 tracey if (strcmp(str2, "") != 0) {
1767 21a55cc7 2020-02-04 tracey if (asprintf(&ref_str, "(%s)", str2) == -1) {
1768 21a55cc7 2020-02-04 tracey error = got_error_from_errno("asprintf");
1769 21a55cc7 2020-02-04 tracey goto done;
1770 21a55cc7 2020-02-04 tracey }
1771 21a55cc7 2020-02-04 tracey } else
1772 21a55cc7 2020-02-04 tracey ref_str = strdup("");
1773 21a55cc7 2020-02-04 tracey
1774 21a55cc7 2020-02-04 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1775 21a55cc7 2020-02-04 tracey KATTR_ID, "header_commit_title", KATTR__MAX);
1776 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1777 21a55cc7 2020-02-04 tracey goto done;
1778 21a55cc7 2020-02-04 tracey kerr = khtml_puts(gw_trans->gw_html_req, "Commit: ");
1779 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1780 21a55cc7 2020-02-04 tracey goto done;
1781 21a55cc7 2020-02-04 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1782 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1783 21a55cc7 2020-02-04 tracey goto done;
1784 21a55cc7 2020-02-04 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1785 21a55cc7 2020-02-04 tracey KATTR_ID, "header_commit", KATTR__MAX);
1786 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1787 21a55cc7 2020-02-04 tracey goto done;
1788 21a55cc7 2020-02-04 tracey kerr = khtml_puts(gw_trans->gw_html_req, str1);
1789 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1790 21a55cc7 2020-02-04 tracey goto done;
1791 21a55cc7 2020-02-04 tracey kerr = khtml_puts(gw_trans->gw_html_req, " ");
1792 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1793 21a55cc7 2020-02-04 tracey goto done;
1794 21a55cc7 2020-02-04 tracey kerr = khtml_puts(gw_trans->gw_html_req, ref_str);
1795 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1796 21a55cc7 2020-02-04 tracey goto done;
1797 21a55cc7 2020-02-04 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1798 21a55cc7 2020-02-04 tracey done:
1799 21a55cc7 2020-02-04 tracey if (error == NULL && kerr != KCGI_OK)
1800 2447adad 2020-02-06 stsp error = gw_kcgi_error(kerr);
1801 21a55cc7 2020-02-04 tracey return error;
1802 21a55cc7 2020-02-04 tracey }
1803 21a55cc7 2020-02-04 tracey
1804 f7cc9480 2020-02-05 tracey static const struct got_error *
1805 f7cc9480 2020-02-05 tracey gw_gen_diff_header(struct gw_trans *gw_trans, char *str1, char *str2)
1806 f2f46662 2020-01-23 tracey {
1807 27192be7 2020-02-04 tracey const struct got_error *error = NULL;
1808 f7cc9480 2020-02-05 tracey enum kcgi_err kerr = KCGI_OK;
1809 f2f46662 2020-01-23 tracey
1810 f7cc9480 2020-02-05 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1811 f7cc9480 2020-02-05 tracey KATTR_ID, "header_diff_title", KATTR__MAX);
1812 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
1813 f7cc9480 2020-02-05 tracey goto done;
1814 f7cc9480 2020-02-05 tracey kerr = khtml_puts(gw_trans->gw_html_req, "Diff: ");
1815 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
1816 f7cc9480 2020-02-05 tracey goto done;
1817 f7cc9480 2020-02-05 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1818 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
1819 f7cc9480 2020-02-05 tracey goto done;
1820 f7cc9480 2020-02-05 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1821 f7cc9480 2020-02-05 tracey KATTR_ID, "header_diff", KATTR__MAX);
1822 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
1823 f7cc9480 2020-02-05 tracey goto done;
1824 f7cc9480 2020-02-05 tracey kerr = khtml_puts(gw_trans->gw_html_req, str1);
1825 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
1826 f7cc9480 2020-02-05 tracey goto done;
1827 f7cc9480 2020-02-05 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_BR, KATTR__MAX);
1828 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
1829 f7cc9480 2020-02-05 tracey goto done;
1830 f7cc9480 2020-02-05 tracey kerr = khtml_puts(gw_trans->gw_html_req, str2);
1831 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
1832 f7cc9480 2020-02-05 tracey goto done;
1833 f7cc9480 2020-02-05 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1834 f7cc9480 2020-02-05 tracey done:
1835 f7cc9480 2020-02-05 tracey if (error == NULL && kerr != KCGI_OK)
1836 2447adad 2020-02-06 stsp error = gw_kcgi_error(kerr);
1837 f7cc9480 2020-02-05 tracey return error;
1838 21a55cc7 2020-02-04 tracey }
1839 21a55cc7 2020-02-04 tracey
1840 21a55cc7 2020-02-04 tracey static const struct got_error *
1841 21a55cc7 2020-02-04 tracey gw_gen_age_header(struct gw_trans *gw_trans, const char *str)
1842 21a55cc7 2020-02-04 tracey {
1843 21a55cc7 2020-02-04 tracey const struct got_error *error = NULL;
1844 21a55cc7 2020-02-04 tracey enum kcgi_err kerr = KCGI_OK;
1845 21a55cc7 2020-02-04 tracey
1846 21a55cc7 2020-02-04 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1847 21a55cc7 2020-02-04 tracey KATTR_ID, "header_age_title", KATTR__MAX);
1848 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1849 21a55cc7 2020-02-04 tracey goto done;
1850 21a55cc7 2020-02-04 tracey kerr = khtml_puts(gw_trans->gw_html_req, "Date: ");
1851 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1852 21a55cc7 2020-02-04 tracey goto done;
1853 21a55cc7 2020-02-04 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1854 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1855 21a55cc7 2020-02-04 tracey goto done;
1856 21a55cc7 2020-02-04 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1857 21a55cc7 2020-02-04 tracey KATTR_ID, "header_age", KATTR__MAX);
1858 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1859 21a55cc7 2020-02-04 tracey goto done;
1860 21a55cc7 2020-02-04 tracey kerr = khtml_puts(gw_trans->gw_html_req, str);
1861 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1862 21a55cc7 2020-02-04 tracey goto done;
1863 21a55cc7 2020-02-04 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1864 21a55cc7 2020-02-04 tracey done:
1865 21a55cc7 2020-02-04 tracey if (error == NULL && kerr != KCGI_OK)
1866 2447adad 2020-02-06 stsp error = gw_kcgi_error(kerr);
1867 21a55cc7 2020-02-04 tracey return error;
1868 21a55cc7 2020-02-04 tracey }
1869 21a55cc7 2020-02-04 tracey
1870 21a55cc7 2020-02-04 tracey static const struct got_error *
1871 21a55cc7 2020-02-04 tracey gw_gen_author_header(struct gw_trans *gw_trans, const char *str)
1872 21a55cc7 2020-02-04 tracey {
1873 21a55cc7 2020-02-04 tracey const struct got_error *error = NULL;
1874 21a55cc7 2020-02-04 tracey enum kcgi_err kerr;
1875 21a55cc7 2020-02-04 tracey
1876 21a55cc7 2020-02-04 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1877 21a55cc7 2020-02-04 tracey KATTR_ID, "header_author_title", KATTR__MAX);
1878 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1879 21a55cc7 2020-02-04 tracey goto done;
1880 21a55cc7 2020-02-04 tracey kerr = khtml_puts(gw_trans->gw_html_req, "Author: ");
1881 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1882 21a55cc7 2020-02-04 tracey goto done;
1883 21a55cc7 2020-02-04 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1884 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1885 21a55cc7 2020-02-04 tracey goto done;
1886 21a55cc7 2020-02-04 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1887 21a55cc7 2020-02-04 tracey KATTR_ID, "header_author", KATTR__MAX);
1888 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1889 21a55cc7 2020-02-04 tracey goto done;
1890 21a55cc7 2020-02-04 tracey kerr = khtml_puts(gw_trans->gw_html_req, str);
1891 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1892 21a55cc7 2020-02-04 tracey goto done;
1893 21a55cc7 2020-02-04 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1894 21a55cc7 2020-02-04 tracey done:
1895 21a55cc7 2020-02-04 tracey if (error == NULL && kerr != KCGI_OK)
1896 2447adad 2020-02-06 stsp error = gw_kcgi_error(kerr);
1897 21a55cc7 2020-02-04 tracey return error;
1898 f2f46662 2020-01-23 tracey }
1899 f2f46662 2020-01-23 tracey
1900 21a55cc7 2020-02-04 tracey static const struct got_error *
1901 21a55cc7 2020-02-04 tracey gw_gen_committer_header(struct gw_trans *gw_trans, const char *str)
1902 21a55cc7 2020-02-04 tracey {
1903 21a55cc7 2020-02-04 tracey const struct got_error *error = NULL;
1904 21a55cc7 2020-02-04 tracey enum kcgi_err kerr;
1905 21a55cc7 2020-02-04 tracey
1906 21a55cc7 2020-02-04 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1907 21a55cc7 2020-02-04 tracey KATTR_ID, "header_committer_title", KATTR__MAX);
1908 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1909 21a55cc7 2020-02-04 tracey goto done;
1910 87ca24ac 2020-02-04 tracey kerr = khtml_puts(gw_trans->gw_html_req, "Committer: ");
1911 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1912 21a55cc7 2020-02-04 tracey goto done;
1913 21a55cc7 2020-02-04 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1914 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1915 21a55cc7 2020-02-04 tracey goto done;
1916 21a55cc7 2020-02-04 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1917 21a55cc7 2020-02-04 tracey KATTR_ID, "header_committer", KATTR__MAX);
1918 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1919 21a55cc7 2020-02-04 tracey goto done;
1920 21a55cc7 2020-02-04 tracey kerr = khtml_puts(gw_trans->gw_html_req, str);
1921 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1922 21a55cc7 2020-02-04 tracey goto done;
1923 21a55cc7 2020-02-04 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1924 21a55cc7 2020-02-04 tracey done:
1925 21a55cc7 2020-02-04 tracey if (error == NULL && kerr != KCGI_OK)
1926 2447adad 2020-02-06 stsp error = gw_kcgi_error(kerr);
1927 21a55cc7 2020-02-04 tracey return error;
1928 21a55cc7 2020-02-04 tracey }
1929 21a55cc7 2020-02-04 tracey
1930 f7cc9480 2020-02-05 tracey static const struct got_error *
1931 f7cc9480 2020-02-05 tracey gw_gen_commit_msg_header(struct gw_trans *gw_trans, char *str)
1932 f2f46662 2020-01-23 tracey {
1933 27192be7 2020-02-04 tracey const struct got_error *error = NULL;
1934 f7cc9480 2020-02-05 tracey enum kcgi_err kerr;
1935 f2f46662 2020-01-23 tracey
1936 f7cc9480 2020-02-05 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1937 f7cc9480 2020-02-05 tracey KATTR_ID, "header_commit_msg_title", KATTR__MAX);
1938 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
1939 f7cc9480 2020-02-05 tracey goto done;
1940 f7cc9480 2020-02-05 tracey kerr = khtml_puts(gw_trans->gw_html_req, "Message: ");
1941 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
1942 f7cc9480 2020-02-05 tracey goto done;
1943 f7cc9480 2020-02-05 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1944 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
1945 f7cc9480 2020-02-05 tracey goto done;
1946 f7cc9480 2020-02-05 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1947 f7cc9480 2020-02-05 tracey KATTR_ID, "header_commit_msg", KATTR__MAX);
1948 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
1949 f7cc9480 2020-02-05 tracey goto done;
1950 f7cc9480 2020-02-05 tracey kerr = khttp_puts(gw_trans->gw_req, str);
1951 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
1952 f7cc9480 2020-02-05 tracey goto done;
1953 f7cc9480 2020-02-05 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1954 f7cc9480 2020-02-05 tracey done:
1955 f7cc9480 2020-02-05 tracey if (error == NULL && kerr != KCGI_OK)
1956 2447adad 2020-02-06 stsp error = gw_kcgi_error(kerr);
1957 f7cc9480 2020-02-05 tracey return error;
1958 f2f46662 2020-01-23 tracey }
1959 f2f46662 2020-01-23 tracey
1960 f7cc9480 2020-02-05 tracey static const struct got_error *
1961 f7cc9480 2020-02-05 tracey gw_gen_tree_header(struct gw_trans *gw_trans, char *str)
1962 f2f46662 2020-01-23 tracey {
1963 f7cc9480 2020-02-05 tracey const struct got_error *error = NULL;
1964 f7cc9480 2020-02-05 tracey enum kcgi_err kerr;
1965 f2f46662 2020-01-23 tracey
1966 f7cc9480 2020-02-05 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1967 f7cc9480 2020-02-05 tracey KATTR_ID, "header_tree_title", KATTR__MAX);
1968 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
1969 f7cc9480 2020-02-05 tracey goto done;
1970 f7cc9480 2020-02-05 tracey kerr = khtml_puts(gw_trans->gw_html_req, "Tree: ");
1971 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
1972 f7cc9480 2020-02-05 tracey goto done;
1973 f7cc9480 2020-02-05 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1974 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
1975 f7cc9480 2020-02-05 tracey goto done;
1976 f7cc9480 2020-02-05 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1977 f7cc9480 2020-02-05 tracey KATTR_ID, "header_tree", KATTR__MAX);
1978 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
1979 f7cc9480 2020-02-05 tracey goto done;
1980 f7cc9480 2020-02-05 tracey kerr = khtml_puts(gw_trans->gw_html_req, str);
1981 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
1982 f7cc9480 2020-02-05 tracey goto done;
1983 f7cc9480 2020-02-05 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1984 f7cc9480 2020-02-05 tracey done:
1985 f7cc9480 2020-02-05 tracey if (error == NULL && kerr != KCGI_OK)
1986 2447adad 2020-02-06 stsp error = gw_kcgi_error(kerr);
1987 f7cc9480 2020-02-05 tracey return error;
1988 f2f46662 2020-01-23 tracey }
1989 f2f46662 2020-01-23 tracey
1990 32cd4d18 2020-02-03 stsp static const struct got_error *
1991 32cd4d18 2020-02-03 stsp gw_get_repo_description(char **description, struct gw_trans *gw_trans,
1992 32cd4d18 2020-02-03 stsp char *dir)
1993 2c251c14 2020-01-15 tracey {
1994 32cd4d18 2020-02-03 stsp const struct got_error *error = NULL;
1995 b8b04565 2020-02-02 tracey FILE *f = NULL;
1996 32cd4d18 2020-02-03 stsp char *d_file = NULL;
1997 2c251c14 2020-01-15 tracey unsigned int len;
1998 1ab830c1 2020-02-03 stsp size_t n;
1999 2c251c14 2020-01-15 tracey
2000 32cd4d18 2020-02-03 stsp *description = NULL;
2001 0b20762b 2020-01-29 stsp if (gw_trans->gw_conf->got_show_repo_description == 0)
2002 32cd4d18 2020-02-03 stsp return gw_empty_string(description);
2003 2c251c14 2020-01-15 tracey
2004 88d59c36 2020-01-29 stsp if (asprintf(&d_file, "%s/description", dir) == -1)
2005 32cd4d18 2020-02-03 stsp return got_error_from_errno("asprintf");
2006 2c251c14 2020-01-15 tracey
2007 32cd4d18 2020-02-03 stsp f = fopen(d_file, "r");
2008 32cd4d18 2020-02-03 stsp if (f == NULL) {
2009 32cd4d18 2020-02-03 stsp if (errno == ENOENT || errno == EACCES)
2010 32cd4d18 2020-02-03 stsp return gw_empty_string(description);
2011 32cd4d18 2020-02-03 stsp error = got_error_from_errno2("fopen", d_file);
2012 32cd4d18 2020-02-03 stsp goto done;
2013 32cd4d18 2020-02-03 stsp }
2014 2c251c14 2020-01-15 tracey
2015 32cd4d18 2020-02-03 stsp if (fseek(f, 0, SEEK_END) == -1) {
2016 32cd4d18 2020-02-03 stsp error = got_ferror(f, GOT_ERR_IO);
2017 32cd4d18 2020-02-03 stsp goto done;
2018 32cd4d18 2020-02-03 stsp }
2019 32cd4d18 2020-02-03 stsp len = ftell(f);
2020 32cd4d18 2020-02-03 stsp if (len == -1) {
2021 32cd4d18 2020-02-03 stsp error = got_ferror(f, GOT_ERR_IO);
2022 32cd4d18 2020-02-03 stsp goto done;
2023 32cd4d18 2020-02-03 stsp }
2024 32cd4d18 2020-02-03 stsp if (fseek(f, 0, SEEK_SET) == -1) {
2025 32cd4d18 2020-02-03 stsp error = got_ferror(f, GOT_ERR_IO);
2026 32cd4d18 2020-02-03 stsp goto done;
2027 32cd4d18 2020-02-03 stsp }
2028 32cd4d18 2020-02-03 stsp *description = calloc(len + 1, sizeof(**description));
2029 32cd4d18 2020-02-03 stsp if (*description == NULL) {
2030 32cd4d18 2020-02-03 stsp error = got_error_from_errno("calloc");
2031 32cd4d18 2020-02-03 stsp goto done;
2032 32cd4d18 2020-02-03 stsp }
2033 32cd4d18 2020-02-03 stsp
2034 32cd4d18 2020-02-03 stsp n = fread(*description, 1, len, f);
2035 1ab830c1 2020-02-03 stsp if (n == 0 && ferror(f))
2036 32cd4d18 2020-02-03 stsp error = got_ferror(f, GOT_ERR_IO);
2037 32cd4d18 2020-02-03 stsp done:
2038 32cd4d18 2020-02-03 stsp if (f != NULL && fclose(f) == -1 && error == NULL)
2039 32cd4d18 2020-02-03 stsp error = got_error_from_errno("fclose");
2040 2c251c14 2020-01-15 tracey free(d_file);
2041 32cd4d18 2020-02-03 stsp return error;
2042 2c251c14 2020-01-15 tracey }
2043 2c251c14 2020-01-15 tracey
2044 55ccf528 2020-02-03 stsp static const struct got_error *
2045 55ccf528 2020-02-03 stsp gw_get_time_str(char **repo_age, time_t committer_time, int ref_tm)
2046 474370cb 2020-01-15 tracey {
2047 474370cb 2020-01-15 tracey struct tm tm;
2048 474370cb 2020-01-15 tracey time_t diff_time;
2049 474370cb 2020-01-15 tracey char *years = "years ago", *months = "months ago";
2050 474370cb 2020-01-15 tracey char *weeks = "weeks ago", *days = "days ago", *hours = "hours ago";
2051 474370cb 2020-01-15 tracey char *minutes = "minutes ago", *seconds = "seconds ago";
2052 474370cb 2020-01-15 tracey char *now = "right now";
2053 55ccf528 2020-02-03 stsp char *s;
2054 6c6c85af 2020-01-15 tracey char datebuf[29];
2055 474370cb 2020-01-15 tracey
2056 55ccf528 2020-02-03 stsp *repo_age = NULL;
2057 55ccf528 2020-02-03 stsp
2058 474370cb 2020-01-15 tracey switch (ref_tm) {
2059 474370cb 2020-01-15 tracey case TM_DIFF:
2060 474370cb 2020-01-15 tracey diff_time = time(NULL) - committer_time;
2061 474370cb 2020-01-15 tracey if (diff_time > 60 * 60 * 24 * 365 * 2) {
2062 55ccf528 2020-02-03 stsp if (asprintf(repo_age, "%lld %s",
2063 88d59c36 2020-01-29 stsp (diff_time / 60 / 60 / 24 / 365), years) == -1)
2064 55ccf528 2020-02-03 stsp return got_error_from_errno("asprintf");
2065 474370cb 2020-01-15 tracey } else if (diff_time > 60 * 60 * 24 * (365 / 12) * 2) {
2066 55ccf528 2020-02-03 stsp if (asprintf(repo_age, "%lld %s",
2067 474370cb 2020-01-15 tracey (diff_time / 60 / 60 / 24 / (365 / 12)),
2068 88d59c36 2020-01-29 stsp months) == -1)
2069 55ccf528 2020-02-03 stsp return got_error_from_errno("asprintf");
2070 474370cb 2020-01-15 tracey } else if (diff_time > 60 * 60 * 24 * 7 * 2) {
2071 55ccf528 2020-02-03 stsp if (asprintf(repo_age, "%lld %s",
2072 88d59c36 2020-01-29 stsp (diff_time / 60 / 60 / 24 / 7), weeks) == -1)
2073 55ccf528 2020-02-03 stsp return got_error_from_errno("asprintf");
2074 474370cb 2020-01-15 tracey } else if (diff_time > 60 * 60 * 24 * 2) {
2075 55ccf528 2020-02-03 stsp if (asprintf(repo_age, "%lld %s",
2076 88d59c36 2020-01-29 stsp (diff_time / 60 / 60 / 24), days) == -1)
2077 55ccf528 2020-02-03 stsp return got_error_from_errno("asprintf");
2078 474370cb 2020-01-15 tracey } else if (diff_time > 60 * 60 * 2) {
2079 55ccf528 2020-02-03 stsp if (asprintf(repo_age, "%lld %s",
2080 88d59c36 2020-01-29 stsp (diff_time / 60 / 60), hours) == -1)
2081 55ccf528 2020-02-03 stsp return got_error_from_errno("asprintf");
2082 474370cb 2020-01-15 tracey } else if (diff_time > 60 * 2) {
2083 55ccf528 2020-02-03 stsp if (asprintf(repo_age, "%lld %s", (diff_time / 60),
2084 88d59c36 2020-01-29 stsp minutes) == -1)
2085 55ccf528 2020-02-03 stsp return got_error_from_errno("asprintf");
2086 474370cb 2020-01-15 tracey } else if (diff_time > 2) {
2087 55ccf528 2020-02-03 stsp if (asprintf(repo_age, "%lld %s", diff_time,
2088 88d59c36 2020-01-29 stsp seconds) == -1)
2089 55ccf528 2020-02-03 stsp return got_error_from_errno("asprintf");
2090 474370cb 2020-01-15 tracey } else {
2091 55ccf528 2020-02-03 stsp if (asprintf(repo_age, "%s", now) == -1)
2092 55ccf528 2020-02-03 stsp return got_error_from_errno("asprintf");
2093 474370cb 2020-01-15 tracey }
2094 474370cb 2020-01-15 tracey break;
2095 474370cb 2020-01-15 tracey case TM_LONG:
2096 474370cb 2020-01-15 tracey if (gmtime_r(&committer_time, &tm) == NULL)
2097 55ccf528 2020-02-03 stsp return got_error_from_errno("gmtime_r");
2098 474370cb 2020-01-15 tracey
2099 474370cb 2020-01-15 tracey s = asctime_r(&tm, datebuf);
2100 474370cb 2020-01-15 tracey if (s == NULL)
2101 55ccf528 2020-02-03 stsp return got_error_from_errno("asctime_r");
2102 474370cb 2020-01-15 tracey
2103 55ccf528 2020-02-03 stsp if (asprintf(repo_age, "%s UTC", datebuf) == -1)
2104 55ccf528 2020-02-03 stsp return got_error_from_errno("asprintf");
2105 474370cb 2020-01-15 tracey break;
2106 474370cb 2020-01-15 tracey }
2107 55ccf528 2020-02-03 stsp return NULL;
2108 474370cb 2020-01-15 tracey }
2109 474370cb 2020-01-15 tracey
2110 d126c1b7 2020-01-29 stsp static const struct got_error *
2111 d126c1b7 2020-01-29 stsp gw_get_repo_age(char **repo_age, struct gw_trans *gw_trans, char *dir,
2112 d126c1b7 2020-01-29 stsp char *repo_ref, int ref_tm)
2113 2c251c14 2020-01-15 tracey {
2114 2c251c14 2020-01-15 tracey const struct got_error *error = NULL;
2115 2c251c14 2020-01-15 tracey struct got_object_id *id = NULL;
2116 2c251c14 2020-01-15 tracey struct got_repository *repo = NULL;
2117 2c251c14 2020-01-15 tracey struct got_commit_object *commit = NULL;
2118 2c251c14 2020-01-15 tracey struct got_reflist_head refs;
2119 2c251c14 2020-01-15 tracey struct got_reflist_entry *re;
2120 2c251c14 2020-01-15 tracey struct got_reference *head_ref;
2121 87f9ebf5 2020-01-15 tracey int is_head = 0;
2122 474370cb 2020-01-15 tracey time_t committer_time = 0, cmp_time = 0;
2123 87f9ebf5 2020-01-15 tracey const char *refname;
2124 a0f36e03 2020-01-28 stsp
2125 d126c1b7 2020-01-29 stsp *repo_age = NULL;
2126 a0f36e03 2020-01-28 stsp SIMPLEQ_INIT(&refs);
2127 387a29ba 2020-01-15 tracey
2128 387a29ba 2020-01-15 tracey if (repo_ref == NULL)
2129 387a29ba 2020-01-15 tracey return NULL;
2130 87f9ebf5 2020-01-15 tracey
2131 87f9ebf5 2020-01-15 tracey if (strncmp(repo_ref, "refs/heads/", 11) == 0)
2132 87f9ebf5 2020-01-15 tracey is_head = 1;
2133 2c251c14 2020-01-15 tracey
2134 55ccf528 2020-02-03 stsp if (gw_trans->gw_conf->got_show_repo_age == 0)
2135 d126c1b7 2020-01-29 stsp return NULL;
2136 87f9ebf5 2020-01-15 tracey
2137 2c251c14 2020-01-15 tracey error = got_repo_open(&repo, dir, NULL);
2138 ec46ccd7 2020-01-15 tracey if (error)
2139 d126c1b7 2020-01-29 stsp goto done;
2140 2c251c14 2020-01-15 tracey
2141 87f9ebf5 2020-01-15 tracey if (is_head)
2142 87f9ebf5 2020-01-15 tracey error = got_ref_list(&refs, repo, "refs/heads",
2143 87f9ebf5 2020-01-15 tracey got_ref_cmp_by_name, NULL);
2144 87f9ebf5 2020-01-15 tracey else
2145 87f9ebf5 2020-01-15 tracey error = got_ref_list(&refs, repo, repo_ref,
2146 87f9ebf5 2020-01-15 tracey got_ref_cmp_by_name, NULL);
2147 ec46ccd7 2020-01-15 tracey if (error)
2148 d126c1b7 2020-01-29 stsp goto done;
2149 2c251c14 2020-01-15 tracey
2150 2c251c14 2020-01-15 tracey SIMPLEQ_FOREACH(re, &refs, entry) {
2151 87f9ebf5 2020-01-15 tracey if (is_head)
2152 87f9ebf5 2020-01-15 tracey refname = strdup(repo_ref);
2153 87f9ebf5 2020-01-15 tracey else
2154 87f9ebf5 2020-01-15 tracey refname = got_ref_get_name(re->ref);
2155 2c251c14 2020-01-15 tracey error = got_ref_open(&head_ref, repo, refname, 0);
2156 ec46ccd7 2020-01-15 tracey if (error)
2157 d126c1b7 2020-01-29 stsp goto done;
2158 2c251c14 2020-01-15 tracey
2159 2c251c14 2020-01-15 tracey error = got_ref_resolve(&id, repo, head_ref);
2160 2c251c14 2020-01-15 tracey got_ref_close(head_ref);
2161 ec46ccd7 2020-01-15 tracey if (error)
2162 d126c1b7 2020-01-29 stsp goto done;
2163 2c251c14 2020-01-15 tracey
2164 2c251c14 2020-01-15 tracey error = got_object_open_as_commit(&commit, repo, id);
2165 ec46ccd7 2020-01-15 tracey if (error)
2166 d126c1b7 2020-01-29 stsp goto done;
2167 2c251c14 2020-01-15 tracey
2168 2c251c14 2020-01-15 tracey committer_time =
2169 2c251c14 2020-01-15 tracey got_object_commit_get_committer_time(commit);
2170 2c251c14 2020-01-15 tracey
2171 387a29ba 2020-01-15 tracey if (cmp_time < committer_time)
2172 2c251c14 2020-01-15 tracey cmp_time = committer_time;
2173 2c251c14 2020-01-15 tracey }
2174 2c251c14 2020-01-15 tracey
2175 474370cb 2020-01-15 tracey if (cmp_time != 0) {
2176 2c251c14 2020-01-15 tracey committer_time = cmp_time;
2177 55ccf528 2020-02-03 stsp error = gw_get_time_str(repo_age, committer_time, ref_tm);
2178 d126c1b7 2020-01-29 stsp }
2179 d126c1b7 2020-01-29 stsp done:
2180 2c251c14 2020-01-15 tracey got_ref_list_free(&refs);
2181 2c251c14 2020-01-15 tracey free(id);
2182 d126c1b7 2020-01-29 stsp return error;
2183 ec46ccd7 2020-01-15 tracey }
2184 ec46ccd7 2020-01-15 tracey
2185 83eb9a68 2020-02-03 stsp static const struct got_error *
2186 38b240fb 2020-02-06 tracey gw_output_diff(struct gw_trans *gw_trans, struct gw_header *header)
2187 ec46ccd7 2020-01-15 tracey {
2188 ec46ccd7 2020-01-15 tracey const struct got_error *error;
2189 ec46ccd7 2020-01-15 tracey FILE *f = NULL;
2190 ec46ccd7 2020-01-15 tracey struct got_object_id *id1 = NULL, *id2 = NULL;
2191 f7cc9480 2020-02-05 tracey char *label1 = NULL, *label2 = NULL, *line = NULL;
2192 05ce9a79 2020-01-24 tracey int obj_type;
2193 f7cc9480 2020-02-05 tracey size_t linesize = 0;
2194 83eb9a68 2020-02-03 stsp ssize_t linelen;
2195 f7cc9480 2020-02-05 tracey enum kcgi_err kerr = KCGI_OK;
2196 ec46ccd7 2020-01-15 tracey
2197 ec46ccd7 2020-01-15 tracey f = got_opentemp();
2198 ec46ccd7 2020-01-15 tracey if (f == NULL)
2199 ec46ccd7 2020-01-15 tracey return NULL;
2200 ec46ccd7 2020-01-15 tracey
2201 90f16cb8 2020-01-24 tracey error = got_repo_open(&header->repo, gw_trans->repo_path, NULL);
2202 ec46ccd7 2020-01-15 tracey if (error)
2203 ec46ccd7 2020-01-15 tracey goto done;
2204 ec46ccd7 2020-01-15 tracey
2205 05ce9a79 2020-01-24 tracey if (strncmp(header->parent_id, "/dev/null", 9) != 0) {
2206 05ce9a79 2020-01-24 tracey error = got_repo_match_object_id(&id1, &label1,
2207 05ce9a79 2020-01-24 tracey header->parent_id, GOT_OBJ_TYPE_ANY, 1, header->repo);
2208 05ce9a79 2020-01-24 tracey if (error)
2209 05ce9a79 2020-01-24 tracey goto done;
2210 05ce9a79 2020-01-24 tracey }
2211 ec46ccd7 2020-01-15 tracey
2212 90f16cb8 2020-01-24 tracey error = got_repo_match_object_id(&id2, &label2,
2213 2ac037ec 2020-01-24 tracey header->commit_id, GOT_OBJ_TYPE_ANY, 1, header->repo);
2214 90f16cb8 2020-01-24 tracey if (error)
2215 90f16cb8 2020-01-24 tracey goto done;
2216 ec46ccd7 2020-01-15 tracey
2217 05ce9a79 2020-01-24 tracey error = got_object_get_type(&obj_type, header->repo, id2);
2218 90f16cb8 2020-01-24 tracey if (error)
2219 90f16cb8 2020-01-24 tracey goto done;
2220 05ce9a79 2020-01-24 tracey switch (obj_type) {
2221 ec46ccd7 2020-01-15 tracey case GOT_OBJ_TYPE_BLOB:
2222 90f16cb8 2020-01-24 tracey error = got_diff_objects_as_blobs(id1, id2, NULL, NULL, 3, 0,
2223 90f16cb8 2020-01-24 tracey header->repo, f);
2224 ec46ccd7 2020-01-15 tracey break;
2225 ec46ccd7 2020-01-15 tracey case GOT_OBJ_TYPE_TREE:
2226 90f16cb8 2020-01-24 tracey error = got_diff_objects_as_trees(id1, id2, "", "", 3, 0,
2227 90f16cb8 2020-01-24 tracey header->repo, f);
2228 ec46ccd7 2020-01-15 tracey break;
2229 ec46ccd7 2020-01-15 tracey case GOT_OBJ_TYPE_COMMIT:
2230 90f16cb8 2020-01-24 tracey error = got_diff_objects_as_commits(id1, id2, 3, 0,
2231 90f16cb8 2020-01-24 tracey header->repo, f);
2232 ec46ccd7 2020-01-15 tracey break;
2233 ec46ccd7 2020-01-15 tracey default:
2234 ec46ccd7 2020-01-15 tracey error = got_error(GOT_ERR_OBJ_TYPE);
2235 ec46ccd7 2020-01-15 tracey }
2236 b8b04565 2020-02-02 tracey if (error)
2237 b8b04565 2020-02-02 tracey goto done;
2238 b8b04565 2020-02-02 tracey
2239 d4729381 2020-02-03 stsp if (fseek(f, 0, SEEK_SET) == -1) {
2240 d4729381 2020-02-03 stsp error = got_ferror(f, GOT_ERR_IO);
2241 ec46ccd7 2020-01-15 tracey goto done;
2242 d4729381 2020-02-03 stsp }
2243 ec46ccd7 2020-01-15 tracey
2244 83eb9a68 2020-02-03 stsp while ((linelen = getline(&line, &linesize, f)) != -1) {
2245 f7cc9480 2020-02-05 tracey error = gw_colordiff_line(gw_trans, line);
2246 ec46ccd7 2020-01-15 tracey if (error)
2247 b8b04565 2020-02-02 tracey goto done;
2248 f7cc9480 2020-02-05 tracey /* XXX: KHTML_PRETTY breaks this */
2249 f7cc9480 2020-02-05 tracey kerr = khtml_puts(gw_trans->gw_html_req, line);
2250 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
2251 83eb9a68 2020-02-03 stsp goto done;
2252 f7cc9480 2020-02-05 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
2253 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
2254 b8b04565 2020-02-02 tracey goto done;
2255 ec46ccd7 2020-01-15 tracey }
2256 f7cc9480 2020-02-05 tracey if (linelen == -1 && ferror(f))
2257 83eb9a68 2020-02-03 stsp error = got_error_from_errno("getline");
2258 ec46ccd7 2020-01-15 tracey done:
2259 d4729381 2020-02-03 stsp if (f && fclose(f) == -1 && error == NULL)
2260 d4729381 2020-02-03 stsp error = got_error_from_errno("fclose");
2261 d4729381 2020-02-03 stsp free(line);
2262 ec46ccd7 2020-01-15 tracey free(label1);
2263 ec46ccd7 2020-01-15 tracey free(label2);
2264 ec46ccd7 2020-01-15 tracey free(id1);
2265 ec46ccd7 2020-01-15 tracey free(id2);
2266 ec46ccd7 2020-01-15 tracey
2267 f7cc9480 2020-02-05 tracey if (error == NULL && kerr != KCGI_OK)
2268 2447adad 2020-02-06 stsp error = gw_kcgi_error(kerr);
2269 83eb9a68 2020-02-03 stsp return error;
2270 2c251c14 2020-01-15 tracey }
2271 2c251c14 2020-01-15 tracey
2272 9a1cc63f 2020-02-03 stsp static const struct got_error *
2273 9a1cc63f 2020-02-03 stsp gw_get_repo_owner(char **owner, struct gw_trans *gw_trans, char *dir)
2274 9a1cc63f 2020-02-03 stsp {
2275 9a1cc63f 2020-02-03 stsp const struct got_error *error = NULL;
2276 9a1cc63f 2020-02-03 stsp struct got_repository *repo;
2277 9a1cc63f 2020-02-03 stsp const char *gitconfig_owner;
2278 2c251c14 2020-01-15 tracey
2279 9a1cc63f 2020-02-03 stsp *owner = NULL;
2280 2c251c14 2020-01-15 tracey
2281 9a1cc63f 2020-02-03 stsp if (gw_trans->gw_conf->got_show_repo_owner == 0)
2282 9a1cc63f 2020-02-03 stsp return NULL;
2283 2c251c14 2020-01-15 tracey
2284 9a1cc63f 2020-02-03 stsp error = got_repo_open(&repo, dir, NULL);
2285 9a1cc63f 2020-02-03 stsp if (error)
2286 9a1cc63f 2020-02-03 stsp return error;
2287 9a1cc63f 2020-02-03 stsp gitconfig_owner = got_repo_get_gitconfig_owner(repo);
2288 9a1cc63f 2020-02-03 stsp if (gitconfig_owner) {
2289 9a1cc63f 2020-02-03 stsp *owner = strdup(gitconfig_owner);
2290 9a1cc63f 2020-02-03 stsp if (*owner == NULL)
2291 9a1cc63f 2020-02-03 stsp error = got_error_from_errno("strdup");
2292 2c251c14 2020-01-15 tracey }
2293 9a1cc63f 2020-02-03 stsp got_repo_close(repo);
2294 9a1cc63f 2020-02-03 stsp return error;
2295 2c251c14 2020-01-15 tracey }
2296 2c251c14 2020-01-15 tracey
2297 59d3c40e 2020-02-03 stsp static const struct got_error *
2298 59d3c40e 2020-02-03 stsp gw_get_clone_url(char **url, struct gw_trans *gw_trans, char *dir)
2299 2c251c14 2020-01-15 tracey {
2300 59d3c40e 2020-02-03 stsp const struct got_error *error = NULL;
2301 2c251c14 2020-01-15 tracey FILE *f;
2302 59d3c40e 2020-02-03 stsp char *d_file = NULL;
2303 2c251c14 2020-01-15 tracey unsigned int len;
2304 59d3c40e 2020-02-03 stsp size_t n;
2305 2c251c14 2020-01-15 tracey
2306 59d3c40e 2020-02-03 stsp *url = NULL;
2307 2c251c14 2020-01-15 tracey
2308 59d3c40e 2020-02-03 stsp if (asprintf(&d_file, "%s/cloneurl", dir) == -1)
2309 59d3c40e 2020-02-03 stsp return got_error_from_errno("asprintf");
2310 2c251c14 2020-01-15 tracey
2311 59d3c40e 2020-02-03 stsp f = fopen(d_file, "r");
2312 59d3c40e 2020-02-03 stsp if (f == NULL) {
2313 59d3c40e 2020-02-03 stsp if (errno != ENOENT && errno != EACCES)
2314 59d3c40e 2020-02-03 stsp error = got_error_from_errno2("fopen", d_file);
2315 59d3c40e 2020-02-03 stsp goto done;
2316 59d3c40e 2020-02-03 stsp }
2317 59d3c40e 2020-02-03 stsp
2318 59d3c40e 2020-02-03 stsp if (fseek(f, 0, SEEK_END) == -1) {
2319 59d3c40e 2020-02-03 stsp error = got_ferror(f, GOT_ERR_IO);
2320 59d3c40e 2020-02-03 stsp goto done;
2321 59d3c40e 2020-02-03 stsp }
2322 59d3c40e 2020-02-03 stsp len = ftell(f);
2323 59d3c40e 2020-02-03 stsp if (len == -1) {
2324 59d3c40e 2020-02-03 stsp error = got_ferror(f, GOT_ERR_IO);
2325 59d3c40e 2020-02-03 stsp goto done;
2326 59d3c40e 2020-02-03 stsp }
2327 59d3c40e 2020-02-03 stsp if (fseek(f, 0, SEEK_SET) == -1) {
2328 59d3c40e 2020-02-03 stsp error = got_ferror(f, GOT_ERR_IO);
2329 59d3c40e 2020-02-03 stsp goto done;
2330 59d3c40e 2020-02-03 stsp }
2331 2c251c14 2020-01-15 tracey
2332 59d3c40e 2020-02-03 stsp *url = calloc(len + 1, sizeof(**url));
2333 59d3c40e 2020-02-03 stsp if (*url == NULL) {
2334 59d3c40e 2020-02-03 stsp error = got_error_from_errno("calloc");
2335 59d3c40e 2020-02-03 stsp goto done;
2336 59d3c40e 2020-02-03 stsp }
2337 2c251c14 2020-01-15 tracey
2338 59d3c40e 2020-02-03 stsp n = fread(*url, 1, len, f);
2339 59d3c40e 2020-02-03 stsp if (n == 0 && ferror(f))
2340 59d3c40e 2020-02-03 stsp error = got_ferror(f, GOT_ERR_IO);
2341 59d3c40e 2020-02-03 stsp done:
2342 59d3c40e 2020-02-03 stsp if (f && fclose(f) == -1 && error == NULL)
2343 59d3c40e 2020-02-03 stsp error = got_error_from_errno("fclose");
2344 2c251c14 2020-01-15 tracey free(d_file);
2345 59d3c40e 2020-02-03 stsp return NULL;
2346 8d4d2453 2020-01-15 tracey }
2347 8d4d2453 2020-01-15 tracey
2348 6eccd105 2020-02-03 stsp static const struct got_error *
2349 38b240fb 2020-02-06 tracey gw_output_repo_tags(struct gw_trans *gw_trans, struct gw_header *header,
2350 38b240fb 2020-02-06 tracey int limit, int tag_type)
2351 8d4d2453 2020-01-15 tracey {
2352 87f9ebf5 2020-01-15 tracey const struct got_error *error = NULL;
2353 87f9ebf5 2020-01-15 tracey struct got_repository *repo = NULL;
2354 87f9ebf5 2020-01-15 tracey struct got_reflist_head refs;
2355 87f9ebf5 2020-01-15 tracey struct got_reflist_entry *re;
2356 38b240fb 2020-02-06 tracey char *age = NULL;
2357 38b240fb 2020-02-06 tracey char *escaped_tag_commit = NULL;
2358 38b240fb 2020-02-06 tracey char *id_str = NULL, *refstr = NULL, *newline, *href_commits = NULL;
2359 38b240fb 2020-02-06 tracey char *tag_commit0 = NULL, *href_tag = NULL, *href_briefs = NULL;
2360 6eccd105 2020-02-03 stsp struct got_tag_object *tag = NULL;
2361 38b240fb 2020-02-06 tracey enum kcgi_err kerr = KCGI_OK;
2362 38b240fb 2020-02-06 tracey int summary_header_displayed = 0;
2363 8d4d2453 2020-01-15 tracey
2364 a0f36e03 2020-01-28 stsp SIMPLEQ_INIT(&refs);
2365 a0f36e03 2020-01-28 stsp
2366 87f9ebf5 2020-01-15 tracey error = got_repo_open(&repo, gw_trans->repo_path, NULL);
2367 ec46ccd7 2020-01-15 tracey if (error)
2368 87f9ebf5 2020-01-15 tracey goto done;
2369 87f9ebf5 2020-01-15 tracey
2370 add40c4f 2020-01-15 tracey error = got_ref_list(&refs, repo, "refs/tags", got_ref_cmp_tags, repo);
2371 87f9ebf5 2020-01-15 tracey if (error)
2372 87f9ebf5 2020-01-15 tracey goto done;
2373 87f9ebf5 2020-01-15 tracey
2374 87f9ebf5 2020-01-15 tracey SIMPLEQ_FOREACH(re, &refs, entry) {
2375 87f9ebf5 2020-01-15 tracey const char *refname;
2376 4ff7391f 2020-01-28 tracey const char *tagger;
2377 6eccd105 2020-02-03 stsp const char *tag_commit;
2378 87f9ebf5 2020-01-15 tracey time_t tagger_time;
2379 87f9ebf5 2020-01-15 tracey struct got_object_id *id;
2380 87f9ebf5 2020-01-15 tracey
2381 87f9ebf5 2020-01-15 tracey refname = got_ref_get_name(re->ref);
2382 87f9ebf5 2020-01-15 tracey if (strncmp(refname, "refs/tags/", 10) != 0)
2383 87f9ebf5 2020-01-15 tracey continue;
2384 87f9ebf5 2020-01-15 tracey refname += 10;
2385 87f9ebf5 2020-01-15 tracey refstr = got_ref_to_str(re->ref);
2386 87f9ebf5 2020-01-15 tracey if (refstr == NULL) {
2387 87f9ebf5 2020-01-15 tracey error = got_error_from_errno("got_ref_to_str");
2388 87f9ebf5 2020-01-15 tracey goto done;
2389 87f9ebf5 2020-01-15 tracey }
2390 87f9ebf5 2020-01-15 tracey
2391 87f9ebf5 2020-01-15 tracey error = got_ref_resolve(&id, repo, re->ref);
2392 87f9ebf5 2020-01-15 tracey if (error)
2393 87f9ebf5 2020-01-15 tracey goto done;
2394 38b240fb 2020-02-06 tracey
2395 38b240fb 2020-02-06 tracey /*
2396 38b240fb 2020-02-06 tracey * XXX: some of my repos are failing here. need to investigate.
2397 38b240fb 2020-02-06 tracey * currently setting error to NULL so no error is returned,
2398 38b240fb 2020-02-06 tracey * which stops Heads from being displayed on gw_summary.
2399 38b240fb 2020-02-06 tracey *
2400 38b240fb 2020-02-06 tracey * got ref -l lists refs and first tag ref above can be
2401 38b240fb 2020-02-06 tracey * displayed
2402 38b240fb 2020-02-06 tracey *
2403 38b240fb 2020-02-06 tracey * got tag -l will list tags just fine, so I don't know what
2404 38b240fb 2020-02-06 tracey * is happening.
2405 38b240fb 2020-02-06 tracey */
2406 87f9ebf5 2020-01-15 tracey error = got_object_open_as_tag(&tag, repo, id);
2407 87f9ebf5 2020-01-15 tracey free(id);
2408 38b240fb 2020-02-06 tracey if (error) {
2409 38b240fb 2020-02-06 tracey error = NULL;
2410 87f9ebf5 2020-01-15 tracey goto done;
2411 38b240fb 2020-02-06 tracey }
2412 87f9ebf5 2020-01-15 tracey
2413 4ff7391f 2020-01-28 tracey tagger = got_object_tag_get_tagger(tag);
2414 87f9ebf5 2020-01-15 tracey tagger_time = got_object_tag_get_tagger_time(tag);
2415 87f9ebf5 2020-01-15 tracey
2416 87f9ebf5 2020-01-15 tracey error = got_object_id_str(&id_str,
2417 87f9ebf5 2020-01-15 tracey got_object_tag_get_object_id(tag));
2418 87f9ebf5 2020-01-15 tracey if (error)
2419 87f9ebf5 2020-01-15 tracey goto done;
2420 87f9ebf5 2020-01-15 tracey
2421 38b240fb 2020-02-06 tracey if (tag_type == TAGFULL && strncmp(id_str, header->commit_id,
2422 38b240fb 2020-02-06 tracey strlen(id_str)) != 0)
2423 38b240fb 2020-02-06 tracey continue;
2424 38b240fb 2020-02-06 tracey
2425 f2f46662 2020-01-23 tracey tag_commit0 = strdup(got_object_tag_get_message(tag));
2426 f2f46662 2020-01-23 tracey if (tag_commit0 == NULL) {
2427 87f9ebf5 2020-01-15 tracey error = got_error_from_errno("strdup");
2428 87f9ebf5 2020-01-15 tracey goto done;
2429 87f9ebf5 2020-01-15 tracey }
2430 87f9ebf5 2020-01-15 tracey
2431 f2f46662 2020-01-23 tracey tag_commit = tag_commit0;
2432 f2f46662 2020-01-23 tracey while (*tag_commit == '\n')
2433 f2f46662 2020-01-23 tracey tag_commit++;
2434 87f9ebf5 2020-01-15 tracey
2435 87f9ebf5 2020-01-15 tracey switch (tag_type) {
2436 87f9ebf5 2020-01-15 tracey case TAGBRIEF:
2437 f2f46662 2020-01-23 tracey newline = strchr(tag_commit, '\n');
2438 87f9ebf5 2020-01-15 tracey if (newline)
2439 87f9ebf5 2020-01-15 tracey *newline = '\0';
2440 87f9ebf5 2020-01-15 tracey
2441 38b240fb 2020-02-06 tracey if (summary_header_displayed == 0) {
2442 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req,
2443 38b240fb 2020-02-06 tracey KELEM_DIV, KATTR_ID,
2444 38b240fb 2020-02-06 tracey "summary_tags_title_wrapper", KATTR__MAX);
2445 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2446 38b240fb 2020-02-06 tracey goto done;
2447 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req,
2448 38b240fb 2020-02-06 tracey KELEM_DIV, KATTR_ID,
2449 38b240fb 2020-02-06 tracey "summary_tags_title", KATTR__MAX);
2450 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2451 38b240fb 2020-02-06 tracey goto done;
2452 38b240fb 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req,
2453 38b240fb 2020-02-06 tracey "Tags");
2454 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2455 38b240fb 2020-02-06 tracey goto done;
2456 38b240fb 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req,
2457 38b240fb 2020-02-06 tracey 2);
2458 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2459 38b240fb 2020-02-06 tracey goto done;
2460 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req,
2461 38b240fb 2020-02-06 tracey KELEM_DIV, KATTR_ID,
2462 38b240fb 2020-02-06 tracey "summary_tags_content", KATTR__MAX);
2463 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2464 38b240fb 2020-02-06 tracey goto done;
2465 38b240fb 2020-02-06 tracey summary_header_displayed = 1;
2466 38b240fb 2020-02-06 tracey }
2467 38b240fb 2020-02-06 tracey
2468 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
2469 38b240fb 2020-02-06 tracey KATTR_ID, "tags_wrapper", KATTR__MAX);
2470 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2471 38b240fb 2020-02-06 tracey goto done;
2472 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
2473 38b240fb 2020-02-06 tracey KATTR_ID, "tags_age", KATTR__MAX);
2474 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2475 38b240fb 2020-02-06 tracey goto done;
2476 55ccf528 2020-02-03 stsp error = gw_get_time_str(&age, tagger_time, TM_DIFF);
2477 55ccf528 2020-02-03 stsp if (error)
2478 87f9ebf5 2020-01-15 tracey goto done;
2479 38b240fb 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req,
2480 38b240fb 2020-02-06 tracey age ? age : "");
2481 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2482 38b240fb 2020-02-06 tracey goto done;
2483 38b240fb 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
2484 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2485 38b240fb 2020-02-06 tracey goto done;
2486 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
2487 38b240fb 2020-02-06 tracey KATTR_ID, "tags", KATTR__MAX);
2488 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2489 38b240fb 2020-02-06 tracey goto done;
2490 38b240fb 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req, refname);
2491 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2492 38b240fb 2020-02-06 tracey goto done;
2493 38b240fb 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
2494 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2495 38b240fb 2020-02-06 tracey goto done;
2496 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
2497 38b240fb 2020-02-06 tracey KATTR_ID, "tags_name", KATTR__MAX);
2498 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2499 dad0fde4 2020-02-06 tracey goto done;
2500 dad0fde4 2020-02-06 tracey if (asprintf(&href_tag, "?path=%s&action=tag&commit=%s",
2501 dad0fde4 2020-02-06 tracey gw_trans->repo_name, id_str) == -1) {
2502 dad0fde4 2020-02-06 tracey error = got_error_from_errno("asprintf");
2503 38b240fb 2020-02-06 tracey goto done;
2504 dad0fde4 2020-02-06 tracey }
2505 056e30c8 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
2506 056e30c8 2020-02-06 tracey KATTR_HREF, href_tag, KATTR__MAX);
2507 056e30c8 2020-02-06 tracey if (kerr != KCGI_OK)
2508 056e30c8 2020-02-06 tracey goto done;
2509 38b240fb 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req, tag_commit);
2510 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2511 38b240fb 2020-02-06 tracey goto done;
2512 dad0fde4 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 3);
2513 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2514 38b240fb 2020-02-06 tracey goto done;
2515 87f9ebf5 2020-01-15 tracey
2516 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
2517 38b240fb 2020-02-06 tracey KATTR_ID, "navs_wrapper", KATTR__MAX);
2518 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2519 38b240fb 2020-02-06 tracey goto done;
2520 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
2521 38b240fb 2020-02-06 tracey KATTR_ID, "navs", KATTR__MAX);
2522 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2523 38b240fb 2020-02-06 tracey goto done;
2524 38b240fb 2020-02-06 tracey
2525 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
2526 38b240fb 2020-02-06 tracey KATTR_HREF, href_tag, KATTR__MAX);
2527 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2528 38b240fb 2020-02-06 tracey goto done;
2529 38b240fb 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req, "tag");
2530 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2531 38b240fb 2020-02-06 tracey goto done;
2532 38b240fb 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
2533 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2534 38b240fb 2020-02-06 tracey goto done;
2535 87f9ebf5 2020-01-15 tracey
2536 38b240fb 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req, " | ");
2537 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2538 38b240fb 2020-02-06 tracey goto done;
2539 38b240fb 2020-02-06 tracey
2540 38b240fb 2020-02-06 tracey if (asprintf(&href_briefs,
2541 38b240fb 2020-02-06 tracey "?path=%s&action=briefs&commit=%s",
2542 38b240fb 2020-02-06 tracey gw_trans->repo_name, id_str) == -1) {
2543 87f9ebf5 2020-01-15 tracey error = got_error_from_errno("asprintf");
2544 87f9ebf5 2020-01-15 tracey goto done;
2545 87f9ebf5 2020-01-15 tracey }
2546 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
2547 38b240fb 2020-02-06 tracey KATTR_HREF, href_briefs, KATTR__MAX);
2548 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2549 38b240fb 2020-02-06 tracey goto done;
2550 38b240fb 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req,
2551 38b240fb 2020-02-06 tracey "commit briefs");
2552 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2553 38b240fb 2020-02-06 tracey goto done;
2554 38b240fb 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
2555 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2556 38b240fb 2020-02-06 tracey goto done;
2557 87f9ebf5 2020-01-15 tracey
2558 38b240fb 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req, " | ");
2559 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2560 38b240fb 2020-02-06 tracey goto done;
2561 38b240fb 2020-02-06 tracey
2562 38b240fb 2020-02-06 tracey if (asprintf(&href_commits,
2563 38b240fb 2020-02-06 tracey "?path=%s&action=commits&commit=%s",
2564 38b240fb 2020-02-06 tracey gw_trans->repo_name, id_str) == -1) {
2565 38b240fb 2020-02-06 tracey error = got_error_from_errno("asprintf");
2566 38b240fb 2020-02-06 tracey goto done;
2567 38b240fb 2020-02-06 tracey }
2568 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
2569 38b240fb 2020-02-06 tracey KATTR_HREF, href_commits, KATTR__MAX);
2570 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2571 38b240fb 2020-02-06 tracey goto done;
2572 38b240fb 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req,
2573 38b240fb 2020-02-06 tracey "commits");
2574 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2575 38b240fb 2020-02-06 tracey goto done;
2576 38b240fb 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 3);
2577 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2578 38b240fb 2020-02-06 tracey goto done;
2579 38b240fb 2020-02-06 tracey
2580 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
2581 38b240fb 2020-02-06 tracey KATTR_ID, "dotted_line", KATTR__MAX);
2582 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2583 38b240fb 2020-02-06 tracey goto done;
2584 38b240fb 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
2585 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2586 38b240fb 2020-02-06 tracey goto done;
2587 87f9ebf5 2020-01-15 tracey break;
2588 87f9ebf5 2020-01-15 tracey case TAGFULL:
2589 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
2590 38b240fb 2020-02-06 tracey KATTR_ID, "tag_info_date_title", KATTR__MAX);
2591 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2592 38b240fb 2020-02-06 tracey goto done;
2593 38b240fb 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req, "Tag Date:");
2594 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2595 38b240fb 2020-02-06 tracey goto done;
2596 38b240fb 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
2597 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2598 38b240fb 2020-02-06 tracey goto done;
2599 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
2600 38b240fb 2020-02-06 tracey KATTR_ID, "tag_info_date", KATTR__MAX);
2601 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2602 38b240fb 2020-02-06 tracey goto done;
2603 55ccf528 2020-02-03 stsp error = gw_get_time_str(&age, tagger_time, TM_LONG);
2604 55ccf528 2020-02-03 stsp if (error)
2605 4ff7391f 2020-01-28 tracey goto done;
2606 38b240fb 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req,
2607 38b240fb 2020-02-06 tracey age ? age : "");
2608 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2609 070fee27 2020-02-03 stsp goto done;
2610 38b240fb 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
2611 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2612 38b240fb 2020-02-06 tracey goto done;
2613 38b240fb 2020-02-06 tracey
2614 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
2615 38b240fb 2020-02-06 tracey KATTR_ID, "tag_info_tagger_title", KATTR__MAX);
2616 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2617 38b240fb 2020-02-06 tracey goto done;
2618 38b240fb 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req, "Tagger:");
2619 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2620 38b240fb 2020-02-06 tracey goto done;
2621 38b240fb 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
2622 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2623 38b240fb 2020-02-06 tracey goto done;
2624 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
2625 38b240fb 2020-02-06 tracey KATTR_ID, "tag_info_date", KATTR__MAX);
2626 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2627 38b240fb 2020-02-06 tracey goto done;
2628 38b240fb 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req, tagger);
2629 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2630 38b240fb 2020-02-06 tracey goto done;
2631 38b240fb 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
2632 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2633 38b240fb 2020-02-06 tracey goto done;
2634 38b240fb 2020-02-06 tracey
2635 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
2636 38b240fb 2020-02-06 tracey KATTR_ID, "tag_info", KATTR__MAX);
2637 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2638 38b240fb 2020-02-06 tracey goto done;
2639 38b240fb 2020-02-06 tracey /*
2640 38b240fb 2020-02-06 tracey * XXX: keeping this for now, since kcgihtml does not
2641 38b240fb 2020-02-06 tracey * convert \n into <br /> yet.
2642 38b240fb 2020-02-06 tracey */
2643 070fee27 2020-02-03 stsp error = gw_html_escape(&escaped_tag_commit, tag_commit);
2644 070fee27 2020-02-03 stsp if (error)
2645 070fee27 2020-02-03 stsp goto done;
2646 38b240fb 2020-02-06 tracey kerr = khttp_puts(gw_trans->gw_req, escaped_tag_commit);
2647 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2648 4ff7391f 2020-01-28 tracey goto done;
2649 87f9ebf5 2020-01-15 tracey break;
2650 87f9ebf5 2020-01-15 tracey default:
2651 87f9ebf5 2020-01-15 tracey break;
2652 87f9ebf5 2020-01-15 tracey }
2653 38b240fb 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
2654 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2655 6eccd105 2020-02-03 stsp goto done;
2656 87ca24ac 2020-02-04 tracey
2657 6eccd105 2020-02-03 stsp if (limit && --limit == 0)
2658 6eccd105 2020-02-03 stsp break;
2659 87f9ebf5 2020-01-15 tracey
2660 6eccd105 2020-02-03 stsp got_object_tag_close(tag);
2661 6eccd105 2020-02-03 stsp tag = NULL;
2662 6c6c85af 2020-01-15 tracey free(id_str);
2663 6eccd105 2020-02-03 stsp id_str = NULL;
2664 6c6c85af 2020-01-15 tracey free(refstr);
2665 6eccd105 2020-02-03 stsp refstr = NULL;
2666 6c6c85af 2020-01-15 tracey free(age);
2667 55ccf528 2020-02-03 stsp age = NULL;
2668 070fee27 2020-02-03 stsp free(escaped_tag_commit);
2669 070fee27 2020-02-03 stsp escaped_tag_commit = NULL;
2670 f2f46662 2020-01-23 tracey free(tag_commit0);
2671 6eccd105 2020-02-03 stsp tag_commit0 = NULL;
2672 38b240fb 2020-02-06 tracey free(href_tag);
2673 38b240fb 2020-02-06 tracey href_tag = NULL;
2674 38b240fb 2020-02-06 tracey free(href_briefs);
2675 38b240fb 2020-02-06 tracey href_briefs = NULL;
2676 38b240fb 2020-02-06 tracey free(href_commits);
2677 38b240fb 2020-02-06 tracey href_commits = NULL;
2678 6c6c85af 2020-01-15 tracey }
2679 87f9ebf5 2020-01-15 tracey done:
2680 6eccd105 2020-02-03 stsp if (tag)
2681 6eccd105 2020-02-03 stsp got_object_tag_close(tag);
2682 6eccd105 2020-02-03 stsp free(id_str);
2683 6eccd105 2020-02-03 stsp free(refstr);
2684 55ccf528 2020-02-03 stsp free(age);
2685 070fee27 2020-02-03 stsp free(escaped_tag_commit);
2686 6eccd105 2020-02-03 stsp free(tag_commit0);
2687 38b240fb 2020-02-06 tracey free(href_tag);
2688 38b240fb 2020-02-06 tracey free(href_briefs);
2689 38b240fb 2020-02-06 tracey free(href_commits);
2690 6eccd105 2020-02-03 stsp got_ref_list_free(&refs);
2691 6eccd105 2020-02-03 stsp if (repo)
2692 6eccd105 2020-02-03 stsp got_repo_close(repo);
2693 38b240fb 2020-02-06 tracey if (error == NULL && kerr != KCGI_OK)
2694 38b240fb 2020-02-06 tracey error = gw_kcgi_error(kerr);
2695 6eccd105 2020-02-03 stsp return error;
2696 f2f46662 2020-01-23 tracey }
2697 f2f46662 2020-01-23 tracey
2698 f2f46662 2020-01-23 tracey static void
2699 f2f46662 2020-01-23 tracey gw_free_headers(struct gw_header *header)
2700 f2f46662 2020-01-23 tracey {
2701 f2f46662 2020-01-23 tracey free(header->id);
2702 f2f46662 2020-01-23 tracey free(header->path);
2703 f2f46662 2020-01-23 tracey if (header->commit != NULL)
2704 f2f46662 2020-01-23 tracey got_object_commit_close(header->commit);
2705 f2f46662 2020-01-23 tracey if (header->repo)
2706 f2f46662 2020-01-23 tracey got_repo_close(header->repo);
2707 f2f46662 2020-01-23 tracey free(header->refs_str);
2708 f2f46662 2020-01-23 tracey free(header->commit_id);
2709 f2f46662 2020-01-23 tracey free(header->parent_id);
2710 f2f46662 2020-01-23 tracey free(header->tree_id);
2711 f2f46662 2020-01-23 tracey free(header->commit_msg);
2712 f2f46662 2020-01-23 tracey }
2713 f2f46662 2020-01-23 tracey
2714 f2f46662 2020-01-23 tracey static struct gw_header *
2715 f2f46662 2020-01-23 tracey gw_init_header()
2716 f2f46662 2020-01-23 tracey {
2717 f2f46662 2020-01-23 tracey struct gw_header *header;
2718 f2f46662 2020-01-23 tracey
2719 ae36ed87 2020-01-28 stsp header = malloc(sizeof(*header));
2720 ae36ed87 2020-01-28 stsp if (header == NULL)
2721 f2f46662 2020-01-23 tracey return NULL;
2722 f2f46662 2020-01-23 tracey
2723 f2f46662 2020-01-23 tracey header->repo = NULL;
2724 f2f46662 2020-01-23 tracey header->commit = NULL;
2725 f2f46662 2020-01-23 tracey header->id = NULL;
2726 f2f46662 2020-01-23 tracey header->path = NULL;
2727 ae36ed87 2020-01-28 stsp SIMPLEQ_INIT(&header->refs);
2728 f2f46662 2020-01-23 tracey
2729 f2f46662 2020-01-23 tracey return header;
2730 f2f46662 2020-01-23 tracey }
2731 f2f46662 2020-01-23 tracey
2732 f2f46662 2020-01-23 tracey static const struct got_error *
2733 f2f46662 2020-01-23 tracey gw_get_commits(struct gw_trans * gw_trans, struct gw_header *header,
2734 f2f46662 2020-01-23 tracey int limit)
2735 f2f46662 2020-01-23 tracey {
2736 f2f46662 2020-01-23 tracey const struct got_error *error = NULL;
2737 f2f46662 2020-01-23 tracey struct got_commit_graph *graph = NULL;
2738 f2f46662 2020-01-23 tracey
2739 f2f46662 2020-01-23 tracey error = got_commit_graph_open(&graph, header->path, 0);
2740 f2f46662 2020-01-23 tracey if (error)
2741 f2f46662 2020-01-23 tracey goto done;
2742 f2f46662 2020-01-23 tracey
2743 f2f46662 2020-01-23 tracey error = got_commit_graph_iter_start(graph, header->id, header->repo,
2744 f2f46662 2020-01-23 tracey NULL, NULL);
2745 f2f46662 2020-01-23 tracey if (error)
2746 f2f46662 2020-01-23 tracey goto done;
2747 f2f46662 2020-01-23 tracey
2748 f2f46662 2020-01-23 tracey for (;;) {
2749 f2f46662 2020-01-23 tracey error = got_commit_graph_iter_next(&header->id, graph,
2750 f2f46662 2020-01-23 tracey header->repo, NULL, NULL);
2751 f2f46662 2020-01-23 tracey if (error) {
2752 f2f46662 2020-01-23 tracey if (error->code == GOT_ERR_ITER_COMPLETED)
2753 f2f46662 2020-01-23 tracey error = NULL;
2754 f2f46662 2020-01-23 tracey goto done;
2755 f2f46662 2020-01-23 tracey }
2756 f2f46662 2020-01-23 tracey if (header->id == NULL)
2757 f2f46662 2020-01-23 tracey goto done;
2758 f2f46662 2020-01-23 tracey
2759 f2f46662 2020-01-23 tracey error = got_object_open_as_commit(&header->commit, header->repo,
2760 f2f46662 2020-01-23 tracey header->id);
2761 f2f46662 2020-01-23 tracey if (error)
2762 f2f46662 2020-01-23 tracey goto done;
2763 f2f46662 2020-01-23 tracey
2764 f2f46662 2020-01-23 tracey error = gw_get_commit(gw_trans, header);
2765 f2f46662 2020-01-23 tracey if (limit > 1) {
2766 f2f46662 2020-01-23 tracey struct gw_header *n_header = NULL;
2767 5147ab56 2020-01-29 stsp if ((n_header = gw_init_header()) == NULL) {
2768 f2f46662 2020-01-23 tracey error = got_error_from_errno("malloc");
2769 5147ab56 2020-01-29 stsp goto done;
2770 5147ab56 2020-01-29 stsp }
2771 f2f46662 2020-01-23 tracey
2772 f2f46662 2020-01-23 tracey n_header->refs_str = strdup(header->refs_str);
2773 f2f46662 2020-01-23 tracey n_header->commit_id = strdup(header->commit_id);
2774 f2f46662 2020-01-23 tracey n_header->parent_id = strdup(header->parent_id);
2775 f2f46662 2020-01-23 tracey n_header->tree_id = strdup(header->tree_id);
2776 f2f46662 2020-01-23 tracey n_header->author = strdup(header->author);
2777 f2f46662 2020-01-23 tracey n_header->committer = strdup(header->committer);
2778 f2f46662 2020-01-23 tracey n_header->commit_msg = strdup(header->commit_msg);
2779 f2f46662 2020-01-23 tracey n_header->committer_time = header->committer_time;
2780 f2f46662 2020-01-23 tracey TAILQ_INSERT_TAIL(&gw_trans->gw_headers, n_header,
2781 f2f46662 2020-01-23 tracey entry);
2782 f2f46662 2020-01-23 tracey }
2783 f2f46662 2020-01-23 tracey if (error || (limit && --limit == 0))
2784 f2f46662 2020-01-23 tracey break;
2785 f2f46662 2020-01-23 tracey }
2786 f2f46662 2020-01-23 tracey done:
2787 f2f46662 2020-01-23 tracey if (graph)
2788 f2f46662 2020-01-23 tracey got_commit_graph_close(graph);
2789 f2f46662 2020-01-23 tracey return error;
2790 f2f46662 2020-01-23 tracey }
2791 f2f46662 2020-01-23 tracey
2792 f2f46662 2020-01-23 tracey static const struct got_error *
2793 f2f46662 2020-01-23 tracey gw_get_commit(struct gw_trans *gw_trans, struct gw_header *header)
2794 f2f46662 2020-01-23 tracey {
2795 f2f46662 2020-01-23 tracey const struct got_error *error = NULL;
2796 f2f46662 2020-01-23 tracey struct got_reflist_entry *re;
2797 f2f46662 2020-01-23 tracey struct got_object_id *id2 = NULL;
2798 f2f46662 2020-01-23 tracey struct got_object_qid *parent_id;
2799 e46f587c 2020-01-29 tracey char *refs_str = NULL, *commit_msg = NULL, *commit_msg0;
2800 f2f46662 2020-01-23 tracey
2801 f2f46662 2020-01-23 tracey /*print commit*/
2802 f2f46662 2020-01-23 tracey SIMPLEQ_FOREACH(re, &header->refs, entry) {
2803 f2f46662 2020-01-23 tracey char *s;
2804 f2f46662 2020-01-23 tracey const char *name;
2805 f2f46662 2020-01-23 tracey struct got_tag_object *tag = NULL;
2806 f2f46662 2020-01-23 tracey int cmp;
2807 f2f46662 2020-01-23 tracey
2808 f2f46662 2020-01-23 tracey name = got_ref_get_name(re->ref);
2809 f2f46662 2020-01-23 tracey if (strcmp(name, GOT_REF_HEAD) == 0)
2810 f2f46662 2020-01-23 tracey continue;
2811 f2f46662 2020-01-23 tracey if (strncmp(name, "refs/", 5) == 0)
2812 f2f46662 2020-01-23 tracey name += 5;
2813 f2f46662 2020-01-23 tracey if (strncmp(name, "got/", 4) == 0)
2814 f2f46662 2020-01-23 tracey continue;
2815 f2f46662 2020-01-23 tracey if (strncmp(name, "heads/", 6) == 0)
2816 f2f46662 2020-01-23 tracey name += 6;
2817 f2f46662 2020-01-23 tracey if (strncmp(name, "remotes/", 8) == 0)
2818 f2f46662 2020-01-23 tracey name += 8;
2819 f2f46662 2020-01-23 tracey if (strncmp(name, "tags/", 5) == 0) {
2820 f2f46662 2020-01-23 tracey error = got_object_open_as_tag(&tag, header->repo,
2821 f2f46662 2020-01-23 tracey re->id);
2822 f2f46662 2020-01-23 tracey if (error) {
2823 f2f46662 2020-01-23 tracey if (error->code != GOT_ERR_OBJ_TYPE)
2824 f2f46662 2020-01-23 tracey continue;
2825 f2f46662 2020-01-23 tracey /*
2826 f2f46662 2020-01-23 tracey * Ref points at something other
2827 f2f46662 2020-01-23 tracey * than a tag.
2828 f2f46662 2020-01-23 tracey */
2829 f2f46662 2020-01-23 tracey error = NULL;
2830 f2f46662 2020-01-23 tracey tag = NULL;
2831 f2f46662 2020-01-23 tracey }
2832 f2f46662 2020-01-23 tracey }
2833 f2f46662 2020-01-23 tracey cmp = got_object_id_cmp(tag ?
2834 f2f46662 2020-01-23 tracey got_object_tag_get_object_id(tag) : re->id, header->id);
2835 f2f46662 2020-01-23 tracey if (tag)
2836 f2f46662 2020-01-23 tracey got_object_tag_close(tag);
2837 f2f46662 2020-01-23 tracey if (cmp != 0)
2838 f2f46662 2020-01-23 tracey continue;
2839 f2f46662 2020-01-23 tracey s = refs_str;
2840 88d59c36 2020-01-29 stsp if (asprintf(&refs_str, "%s%s%s", s ? s : "",
2841 88d59c36 2020-01-29 stsp s ? ", " : "", name) == -1) {
2842 f2f46662 2020-01-23 tracey error = got_error_from_errno("asprintf");
2843 f2f46662 2020-01-23 tracey free(s);
2844 f2f46662 2020-01-23 tracey return error;
2845 f2f46662 2020-01-23 tracey }
2846 f2f46662 2020-01-23 tracey header->refs_str = strdup(refs_str);
2847 f2f46662 2020-01-23 tracey free(s);
2848 f2f46662 2020-01-23 tracey }
2849 f2f46662 2020-01-23 tracey
2850 f2f46662 2020-01-23 tracey if (refs_str == NULL)
2851 f2f46662 2020-01-23 tracey header->refs_str = strdup("");
2852 f2f46662 2020-01-23 tracey free(refs_str);
2853 f2f46662 2020-01-23 tracey
2854 f2f46662 2020-01-23 tracey error = got_object_id_str(&header->commit_id, header->id);
2855 f2f46662 2020-01-23 tracey if (error)
2856 f2f46662 2020-01-23 tracey return error;
2857 f2f46662 2020-01-23 tracey
2858 f2f46662 2020-01-23 tracey error = got_object_id_str(&header->tree_id,
2859 f2f46662 2020-01-23 tracey got_object_commit_get_tree_id(header->commit));
2860 f2f46662 2020-01-23 tracey if (error)
2861 f2f46662 2020-01-23 tracey return error;
2862 f2f46662 2020-01-23 tracey
2863 f2f46662 2020-01-23 tracey if (gw_trans->action == GW_DIFF) {
2864 f2f46662 2020-01-23 tracey parent_id = SIMPLEQ_FIRST(
2865 f2f46662 2020-01-23 tracey got_object_commit_get_parent_ids(header->commit));
2866 f2f46662 2020-01-23 tracey if (parent_id != NULL) {
2867 f2f46662 2020-01-23 tracey id2 = got_object_id_dup(parent_id->id);
2868 f2f46662 2020-01-23 tracey free (parent_id);
2869 f2f46662 2020-01-23 tracey error = got_object_id_str(&header->parent_id, id2);
2870 f2f46662 2020-01-23 tracey if (error)
2871 f2f46662 2020-01-23 tracey return error;
2872 f2f46662 2020-01-23 tracey free(id2);
2873 f2f46662 2020-01-23 tracey } else
2874 f2f46662 2020-01-23 tracey header->parent_id = strdup("/dev/null");
2875 f2f46662 2020-01-23 tracey } else
2876 f2f46662 2020-01-23 tracey header->parent_id = strdup("");
2877 f2f46662 2020-01-23 tracey
2878 f2f46662 2020-01-23 tracey header->committer_time =
2879 f2f46662 2020-01-23 tracey got_object_commit_get_committer_time(header->commit);
2880 1177268c 2020-01-28 tracey
2881 bd275801 2020-02-03 tracey header->author =
2882 bd275801 2020-02-03 tracey got_object_commit_get_author(header->commit);
2883 27192be7 2020-02-04 tracey header->committer =
2884 27192be7 2020-02-04 tracey got_object_commit_get_committer(header->commit);
2885 070fee27 2020-02-03 stsp if (error)
2886 070fee27 2020-02-03 stsp return error;
2887 1177268c 2020-01-28 tracey
2888 070fee27 2020-02-03 stsp /* XXX Doesn't the log message require escaping? */
2889 f2f46662 2020-01-23 tracey error = got_object_commit_get_logmsg(&commit_msg0, header->commit);
2890 f2f46662 2020-01-23 tracey if (error)
2891 f2f46662 2020-01-23 tracey return error;
2892 f2f46662 2020-01-23 tracey
2893 f2f46662 2020-01-23 tracey commit_msg = commit_msg0;
2894 f2f46662 2020-01-23 tracey while (*commit_msg == '\n')
2895 f2f46662 2020-01-23 tracey commit_msg++;
2896 f2f46662 2020-01-23 tracey
2897 f2f46662 2020-01-23 tracey header->commit_msg = strdup(commit_msg);
2898 f2f46662 2020-01-23 tracey free(commit_msg0);
2899 f2f46662 2020-01-23 tracey return error;
2900 f2f46662 2020-01-23 tracey }
2901 f2f46662 2020-01-23 tracey
2902 f2f46662 2020-01-23 tracey static const struct got_error *
2903 f2f46662 2020-01-23 tracey gw_get_header(struct gw_trans *gw_trans, struct gw_header *header, int limit)
2904 f2f46662 2020-01-23 tracey {
2905 f2f46662 2020-01-23 tracey const struct got_error *error = NULL;
2906 f2f46662 2020-01-23 tracey char *in_repo_path = NULL;
2907 f2f46662 2020-01-23 tracey
2908 f2f46662 2020-01-23 tracey error = got_repo_open(&header->repo, gw_trans->repo_path, NULL);
2909 f2f46662 2020-01-23 tracey if (error)
2910 f2f46662 2020-01-23 tracey return error;
2911 f2f46662 2020-01-23 tracey
2912 f2f46662 2020-01-23 tracey if (gw_trans->commit == NULL) {
2913 f2f46662 2020-01-23 tracey struct got_reference *head_ref;
2914 f2f46662 2020-01-23 tracey error = got_ref_open(&head_ref, header->repo,
2915 f2f46662 2020-01-23 tracey gw_trans->headref, 0);
2916 f2f46662 2020-01-23 tracey if (error)
2917 f2f46662 2020-01-23 tracey return error;
2918 f2f46662 2020-01-23 tracey
2919 f2f46662 2020-01-23 tracey error = got_ref_resolve(&header->id, header->repo, head_ref);
2920 f2f46662 2020-01-23 tracey got_ref_close(head_ref);
2921 f2f46662 2020-01-23 tracey if (error)
2922 f2f46662 2020-01-23 tracey return error;
2923 f2f46662 2020-01-23 tracey
2924 f2f46662 2020-01-23 tracey error = got_object_open_as_commit(&header->commit,
2925 f2f46662 2020-01-23 tracey header->repo, header->id);
2926 f2f46662 2020-01-23 tracey } else {
2927 f2f46662 2020-01-23 tracey struct got_reference *ref;
2928 f2f46662 2020-01-23 tracey error = got_ref_open(&ref, header->repo, gw_trans->commit, 0);
2929 f2f46662 2020-01-23 tracey if (error == NULL) {
2930 f2f46662 2020-01-23 tracey int obj_type;
2931 f2f46662 2020-01-23 tracey error = got_ref_resolve(&header->id, header->repo, ref);
2932 f2f46662 2020-01-23 tracey got_ref_close(ref);
2933 f2f46662 2020-01-23 tracey if (error)
2934 f2f46662 2020-01-23 tracey return error;
2935 f2f46662 2020-01-23 tracey error = got_object_get_type(&obj_type, header->repo,
2936 f2f46662 2020-01-23 tracey header->id);
2937 f2f46662 2020-01-23 tracey if (error)
2938 f2f46662 2020-01-23 tracey return error;
2939 f2f46662 2020-01-23 tracey if (obj_type == GOT_OBJ_TYPE_TAG) {
2940 f2f46662 2020-01-23 tracey struct got_tag_object *tag;
2941 f2f46662 2020-01-23 tracey error = got_object_open_as_tag(&tag,
2942 f2f46662 2020-01-23 tracey header->repo, header->id);
2943 f2f46662 2020-01-23 tracey if (error)
2944 f2f46662 2020-01-23 tracey return error;
2945 f2f46662 2020-01-23 tracey if (got_object_tag_get_object_type(tag) !=
2946 f2f46662 2020-01-23 tracey GOT_OBJ_TYPE_COMMIT) {
2947 f2f46662 2020-01-23 tracey got_object_tag_close(tag);
2948 f2f46662 2020-01-23 tracey error = got_error(GOT_ERR_OBJ_TYPE);
2949 f2f46662 2020-01-23 tracey return error;
2950 f2f46662 2020-01-23 tracey }
2951 f2f46662 2020-01-23 tracey free(header->id);
2952 f2f46662 2020-01-23 tracey header->id = got_object_id_dup(
2953 f2f46662 2020-01-23 tracey got_object_tag_get_object_id(tag));
2954 f2f46662 2020-01-23 tracey if (header->id == NULL)
2955 f2f46662 2020-01-23 tracey error = got_error_from_errno(
2956 f2f46662 2020-01-23 tracey "got_object_id_dup");
2957 f2f46662 2020-01-23 tracey got_object_tag_close(tag);
2958 f2f46662 2020-01-23 tracey if (error)
2959 f2f46662 2020-01-23 tracey return error;
2960 f2f46662 2020-01-23 tracey } else if (obj_type != GOT_OBJ_TYPE_COMMIT) {
2961 f2f46662 2020-01-23 tracey error = got_error(GOT_ERR_OBJ_TYPE);
2962 f2f46662 2020-01-23 tracey return error;
2963 f2f46662 2020-01-23 tracey }
2964 f2f46662 2020-01-23 tracey error = got_object_open_as_commit(&header->commit,
2965 f2f46662 2020-01-23 tracey header->repo, header->id);
2966 f2f46662 2020-01-23 tracey if (error)
2967 f2f46662 2020-01-23 tracey return error;
2968 f2f46662 2020-01-23 tracey }
2969 f2f46662 2020-01-23 tracey if (header->commit == NULL) {
2970 f2f46662 2020-01-23 tracey error = got_repo_match_object_id_prefix(&header->id,
2971 f2f46662 2020-01-23 tracey gw_trans->commit, GOT_OBJ_TYPE_COMMIT,
2972 f2f46662 2020-01-23 tracey header->repo);
2973 f2f46662 2020-01-23 tracey if (error)
2974 f2f46662 2020-01-23 tracey return error;
2975 f2f46662 2020-01-23 tracey }
2976 f2f46662 2020-01-23 tracey error = got_repo_match_object_id_prefix(&header->id,
2977 f2f46662 2020-01-23 tracey gw_trans->commit, GOT_OBJ_TYPE_COMMIT,
2978 f2f46662 2020-01-23 tracey header->repo);
2979 f2f46662 2020-01-23 tracey }
2980 f2f46662 2020-01-23 tracey
2981 f2f46662 2020-01-23 tracey error = got_repo_map_path(&in_repo_path, header->repo,
2982 f2f46662 2020-01-23 tracey gw_trans->repo_path, 1);
2983 f2f46662 2020-01-23 tracey if (error)
2984 f2f46662 2020-01-23 tracey return error;
2985 f2f46662 2020-01-23 tracey
2986 f2f46662 2020-01-23 tracey if (in_repo_path) {
2987 f2f46662 2020-01-23 tracey header->path = strdup(in_repo_path);
2988 f2f46662 2020-01-23 tracey }
2989 f2f46662 2020-01-23 tracey free(in_repo_path);
2990 f2f46662 2020-01-23 tracey
2991 f2f46662 2020-01-23 tracey error = got_ref_list(&header->refs, header->repo, NULL,
2992 f2f46662 2020-01-23 tracey got_ref_cmp_by_name, NULL);
2993 f2f46662 2020-01-23 tracey if (error)
2994 f2f46662 2020-01-23 tracey return error;
2995 f2f46662 2020-01-23 tracey
2996 f2f46662 2020-01-23 tracey error = gw_get_commits(gw_trans, header, limit);
2997 f2f46662 2020-01-23 tracey return error;
2998 ec46ccd7 2020-01-15 tracey }
2999 ec46ccd7 2020-01-15 tracey
3000 ec46ccd7 2020-01-15 tracey struct blame_line {
3001 ec46ccd7 2020-01-15 tracey int annotated;
3002 ec46ccd7 2020-01-15 tracey char *id_str;
3003 ec46ccd7 2020-01-15 tracey char *committer;
3004 ec46ccd7 2020-01-15 tracey char datebuf[11]; /* YYYY-MM-DD + NUL */
3005 ec46ccd7 2020-01-15 tracey };
3006 ec46ccd7 2020-01-15 tracey
3007 147269d5 2020-01-15 tracey struct gw_blame_cb_args {
3008 ec46ccd7 2020-01-15 tracey struct blame_line *lines;
3009 ec46ccd7 2020-01-15 tracey int nlines;
3010 ec46ccd7 2020-01-15 tracey int nlines_prec;
3011 ec46ccd7 2020-01-15 tracey int lineno_cur;
3012 ec46ccd7 2020-01-15 tracey off_t *line_offsets;
3013 ec46ccd7 2020-01-15 tracey FILE *f;
3014 ec46ccd7 2020-01-15 tracey struct got_repository *repo;
3015 54415d85 2020-01-15 tracey struct gw_trans *gw_trans;
3016 ec46ccd7 2020-01-15 tracey };
3017 ec46ccd7 2020-01-15 tracey
3018 ec46ccd7 2020-01-15 tracey static const struct got_error *
3019 147269d5 2020-01-15 tracey gw_blame_cb(void *arg, int nlines, int lineno, struct got_object_id *id)
3020 ec46ccd7 2020-01-15 tracey {
3021 ec46ccd7 2020-01-15 tracey const struct got_error *err = NULL;
3022 147269d5 2020-01-15 tracey struct gw_blame_cb_args *a = arg;
3023 ec46ccd7 2020-01-15 tracey struct blame_line *bline;
3024 ec46ccd7 2020-01-15 tracey char *line = NULL;
3025 9a9d12ca 2020-02-06 tracey size_t linesize = 0;
3026 ec46ccd7 2020-01-15 tracey struct got_commit_object *commit = NULL;
3027 ec46ccd7 2020-01-15 tracey off_t offset;
3028 ec46ccd7 2020-01-15 tracey struct tm tm;
3029 ec46ccd7 2020-01-15 tracey time_t committer_time;
3030 9a9d12ca 2020-02-06 tracey enum kcgi_err kerr = KCGI_OK;
3031 ec46ccd7 2020-01-15 tracey
3032 ec46ccd7 2020-01-15 tracey if (nlines != a->nlines ||
3033 ec46ccd7 2020-01-15 tracey (lineno != -1 && lineno < 1) || lineno > a->nlines)
3034 ec46ccd7 2020-01-15 tracey return got_error(GOT_ERR_RANGE);
3035 ec46ccd7 2020-01-15 tracey
3036 ec46ccd7 2020-01-15 tracey if (lineno == -1)
3037 ec46ccd7 2020-01-15 tracey return NULL; /* no change in this commit */
3038 ec46ccd7 2020-01-15 tracey
3039 ec46ccd7 2020-01-15 tracey /* Annotate this line. */
3040 ec46ccd7 2020-01-15 tracey bline = &a->lines[lineno - 1];
3041 ec46ccd7 2020-01-15 tracey if (bline->annotated)
3042 ec46ccd7 2020-01-15 tracey return NULL;
3043 ec46ccd7 2020-01-15 tracey err = got_object_id_str(&bline->id_str, id);
3044 ec46ccd7 2020-01-15 tracey if (err)
3045 ec46ccd7 2020-01-15 tracey return err;
3046 ec46ccd7 2020-01-15 tracey
3047 ec46ccd7 2020-01-15 tracey err = got_object_open_as_commit(&commit, a->repo, id);
3048 ec46ccd7 2020-01-15 tracey if (err)
3049 ec46ccd7 2020-01-15 tracey goto done;
3050 ec46ccd7 2020-01-15 tracey
3051 ec46ccd7 2020-01-15 tracey bline->committer = strdup(got_object_commit_get_committer(commit));
3052 ec46ccd7 2020-01-15 tracey if (bline->committer == NULL) {
3053 ec46ccd7 2020-01-15 tracey err = got_error_from_errno("strdup");
3054 ec46ccd7 2020-01-15 tracey goto done;
3055 ec46ccd7 2020-01-15 tracey }
3056 ec46ccd7 2020-01-15 tracey
3057 ec46ccd7 2020-01-15 tracey committer_time = got_object_commit_get_committer_time(commit);
3058 ec46ccd7 2020-01-15 tracey if (localtime_r(&committer_time, &tm) == NULL)
3059 ec46ccd7 2020-01-15 tracey return got_error_from_errno("localtime_r");
3060 ec46ccd7 2020-01-15 tracey if (strftime(bline->datebuf, sizeof(bline->datebuf), "%G-%m-%d",
3061 ec46ccd7 2020-01-15 tracey &tm) >= sizeof(bline->datebuf)) {
3062 ec46ccd7 2020-01-15 tracey err = got_error(GOT_ERR_NO_SPACE);
3063 ec46ccd7 2020-01-15 tracey goto done;
3064 ec46ccd7 2020-01-15 tracey }
3065 ec46ccd7 2020-01-15 tracey bline->annotated = 1;
3066 ec46ccd7 2020-01-15 tracey
3067 ec46ccd7 2020-01-15 tracey /* Print lines annotated so far. */
3068 ec46ccd7 2020-01-15 tracey bline = &a->lines[a->lineno_cur - 1];
3069 ec46ccd7 2020-01-15 tracey if (!bline->annotated)
3070 ec46ccd7 2020-01-15 tracey goto done;
3071 ec46ccd7 2020-01-15 tracey
3072 ec46ccd7 2020-01-15 tracey offset = a->line_offsets[a->lineno_cur - 1];
3073 ec46ccd7 2020-01-15 tracey if (fseeko(a->f, offset, SEEK_SET) == -1) {
3074 ec46ccd7 2020-01-15 tracey err = got_error_from_errno("fseeko");
3075 ec46ccd7 2020-01-15 tracey goto done;
3076 ec46ccd7 2020-01-15 tracey }
3077 ec46ccd7 2020-01-15 tracey
3078 ec46ccd7 2020-01-15 tracey while (bline->annotated) {
3079 9a9d12ca 2020-02-06 tracey char *smallerthan, *at, *nl, *committer;
3080 9a9d12ca 2020-02-06 tracey char *lineno = NULL, *href_diff = NULL, *href_link = NULL;
3081 ec46ccd7 2020-01-15 tracey size_t len;
3082 ec46ccd7 2020-01-15 tracey
3083 ec46ccd7 2020-01-15 tracey if (getline(&line, &linesize, a->f) == -1) {
3084 ec46ccd7 2020-01-15 tracey if (ferror(a->f))
3085 ec46ccd7 2020-01-15 tracey err = got_error_from_errno("getline");
3086 ec46ccd7 2020-01-15 tracey break;
3087 ec46ccd7 2020-01-15 tracey }
3088 ec46ccd7 2020-01-15 tracey
3089 ec46ccd7 2020-01-15 tracey committer = bline->committer;
3090 ec46ccd7 2020-01-15 tracey smallerthan = strchr(committer, '<');
3091 ec46ccd7 2020-01-15 tracey if (smallerthan && smallerthan[1] != '\0')
3092 ec46ccd7 2020-01-15 tracey committer = smallerthan + 1;
3093 ec46ccd7 2020-01-15 tracey at = strchr(committer, '@');
3094 ec46ccd7 2020-01-15 tracey if (at)
3095 ec46ccd7 2020-01-15 tracey *at = '\0';
3096 ec46ccd7 2020-01-15 tracey len = strlen(committer);
3097 ec46ccd7 2020-01-15 tracey if (len >= 9)
3098 ec46ccd7 2020-01-15 tracey committer[8] = '\0';
3099 ec46ccd7 2020-01-15 tracey
3100 ec46ccd7 2020-01-15 tracey nl = strchr(line, '\n');
3101 ec46ccd7 2020-01-15 tracey if (nl)
3102 ec46ccd7 2020-01-15 tracey *nl = '\0';
3103 0311ce2d 2020-01-15 tracey
3104 de6bdba4 2020-01-31 tracey if (a->gw_trans->repo_folder == NULL)
3105 de6bdba4 2020-01-31 tracey a->gw_trans->repo_folder = strdup("");
3106 de6bdba4 2020-01-31 tracey if (a->gw_trans->repo_folder == NULL)
3107 de6bdba4 2020-01-31 tracey goto err;
3108 9a9d12ca 2020-02-06 tracey
3109 9a9d12ca 2020-02-06 tracey /* blame line */
3110 9a9d12ca 2020-02-06 tracey kerr = khtml_attr(a->gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
3111 9a9d12ca 2020-02-06 tracey "blame_wrapper", KATTR__MAX);
3112 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
3113 9a9d12ca 2020-02-06 tracey goto err;
3114 9a9d12ca 2020-02-06 tracey kerr = khtml_attr(a->gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
3115 9a9d12ca 2020-02-06 tracey "blame_number", KATTR__MAX);
3116 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
3117 9a9d12ca 2020-02-06 tracey goto err;
3118 9a9d12ca 2020-02-06 tracey if (asprintf(&lineno, "%.*d", a->nlines_prec,
3119 9a9d12ca 2020-02-06 tracey a->lineno_cur) == -1)
3120 9a9d12ca 2020-02-06 tracey goto err;
3121 9a9d12ca 2020-02-06 tracey kerr = khtml_puts(a->gw_trans->gw_html_req, lineno);
3122 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
3123 9a9d12ca 2020-02-06 tracey goto err;
3124 9a9d12ca 2020-02-06 tracey kerr = khtml_closeelem(a->gw_trans->gw_html_req, 1);
3125 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
3126 9a9d12ca 2020-02-06 tracey goto err;
3127 9a9d12ca 2020-02-06 tracey
3128 9a9d12ca 2020-02-06 tracey kerr = khtml_attr(a->gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
3129 9a9d12ca 2020-02-06 tracey "blame_hash", KATTR__MAX);
3130 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
3131 9a9d12ca 2020-02-06 tracey goto err;
3132 9a9d12ca 2020-02-06 tracey if (asprintf(&href_diff,
3133 9a9d12ca 2020-02-06 tracey "?path=%s&action=diff&commit=%s&file=%s&folder=%s",
3134 10d47faf 2020-01-31 tracey a->gw_trans->repo_name, bline->id_str,
3135 9a9d12ca 2020-02-06 tracey a->gw_trans->repo_file, a->gw_trans->repo_folder) == -1) {
3136 9a9d12ca 2020-02-06 tracey err = got_error_from_errno("asprintf");
3137 9a9d12ca 2020-02-06 tracey goto err;
3138 9a9d12ca 2020-02-06 tracey }
3139 9a9d12ca 2020-02-06 tracey if (asprintf(&href_link, "%.8s", bline->id_str) == -1) {
3140 9a9d12ca 2020-02-06 tracey err = got_error_from_errno("asprintf");
3141 9a9d12ca 2020-02-06 tracey goto err;
3142 9a9d12ca 2020-02-06 tracey }
3143 9a9d12ca 2020-02-06 tracey kerr = khtml_attr(a->gw_trans->gw_html_req, KELEM_A,
3144 9a9d12ca 2020-02-06 tracey KATTR_HREF, href_diff, KATTR__MAX);
3145 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
3146 9a9d12ca 2020-02-06 tracey goto done;
3147 9a9d12ca 2020-02-06 tracey kerr = khtml_puts(a->gw_trans->gw_html_req, href_link);
3148 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
3149 9a9d12ca 2020-02-06 tracey goto err;
3150 9a9d12ca 2020-02-06 tracey kerr = khtml_closeelem(a->gw_trans->gw_html_req, 2);
3151 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
3152 9a9d12ca 2020-02-06 tracey goto err;
3153 2e676fc5 2020-01-15 tracey
3154 9a9d12ca 2020-02-06 tracey kerr = khtml_attr(a->gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
3155 9a9d12ca 2020-02-06 tracey "blame_date", KATTR__MAX);
3156 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
3157 9a9d12ca 2020-02-06 tracey goto err;
3158 9a9d12ca 2020-02-06 tracey kerr = khtml_puts(a->gw_trans->gw_html_req, bline->datebuf);
3159 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
3160 9a9d12ca 2020-02-06 tracey goto err;
3161 9a9d12ca 2020-02-06 tracey kerr = khtml_closeelem(a->gw_trans->gw_html_req, 1);
3162 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
3163 9a9d12ca 2020-02-06 tracey goto err;
3164 9a9d12ca 2020-02-06 tracey
3165 9a9d12ca 2020-02-06 tracey kerr = khtml_attr(a->gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
3166 9a9d12ca 2020-02-06 tracey "blame_author", KATTR__MAX);
3167 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
3168 9a9d12ca 2020-02-06 tracey goto err;
3169 9a9d12ca 2020-02-06 tracey kerr = khtml_puts(a->gw_trans->gw_html_req, committer);
3170 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
3171 9a9d12ca 2020-02-06 tracey goto err;
3172 9a9d12ca 2020-02-06 tracey kerr = khtml_closeelem(a->gw_trans->gw_html_req, 1);
3173 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
3174 9a9d12ca 2020-02-06 tracey goto err;
3175 9a9d12ca 2020-02-06 tracey
3176 9a9d12ca 2020-02-06 tracey kerr = khtml_attr(a->gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
3177 9a9d12ca 2020-02-06 tracey "blame_code", KATTR__MAX);
3178 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
3179 9a9d12ca 2020-02-06 tracey goto err;
3180 9a9d12ca 2020-02-06 tracey kerr = khtml_puts(a->gw_trans->gw_html_req, line);
3181 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
3182 9a9d12ca 2020-02-06 tracey goto err;
3183 9a9d12ca 2020-02-06 tracey kerr = khtml_closeelem(a->gw_trans->gw_html_req, 1);
3184 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
3185 9a9d12ca 2020-02-06 tracey goto err;
3186 9a9d12ca 2020-02-06 tracey
3187 9a9d12ca 2020-02-06 tracey kerr = khtml_closeelem(a->gw_trans->gw_html_req, 1);
3188 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
3189 9a9d12ca 2020-02-06 tracey goto err;
3190 9a9d12ca 2020-02-06 tracey
3191 9a9d12ca 2020-02-06 tracey a->lineno_cur++;
3192 ec46ccd7 2020-01-15 tracey bline = &a->lines[a->lineno_cur - 1];
3193 de6bdba4 2020-01-31 tracey err:
3194 9a9d12ca 2020-02-06 tracey free(lineno);
3195 9a9d12ca 2020-02-06 tracey free(href_diff);
3196 9a9d12ca 2020-02-06 tracey free(href_link);
3197 ec46ccd7 2020-01-15 tracey }
3198 ec46ccd7 2020-01-15 tracey done:
3199 ec46ccd7 2020-01-15 tracey if (commit)
3200 ec46ccd7 2020-01-15 tracey got_object_commit_close(commit);
3201 ec46ccd7 2020-01-15 tracey free(line);
3202 9a9d12ca 2020-02-06 tracey if (err == NULL && kerr != KCGI_OK)
3203 9a9d12ca 2020-02-06 tracey err = gw_kcgi_error(kerr);
3204 ec46ccd7 2020-01-15 tracey return err;
3205 872742ce 2020-02-01 stsp }
3206 872742ce 2020-02-01 stsp
3207 a81f3554 2020-02-03 stsp static const struct got_error *
3208 9a9d12ca 2020-02-06 tracey gw_output_file_blame(struct gw_trans *gw_trans)
3209 bcbc97d8 2020-01-15 tracey {
3210 bcbc97d8 2020-01-15 tracey const struct got_error *error = NULL;
3211 bcbc97d8 2020-01-15 tracey struct got_repository *repo = NULL;
3212 ec46ccd7 2020-01-15 tracey struct got_object_id *obj_id = NULL;
3213 ec46ccd7 2020-01-15 tracey struct got_object_id *commit_id = NULL;
3214 ec46ccd7 2020-01-15 tracey struct got_blob_object *blob = NULL;
3215 a81f3554 2020-02-03 stsp char *path = NULL, *in_repo_path = NULL;
3216 147269d5 2020-01-15 tracey struct gw_blame_cb_args bca;
3217 119bf4ed 2020-01-15 tracey int i, obj_type;
3218 ec46ccd7 2020-01-15 tracey size_t filesize;
3219 ec46ccd7 2020-01-15 tracey
3220 ec46ccd7 2020-01-15 tracey error = got_repo_open(&repo, gw_trans->repo_path, NULL);
3221 ec46ccd7 2020-01-15 tracey if (error)
3222 a81f3554 2020-02-03 stsp return error;
3223 ec46ccd7 2020-01-15 tracey
3224 a81f3554 2020-02-03 stsp if (asprintf(&path, "%s%s%s",
3225 a81f3554 2020-02-03 stsp gw_trans->repo_folder ? gw_trans->repo_folder : "",
3226 4fd4726a 2020-02-03 stsp gw_trans->repo_folder ? "/" : "",
3227 a81f3554 2020-02-03 stsp gw_trans->repo_file) == -1) {
3228 2e676fc5 2020-01-15 tracey error = got_error_from_errno("asprintf");
3229 2e676fc5 2020-01-15 tracey goto done;
3230 2e676fc5 2020-01-15 tracey }
3231 2e676fc5 2020-01-15 tracey
3232 2e676fc5 2020-01-15 tracey error = got_repo_map_path(&in_repo_path, repo, path, 1);
3233 ec46ccd7 2020-01-15 tracey if (error)
3234 ec46ccd7 2020-01-15 tracey goto done;
3235 ec46ccd7 2020-01-15 tracey
3236 f2f46662 2020-01-23 tracey error = got_repo_match_object_id(&commit_id, NULL, gw_trans->commit,
3237 147269d5 2020-01-15 tracey GOT_OBJ_TYPE_COMMIT, 1, repo);
3238 ec46ccd7 2020-01-15 tracey if (error)
3239 ec46ccd7 2020-01-15 tracey goto done;
3240 ec46ccd7 2020-01-15 tracey
3241 ec46ccd7 2020-01-15 tracey error = got_object_id_by_path(&obj_id, repo, commit_id, in_repo_path);
3242 ec46ccd7 2020-01-15 tracey if (error)
3243 ec46ccd7 2020-01-15 tracey goto done;
3244 2e676fc5 2020-01-15 tracey
3245 ec46ccd7 2020-01-15 tracey if (obj_id == NULL) {
3246 ec46ccd7 2020-01-15 tracey error = got_error(GOT_ERR_NO_OBJ);
3247 ec46ccd7 2020-01-15 tracey goto done;
3248 ec46ccd7 2020-01-15 tracey }
3249 ec46ccd7 2020-01-15 tracey
3250 ec46ccd7 2020-01-15 tracey error = got_object_get_type(&obj_type, repo, obj_id);
3251 ec46ccd7 2020-01-15 tracey if (error)
3252 ec46ccd7 2020-01-15 tracey goto done;
3253 ec46ccd7 2020-01-15 tracey
3254 ec46ccd7 2020-01-15 tracey if (obj_type != GOT_OBJ_TYPE_BLOB) {
3255 ec46ccd7 2020-01-15 tracey error = got_error(GOT_ERR_OBJ_TYPE);
3256 ec46ccd7 2020-01-15 tracey goto done;
3257 ec46ccd7 2020-01-15 tracey }
3258 ec46ccd7 2020-01-15 tracey
3259 ec46ccd7 2020-01-15 tracey error = got_object_open_as_blob(&blob, repo, obj_id, 8192);
3260 ec46ccd7 2020-01-15 tracey if (error)
3261 ec46ccd7 2020-01-15 tracey goto done;
3262 ec46ccd7 2020-01-15 tracey
3263 ec46ccd7 2020-01-15 tracey bca.f = got_opentemp();
3264 ec46ccd7 2020-01-15 tracey if (bca.f == NULL) {
3265 ec46ccd7 2020-01-15 tracey error = got_error_from_errno("got_opentemp");
3266 ec46ccd7 2020-01-15 tracey goto done;
3267 ec46ccd7 2020-01-15 tracey }
3268 ec46ccd7 2020-01-15 tracey error = got_object_blob_dump_to_file(&filesize, &bca.nlines,
3269 ec46ccd7 2020-01-15 tracey &bca.line_offsets, bca.f, blob);
3270 ec46ccd7 2020-01-15 tracey if (error || bca.nlines == 0)
3271 ec46ccd7 2020-01-15 tracey goto done;
3272 a81f3554 2020-02-03 stsp
3273 ec46ccd7 2020-01-15 tracey /* Don't include \n at EOF in the blame line count. */
3274 ec46ccd7 2020-01-15 tracey if (bca.line_offsets[bca.nlines - 1] == filesize)
3275 ec46ccd7 2020-01-15 tracey bca.nlines--;
3276 ec46ccd7 2020-01-15 tracey
3277 ec46ccd7 2020-01-15 tracey bca.lines = calloc(bca.nlines, sizeof(*bca.lines));
3278 ec46ccd7 2020-01-15 tracey if (bca.lines == NULL) {
3279 ec46ccd7 2020-01-15 tracey error = got_error_from_errno("calloc");
3280 ec46ccd7 2020-01-15 tracey goto done;
3281 ec46ccd7 2020-01-15 tracey }
3282 ec46ccd7 2020-01-15 tracey bca.lineno_cur = 1;
3283 ec46ccd7 2020-01-15 tracey bca.nlines_prec = 0;
3284 ec46ccd7 2020-01-15 tracey i = bca.nlines;
3285 ec46ccd7 2020-01-15 tracey while (i > 0) {
3286 ec46ccd7 2020-01-15 tracey i /= 10;
3287 ec46ccd7 2020-01-15 tracey bca.nlines_prec++;
3288 ec46ccd7 2020-01-15 tracey }
3289 ec46ccd7 2020-01-15 tracey bca.repo = repo;
3290 2e676fc5 2020-01-15 tracey bca.gw_trans = gw_trans;
3291 ec46ccd7 2020-01-15 tracey
3292 147269d5 2020-01-15 tracey error = got_blame(in_repo_path, commit_id, repo, gw_blame_cb, &bca,
3293 147269d5 2020-01-15 tracey NULL, NULL);
3294 e46f587c 2020-01-29 tracey if (error)
3295 e46f587c 2020-01-29 tracey goto done;
3296 ec46ccd7 2020-01-15 tracey done:
3297 e46f587c 2020-01-29 tracey free(bca.line_offsets);
3298 2e676fc5 2020-01-15 tracey free(in_repo_path);
3299 2e676fc5 2020-01-15 tracey free(commit_id);
3300 2e676fc5 2020-01-15 tracey free(obj_id);
3301 2e676fc5 2020-01-15 tracey free(path);
3302 2e676fc5 2020-01-15 tracey
3303 4fd4726a 2020-02-03 stsp for (i = 0; i < bca.nlines; i++) {
3304 4fd4726a 2020-02-03 stsp struct blame_line *bline = &bca.lines[i];
3305 4fd4726a 2020-02-03 stsp free(bline->id_str);
3306 4fd4726a 2020-02-03 stsp free(bline->committer);
3307 2e676fc5 2020-01-15 tracey }
3308 4fd4726a 2020-02-03 stsp free(bca.lines);
3309 2e676fc5 2020-01-15 tracey if (bca.f && fclose(bca.f) == EOF && error == NULL)
3310 a81f3554 2020-02-03 stsp error = got_error_from_errno("fclose");
3311 4fd4726a 2020-02-03 stsp if (blob)
3312 4fd4726a 2020-02-03 stsp got_object_blob_close(blob);
3313 4fd4726a 2020-02-03 stsp if (repo)
3314 4fd4726a 2020-02-03 stsp got_repo_close(repo);
3315 4fd4726a 2020-02-03 stsp return error;
3316 4fd4726a 2020-02-03 stsp }
3317 4fd4726a 2020-02-03 stsp
3318 4fd4726a 2020-02-03 stsp static const struct got_error *
3319 e0857cfe 2020-02-06 tracey gw_output_blob_buf(struct gw_trans *gw_trans)
3320 4fd4726a 2020-02-03 stsp {
3321 4fd4726a 2020-02-03 stsp const struct got_error *error = NULL;
3322 4fd4726a 2020-02-03 stsp struct got_repository *repo = NULL;
3323 4fd4726a 2020-02-03 stsp struct got_object_id *obj_id = NULL;
3324 4fd4726a 2020-02-03 stsp struct got_object_id *commit_id = NULL;
3325 4fd4726a 2020-02-03 stsp struct got_blob_object *blob = NULL;
3326 4fd4726a 2020-02-03 stsp char *path = NULL, *in_repo_path = NULL;
3327 e0857cfe 2020-02-06 tracey int obj_type, set_mime = 0;
3328 e0857cfe 2020-02-06 tracey size_t len, hdrlen;
3329 e0857cfe 2020-02-06 tracey const uint8_t *buf;
3330 e0857cfe 2020-02-06 tracey enum kcgi_err kerr = KCGI_OK;
3331 4fd4726a 2020-02-03 stsp
3332 4fd4726a 2020-02-03 stsp error = got_repo_open(&repo, gw_trans->repo_path, NULL);
3333 4fd4726a 2020-02-03 stsp if (error)
3334 4fd4726a 2020-02-03 stsp return error;
3335 4fd4726a 2020-02-03 stsp
3336 4fd4726a 2020-02-03 stsp if (asprintf(&path, "%s%s%s",
3337 4fd4726a 2020-02-03 stsp gw_trans->repo_folder ? gw_trans->repo_folder : "",
3338 4fd4726a 2020-02-03 stsp gw_trans->repo_folder ? "/" : "",
3339 4fd4726a 2020-02-03 stsp gw_trans->repo_file) == -1) {
3340 4fd4726a 2020-02-03 stsp error = got_error_from_errno("asprintf");
3341 4fd4726a 2020-02-03 stsp goto done;
3342 4fd4726a 2020-02-03 stsp }
3343 4fd4726a 2020-02-03 stsp
3344 4fd4726a 2020-02-03 stsp error = got_repo_map_path(&in_repo_path, repo, path, 1);
3345 4fd4726a 2020-02-03 stsp if (error)
3346 4fd4726a 2020-02-03 stsp goto done;
3347 4fd4726a 2020-02-03 stsp
3348 4fd4726a 2020-02-03 stsp error = got_repo_match_object_id(&commit_id, NULL, gw_trans->commit,
3349 4fd4726a 2020-02-03 stsp GOT_OBJ_TYPE_COMMIT, 1, repo);
3350 4fd4726a 2020-02-03 stsp if (error)
3351 4fd4726a 2020-02-03 stsp goto done;
3352 4fd4726a 2020-02-03 stsp
3353 4fd4726a 2020-02-03 stsp error = got_object_id_by_path(&obj_id, repo, commit_id, in_repo_path);
3354 4fd4726a 2020-02-03 stsp if (error)
3355 4fd4726a 2020-02-03 stsp goto done;
3356 4fd4726a 2020-02-03 stsp
3357 4fd4726a 2020-02-03 stsp if (obj_id == NULL) {
3358 4fd4726a 2020-02-03 stsp error = got_error(GOT_ERR_NO_OBJ);
3359 4fd4726a 2020-02-03 stsp goto done;
3360 4fd4726a 2020-02-03 stsp }
3361 4fd4726a 2020-02-03 stsp
3362 4fd4726a 2020-02-03 stsp error = got_object_get_type(&obj_type, repo, obj_id);
3363 4fd4726a 2020-02-03 stsp if (error)
3364 4fd4726a 2020-02-03 stsp goto done;
3365 4fd4726a 2020-02-03 stsp
3366 4fd4726a 2020-02-03 stsp if (obj_type != GOT_OBJ_TYPE_BLOB) {
3367 4fd4726a 2020-02-03 stsp error = got_error(GOT_ERR_OBJ_TYPE);
3368 4fd4726a 2020-02-03 stsp goto done;
3369 4fd4726a 2020-02-03 stsp }
3370 4fd4726a 2020-02-03 stsp
3371 4fd4726a 2020-02-03 stsp error = got_object_open_as_blob(&blob, repo, obj_id, 8192);
3372 4fd4726a 2020-02-03 stsp if (error)
3373 4fd4726a 2020-02-03 stsp goto done;
3374 4fd4726a 2020-02-03 stsp
3375 e0857cfe 2020-02-06 tracey hdrlen = got_object_blob_get_hdrlen(blob);
3376 e0857cfe 2020-02-06 tracey do {
3377 e0857cfe 2020-02-06 tracey error = got_object_blob_read_block(&len, blob);
3378 e0857cfe 2020-02-06 tracey if (error)
3379 e0857cfe 2020-02-06 tracey goto done;
3380 e0857cfe 2020-02-06 tracey buf = got_object_blob_get_read_buf(blob);
3381 4fd4726a 2020-02-03 stsp
3382 e0857cfe 2020-02-06 tracey /*
3383 e0857cfe 2020-02-06 tracey * Skip blob object header first time around,
3384 e0857cfe 2020-02-06 tracey * which also contains a zero byte.
3385 e0857cfe 2020-02-06 tracey */
3386 e0857cfe 2020-02-06 tracey buf += hdrlen;
3387 e0857cfe 2020-02-06 tracey if (set_mime == 0) {
3388 e0857cfe 2020-02-06 tracey if (isbinary(buf, len - hdrlen))
3389 e0857cfe 2020-02-06 tracey gw_trans->mime = KMIME_APP_OCTET_STREAM;
3390 e0857cfe 2020-02-06 tracey else
3391 e0857cfe 2020-02-06 tracey gw_trans->mime = KMIME_TEXT_PLAIN;
3392 e0857cfe 2020-02-06 tracey set_mime = 1;
3393 e0857cfe 2020-02-06 tracey error = gw_display_index(gw_trans);
3394 e0857cfe 2020-02-06 tracey if (error)
3395 e0857cfe 2020-02-06 tracey goto done;
3396 e0857cfe 2020-02-06 tracey }
3397 e0857cfe 2020-02-06 tracey khttp_write(gw_trans->gw_req, buf, len - hdrlen);
3398 e0857cfe 2020-02-06 tracey hdrlen = 0;
3399 e0857cfe 2020-02-06 tracey } while (len != 0);
3400 4fd4726a 2020-02-03 stsp done:
3401 4fd4726a 2020-02-03 stsp free(in_repo_path);
3402 4fd4726a 2020-02-03 stsp free(commit_id);
3403 4fd4726a 2020-02-03 stsp free(obj_id);
3404 4fd4726a 2020-02-03 stsp free(path);
3405 e46f587c 2020-01-29 tracey if (blob)
3406 a81f3554 2020-02-03 stsp got_object_blob_close(blob);
3407 e46f587c 2020-01-29 tracey if (repo)
3408 a81f3554 2020-02-03 stsp got_repo_close(repo);
3409 e0857cfe 2020-02-06 tracey if (error == NULL && kerr != KCGI_OK)
3410 e0857cfe 2020-02-06 tracey error = gw_kcgi_error(kerr);
3411 a81f3554 2020-02-03 stsp return error;
3412 ec46ccd7 2020-01-15 tracey }
3413 ec46ccd7 2020-01-15 tracey
3414 84bf4df2 2020-02-03 stsp static const struct got_error *
3415 626b25b6 2020-02-06 tracey gw_output_repo_tree(struct gw_trans *gw_trans)
3416 ec46ccd7 2020-01-15 tracey {
3417 ec46ccd7 2020-01-15 tracey const struct got_error *error = NULL;
3418 ec46ccd7 2020-01-15 tracey struct got_repository *repo = NULL;
3419 bcbc97d8 2020-01-15 tracey struct got_object_id *tree_id = NULL, *commit_id = NULL;
3420 bcbc97d8 2020-01-15 tracey struct got_tree_object *tree = NULL;
3421 626b25b6 2020-02-06 tracey char *path = NULL, *in_repo_path = NULL;
3422 84bf4df2 2020-02-03 stsp char *id_str = NULL;
3423 84bf4df2 2020-02-03 stsp char *build_folder = NULL;
3424 626b25b6 2020-02-06 tracey char *href_blob = NULL, *href_blame = NULL;
3425 84bf4df2 2020-02-03 stsp const char *class = NULL;
3426 c3bcdfd5 2020-01-29 tracey int nentries, i, class_flip = 0;
3427 626b25b6 2020-02-06 tracey enum kcgi_err kerr = KCGI_OK;
3428 8d4d2453 2020-01-15 tracey
3429 bcbc97d8 2020-01-15 tracey error = got_repo_open(&repo, gw_trans->repo_path, NULL);
3430 ec46ccd7 2020-01-15 tracey if (error)
3431 bcbc97d8 2020-01-15 tracey goto done;
3432 bcbc97d8 2020-01-15 tracey
3433 ec46ccd7 2020-01-15 tracey if (gw_trans->repo_folder != NULL)
3434 ec46ccd7 2020-01-15 tracey path = strdup(gw_trans->repo_folder);
3435 84bf4df2 2020-02-03 stsp else {
3436 84bf4df2 2020-02-03 stsp error = got_repo_map_path(&in_repo_path, repo,
3437 84bf4df2 2020-02-03 stsp gw_trans->repo_path, 1);
3438 84bf4df2 2020-02-03 stsp if (error)
3439 84bf4df2 2020-02-03 stsp goto done;
3440 bcbc97d8 2020-01-15 tracey free(path);
3441 bcbc97d8 2020-01-15 tracey path = in_repo_path;
3442 bcbc97d8 2020-01-15 tracey }
3443 bcbc97d8 2020-01-15 tracey
3444 f2f46662 2020-01-23 tracey if (gw_trans->commit == NULL) {
3445 ec46ccd7 2020-01-15 tracey struct got_reference *head_ref;
3446 ec46ccd7 2020-01-15 tracey error = got_ref_open(&head_ref, repo, gw_trans->headref, 0);
3447 ec46ccd7 2020-01-15 tracey if (error)
3448 ec46ccd7 2020-01-15 tracey goto done;
3449 ec46ccd7 2020-01-15 tracey error = got_ref_resolve(&commit_id, repo, head_ref);
3450 84bf4df2 2020-02-03 stsp if (error)
3451 84bf4df2 2020-02-03 stsp goto done;
3452 ec46ccd7 2020-01-15 tracey got_ref_close(head_ref);
3453 ec46ccd7 2020-01-15 tracey
3454 84bf4df2 2020-02-03 stsp } else {
3455 f2f46662 2020-01-23 tracey error = got_repo_match_object_id(&commit_id, NULL,
3456 f2f46662 2020-01-23 tracey gw_trans->commit, GOT_OBJ_TYPE_COMMIT, 1, repo);
3457 84bf4df2 2020-02-03 stsp if (error)
3458 84bf4df2 2020-02-03 stsp goto done;
3459 84bf4df2 2020-02-03 stsp }
3460 f2f46662 2020-01-23 tracey
3461 f2f46662 2020-01-23 tracey error = got_object_id_str(&gw_trans->commit, commit_id);
3462 bcbc97d8 2020-01-15 tracey if (error)
3463 bcbc97d8 2020-01-15 tracey goto done;
3464 bcbc97d8 2020-01-15 tracey
3465 ec46ccd7 2020-01-15 tracey error = got_object_id_by_path(&tree_id, repo, commit_id, path);
3466 bcbc97d8 2020-01-15 tracey if (error)
3467 bcbc97d8 2020-01-15 tracey goto done;
3468 bcbc97d8 2020-01-15 tracey
3469 bcbc97d8 2020-01-15 tracey error = got_object_open_as_tree(&tree, repo, tree_id);
3470 bcbc97d8 2020-01-15 tracey if (error)
3471 bcbc97d8 2020-01-15 tracey goto done;
3472 bcbc97d8 2020-01-15 tracey
3473 bcbc97d8 2020-01-15 tracey nentries = got_object_tree_get_nentries(tree);
3474 bcbc97d8 2020-01-15 tracey for (i = 0; i < nentries; i++) {
3475 bcbc97d8 2020-01-15 tracey struct got_tree_entry *te;
3476 ec46ccd7 2020-01-15 tracey const char *modestr = "";
3477 84bf4df2 2020-02-03 stsp mode_t mode;
3478 bcbc97d8 2020-01-15 tracey
3479 bcbc97d8 2020-01-15 tracey te = got_object_tree_get_entry(tree, i);
3480 bcbc97d8 2020-01-15 tracey
3481 bcbc97d8 2020-01-15 tracey error = got_object_id_str(&id_str, got_tree_entry_get_id(te));
3482 bcbc97d8 2020-01-15 tracey if (error)
3483 bcbc97d8 2020-01-15 tracey goto done;
3484 bcbc97d8 2020-01-15 tracey
3485 84bf4df2 2020-02-03 stsp mode = got_tree_entry_get_mode(te);
3486 bcbc97d8 2020-01-15 tracey if (got_object_tree_entry_is_submodule(te))
3487 bcbc97d8 2020-01-15 tracey modestr = "$";
3488 bcbc97d8 2020-01-15 tracey else if (S_ISLNK(mode))
3489 bcbc97d8 2020-01-15 tracey modestr = "@";
3490 bcbc97d8 2020-01-15 tracey else if (S_ISDIR(mode))
3491 bcbc97d8 2020-01-15 tracey modestr = "/";
3492 bcbc97d8 2020-01-15 tracey else if (mode & S_IXUSR)
3493 bcbc97d8 2020-01-15 tracey modestr = "*";
3494 c3bcdfd5 2020-01-29 tracey
3495 c3bcdfd5 2020-01-29 tracey if (class_flip == 0) {
3496 84bf4df2 2020-02-03 stsp class = "back_lightgray";
3497 c3bcdfd5 2020-01-29 tracey class_flip = 1;
3498 c3bcdfd5 2020-01-29 tracey } else {
3499 84bf4df2 2020-02-03 stsp class = "back_white";
3500 c3bcdfd5 2020-01-29 tracey class_flip = 0;
3501 c3bcdfd5 2020-01-29 tracey }
3502 bcbc97d8 2020-01-15 tracey
3503 84bf4df2 2020-02-03 stsp if (S_ISDIR(mode)) {
3504 a5594e37 2020-02-05 tracey if (asprintf(&build_folder, "%s/%s",
3505 84bf4df2 2020-02-03 stsp gw_trans->repo_folder ? gw_trans->repo_folder : "",
3506 84bf4df2 2020-02-03 stsp got_tree_entry_get_name(te)) == -1) {
3507 84bf4df2 2020-02-03 stsp error = got_error_from_errno(
3508 84bf4df2 2020-02-03 stsp "asprintf");
3509 84bf4df2 2020-02-03 stsp goto done;
3510 ec46ccd7 2020-01-15 tracey }
3511 626b25b6 2020-02-06 tracey if (asprintf(&href_blob,
3512 626b25b6 2020-02-06 tracey "?path=%s&action=%s&commit=%s&folder=%s",
3513 ec46ccd7 2020-01-15 tracey gw_trans->repo_name, gw_trans->action_name,
3514 626b25b6 2020-02-06 tracey gw_trans->commit, build_folder) == -1) {
3515 ec46ccd7 2020-01-15 tracey error = got_error_from_errno("asprintf");
3516 ec46ccd7 2020-01-15 tracey goto done;
3517 ec46ccd7 2020-01-15 tracey }
3518 626b25b6 2020-02-06 tracey
3519 626b25b6 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
3520 626b25b6 2020-02-06 tracey KATTR_ID, "tree_wrapper", KATTR__MAX);
3521 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3522 626b25b6 2020-02-06 tracey goto done;
3523 626b25b6 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
3524 626b25b6 2020-02-06 tracey KATTR_ID, "tree_line", KATTR_CLASS, class,
3525 626b25b6 2020-02-06 tracey KATTR__MAX);
3526 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3527 626b25b6 2020-02-06 tracey goto done;
3528 626b25b6 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
3529 626b25b6 2020-02-06 tracey KATTR_HREF, href_blob, KATTR_CLASS,
3530 626b25b6 2020-02-06 tracey "diff_directory", KATTR__MAX);
3531 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3532 626b25b6 2020-02-06 tracey goto done;
3533 626b25b6 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req,
3534 626b25b6 2020-02-06 tracey got_tree_entry_get_name(te));
3535 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3536 626b25b6 2020-02-06 tracey goto done;
3537 626b25b6 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req, modestr);
3538 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3539 626b25b6 2020-02-06 tracey goto done;
3540 626b25b6 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
3541 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3542 626b25b6 2020-02-06 tracey goto done;
3543 626b25b6 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
3544 626b25b6 2020-02-06 tracey KATTR_ID, "tree_line_blank", KATTR_CLASS, class,
3545 626b25b6 2020-02-06 tracey KATTR__MAX);
3546 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3547 84bf4df2 2020-02-03 stsp goto done;
3548 626b25b6 2020-02-06 tracey kerr = khtml_entity(gw_trans->gw_html_req,
3549 626b25b6 2020-02-06 tracey KENTITY_nbsp);
3550 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3551 626b25b6 2020-02-06 tracey goto done;
3552 626b25b6 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
3553 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3554 626b25b6 2020-02-06 tracey goto done;
3555 ec46ccd7 2020-01-15 tracey } else {
3556 626b25b6 2020-02-06 tracey if (asprintf(&href_blob,
3557 626b25b6 2020-02-06 tracey "?path=%s&action=%s&commit=%s&file=%s&folder=%s",
3558 626b25b6 2020-02-06 tracey gw_trans->repo_name, "blob", gw_trans->commit,
3559 84bf4df2 2020-02-03 stsp got_tree_entry_get_name(te),
3560 626b25b6 2020-02-06 tracey gw_trans->repo_folder ?
3561 626b25b6 2020-02-06 tracey gw_trans->repo_folder : "") == -1) {
3562 ec46ccd7 2020-01-15 tracey error = got_error_from_errno("asprintf");
3563 ec46ccd7 2020-01-15 tracey goto done;
3564 ec46ccd7 2020-01-15 tracey }
3565 626b25b6 2020-02-06 tracey if (asprintf(&href_blame,
3566 626b25b6 2020-02-06 tracey "?path=%s&action=%s&commit=%s&file=%s&folder=%s",
3567 626b25b6 2020-02-06 tracey gw_trans->repo_name, "blame", gw_trans->commit,
3568 84bf4df2 2020-02-03 stsp got_tree_entry_get_name(te),
3569 626b25b6 2020-02-06 tracey gw_trans->repo_folder ?
3570 626b25b6 2020-02-06 tracey gw_trans->repo_folder : "") == -1) {
3571 e46f587c 2020-01-29 tracey error = got_error_from_errno("asprintf");
3572 e46f587c 2020-01-29 tracey goto done;
3573 e46f587c 2020-01-29 tracey }
3574 ec46ccd7 2020-01-15 tracey
3575 626b25b6 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
3576 626b25b6 2020-02-06 tracey KATTR_ID, "tree_wrapper", KATTR__MAX);
3577 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3578 626b25b6 2020-02-06 tracey goto done;
3579 626b25b6 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
3580 626b25b6 2020-02-06 tracey KATTR_ID, "tree_line", KATTR_CLASS, class,
3581 626b25b6 2020-02-06 tracey KATTR__MAX);
3582 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3583 626b25b6 2020-02-06 tracey goto done;
3584 626b25b6 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
3585 626b25b6 2020-02-06 tracey KATTR_HREF, href_blob, KATTR__MAX);
3586 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3587 626b25b6 2020-02-06 tracey goto done;
3588 626b25b6 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req,
3589 626b25b6 2020-02-06 tracey got_tree_entry_get_name(te));
3590 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3591 626b25b6 2020-02-06 tracey goto done;
3592 626b25b6 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req, modestr);
3593 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3594 626b25b6 2020-02-06 tracey goto done;
3595 626b25b6 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
3596 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3597 626b25b6 2020-02-06 tracey goto done;
3598 626b25b6 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
3599 626b25b6 2020-02-06 tracey KATTR_ID, "tree_line_navs", KATTR_CLASS, class,
3600 626b25b6 2020-02-06 tracey KATTR__MAX);
3601 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3602 626b25b6 2020-02-06 tracey goto done;
3603 ec46ccd7 2020-01-15 tracey
3604 626b25b6 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
3605 626b25b6 2020-02-06 tracey KATTR_HREF, href_blob, KATTR__MAX);
3606 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3607 626b25b6 2020-02-06 tracey goto done;
3608 626b25b6 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req, "blob");
3609 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3610 626b25b6 2020-02-06 tracey goto done;
3611 626b25b6 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
3612 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3613 626b25b6 2020-02-06 tracey goto done;
3614 626b25b6 2020-02-06 tracey
3615 626b25b6 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req, " | ");
3616 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3617 626b25b6 2020-02-06 tracey goto done;
3618 626b25b6 2020-02-06 tracey
3619 626b25b6 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
3620 626b25b6 2020-02-06 tracey KATTR_HREF, href_blame, KATTR__MAX);
3621 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3622 626b25b6 2020-02-06 tracey goto done;
3623 626b25b6 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req, "blame");
3624 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3625 626b25b6 2020-02-06 tracey goto done;
3626 626b25b6 2020-02-06 tracey
3627 626b25b6 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 3);
3628 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3629 626b25b6 2020-02-06 tracey goto done;
3630 626b25b6 2020-02-06 tracey }
3631 bcbc97d8 2020-01-15 tracey free(id_str);
3632 84bf4df2 2020-02-03 stsp id_str = NULL;
3633 626b25b6 2020-02-06 tracey free(href_blob);
3634 626b25b6 2020-02-06 tracey href_blob = NULL;
3635 84bf4df2 2020-02-03 stsp free(build_folder);
3636 84bf4df2 2020-02-03 stsp build_folder = NULL;
3637 bcbc97d8 2020-01-15 tracey }
3638 bcbc97d8 2020-01-15 tracey done:
3639 bcbc97d8 2020-01-15 tracey if (tree)
3640 bcbc97d8 2020-01-15 tracey got_object_tree_close(tree);
3641 2e676fc5 2020-01-15 tracey if (repo)
3642 2e676fc5 2020-01-15 tracey got_repo_close(repo);
3643 84bf4df2 2020-02-03 stsp free(id_str);
3644 626b25b6 2020-02-06 tracey free(href_blob);
3645 626b25b6 2020-02-06 tracey free(href_blame);
3646 2e676fc5 2020-01-15 tracey free(in_repo_path);
3647 bcbc97d8 2020-01-15 tracey free(tree_id);
3648 84bf4df2 2020-02-03 stsp free(build_folder);
3649 626b25b6 2020-02-06 tracey if (error == NULL && kerr != KCGI_OK)
3650 626b25b6 2020-02-06 tracey error = gw_kcgi_error(kerr);
3651 84bf4df2 2020-02-03 stsp return error;
3652 bcbc97d8 2020-01-15 tracey }
3653 bcbc97d8 2020-01-15 tracey
3654 51d4a92d 2020-02-03 tracey static const struct got_error *
3655 51d4a92d 2020-02-03 tracey gw_get_repo_heads(char **head_html, struct gw_trans *gw_trans)
3656 8d4d2453 2020-01-15 tracey {
3657 87f9ebf5 2020-01-15 tracey const struct got_error *error = NULL;
3658 87f9ebf5 2020-01-15 tracey struct got_repository *repo = NULL;
3659 87f9ebf5 2020-01-15 tracey struct got_reflist_head refs;
3660 87f9ebf5 2020-01-15 tracey struct got_reflist_entry *re;
3661 51d4a92d 2020-02-03 tracey char *head_row = NULL, *head_navs_disp = NULL, *age = NULL;
3662 87f9ebf5 2020-01-15 tracey struct buf *diffbuf = NULL;
3663 87f9ebf5 2020-01-15 tracey size_t newsize;
3664 a0f36e03 2020-01-28 stsp
3665 51d4a92d 2020-02-03 tracey *head_html = NULL;
3666 51d4a92d 2020-02-03 tracey
3667 a0f36e03 2020-01-28 stsp SIMPLEQ_INIT(&refs);
3668 8d4d2453 2020-01-15 tracey
3669 6c6c85af 2020-01-15 tracey error = buf_alloc(&diffbuf, 0);
3670 ec46ccd7 2020-01-15 tracey if (error)
3671 6c6c85af 2020-01-15 tracey return NULL;
3672 87f9ebf5 2020-01-15 tracey
3673 87f9ebf5 2020-01-15 tracey error = got_repo_open(&repo, gw_trans->repo_path, NULL);
3674 ec46ccd7 2020-01-15 tracey if (error)
3675 87f9ebf5 2020-01-15 tracey goto done;
3676 87f9ebf5 2020-01-15 tracey
3677 87f9ebf5 2020-01-15 tracey error = got_ref_list(&refs, repo, "refs/heads", got_ref_cmp_by_name,
3678 87f9ebf5 2020-01-15 tracey NULL);
3679 87f9ebf5 2020-01-15 tracey if (error)
3680 87f9ebf5 2020-01-15 tracey goto done;
3681 87f9ebf5 2020-01-15 tracey
3682 87f9ebf5 2020-01-15 tracey SIMPLEQ_FOREACH(re, &refs, entry) {
3683 87f9ebf5 2020-01-15 tracey char *refname;
3684 87f9ebf5 2020-01-15 tracey
3685 87f9ebf5 2020-01-15 tracey refname = strdup(got_ref_get_name(re->ref));
3686 87f9ebf5 2020-01-15 tracey if (refname == NULL) {
3687 87f9ebf5 2020-01-15 tracey error = got_error_from_errno("got_ref_to_str");
3688 87f9ebf5 2020-01-15 tracey goto done;
3689 87f9ebf5 2020-01-15 tracey }
3690 87f9ebf5 2020-01-15 tracey
3691 87f9ebf5 2020-01-15 tracey if (strncmp(refname, "refs/heads/", 11) != 0) {
3692 87f9ebf5 2020-01-15 tracey free(refname);
3693 87f9ebf5 2020-01-15 tracey continue;
3694 87f9ebf5 2020-01-15 tracey }
3695 87f9ebf5 2020-01-15 tracey
3696 017d6da3 2020-01-29 tracey error = gw_get_repo_age(&age, gw_trans, gw_trans->gw_dir->path,
3697 017d6da3 2020-01-29 tracey refname, TM_DIFF);
3698 d126c1b7 2020-01-29 stsp if (error)
3699 d126c1b7 2020-01-29 stsp goto done;
3700 87f9ebf5 2020-01-15 tracey
3701 88d59c36 2020-01-29 stsp if (asprintf(&head_navs_disp, heads_navs, gw_trans->repo_name,
3702 87f9ebf5 2020-01-15 tracey refname, gw_trans->repo_name, refname,
3703 87f9ebf5 2020-01-15 tracey gw_trans->repo_name, refname, gw_trans->repo_name,
3704 88d59c36 2020-01-29 stsp refname) == -1) {
3705 87f9ebf5 2020-01-15 tracey error = got_error_from_errno("asprintf");
3706 87f9ebf5 2020-01-15 tracey goto done;
3707 87f9ebf5 2020-01-15 tracey }
3708 87f9ebf5 2020-01-15 tracey
3709 87f9ebf5 2020-01-15 tracey if (strncmp(refname, "refs/heads/", 11) == 0)
3710 87f9ebf5 2020-01-15 tracey refname += 11;
3711 87f9ebf5 2020-01-15 tracey
3712 88d59c36 2020-01-29 stsp if (asprintf(&head_row, heads_row, age, refname,
3713 88d59c36 2020-01-29 stsp head_navs_disp) == -1) {
3714 87f9ebf5 2020-01-15 tracey error = got_error_from_errno("asprintf");
3715 87f9ebf5 2020-01-15 tracey goto done;
3716 87f9ebf5 2020-01-15 tracey }
3717 87f9ebf5 2020-01-15 tracey
3718 6c6c85af 2020-01-15 tracey error = buf_puts(&newsize, diffbuf, head_row);
3719 87f9ebf5 2020-01-15 tracey
3720 87f9ebf5 2020-01-15 tracey free(head_navs_disp);
3721 87f9ebf5 2020-01-15 tracey free(head_row);
3722 87f9ebf5 2020-01-15 tracey }
3723 87f9ebf5 2020-01-15 tracey
3724 6c6c85af 2020-01-15 tracey if (buf_len(diffbuf) > 0) {
3725 6c6c85af 2020-01-15 tracey error = buf_putc(diffbuf, '\0');
3726 51d4a92d 2020-02-03 tracey *head_html = strdup(buf_get(diffbuf));
3727 51d4a92d 2020-02-03 tracey if (*head_html == NULL)
3728 51d4a92d 2020-02-03 tracey error = got_error_from_errno("strdup");
3729 6c6c85af 2020-01-15 tracey }
3730 87f9ebf5 2020-01-15 tracey done:
3731 87f9ebf5 2020-01-15 tracey buf_free(diffbuf);
3732 87f9ebf5 2020-01-15 tracey got_ref_list_free(&refs);
3733 87f9ebf5 2020-01-15 tracey if (repo)
3734 87f9ebf5 2020-01-15 tracey got_repo_close(repo);
3735 51d4a92d 2020-02-03 tracey return error;
3736 8d4d2453 2020-01-15 tracey }
3737 8d4d2453 2020-01-15 tracey
3738 8d4d2453 2020-01-15 tracey static char *
3739 54415d85 2020-01-15 tracey gw_get_site_link(struct gw_trans *gw_trans)
3740 2c251c14 2020-01-15 tracey {
3741 eb89db64 2020-02-03 stsp char *link = NULL, *repo = NULL, *action = NULL;
3742 2c251c14 2020-01-15 tracey
3743 eb89db64 2020-02-03 stsp if (gw_trans->repo_name != NULL &&
3744 eb89db64 2020-02-03 stsp asprintf(&repo, " / <a href='?path=%s&action=summary'>%s</a>",
3745 eb89db64 2020-02-03 stsp gw_trans->repo_name, gw_trans->repo_name) == -1)
3746 eb89db64 2020-02-03 stsp return NULL;
3747 2c251c14 2020-01-15 tracey
3748 eb89db64 2020-02-03 stsp if (gw_trans->action_name != NULL &&
3749 eb89db64 2020-02-03 stsp asprintf(&action, " / %s", gw_trans->action_name) == -1) {
3750 eb89db64 2020-02-03 stsp free(repo);
3751 eb89db64 2020-02-03 stsp return NULL;
3752 eb89db64 2020-02-03 stsp }
3753 2c251c14 2020-01-15 tracey
3754 88d59c36 2020-01-29 stsp if (asprintf(&link, site_link, GOTWEB,
3755 eb89db64 2020-02-03 stsp gw_trans->gw_conf->got_site_link,
3756 eb89db64 2020-02-03 stsp repo ? repo : "", action ? action : "") == -1) {
3757 eb89db64 2020-02-03 stsp free(repo);
3758 eb89db64 2020-02-03 stsp free(action);
3759 2c251c14 2020-01-15 tracey return NULL;
3760 eb89db64 2020-02-03 stsp }
3761 2c251c14 2020-01-15 tracey
3762 eb89db64 2020-02-03 stsp free(repo);
3763 eb89db64 2020-02-03 stsp free(action);
3764 2c251c14 2020-01-15 tracey return link;
3765 2c251c14 2020-01-15 tracey }
3766 2c251c14 2020-01-15 tracey
3767 83eb9a68 2020-02-03 stsp static const struct got_error *
3768 f7cc9480 2020-02-05 tracey gw_colordiff_line(struct gw_trans *gw_trans, char *buf)
3769 ec46ccd7 2020-01-15 tracey {
3770 ec46ccd7 2020-01-15 tracey const struct got_error *error = NULL;
3771 f7cc9480 2020-02-05 tracey char *color = NULL;
3772 f7cc9480 2020-02-05 tracey enum kcgi_err kerr = KCGI_OK;
3773 83eb9a68 2020-02-03 stsp
3774 ec46ccd7 2020-01-15 tracey if (strncmp(buf, "-", 1) == 0)
3775 ec46ccd7 2020-01-15 tracey color = "diff_minus";
3776 83eb9a68 2020-02-03 stsp else if (strncmp(buf, "+", 1) == 0)
3777 ec46ccd7 2020-01-15 tracey color = "diff_plus";
3778 83eb9a68 2020-02-03 stsp else if (strncmp(buf, "@@", 2) == 0)
3779 ec46ccd7 2020-01-15 tracey color = "diff_chunk_header";
3780 83eb9a68 2020-02-03 stsp else if (strncmp(buf, "@@", 2) == 0)
3781 ec46ccd7 2020-01-15 tracey color = "diff_chunk_header";
3782 83eb9a68 2020-02-03 stsp else if (strncmp(buf, "commit +", 8) == 0)
3783 ec46ccd7 2020-01-15 tracey color = "diff_meta";
3784 83eb9a68 2020-02-03 stsp else if (strncmp(buf, "commit -", 8) == 0)
3785 ec46ccd7 2020-01-15 tracey color = "diff_meta";
3786 83eb9a68 2020-02-03 stsp else if (strncmp(buf, "blob +", 6) == 0)
3787 ec46ccd7 2020-01-15 tracey color = "diff_meta";
3788 83eb9a68 2020-02-03 stsp else if (strncmp(buf, "blob -", 6) == 0)
3789 ec46ccd7 2020-01-15 tracey color = "diff_meta";
3790 83eb9a68 2020-02-03 stsp else if (strncmp(buf, "file +", 6) == 0)
3791 ec46ccd7 2020-01-15 tracey color = "diff_meta";
3792 83eb9a68 2020-02-03 stsp else if (strncmp(buf, "file -", 6) == 0)
3793 ec46ccd7 2020-01-15 tracey color = "diff_meta";
3794 83eb9a68 2020-02-03 stsp else if (strncmp(buf, "from:", 5) == 0)
3795 ec46ccd7 2020-01-15 tracey color = "diff_author";
3796 83eb9a68 2020-02-03 stsp else if (strncmp(buf, "via:", 4) == 0)
3797 ec46ccd7 2020-01-15 tracey color = "diff_author";
3798 83eb9a68 2020-02-03 stsp else if (strncmp(buf, "date:", 5) == 0)
3799 ec46ccd7 2020-01-15 tracey color = "diff_date";
3800 f7cc9480 2020-02-05 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
3801 f7cc9480 2020-02-05 tracey "diff_line", KATTR_CLASS, color ? color : "", KATTR__MAX);
3802 f7cc9480 2020-02-05 tracey if (error == NULL && kerr != KCGI_OK)
3803 2447adad 2020-02-06 stsp error = gw_kcgi_error(kerr);
3804 83eb9a68 2020-02-03 stsp return error;
3805 ec46ccd7 2020-01-15 tracey }
3806 ec46ccd7 2020-01-15 tracey
3807 070fee27 2020-02-03 stsp /*
3808 070fee27 2020-02-03 stsp * XXX This function should not exist.
3809 070fee27 2020-02-03 stsp * We should let khtml_puts(3) handle HTML escaping.
3810 070fee27 2020-02-03 stsp */
3811 070fee27 2020-02-03 stsp static const struct got_error *
3812 070fee27 2020-02-03 stsp gw_html_escape(char **escaped_html, const char *orig_html)
3813 2c251c14 2020-01-15 tracey {
3814 070fee27 2020-02-03 stsp const struct got_error *error = NULL;
3815 070fee27 2020-02-03 stsp struct escape_pair {
3816 070fee27 2020-02-03 stsp char c;
3817 070fee27 2020-02-03 stsp const char *s;
3818 070fee27 2020-02-03 stsp } esc[] = {
3819 070fee27 2020-02-03 stsp { '>', "&gt;" },
3820 070fee27 2020-02-03 stsp { '<', "&lt;" },
3821 070fee27 2020-02-03 stsp { '&', "&amp;" },
3822 070fee27 2020-02-03 stsp { '"', "&quot;" },
3823 070fee27 2020-02-03 stsp { '\'', "&apos;" },
3824 070fee27 2020-02-03 stsp { '\n', "<br />" },
3825 070fee27 2020-02-03 stsp };
3826 070fee27 2020-02-03 stsp size_t orig_len, len;
3827 070fee27 2020-02-03 stsp int i, j, x;
3828 2c251c14 2020-01-15 tracey
3829 070fee27 2020-02-03 stsp orig_len = strlen(orig_html);
3830 070fee27 2020-02-03 stsp len = orig_len;
3831 070fee27 2020-02-03 stsp for (i = 0; i < orig_len; i++) {
3832 070fee27 2020-02-03 stsp for (j = 0; j < nitems(esc); j++) {
3833 070fee27 2020-02-03 stsp if (orig_html[i] != esc[j].c)
3834 070fee27 2020-02-03 stsp continue;
3835 070fee27 2020-02-03 stsp len += strlen(esc[j].s) - 1 /* escaped char */;
3836 070fee27 2020-02-03 stsp }
3837 070fee27 2020-02-03 stsp }
3838 2c251c14 2020-01-15 tracey
3839 070fee27 2020-02-03 stsp *escaped_html = calloc(len + 1 /* NUL */, sizeof(**escaped_html));
3840 070fee27 2020-02-03 stsp if (*escaped_html == NULL)
3841 070fee27 2020-02-03 stsp return got_error_from_errno("calloc");
3842 070fee27 2020-02-03 stsp
3843 070fee27 2020-02-03 stsp x = 0;
3844 070fee27 2020-02-03 stsp for (i = 0; i < orig_len; i++) {
3845 070fee27 2020-02-03 stsp int escaped = 0;
3846 070fee27 2020-02-03 stsp for (j = 0; j < nitems(esc); j++) {
3847 070fee27 2020-02-03 stsp if (orig_html[i] != esc[j].c)
3848 070fee27 2020-02-03 stsp continue;
3849 2c251c14 2020-01-15 tracey
3850 070fee27 2020-02-03 stsp if (strlcat(*escaped_html, esc[j].s, len + 1)
3851 070fee27 2020-02-03 stsp >= len + 1) {
3852 070fee27 2020-02-03 stsp error = got_error(GOT_ERR_NO_SPACE);
3853 070fee27 2020-02-03 stsp goto done;
3854 070fee27 2020-02-03 stsp }
3855 070fee27 2020-02-03 stsp x += strlen(esc[j].s);
3856 070fee27 2020-02-03 stsp escaped = 1;
3857 2c251c14 2020-01-15 tracey break;
3858 2c251c14 2020-01-15 tracey }
3859 070fee27 2020-02-03 stsp if (!escaped) {
3860 070fee27 2020-02-03 stsp (*escaped_html)[x] = orig_html[i];
3861 070fee27 2020-02-03 stsp x++;
3862 070fee27 2020-02-03 stsp }
3863 2c251c14 2020-01-15 tracey }
3864 070fee27 2020-02-03 stsp done:
3865 070fee27 2020-02-03 stsp if (error) {
3866 070fee27 2020-02-03 stsp free(*escaped_html);
3867 070fee27 2020-02-03 stsp *escaped_html = NULL;
3868 070fee27 2020-02-03 stsp } else {
3869 070fee27 2020-02-03 stsp (*escaped_html)[x] = '\0';
3870 070fee27 2020-02-03 stsp }
3871 070fee27 2020-02-03 stsp return error;
3872 2c251c14 2020-01-15 tracey }
3873 2c251c14 2020-01-15 tracey
3874 2c251c14 2020-01-15 tracey int
3875 c08369d7 2020-01-15 tracey main(int argc, char *argv[])
3876 2c251c14 2020-01-15 tracey {
3877 2c251c14 2020-01-15 tracey const struct got_error *error = NULL;
3878 54415d85 2020-01-15 tracey struct gw_trans *gw_trans;
3879 2c251c14 2020-01-15 tracey struct gw_dir *dir = NULL, *tdir;
3880 2c251c14 2020-01-15 tracey const char *page = "index";
3881 4ceb8155 2020-01-15 tracey int gw_malloc = 1;
3882 c25c2314 2020-01-28 stsp enum kcgi_err kerr;
3883 2c251c14 2020-01-15 tracey
3884 54415d85 2020-01-15 tracey if ((gw_trans = malloc(sizeof(struct gw_trans))) == NULL)
3885 2c251c14 2020-01-15 tracey errx(1, "malloc");
3886 2c251c14 2020-01-15 tracey
3887 2c251c14 2020-01-15 tracey if ((gw_trans->gw_req = malloc(sizeof(struct kreq))) == NULL)
3888 2c251c14 2020-01-15 tracey errx(1, "malloc");
3889 2c251c14 2020-01-15 tracey
3890 2c251c14 2020-01-15 tracey if ((gw_trans->gw_html_req = malloc(sizeof(struct khtmlreq))) == NULL)
3891 2c251c14 2020-01-15 tracey errx(1, "malloc");
3892 2c251c14 2020-01-15 tracey
3893 2c251c14 2020-01-15 tracey if ((gw_trans->gw_tmpl = malloc(sizeof(struct ktemplate))) == NULL)
3894 2c251c14 2020-01-15 tracey errx(1, "malloc");
3895 2c251c14 2020-01-15 tracey
3896 c25c2314 2020-01-28 stsp kerr = khttp_parse(gw_trans->gw_req, gw_keys, KEY__ZMAX, &page, 1, 0);
3897 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK) {
3898 2447adad 2020-02-06 stsp error = gw_kcgi_error(kerr);
3899 c119608e 2020-01-28 stsp goto done;
3900 c25c2314 2020-01-28 stsp }
3901 2c251c14 2020-01-15 tracey
3902 2c251c14 2020-01-15 tracey if ((gw_trans->gw_conf =
3903 2c251c14 2020-01-15 tracey malloc(sizeof(struct gotweb_conf))) == NULL) {
3904 4ceb8155 2020-01-15 tracey gw_malloc = 0;
3905 387a29ba 2020-01-15 tracey error = got_error_from_errno("malloc");
3906 c119608e 2020-01-28 stsp goto done;
3907 46b9c89b 2020-01-15 tracey }
3908 46b9c89b 2020-01-15 tracey
3909 2c251c14 2020-01-15 tracey TAILQ_INIT(&gw_trans->gw_dirs);
3910 f2f46662 2020-01-23 tracey TAILQ_INIT(&gw_trans->gw_headers);
3911 2c251c14 2020-01-15 tracey
3912 2c251c14 2020-01-15 tracey gw_trans->page = 0;
3913 2c251c14 2020-01-15 tracey gw_trans->repos_total = 0;
3914 2c251c14 2020-01-15 tracey gw_trans->repo_path = NULL;
3915 2c251c14 2020-01-15 tracey gw_trans->commit = NULL;
3916 8087c3c5 2020-01-15 tracey gw_trans->headref = strdup(GOT_REF_HEAD);
3917 2c251c14 2020-01-15 tracey gw_trans->mime = KMIME_TEXT_HTML;
3918 54415d85 2020-01-15 tracey gw_trans->gw_tmpl->key = gw_templs;
3919 2c251c14 2020-01-15 tracey gw_trans->gw_tmpl->keysz = TEMPL__MAX;
3920 2c251c14 2020-01-15 tracey gw_trans->gw_tmpl->arg = gw_trans;
3921 2c251c14 2020-01-15 tracey gw_trans->gw_tmpl->cb = gw_template;
3922 2c251c14 2020-01-15 tracey error = parse_conf(GOTWEB_CONF, gw_trans->gw_conf);
3923 c119608e 2020-01-28 stsp if (error)
3924 2c251c14 2020-01-15 tracey goto done;
3925 2c251c14 2020-01-15 tracey
3926 2c251c14 2020-01-15 tracey error = gw_parse_querystring(gw_trans);
3927 2c251c14 2020-01-15 tracey if (error)
3928 c119608e 2020-01-28 stsp goto done;
3929 2c251c14 2020-01-15 tracey
3930 017d6da3 2020-01-29 tracey if (gw_trans->action == GW_BLOB)
3931 017d6da3 2020-01-29 tracey error = gw_blob(gw_trans);
3932 017d6da3 2020-01-29 tracey else
3933 017d6da3 2020-01-29 tracey error = gw_display_index(gw_trans);
3934 2c251c14 2020-01-15 tracey done:
3935 c119608e 2020-01-28 stsp if (error) {
3936 c119608e 2020-01-28 stsp gw_trans->mime = KMIME_TEXT_PLAIN;
3937 c119608e 2020-01-28 stsp gw_trans->action = GW_ERR;
3938 6d8d8a26 2020-01-29 stsp gw_display_error(gw_trans, error);
3939 c119608e 2020-01-28 stsp }
3940 2c251c14 2020-01-15 tracey if (gw_malloc) {
3941 2c251c14 2020-01-15 tracey free(gw_trans->gw_conf->got_repos_path);
3942 2c251c14 2020-01-15 tracey free(gw_trans->gw_conf->got_site_name);
3943 2c251c14 2020-01-15 tracey free(gw_trans->gw_conf->got_site_owner);
3944 2c251c14 2020-01-15 tracey free(gw_trans->gw_conf->got_site_link);
3945 2c251c14 2020-01-15 tracey free(gw_trans->gw_conf->got_logo);
3946 2c251c14 2020-01-15 tracey free(gw_trans->gw_conf->got_logo_url);
3947 2c251c14 2020-01-15 tracey free(gw_trans->gw_conf);
3948 2c251c14 2020-01-15 tracey free(gw_trans->commit);
3949 2c251c14 2020-01-15 tracey free(gw_trans->repo_path);
3950 2c251c14 2020-01-15 tracey free(gw_trans->repo_name);
3951 2c251c14 2020-01-15 tracey free(gw_trans->repo_file);
3952 2c251c14 2020-01-15 tracey free(gw_trans->action_name);
3953 8087c3c5 2020-01-15 tracey free(gw_trans->headref);
3954 2c251c14 2020-01-15 tracey
3955 2c251c14 2020-01-15 tracey TAILQ_FOREACH_SAFE(dir, &gw_trans->gw_dirs, entry, tdir) {
3956 2c251c14 2020-01-15 tracey free(dir->name);
3957 2c251c14 2020-01-15 tracey free(dir->description);
3958 2c251c14 2020-01-15 tracey free(dir->age);
3959 2c251c14 2020-01-15 tracey free(dir->url);
3960 2c251c14 2020-01-15 tracey free(dir->path);
3961 2c251c14 2020-01-15 tracey free(dir);
3962 2c251c14 2020-01-15 tracey }
3963 2c251c14 2020-01-15 tracey
3964 2c251c14 2020-01-15 tracey }
3965 2c251c14 2020-01-15 tracey
3966 2c251c14 2020-01-15 tracey khttp_free(gw_trans->gw_req);
3967 d56b34ca 2020-01-29 stsp return 0;
3968 2c251c14 2020-01-15 tracey }