#include #include #include #include #include "graphic_render.h" // file-based g(int id, int size) #define DATA_FILE "/ggs/ggs.txt" /* ---------- utils ---------- */ static void trim(char *s){ size_t n=strlen(s); while(n && (s[n-1]=='\r'||s[n-1]=='\n')) s[--n]=0; } static const char* get_user_cookie(void){ const char* c=getenv("HTTP_COOKIE"); if(!c) return NULL; const char* t=strstr(c,"ggs_user="); if(!t) return NULL; t += 9; static char u[64]; size_t i=0; while(*t && *t!=';' && i=sizeof(buf)) vlen=sizeof(buf)-1; memcpy(buf,eq+1,vlen); buf[vlen]=0; return buf; } p = (*amp=='\0') ? NULL : amp+1; } return NULL; } /* ---------- read all ids, sort DESC ---------- */ static size_t load_ids(long **out_ids){ FILE *f=fopen(DATA_FILE,"r"); if(!f){ *out_ids=NULL; return 0; } size_t cap=1024, n=0; long *ids=(long*)malloc(cap*sizeof(long)); char line[65536]; while(fgets(line,sizeof(line),f)){ trim(line); if(!*line) continue; char *comma=strchr(line,','); if(!comma) continue; *comma='\0'; long id=strtol(line,NULL,10); if(n==cap){ cap*=2; ids=(long*)realloc(ids,cap*sizeof(long)); } ids[n++]=id; } fclose(f); int cmp_desc(const void *a,const void *b){ long A=*(const long*)a, B=*(const long*)b; return (AB ? -1 : 0); } qsort(ids,n,sizeof(long),cmp_desc); *out_ids=ids; return n; } /* ---------- append blank 16x16 row ---------- */ static void add_blank_row(void){ long *ids=NULL; size_t n=load_ids(&ids); long next = n ? ids[0] + 1 : 1; free(ids); FILE *f=fopen(DATA_FILE,"a"); if(!f) return; fprintf(f,"%ld", next); for(int i=0;i<256;i++) fprintf(f,",0"); // colors: color0, color1 preset; rest empty; trailing comma matches your file fprintf(f,",#FFFFFF,#000000"); for(int j=2;j<10;j++) fprintf(f,","); fprintf(f,",\n"); fclose(f); } /* ---------- html ---------- */ static void html_header(const char* title){ printf("Content-Type: text/html\r\n\r\n"); printf("" "" "%s" "", title?title:"Loom"); } static void html_footer(void){ printf(""); printf(""); } /* ---------- main ---------- */ int main(void){ const char* action=qs_get("action"); if(action && strcmp(action,"add16")==0){ add_blank_row(); printf("Status: 302 Found\r\nLocation: /cgi-bin/loom.cgi\r\n\r\n"); return 0; } const char* user=get_user_cookie(); html_header("Loom"); printf("

Welcome, %s

", user?user:"guest"); printf(""); long *ids=NULL; size_t n=load_ids(&ids); if(!n){ printf("

No graphics found in %s

", DATA_FILE); html_footer(); return 0; } printf("\n"); for(size_t i=0;i\n"); printf("\n"); } long id=ids[i]; printf("\n"); } if(n%5){ for(size_t k=0;k<5-(n%5);k++) printf(""); printf("\n"); } else if(n) printf("\n"); free(ids); html_footer(); return 0; }
"); printf("
%ld
", id); printf("", id); g((int)id, 3); // thumbnail (size 3) printf("