/* $Id: html.c 14 2024-08-30 07:49:29Z nishi $ */ #include "web_html.h" #include "web_db.h" #include "ia_util.h" #include #include #include #include #include #include #include extern char* webroot; extern const char* ircarc_version; char* web_html_escape(const char* html) { char* str = malloc(strlen(html) * 5 + 1); int i; int incr = 0; for(i = 0; html[i] != 0; i++) { if(html[i] == '&') { str[incr++] = '&'; str[incr++] = 'a'; str[incr++] = 'm'; str[incr++] = 'p'; str[incr++] = ';'; } else if(html[i] == '<') { str[incr++] = '&'; str[incr++] = 'l'; str[incr++] = 't'; str[incr++] = ';'; } else if(html[i] == '>') { str[incr++] = '&'; str[incr++] = 'g'; str[incr++] = 't'; str[incr++] = ';'; } else { str[incr++] = html[i]; ; } } str[incr] = 0; return str; } #define TAG(tagname, el, chr) \ bool attr = true; \ if(bufincr > 0) { \ int k; \ for(k = bufincr - 1; k >= 0; k--) { \ if(buffer[k] == chr) { \ attr = false; \ int l; \ buffer[k] = 0; \ for(l = k; l < bufincr; l++) { \ buffer[l] = buffer[l + 1]; \ } \ break; \ } \ } \ if(!attr) bufincr--; \ } \ if(attr) { \ buffer[bufincr++] = chr; \ char* tmp = fmtmsg; \ fmtmsg = ia_strcat4(tmp, "<" tagname, el, ">"); \ free(tmp); \ } else { \ char* tmp = fmtmsg; \ fmtmsg = ia_strcat(tmp, ""); \ free(tmp); \ } int mtimesort(const struct dirent** d1_, const struct dirent** d2_){ struct dirent* d1 = (struct dirent*)d1_; struct dirent* d2 = (struct dirent*)d2_; char* d1_path = ia_strcat3(webroot, "/", d1->d_name); char* d2_path = ia_strcat3(webroot, "/", d2->d_name); struct stat s1; struct stat s2; stat(d1_path, &s1); stat(d2_path, &s2); free(d1_path); free(d2_path); return s1.st_mtime - s2.st_mtime; } int web_html_generate(const char* name, web_range_t range) { time_t t = time(NULL); char* path = ia_strcat4(webroot, "/", name, ".html"); FILE* f = fopen(path, "w"); if(f != NULL) { entry_t** e = web_db_query(range); char date[512]; struct tm* tm = gmtime(&t); strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S UTC", tm); char* htmlesc = web_html_escape(name); char* title = ia_strcat("Archive: ", htmlesc); free(htmlesc); fprintf(f, "\n"); fprintf(f, "\n"); fprintf(f, " \n"); fprintf(f, " \n"); fprintf(f, " %s\n", title); fprintf(f, " \n"); fprintf(f, " \n"); fprintf(f, " \n"); fprintf(f, "
\n"); fprintf(f, "

%s

