#include #include #include #include #include "config.h" #include "context.h" #include "build.h" #include "ui.h" #define CONTENT_TYPE_FORMAT "Content-Type: %s;\n\n" #define TEXT_HTML "text/html" #define TEXT_CSS "text/css" #define TEXT_PLAIN "text/plain" void print_html() { if (current_project && current_project->name) { if (context.action) { if (!strcmp(context.action, "builds") && context.index) { if (context.extra) { if (!strcmp(context.extra, "raw_log")) { printf(CONTENT_TYPE_FORMAT, TEXT_PLAIN); printf("%s", current_build->log); } else if (!strcmp(context.extra, "log")) { printf(CONTENT_TYPE_FORMAT, TEXT_HTML); print_head(); printf( "
%s
", current_build->log ); } else { printf(CONTENT_TYPE_FORMAT, TEXT_PLAIN); printf("Invalid path"); } } else { printf(CONTENT_TYPE_FORMAT, TEXT_HTML); printf(HTML_START); print_head(); print_title(); print_build_nav(); print_build_info(); printf(HTML_END); } } else if (!strcmp(context.action, "trigger")) { char* token = current_project->token; if (!token) token = config.token; if (context.token && token && !strcmp(context.token, token)) { create_build(); printf(CONTENT_TYPE_FORMAT, TEXT_HTML); printf(HTML_START); print_head(); printf(HTML_END); } else { printf(CONTENT_TYPE_FORMAT, TEXT_HTML); printf(HTML_START); print_head(); print_title(); print_build_nav(); print_build_trigger(); printf(HTML_END); } } } else { printf(CONTENT_TYPE_FORMAT, TEXT_HTML); printf(HTML_START); print_head(); print_title(); print_build_nav(); print_build_list(); printf(HTML_END); } } else { printf(CONTENT_TYPE_FORMAT, TEXT_HTML); printf(HTML_START); print_head(); print_title(); print_project_nav(); print_project_list(); printf(HTML_END); } } void print_head() { printf(""); printf(""); printf("CGCI"); if (current_project && current_project->name) { printf(" : %s", current_project->name); } printf(""); if (current_project && current_project->name && context.action && !strcmp(context.action, "trigger") && context.token && config.token && !strcmp(context.token, config.token)) printf("", current_project->name); printf("", config.path_prefix ? config.path_prefix : ""); printf(""); } void print_title() { printf("

"); printf("CGCI"); if (context.project) { printf(" : %s", config.path_prefix ? config.path_prefix : "", context.project, context.project); if (context.action) { printf(" : %s", context.action); } } printf("

"); } void print_build_nav() { printf( "" "" "" "", current_project->name ); if ((config.token || current_project->token) && current_project->script_path && strlen(current_project->script_path)) { printf( "", current_project->name ); } printf( "" "" "
" "Builds" "" "Trigger Build" "
" ); } void print_build_info() { // YYYY-MM-DD HH:MM char time[18]; strftime(time, sizeof(time), "%Y-%m-%d %H:%M", localtime(¤t_build->timestamp)); char buildtime[18]; strftime(buildtime, sizeof(buildtime), "%Y-%m-%d %H:%M", localtime(¤t_build->completion)); char* log_lines = current_build->log + strlen(current_build->log); int line_count = 20; while (line_count && log_lines > current_build->log) { --log_lines; if (*log_lines == '\n') --line_count; } printf( "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "
Build ID%s
Build Date%s
Completion Time%s
Status%s
Log" "Raw" "
" "
%s
", current_build->name, time, current_build->completion ? buildtime : "", build_class[current_build->status], build_string[current_build->status], current_project->name, current_build->name, log_lines ); } void print_build_trigger() { printf( "
" "
" "%s" "
" "" "
", context.token ? "Invalid token" : "", context.token ? context.token : "" ); } void print_build_list() { printf( "" "" "" "" "" "" "" "" "" "" ); for (size_t i = 0; i < current_project->build_count; ++i) { struct build_t* build = ¤t_project->builds[i]; // YYYY-MM-DD HH:MM char time[18]; strftime(time, sizeof(time), "%Y-%m-%d %H:%M", localtime(&build->timestamp)); char buildtime[255] = ""; strdifftime(build->completion, build->timestamp, buildtime, sizeof(buildtime)); printf( "" "" "" "" "" "", context.project, build->name, build->name, time, buildtime, build_class[build->status], build_string[build->status] ); } printf( "" "
Build IDBuild DateCompletion TimeStatus
" "%s" "%s%s%s
" ); } void print_project_nav() { printf( "" "" "" "" "" "" "
" "Projects" "
", config.path_prefix ? config.path_prefix : "" ); } void print_project_list() { printf( "" "" "" "" "" "" "" "" "" "" "" ); for (size_t i = 0; i < config.project_count; ++i) { struct project_t* project = &config.projects[i]; const char* class = "unknown"; const char* status = "Unknown"; char time[18] = "never"; char buildtime[255] = ""; if (project->build_count > 0) { class = build_class[project->builds[0].status]; status = build_string[project->builds[0].status]; strftime(time, sizeof(time), "%Y-%m-%d %H:%M", localtime(&project->builds[0].timestamp)); strdifftime(project->builds[0].completion, project->builds[0].timestamp, buildtime, sizeof(buildtime)); } printf( "" "" "" "" "" "" "", config.path_prefix ? config.path_prefix : "", project->name, project->name, project->description ? project->description : "", time, buildtime, class, status ); } printf( "" "
NameDescriptionLast Build DateLast Completion TimeLast Build Status
" "%s" "%s%s%s%s
" ); } void print_asset(const char* file) { if (!file) return; printf(CONTENT_TYPE_FORMAT, TEXT_CSS); FILE* fd = fopen(file, "r"); if (!fd) return; char buf[255+1]; while (!feof(fd)) { fread(buf, sizeof(buf)-1, sizeof(buf[0]), fd); buf[sizeof(buf)-1] = '\0'; printf("%s", buf); } } void strdifftime(time_t time1, time_t time0, char* str, size_t size) { if (!size) return; double diff = difftime(time1, time0); if (diff > 0) { *str = '\0'; int seconds = (int)diff % 60; int minutes = (int)(diff / 60); int hours = minutes / 60; if (hours) snprintf(str+strlen(str), size, "%i hours ", hours); if (minutes) snprintf(str+strlen(str), size, "%i minutes ", minutes); if (seconds) snprintf(str+strlen(str), size, "%i seconds ", seconds); } }