summaryrefslogtreecommitdiffabout
authorLars Hjemli <hjemli@gmail.com>2011-05-23 21:10:37 (UTC)
committer Lars Hjemli <hjemli@gmail.com>2011-05-23 21:17:10 (UTC)
commitc8ea73caabcb16ffb74baa70d35650027ed772c4 (patch) (unidiff)
tree07061939e5568c89bd9d96914f7b61ca0b3b6fe7
parent9afc883297b0d0943e9b358d2299950f33e8e5ed (diff)
downloadcgit-c8ea73caabcb16ffb74baa70d35650027ed772c4.zip
cgit-c8ea73caabcb16ffb74baa70d35650027ed772c4.tar.gz
cgit-c8ea73caabcb16ffb74baa70d35650027ed772c4.tar.bz2
ui-repolist.c: do not return random/stale data from read_agefile
When git/date.c:parse_date() cannot parse its input it returns -1. But read_agefile() checks if the result is different from zero, essentialy returning random data from the date buffer when parsing fails. This patch fixes the issue by verifying that the result from parse_date() is positive. Noticed-by: Julius Plenz <plenz@cis.fu-berlin.de> Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--ui-repolist.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/ui-repolist.c b/ui-repolist.c
index 2c98668..e138f59 100644
--- a/ui-repolist.c
+++ b/ui-repolist.c
@@ -1,298 +1,298 @@
1/* ui-repolist.c: functions for generating the repolist page 1/* ui-repolist.c: functions for generating the repolist page
2 * 2 *
3 * Copyright (C) 2006 Lars Hjemli 3 * Copyright (C) 2006 Lars Hjemli
4 * 4 *
5 * Licensed under GNU General Public License v2 5 * Licensed under GNU General Public License v2
6 * (see COPYING for full license text) 6 * (see COPYING for full license text)
7 */ 7 */
8 8
9#include "cgit.h" 9#include "cgit.h"
10#include "html.h" 10#include "html.h"
11#include "ui-shared.h" 11#include "ui-shared.h"
12 12
13time_t read_agefile(char *path) 13time_t read_agefile(char *path)
14{ 14{
15 time_t result; 15 time_t result;
16 size_t size; 16 size_t size;
17 char *buf; 17 char *buf;
18 static char buf2[64]; 18 static char buf2[64];
19 19
20 if (readfile(path, &buf, &size)) 20 if (readfile(path, &buf, &size))
21 return -1; 21 return -1;
22 22
23 if (parse_date(buf, buf2, sizeof(buf2))) 23 if (parse_date(buf, buf2, sizeof(buf2)) > 0)
24 result = strtoul(buf2, NULL, 10); 24 result = strtoul(buf2, NULL, 10);
25 else 25 else
26 result = 0; 26 result = 0;
27 free(buf); 27 free(buf);
28 return result; 28 return result;
29} 29}
30 30
31static int get_repo_modtime(const struct cgit_repo *repo, time_t *mtime) 31static int get_repo_modtime(const struct cgit_repo *repo, time_t *mtime)
32{ 32{
33 char *path; 33 char *path;
34 struct stat s; 34 struct stat s;
35 struct cgit_repo *r = (struct cgit_repo *)repo; 35 struct cgit_repo *r = (struct cgit_repo *)repo;
36 36
37 if (repo->mtime != -1) { 37 if (repo->mtime != -1) {
38 *mtime = repo->mtime; 38 *mtime = repo->mtime;
39 return 1; 39 return 1;
40 } 40 }
41 path = fmt("%s/%s", repo->path, ctx.cfg.agefile); 41 path = fmt("%s/%s", repo->path, ctx.cfg.agefile);
42 if (stat(path, &s) == 0) { 42 if (stat(path, &s) == 0) {
43 *mtime = read_agefile(path); 43 *mtime = read_agefile(path);
44 r->mtime = *mtime; 44 r->mtime = *mtime;
45 return 1; 45 return 1;
46 } 46 }
47 47
48 path = fmt("%s/refs/heads/%s", repo->path, repo->defbranch); 48 path = fmt("%s/refs/heads/%s", repo->path, repo->defbranch);
49 if (stat(path, &s) == 0) 49 if (stat(path, &s) == 0)
50 *mtime = s.st_mtime; 50 *mtime = s.st_mtime;
51 else 51 else
52 *mtime = 0; 52 *mtime = 0;
53 53
54 r->mtime = *mtime; 54 r->mtime = *mtime;
55 return (r->mtime != 0); 55 return (r->mtime != 0);
56} 56}
57 57
58static void print_modtime(struct cgit_repo *repo) 58static void print_modtime(struct cgit_repo *repo)
59{ 59{
60 time_t t; 60 time_t t;
61 if (get_repo_modtime(repo, &t)) 61 if (get_repo_modtime(repo, &t))
62 cgit_print_age(t, -1, NULL); 62 cgit_print_age(t, -1, NULL);
63} 63}
64 64
65int is_match(struct cgit_repo *repo) 65int is_match(struct cgit_repo *repo)
66{ 66{
67 if (!ctx.qry.search) 67 if (!ctx.qry.search)
68 return 1; 68 return 1;
69 if (repo->url && strcasestr(repo->url, ctx.qry.search)) 69 if (repo->url && strcasestr(repo->url, ctx.qry.search))
70 return 1; 70 return 1;
71 if (repo->name && strcasestr(repo->name, ctx.qry.search)) 71 if (repo->name && strcasestr(repo->name, ctx.qry.search))
72 return 1; 72 return 1;
73 if (repo->desc && strcasestr(repo->desc, ctx.qry.search)) 73 if (repo->desc && strcasestr(repo->desc, ctx.qry.search))
74 return 1; 74 return 1;
75 if (repo->owner && strcasestr(repo->owner, ctx.qry.search)) 75 if (repo->owner && strcasestr(repo->owner, ctx.qry.search))
76 return 1; 76 return 1;
77 return 0; 77 return 0;
78} 78}
79 79
80int is_in_url(struct cgit_repo *repo) 80int is_in_url(struct cgit_repo *repo)
81{ 81{
82 if (!ctx.qry.url) 82 if (!ctx.qry.url)
83 return 1; 83 return 1;
84 if (repo->url && !prefixcmp(repo->url, ctx.qry.url)) 84 if (repo->url && !prefixcmp(repo->url, ctx.qry.url))
85 return 1; 85 return 1;
86 return 0; 86 return 0;
87} 87}
88 88
89void print_sort_header(const char *title, const char *sort) 89void print_sort_header(const char *title, const char *sort)
90{ 90{
91 htmlf("<th class='left'><a href='%s?s=%s", cgit_rooturl(), sort); 91 htmlf("<th class='left'><a href='%s?s=%s", cgit_rooturl(), sort);
92 if (ctx.qry.search) { 92 if (ctx.qry.search) {
93 html("&q="); 93 html("&q=");
94 html_url_arg(ctx.qry.search); 94 html_url_arg(ctx.qry.search);
95 } 95 }
96 htmlf("'>%s</a></th>", title); 96 htmlf("'>%s</a></th>", title);
97} 97}
98 98
99void print_header(int columns) 99void print_header(int columns)
100{ 100{
101 html("<tr class='nohover'>"); 101 html("<tr class='nohover'>");
102 print_sort_header("Name", "name"); 102 print_sort_header("Name", "name");
103 print_sort_header("Description", "desc"); 103 print_sort_header("Description", "desc");
104 print_sort_header("Owner", "owner"); 104 print_sort_header("Owner", "owner");
105 print_sort_header("Idle", "idle"); 105 print_sort_header("Idle", "idle");
106 if (ctx.cfg.enable_index_links) 106 if (ctx.cfg.enable_index_links)
107 html("<th class='left'>Links</th>"); 107 html("<th class='left'>Links</th>");
108 html("</tr>\n"); 108 html("</tr>\n");
109} 109}
110 110
111 111
112void print_pager(int items, int pagelen, char *search) 112void print_pager(int items, int pagelen, char *search)
113{ 113{
114 int i; 114 int i;
115 html("<div class='pager'>"); 115 html("<div class='pager'>");
116 for(i = 0; i * pagelen < items; i++) 116 for(i = 0; i * pagelen < items; i++)
117 cgit_index_link(fmt("[%d]", i+1), fmt("Page %d", i+1), NULL, 117 cgit_index_link(fmt("[%d]", i+1), fmt("Page %d", i+1), NULL,
118 search, i * pagelen); 118 search, i * pagelen);
119 html("</div>"); 119 html("</div>");
120} 120}
121 121
122static int cmp(const char *s1, const char *s2) 122static int cmp(const char *s1, const char *s2)
123{ 123{
124 if (s1 && s2) 124 if (s1 && s2)
125 return strcmp(s1, s2); 125 return strcmp(s1, s2);
126 if (s1 && !s2) 126 if (s1 && !s2)
127 return -1; 127 return -1;
128 if (s2 && !s1) 128 if (s2 && !s1)
129 return 1; 129 return 1;
130 return 0; 130 return 0;
131} 131}
132 132
133static int sort_section(const void *a, const void *b) 133static int sort_section(const void *a, const void *b)
134{ 134{
135 const struct cgit_repo *r1 = a; 135 const struct cgit_repo *r1 = a;
136 const struct cgit_repo *r2 = b; 136 const struct cgit_repo *r2 = b;
137 int result; 137 int result;
138 138
139 result = cmp(r1->section, r2->section); 139 result = cmp(r1->section, r2->section);
140 if (!result) 140 if (!result)
141 result = cmp(r1->name, r2->name); 141 result = cmp(r1->name, r2->name);
142 return result; 142 return result;
143} 143}
144 144
145static int sort_name(const void *a, const void *b) 145static int sort_name(const void *a, const void *b)
146{ 146{
147 const struct cgit_repo *r1 = a; 147 const struct cgit_repo *r1 = a;
148 const struct cgit_repo *r2 = b; 148 const struct cgit_repo *r2 = b;
149 149
150 return cmp(r1->name, r2->name); 150 return cmp(r1->name, r2->name);
151} 151}
152 152
153static int sort_desc(const void *a, const void *b) 153static int sort_desc(const void *a, const void *b)
154{ 154{
155 const struct cgit_repo *r1 = a; 155 const struct cgit_repo *r1 = a;
156 const struct cgit_repo *r2 = b; 156 const struct cgit_repo *r2 = b;
157 157
158 return cmp(r1->desc, r2->desc); 158 return cmp(r1->desc, r2->desc);
159} 159}
160 160
161static int sort_owner(const void *a, const void *b) 161static int sort_owner(const void *a, const void *b)
162{ 162{
163 const struct cgit_repo *r1 = a; 163 const struct cgit_repo *r1 = a;
164 const struct cgit_repo *r2 = b; 164 const struct cgit_repo *r2 = b;
165 165
166 return cmp(r1->owner, r2->owner); 166 return cmp(r1->owner, r2->owner);
167} 167}
168 168
169static int sort_idle(const void *a, const void *b) 169static int sort_idle(const void *a, const void *b)
170{ 170{
171 const struct cgit_repo *r1 = a; 171 const struct cgit_repo *r1 = a;
172 const struct cgit_repo *r2 = b; 172 const struct cgit_repo *r2 = b;
173 time_t t1, t2; 173 time_t t1, t2;
174 174
175 t1 = t2 = 0; 175 t1 = t2 = 0;
176 get_repo_modtime(r1, &t1); 176 get_repo_modtime(r1, &t1);
177 get_repo_modtime(r2, &t2); 177 get_repo_modtime(r2, &t2);
178 return t2 - t1; 178 return t2 - t1;
179} 179}
180 180
181struct sortcolumn { 181struct sortcolumn {
182 const char *name; 182 const char *name;
183 int (*fn)(const void *a, const void *b); 183 int (*fn)(const void *a, const void *b);
184}; 184};
185 185
186struct sortcolumn sortcolumn[] = { 186struct sortcolumn sortcolumn[] = {
187 {"section", sort_section}, 187 {"section", sort_section},
188 {"name", sort_name}, 188 {"name", sort_name},
189 {"desc", sort_desc}, 189 {"desc", sort_desc},
190 {"owner", sort_owner}, 190 {"owner", sort_owner},
191 {"idle", sort_idle}, 191 {"idle", sort_idle},
192 {NULL, NULL} 192 {NULL, NULL}
193}; 193};
194 194
195int sort_repolist(char *field) 195int sort_repolist(char *field)
196{ 196{
197 struct sortcolumn *column; 197 struct sortcolumn *column;
198 198
199 for (column = &sortcolumn[0]; column->name; column++) { 199 for (column = &sortcolumn[0]; column->name; column++) {
200 if (strcmp(field, column->name)) 200 if (strcmp(field, column->name))
201 continue; 201 continue;
202 qsort(cgit_repolist.repos, cgit_repolist.count, 202 qsort(cgit_repolist.repos, cgit_repolist.count,
203 sizeof(struct cgit_repo), column->fn); 203 sizeof(struct cgit_repo), column->fn);
204 return 1; 204 return 1;
205 } 205 }
206 return 0; 206 return 0;
207} 207}
208 208
209 209
210void cgit_print_repolist() 210void cgit_print_repolist()
211{ 211{
212 int i, columns = 4, hits = 0, header = 0; 212 int i, columns = 4, hits = 0, header = 0;
213 char *last_section = NULL; 213 char *last_section = NULL;
214 char *section; 214 char *section;
215 int sorted = 0; 215 int sorted = 0;
216 216
217 if (ctx.cfg.enable_index_links) 217 if (ctx.cfg.enable_index_links)
218 columns++; 218 columns++;
219 219
220 ctx.page.title = ctx.cfg.root_title; 220 ctx.page.title = ctx.cfg.root_title;
221 cgit_print_http_headers(&ctx); 221 cgit_print_http_headers(&ctx);
222 cgit_print_docstart(&ctx); 222 cgit_print_docstart(&ctx);
223 cgit_print_pageheader(&ctx); 223 cgit_print_pageheader(&ctx);
224 224
225 if (ctx.cfg.index_header) 225 if (ctx.cfg.index_header)
226 html_include(ctx.cfg.index_header); 226 html_include(ctx.cfg.index_header);
227 227
228 if(ctx.qry.sort) 228 if(ctx.qry.sort)
229 sorted = sort_repolist(ctx.qry.sort); 229 sorted = sort_repolist(ctx.qry.sort);
230 else 230 else
231 sort_repolist("section"); 231 sort_repolist("section");
232 232
233 html("<table summary='repository list' class='list nowrap'>"); 233 html("<table summary='repository list' class='list nowrap'>");
234 for (i=0; i<cgit_repolist.count; i++) { 234 for (i=0; i<cgit_repolist.count; i++) {
235 ctx.repo = &cgit_repolist.repos[i]; 235 ctx.repo = &cgit_repolist.repos[i];
236 if (!(is_match(ctx.repo) && is_in_url(ctx.repo))) 236 if (!(is_match(ctx.repo) && is_in_url(ctx.repo)))
237 continue; 237 continue;
238 hits++; 238 hits++;
239 if (hits <= ctx.qry.ofs) 239 if (hits <= ctx.qry.ofs)
240 continue; 240 continue;
241 if (hits > ctx.qry.ofs + ctx.cfg.max_repo_count) 241 if (hits > ctx.qry.ofs + ctx.cfg.max_repo_count)
242 continue; 242 continue;
243 if (!header++) 243 if (!header++)
244 print_header(columns); 244 print_header(columns);
245 section = ctx.repo->section; 245 section = ctx.repo->section;
246 if (section && !strcmp(section, "")) 246 if (section && !strcmp(section, ""))
247 section = NULL; 247 section = NULL;
248 if (!sorted && 248 if (!sorted &&
249 ((last_section == NULL && section != NULL) || 249 ((last_section == NULL && section != NULL) ||
250 (last_section != NULL && section == NULL) || 250 (last_section != NULL && section == NULL) ||
251 (last_section != NULL && section != NULL && 251 (last_section != NULL && section != NULL &&
252 strcmp(section, last_section)))) { 252 strcmp(section, last_section)))) {
253 htmlf("<tr class='nohover'><td colspan='%d' class='reposection'>", 253 htmlf("<tr class='nohover'><td colspan='%d' class='reposection'>",
254 columns); 254 columns);
255 html_txt(section); 255 html_txt(section);
256 html("</td></tr>"); 256 html("</td></tr>");
257 last_section = section; 257 last_section = section;
258 } 258 }
259 htmlf("<tr><td class='%s'>", 259 htmlf("<tr><td class='%s'>",
260 !sorted && section ? "sublevel-repo" : "toplevel-repo"); 260 !sorted && section ? "sublevel-repo" : "toplevel-repo");
261 cgit_summary_link(ctx.repo->name, ctx.repo->name, NULL, NULL); 261 cgit_summary_link(ctx.repo->name, ctx.repo->name, NULL, NULL);
262 html("</td><td>"); 262 html("</td><td>");
263 html_link_open(cgit_repourl(ctx.repo->url), NULL, NULL); 263 html_link_open(cgit_repourl(ctx.repo->url), NULL, NULL);
264 html_ntxt(ctx.cfg.max_repodesc_len, ctx.repo->desc); 264 html_ntxt(ctx.cfg.max_repodesc_len, ctx.repo->desc);
265 html_link_close(); 265 html_link_close();
266 html("</td><td>"); 266 html("</td><td>");
267 html_txt(ctx.repo->owner); 267 html_txt(ctx.repo->owner);
268 html("</td><td>"); 268 html("</td><td>");
269 print_modtime(ctx.repo); 269 print_modtime(ctx.repo);
270 html("</td>"); 270 html("</td>");
271 if (ctx.cfg.enable_index_links) { 271 if (ctx.cfg.enable_index_links) {
272 html("<td>"); 272 html("<td>");
273 cgit_summary_link("summary", NULL, "button", NULL); 273 cgit_summary_link("summary", NULL, "button", NULL);
274 cgit_log_link("log", NULL, "button", NULL, NULL, NULL, 274 cgit_log_link("log", NULL, "button", NULL, NULL, NULL,
275 0, NULL, NULL, ctx.qry.showmsg); 275 0, NULL, NULL, ctx.qry.showmsg);
276 cgit_tree_link("tree", NULL, "button", NULL, NULL, NULL); 276 cgit_tree_link("tree", NULL, "button", NULL, NULL, NULL);
277 html("</td>"); 277 html("</td>");
278 } 278 }
279 html("</tr>\n"); 279 html("</tr>\n");
280 } 280 }
281 html("</table>"); 281 html("</table>");
282 if (!hits) 282 if (!hits)
283 cgit_print_error("No repositories found"); 283 cgit_print_error("No repositories found");
284 else if (hits > ctx.cfg.max_repo_count) 284 else if (hits > ctx.cfg.max_repo_count)
285 print_pager(hits, ctx.cfg.max_repo_count, ctx.qry.search); 285 print_pager(hits, ctx.cfg.max_repo_count, ctx.qry.search);
286 cgit_print_docend(); 286 cgit_print_docend();
287} 287}
288 288
289void cgit_print_site_readme() 289void cgit_print_site_readme()
290{ 290{
291 if (!ctx.cfg.root_readme) 291 if (!ctx.cfg.root_readme)
292 return; 292 return;
293 if (ctx.cfg.about_filter) 293 if (ctx.cfg.about_filter)
294 cgit_open_filter(ctx.cfg.about_filter); 294 cgit_open_filter(ctx.cfg.about_filter);
295 html_include(ctx.cfg.root_readme); 295 html_include(ctx.cfg.root_readme);
296 if (ctx.cfg.about_filter) 296 if (ctx.cfg.about_filter)
297 cgit_close_filter(ctx.cfg.about_filter); 297 cgit_close_filter(ctx.cfg.about_filter);
298} 298}