escaped path names when listing a directory.
added qse_httpd_escapehtml()
This commit is contained in:
		| @ -55,7 +55,7 @@ struct task_dseg_t | ||||
| 	qse_size_t  tcount; /* total directory entries */ | ||||
| 	qse_size_t  dcount; /* the number of items in the buffer */ | ||||
|  | ||||
| 	qse_mchar_t buf[4096*2]; | ||||
| 	qse_mchar_t buf[4096*2]; /* is this large enough? */ | ||||
| 	int         bufpos;  | ||||
| 	int         buflen; | ||||
| 	int         bufrem; | ||||
|  | ||||
| @ -2143,16 +2143,23 @@ static int format_dir ( | ||||
| 		{ | ||||
| 			/* header */ | ||||
| 			const qse_mchar_t* css; | ||||
| 			int is_root = (qse_mbscmp (qpath, QSE_MT("/")) == 0); | ||||
| 			int is_root; | ||||
| 			qse_mchar_t* qpath_esc; | ||||
|  | ||||
| 			is_root = (qse_mbscmp (qpath, QSE_MT("/")) == 0); | ||||
|  | ||||
| 			if (server_xtn->query (httpd, client->server, QSE_NULL, QSE_NULL, QSE_HTTPD_SERVERSTD_DIRCSS, &css) <= -1) css = QSE_NULL; | ||||
| 			if (css == QSE_NULL) css = QSE_MT(""); | ||||
|  | ||||
| /* TODO: html escaping of qpath */ | ||||
| 			qpath_esc = qse_httpd_escapehtml (httpd, qpath); | ||||
| 			if (qpath_esc == QSE_NULL) return -1; | ||||
|  | ||||
| 			n = snprintf (buf, bufsz, | ||||
| 				QSE_MT("<html><head>%s</head><body><div class='header'>%s</div><div class='body'><table>%s"), css, qpath, | ||||
| 				QSE_MT("<html><head>%s</head><body><div class='header'>%s</div><div class='body'><table>%s"), css, qpath_esc, | ||||
| 				(is_root? QSE_MT(""): QSE_MT("<tr><td class='name'><a href='../'>..</a></td><td class='time'></td><td class='size'></td></tr>")) | ||||
| 			); | ||||
|  | ||||
| 			if (qpath_esc != qpath) qse_httpd_freemem (httpd, qpath_esc); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| @ -2169,12 +2176,15 @@ static int format_dir ( | ||||
| 	{ | ||||
| 		/* main entry */ | ||||
| 		qse_mchar_t* encname; | ||||
| 		qse_mchar_t* escname; | ||||
| 		qse_btime_t bt; | ||||
| 		qse_mchar_t tmbuf[32]; | ||||
| 		qse_mchar_t fszbuf[64]; | ||||
|  | ||||
| 		/* TODO: better buffer management in case there are  | ||||
| 		 *       a lot of file names to escape. */ | ||||
|  | ||||
| 		/* perform percent-encoding for the anchor */ | ||||
| 		encname = qse_perenchttpstrdup (dirent->name, httpd->mmgr); | ||||
| 		if (encname == QSE_NULL) | ||||
| 		{ | ||||
| @ -2182,6 +2192,14 @@ static int format_dir ( | ||||
| 			return -1; | ||||
| 		} | ||||
|  | ||||
| 		/* perform html escaping for the text */ | ||||
| 		escname = qse_httpd_escapehtml (httpd, dirent->name); | ||||
| 		if (escname == QSE_NULL)  | ||||
| 		{ | ||||
| 			if (encname != dirent->name) QSE_MMGR_FREE (httpd->mmgr, encname); | ||||
| 			return -1; | ||||
| 		} | ||||
|  | ||||
| 		qse_localtime (&dirent->stat.mtime, &bt); | ||||
| 		snprintf (tmbuf, QSE_COUNTOF(tmbuf), | ||||
| 			QSE_MT("%04d-%02d-%02d %02d:%02d:%02d"), | ||||
| @ -2205,11 +2223,12 @@ static int format_dir ( | ||||
| 			QSE_MT("<tr><td class='name'><a href='%s%s'>%s%s</a></td><td class='time'>%s</td><td class='size'>%s</td></tr>"), | ||||
| 			encname, | ||||
| 			(dirent->stat.isdir? QSE_MT("/"): QSE_MT("")), | ||||
| 			dirent->name, /* TODO: html escaping for entry name */ | ||||
| 			escname, | ||||
| 			(dirent->stat.isdir? QSE_MT("/"): QSE_MT("")), | ||||
| 			tmbuf, fszbuf | ||||
| 		); | ||||
|  | ||||
| 		if (escname != dirent->name) qse_httpd_freemem (httpd, escname); | ||||
| 		if (encname != dirent->name) QSE_MMGR_FREE (httpd->mmgr, encname); | ||||
| 	} | ||||
|  | ||||
|  | ||||
| @ -1359,4 +1359,68 @@ const qse_mchar_t* qse_httpd_fmtgmtimetobb ( | ||||
|  | ||||
| /* --------------------------------------------------- */ | ||||
|  | ||||
| qse_mchar_t* qse_httpd_escapehtml (qse_httpd_t* httpd, const qse_mchar_t* str) | ||||
| { | ||||
| 	qse_mchar_t* ptr, * buf; | ||||
| 	qse_size_t reqlen = 0; | ||||
|  | ||||
| 	for (ptr = str; *ptr != QSE_MT('\0'); ptr++)  | ||||
| 	{ | ||||
| 		switch (*ptr) | ||||
| 		{ | ||||
| 			case QSE_MT('<'): | ||||
| 			case QSE_MT('>'): | ||||
| 				reqlen += 4; | ||||
| 				break; | ||||
|  | ||||
| 			case QSE_MT('&'): | ||||
| 				reqlen += 5; | ||||
| 				break; | ||||
|  | ||||
| 			default:  | ||||
| 				reqlen++; | ||||
| 				break; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (ptr - str == reqlen) return str; /* no escaping is needed */ | ||||
|  | ||||
| 	buf = qse_httpd_allocmem (httpd, QSE_SIZEOF(*buf) * (reqlen + 1)); | ||||
| 	if (buf == QSE_NULL) return QSE_NULL; | ||||
|  | ||||
| 	ptr = buf; | ||||
| 	while (*str != QSE_MT('\0')) | ||||
| 	{ | ||||
| 		switch (*str) | ||||
| 		{ | ||||
| 			case QSE_MT('<'): | ||||
| 				*ptr++ = QSE_MT('&'); | ||||
| 				*ptr++ = QSE_MT('l'); | ||||
| 				*ptr++ = QSE_MT('t'); | ||||
| 				*ptr++ = QSE_MT(';'); | ||||
| 				break; | ||||
|  | ||||
| 			case QSE_MT('>'): | ||||
| 				*ptr++ = QSE_MT('&'); | ||||
| 				*ptr++ = QSE_MT('g'); | ||||
| 				*ptr++ = QSE_MT('t'); | ||||
| 				*ptr++ = QSE_MT(';'); | ||||
| 				break; | ||||
|  | ||||
| 			case QSE_MT('&'): | ||||
| 				*ptr++ = QSE_MT('&'); | ||||
| 				*ptr++ = QSE_MT('a'); | ||||
| 				*ptr++ = QSE_MT('m'); | ||||
| 				*ptr++ = QSE_MT('p'); | ||||
| 				*ptr++ = QSE_MT(';'); | ||||
| 				break; | ||||
|  | ||||
| 			default:  | ||||
| 				*ptr++ = *str; | ||||
| 				break; | ||||
| 		} | ||||
| 		str++; | ||||
| 	} | ||||
| 	*ptr = QSE_MT('\0'); | ||||
| 	return buf; | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user