summaryrefslogtreecommitdiffstatshomepage
path: root/tests/t0104-tree.sh
blob: 100b02614f374f486ca181b3ea4bb0b4a62a73e5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#!/bin/sh

test_description='Check content on tree page'
. ./setup.sh

test_expect_success 'generate bar/tree' 'cgit_url "bar/tree" >tmp'
test_expect_success 'find file-1' 'grep "file-1" tmp'
test_expect_success 'find file-50' 'grep "file-50" tmp'

test_expect_success 'generate bar/tree/file-50' 'cgit_url "bar/tree/file-50" >tmp'

test_expect_success 'find line 1' '
	grep "<a class=.no. id=.n1. name=.n1. href=.#n1.>1</a>" tmp
'

test_expect_success 'no line 2' '
	! grep "<a class=.no. id=.n2. name=.n2. href=.#n2.>2</a>" tmp
'

test_expect_success 'generate foo+bar/tree' 'cgit_url "foo%2bbar/tree" >tmp'

test_expect_success 'verify a+b link' '
	grep "/foo+bar/tree/a+b" tmp
'

test_expect_success 'generate foo+bar/tree?h=1+2' 'cgit_url "foo%2bbar/tree&h=1%2b2" >tmp'

test_expect_success 'verify a+b?h=1+2 link' '
	grep "/foo+bar/tree/a+b?h=1%2b2" tmp
'

test_done
283 284 285 286 287 288 289 290 291
/* html.c: helper functions for html output
 *
 * Copyright (C) 2006 Lars Hjemli
 *
 * Licensed under GNU General Public License v2
 *   (see COPYING for full license text)
 */

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>

int htmlfd = STDOUT_FILENO;

char *fmt(const char *format, ...)
{
	static char buf[8][1024];
	static int bufidx;
	int len;
	va_list args;

	bufidx++;
	bufidx &= 7;

	va_start(args, format);
	len = vsnprintf(buf[bufidx], sizeof(buf[bufidx]), format, args);
	va_end(args);
	if (len>sizeof(buf[bufidx])) {
		fprintf(stderr, "[html.c] string truncated: %s\n", format);
		exit(1);
	}
	return buf[bufidx];
}

void html_raw(const char *data, size_t size)
{
	write(htmlfd, data, size);
}

void html(const char *txt)
{
	write(htmlfd, txt, strlen(txt));
}

void htmlf(const char *format, ...)
{
	static char buf[65536];
	va_list args;

	va_start(args, format);
	vsnprintf(buf, sizeof(buf), format, args);
	va_end(args);
	html(buf);
}

void html_status(int code, const char *msg, int more_headers)
{
	htmlf("Status: %d %s\n", code, msg);
	if (!more_headers)
		html("\n");
}

void html_txt(const char *txt)
{
	const char *t = txt;
	while(t && *t){
		int c = *t;
		if (c=='<' || c=='>' || c=='&') {
			write(htmlfd, txt, t - txt);
			if (c=='>')
				html("&gt;");
			else if (c=='<')
				html("&lt;");
			else if (c=='&')
				html("&amp;");
			txt = t+1;
		}
		t++;
	}
	if (t!=txt)
		html(txt);
}

void html_ntxt(int len, const char *txt)
{
	const char *t = txt;
	while(t && *t && len--){
		int c = *t;
		if (c=='<' || c=='>' || c=='&') {
			write(htmlfd, txt, t - txt);
			if (c=='>')
				html("&gt;");
			else if (c=='<')
				html("&lt;");
			else if (c=='&')
				html("&amp;");
			txt = t+1;
		}
		t++;
	}
	if (t!=txt)
		write(htmlfd, txt, t - txt);
	if (len<0)
		html("...");
}

void html_attr(const char *txt)
{
	const char *t = txt;
	while(t && *t){
		int c = *t;
		if (c=='<' || c=='>' || c=='\'' || c=='\"') {
			write(htmlfd, txt, t - txt);
			if (c=='>')
				html("&gt;");
			else if (c=='<')
				html("&lt;");
			else if (c=='\'')
				html("&#x27;");
			else if (c=='"')
				html("&quot;");
			txt = t+1;
		}
		t++;
	}
	if (t!=txt)
		html(txt);
}