\n", title); fprintf(f, "
\n"); fprintf(f, " Archived at %s.
\n", date); htmlesc = web_html_escape(range.channel); fprintf(f, " Channel: %s
\n", htmlesc); free(htmlesc); fprintf(f, "
\n"); fprintf(f, " Go back to index\n"); fprintf(f, "
\n"); fprintf(f, "
\n"); fprintf(f, "
");
		int i;
		int bgcolor = 0xd0d0ff;
		int fgcolor = 0x000000;
		for(i = 0; e[i] != NULL; i++) {
			time_t t = e[i]->time;
			struct tm* tm = gmtime(&t);
			char* escusr = web_html_escape(e[i]->username);
			char* escmsg = web_html_escape(e[i]->message);
			char date[512];
			strftime(date, 512, "%Y/%m/%d %H:%M:%S UTC", tm);
			char cbuf[2];
			cbuf[1] = 0;
			char* fmtmsg = ia_strdup("");
			int j;
			char buffer[512];
			memset(buffer, 0, 512);
			int bufincr = 0;
			for(j = 0; escmsg[j] != 0; j++) {
				if(escmsg[j] == 2) {
					TAG("b", "", 'B');
				} else if(escmsg[j] == 0x1d) {
					TAG("i", "", 'I');
				} else if(escmsg[j] == 0x1f) {
					TAG("u", "", 'U');
				} else if(escmsg[j] == 0x1e) {
					TAG("s", "", 'S');
				} else if(escmsg[j] == 0x16) {
					char fgt[32];
					char bgt[32];
					int _c = fgcolor;
					fgcolor = bgcolor;
					bgcolor = _c;
					sprintf(fgt, "#%06X", fgcolor);
					sprintf(bgt, "#%06X", bgcolor);
					char* _ = ia_strcat4(" style=\"background-color: ", bgt, "; color: ", fgt);
					char* style = ia_strcat(_, ";\"");
					free(_);
					TAG("span", style, 'R');
				} else if(escmsg[j] == 0x03) {
					j++;
					int k = j;
					for(; escmsg[j] != 0 && j < k + 2; j++) {
						if(!('0' <= escmsg[j] && escmsg[j] <= '9')) break;
					}
					if(escmsg[j] == ',') {
						j++;
						k = j;
						for(; escmsg[j] != 0 && j < k + 2; j++) {
							if(!('0' <= escmsg[j] && escmsg[j] <= '9')) break;
						}
					}
					j--;
				} else if(escmsg[j] == 0x0f) {
					int k;
					for(k = bufincr - 1; k >= 0; k--) {
						char c = buffer[k];
						if(c == 'B') {
							char* tmp = fmtmsg;
							fmtmsg = ia_strcat(tmp, "");
							free(tmp);
						} else if(c == 'I') {
							char* tmp = fmtmsg;
							fmtmsg = ia_strcat(tmp, "");
							free(tmp);
						} else if(c == 'U') {
							char* tmp = fmtmsg;
							fmtmsg = ia_strcat(tmp, "");
							free(tmp);
						} else if(c == 'S') {
							char* tmp = fmtmsg;
							fmtmsg = ia_strcat(tmp, "");
							free(tmp);
						} else if(c == 'R') {
							char* tmp = fmtmsg;
							fmtmsg = ia_strcat(tmp, "");
							free(tmp);
						}
					}
					bufincr = 0;
					bgcolor = 0xd0d0ff;
					fgcolor = 0x000000;
				} else {
					cbuf[0] = escmsg[j];
					char* tmp;
					tmp = fmtmsg;
					fmtmsg = ia_strcat(tmp, cbuf);
					free(tmp);
				}
			}
			for(j = bufincr - 1; j >= 0; j--) {
				char c = buffer[j];
				if(c == 'B') {
					char* tmp = fmtmsg;
					fmtmsg = ia_strcat(tmp, "");
					free(tmp);
				} else if(c == 'I') {
					char* tmp = fmtmsg;
					fmtmsg = ia_strcat(tmp, "");
					free(tmp);
				} else if(c == 'U') {
					char* tmp = fmtmsg;
					fmtmsg = ia_strcat(tmp, "");
					free(tmp);
				} else if(c == 'S') {
					char* tmp = fmtmsg;
					fmtmsg = ia_strcat(tmp, "");
					free(tmp);
				} else if(c == 'R') {
					char* tmp = fmtmsg;
					fmtmsg = ia_strcat(tmp, "");
					free(tmp);
				}
			}
			fprintf(f, "[%s] <%s> %s\n", date, escusr, fmtmsg);
			free(fmtmsg);
			free(escusr);
			free(escmsg);
			free(e[i]->username);
			free(e[i]->message);
			free(e[i]);
		}
		free(e);
		fprintf(f, "
\n"); fprintf(f, "
Statistics
%d messages
\n", i); fprintf(f, "
\n"); fprintf(f, "
\n"); fprintf(f, "
\n"); fprintf(f, " Go back to index\n"); fprintf(f, "
\n"); fprintf(f, " Generated by IRC-Archiver %s\n", ircarc_version); fprintf(f, " \n"); fprintf(f, "\n"); fclose(f); free(title); } free(path); path = ia_strcat(webroot, "/index.html"); f = fopen(path, "w"); if(f != NULL){ char* title = ia_strdup("Index"); struct dirent **namelist; int n = scandir(webroot, &namelist, NULL, mtimesort); fprintf(f, "\n"); fprintf(f, "\n"); fprintf(f, " \n"); fprintf(f, " \n"); fprintf(f, " %s\n", title); fprintf(f, " \n"); fprintf(f, " \n"); fprintf(f, " \n"); fprintf(f, "
\n"); fprintf(f, "

%s

\n", title); fprintf(f, "
\n"); fprintf(f, "
\n"); fprintf(f, " \n"); fprintf(f, " \n"); fprintf(f, " "); fprintf(f, " \n"); int i; for(i = 0; i < n; i++){ if(strcmp(namelist[i]->d_name, "..") != 0 && strcmp(namelist[i]->d_name, ".") != 0 && strcmp(namelist[i]->d_name, "index.html") != 0){ struct stat s; char* np = ia_strcat3(webroot, "/", namelist[i]->d_name); stat(np, &s); struct tm* tm = gmtime(&s.st_mtime); char date[512]; strftime(date, 512, "%Y/%m/%d %H:%M:%S UTC", tm); char* name = ia_strdup(namelist[i]->d_name); int j; for(j = strlen(name) - 1; j >= 0; j--){ if(name[j] == '.'){ name[j] = 0; break; } } char* esc = web_html_escape(name); free(name); fprintf(f, " \n"); fprintf(f, " ", esc); fprintf(f, " ", date); fprintf(f, " ", namelist[i]->d_name); fprintf(f, " \n"); free(esc); } free(namelist[i]); } free(namelist); fprintf(f, "
NameArchived atLink
%s%sLink
\n"); fprintf(f, "
\n"); fprintf(f, " Generated by IRC-Archiver %s\n", ircarc_version); fprintf(f, " \n"); fprintf(f, "\n"); fclose(f); free(title); } free(path); }