diff --git a/main.c b/main.c index 6fae25f..3824f4b 100644 --- a/main.c +++ b/main.c @@ -2899,85 +2899,76 @@ static void fn(struct mg_connection *c, int ev, void *ev_data) { #undef SM_MANUAL } else if(mg_match(hm->uri,mg_str("/api/sm/gamelist"),NULL)){ - /* server-side game list HTML — no JS string building needed */ - char *imgs_json=sm_api_req("POST","/api/v1/images","{}"); - char *out=malloc(131072); if(!out){mg_http_reply(c,500,"","");if(imgs_json)free(imgs_json);return;} + /* server-side game list HTML using /api/v1/games (has title_name) */ + char *games_json=sm_api_req("POST","/api/v1/games","{}"); + char *out=malloc(131072); if(!out){mg_http_reply(c,500,"","");if(games_json)free(games_json);return;} int pos=0; #define GL(fmt,...) pos+=snprintf(out+pos,131071-pos,fmt,##__VA_ARGS__) - if(!imgs_json){ + if(!games_json){ GL("
SM API nicht erreichbar
"); } else { - /* minimal JSON parse: extract each image object */ - const char *p=strstr(imgs_json,"\"images\""); - if(!p){GL("Keine Spiele gefunden
");} + const char *gstart=strstr(games_json,"\"games\""); + if(!gstart||!strstr(gstart,"\"title_id\"")){GL("Keine Spiele gefunden
");} else { int n=0; - const char *cur=p; + const char *cur=gstart; while((cur=strstr(cur,"{\"path\""))!=NULL&&pos<120000){ - char path[512]={0},mp[256]={0}; - long long sz=0; int mounted=0; - /* extract path */ - const char *pv=strstr(cur,"\"path\":\""); - if(pv){pv+=8;const char *pe=strchr(pv,'"');if(pe&&pe-pv<(int)sizeof(path)){memcpy(path,pv,pe-pv);}} - /* extract mount_point */ - const char *mpv=strstr(cur,"\"mount_point\":\""); - if(mpv){mpv+=15;const char *mpe=strchr(mpv,'"');if(mpe&&mpe-mpv<(int)sizeof(mp)){memcpy(mp,mpv,mpe-mpv);}} - /* extract size */ - const char *sv=strstr(cur,"\"size\":"); - if(sv){sv+=7;sz=strtoll(sv,NULL,10);} + char tid[16]={0},name[128]={0},imgpath[512]={0}; + int mounted=0; + /* extract title_id */ + const char *tv=strstr(cur,"\"title_id\":\""); + if(tv){tv+=12;const char *te=strchr(tv,'"');if(te&&te-tv<(int)sizeof(tid)){memcpy(tid,tv,te-tv);}} + /* extract title_name */ + const char *nv=strstr(cur,"\"title_name\":\""); + if(nv){nv+=14;const char *ne=strchr(nv,'"');if(ne&&ne-nv<(int)sizeof(name)){memcpy(name,nv,ne-nv);}} + /* extract image_path for size */ + const char *iv=strstr(cur,"\"image_path\":\""); + if(iv){iv+=14;const char *ie=strchr(iv,'"');if(ie&&ie-iv<(int)sizeof(imgpath)){memcpy(imgpath,iv,ie-iv);}} /* extract mounted */ const char *mv=strstr(cur,"\"mounted\":"); if(mv){mv+=10;mounted=(mv[0]=='t');} - /* extract title_id from mount_point basename */ - char tid[16]={0}; - const char *bn=strrchr(mp,'/'); bn=bn?bn+1:mp; - char tmp[64]={0}; strncpy(tmp,bn,sizeof(tmp)-1); - char *us=strchr(tmp,'_'); if(us)*us=0; - if(strlen(tmp)==9){ - int ok=1; - for(int i=0;i<4;i++) if(!isalpha((unsigned char)tmp[i])){ok=0;break;} - for(int i=4;i<9;i++) if(!isdigit((unsigned char)tmp[i])){ok=0;break;} - if(ok) strncpy(tid,tmp,sizeof(tid)-1); + /* get file size from image_path */ + char szbuf[32]="?"; + if(imgpath[0]){ + /* unescape JSON \/ */ + char rp[512]={0};int ri=0; + for(int i=0;imgpath[i]&&ri<(int)sizeof(rp)-1;i++){ + if(imgpath[i]=='\\'&&imgpath[i+1]=='/'){rp[ri++]='/';i++;} + else rp[ri++]=imgpath[i];} + struct stat ist; if(stat(rp,&ist)==0){ + if(ist.st_size>1073741824) snprintf(szbuf,sizeof(szbuf),"%.2f GB",(double)ist.st_size/1073741824.0); + else snprintf(szbuf,sizeof(szbuf),"%lld MB",(long long)ist.st_size/1048576);} } - /* format size */ - char szbuf[32]={0}; - if(sz>1073741824) snprintf(szbuf,sizeof(szbuf),"%.2f GB",(double)sz/1073741824.0); - else snprintf(szbuf,sizeof(szbuf),"%lld MB",sz/1048576); - /* extract filename from path, unescape JSON \/ sequences */ - char fn[256]={0}; - {char pp[512]={0};int pi=0; - for(int i=0;path[i]&&pi<(int)sizeof(pp)-1;i++){ - if(path[i]=='\\'&&path[i+1]=='/'){pp[pi++]='/';i++;} - else pp[pi++]=path[i]; - } - const char *sl=strrchr(pp,'/'); - strncpy(fn,sl?sl+1:pp,sizeof(fn)-1);} - /* build card */ + /* unescape name */ + char dname[128]={0};{int di=0; + for(int i=0;name[i]&&di<(int)sizeof(dname)-1;i++){ + if(name[i]=='\\'&&name[i+1]=='/'){ dname[di++]='/';i++;} + else dname[di++]=name[i];} + } + if(!dname[0]) strncpy(dname,tid,sizeof(dname)-1); const char *mntcol=mounted?"color:#10b981":"color:var(--dim)"; const char *mnttxt=mounted?"● aktiv":"○ inaktiv"; - const char *btnstyle=mounted - ?"background:transparent;border:1px solid #f87171;border-radius:4px;color:#f87171;padding:3px 10px;cursor:pointer;font-size:.75rem;" - :"background:transparent;border:1px solid var(--accent);border-radius:4px;color:var(--accent);padding:3px 10px;cursor:pointer;font-size:.75rem;white-space:nowrap;"; - const char *btnfn=mounted?"_smUnmount":"_smMount"; + const char *bs_um="background:transparent;border:1px solid #f87171;border-radius:4px;color:#f87171;padding:3px 10px;cursor:pointer;font-size:.75rem;"; + const char *bs_mt="background:transparent;border:1px solid var(--accent);border-radius:4px;color:var(--accent);padding:3px 10px;cursor:pointer;font-size:.75rem;white-space:nowrap;"; GL("Keine Spiele gefunden
"); } - free(imgs_json); + free(games_json); } out[pos]=0; #undef GL @@ -3020,7 +3011,8 @@ static void fn(struct mg_connection *c, int ev, void *ev_data) { if(ibuf&&(fread(ibuf,1,isz,sf)==(size_t)isz)){ mkdir("/data/SMPlusGui",0777);mkdir(SMG_IC2,0777); FILE *cf=fopen(cache2,"wb");if(cf){fwrite(ibuf,1,isz,cf);fclose(cf);} - mg_http_reply(c,200,"Content-Type: image/png\r\nCache-Control: max-age=86400\r\n","%.*s",(int)isz,ibuf); + mg_printf(c,"HTTP/1.1 200 OK\r\nContent-Type: image/png\r\nContent-Length: %ld\r\nCache-Control: max-age=86400\r\n\r\n",(long)isz); + mg_send(c,ibuf,(size_t)isz); free(ibuf);fclose(sf);return; }free(ibuf); }fclose(sf); @@ -3032,7 +3024,8 @@ static void fn(struct mg_connection *c, int ev, void *ev_data) { if(sz2<=0||sz2>524288){fclose(fi);mg_http_reply(c,404,"Cache-Control: no-store\r\n","");return;} char *buf2=malloc(sz2);if(!buf2){fclose(fi);mg_http_reply(c,500,"","");return;} fread(buf2,1,sz2,fi);fclose(fi); - mg_http_reply(c,200,"Content-Type: image/png\r\nCache-Control: max-age=86400\r\n","%.*s",(int)sz2,buf2); + mg_printf(c,"HTTP/1.1 200 OK\r\nContent-Type: image/png\r\nContent-Length: %ld\r\nCache-Control: max-age=86400\r\n\r\n",(long)sz2); + mg_send(c,buf2,(size_t)sz2); free(buf2); #undef SMG_IC2 }