void html_url_path(const char *txt)
{
	const char *t = txt;
	while(t && *t){
		int c = *t;
		if (c=='"' || c=='#' || c=='\'' || c=='?') {
			write(htmlfd, txt, t - txt);
			write(htmlfd, fmt("%%%2x", c), 3);
			txt = t+1;
		}
		t++;
	}
	if (t!=txt)
		html(txt);
}

void html_url_arg(const char *txt)
{
	const char *t = txt;
	while(t && *t){
		int c = *t;
		if (c=='"' || c=='#' || c=='%' || c=='&' || c=='\'' || c=='+' || c=='?') {
			write(htmlfd, txt, t - txt);
			write(htmlfd, fmt("%%%2x", c), 3);
			txt = t+1;
		}
		t++;
	}
	if (t!=txt)
		html(txt);
}

void html_hidden(const char *name, const char *value)
{
	html("<input type='hidden' name='");
	html_attr(name);
	html("' value='");
	html_attr(value);
	html("'/>");
}

void html_option(const char *value, const char *text, const char *selected_value)
{
	html("<option value='");
	html_attr(value);
	html("'");
	if (selected_value && !strcmp(selected_value, value))
		html(" selected='selected'");
	html(">");
	html_txt(text);
	html("</option>\n");
}

void html_link_open(const char *url, const char *title, const char *class)
{
	html("<a href='");
	html_attr(url);
	if (title) {
		html("' title='");
		html_attr(title);
	}
	if (class) {
		html("' class='");
		html_attr(class);
	}
	html("'>");
}

void html_link_close(void)
{
	html("</a>");
}

void html_fileperm(unsigned short mode)
{
	htmlf("%c%c%c", (mode & 4 ? 'r' : '-'),
	      (mode & 2 ? 'w' : '-'), (mode & 1 ? 'x' : '-'));
}

int html_include(const char *filename)
{
	FILE *f;
	char buf[4096];
	size_t len;

	if (!(f = fopen(filename, "r"))) {
		fprintf(stderr, "[cgit] Failed to include file %s: %s (%d).\n",
			filename, strerror(errno), errno);
		return -1;
	}
	while((len = fread(buf, 1, 4096, f)) > 0)
		write(htmlfd, buf, len);
	fclose(f);
	return 0;
}

int hextoint(char c)
{
	if (c >= 'a' && c <= 'f')
		return 10 + c - 'a';
	else if (c >= 'A' && c <= 'F')
		return 10 + c - 'A';
	else if (c >= '0' && c <= '9')
		return c - '0';
	else
		return -1;
}

char *convert_query_hexchar(char *txt)
{
	int d1, d2;
	if (strlen(txt) < 3) {
		*txt = '\0';
		return txt-1;
	}
	d1 = hextoint(*(txt+1));
	d2 = hextoint(*(txt+2));
	if (d1<0 || d2<0) {
		strcpy(txt, txt+3);
		return txt-1;
	} else {
		*txt = d1 * 16 + d2;
		strcpy(txt+1, txt+3);
		return txt;
	}
}

int http_parse_querystring(const char *txt_, void (*fn)(const char *name, const char *value))
{
	char *t, *txt, *value = NULL, c;

	if (!txt_)
		return 0;

	t = txt = strdup(txt_);
	if (t == NULL) {
		printf("Out of memory\n");
		exit(1);
	}
	while((c=*t) != '\0') {
		if (c=='=') {
			*t = '\0';
			value = t+1;
		} else if (c=='+') {
			*t = ' ';
		} else if (c=='%') {
			t = convert_query_hexchar(t);
		} else if (c=='&') {
			*t = '\0';
			(*fn)(txt, value);
			txt = t+1;
			value = NULL;
		}
		t++;
	}
	if (t!=txt)
		(*fn)(txt, value);
	return 0;
}