From 35d7b6f9356b58a747a51e986bf2829c6bfff4bc Mon Sep 17 00:00:00 2001 From: KarnerF Date: Sun, 30 Aug 2026 13:59:25 +0200 Subject: [PATCH] New /api/icon/{tid} endpoint (no query string); img tag with onerror; reads /user/appmeta/ first --- main.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 58 insertions(+), 5 deletions(-) diff --git a/main.c b/main.c index 3e32230..745bed5 100644 --- a/main.c +++ b/main.c @@ -1797,11 +1797,12 @@ static void fn(struct mg_connection *c, int ev, void *ev_data) { "var ba=img.mounted" "?''" ":'';" - /* use mount_point basename for direct icon lookup; CSS background silently fails if missing */ - "var mp=(img.mount_point||'').split('/').pop();" - "var icurl=mp?'/api/game/icon?mp='+encodeURIComponent(mp):(tid?'/api/game/icon?title_id='+tid:'');" - "var icbg=icurl?'background-image:url(\''+icurl+'\');background-size:cover;background-repeat:no-repeat;':'';" - "var ic='
'+(!img.mounted&&tid?tid.substring(0,4):'')+'
';" + /* /api/icon/{tid} has no query string - safe in CSS url() and img src */ + "var ic=tid" + "?'
'" + "+''+" + "+''+tid.substring(0,4)+'
'" + ":'
';" "h+='
'+ic;" "h+='
';" "h+='
'+fn+'
';" @@ -2930,6 +2931,58 @@ static void fn(struct mg_connection *c, int ev, void *ev_data) { mg_http_reply(c,200,"Content-Type: application/json\r\n","{\"ok\":true}"); #undef SM_MANUAL } + else if(mg_match(hm->uri,mg_str("/api/icon/*"),NULL)){ + /* clean path-based icon endpoint: /api/icon/PPSA20515 */ + const char *p=hm->uri.buf+9; /* skip "/api/icon/" */ + size_t plen=hm->uri.len-9; + char tid[64]={0}; + if(plen>0&&plend_name,tid,tl)==0&&de->d_name[tl]=='_') + {snprintf(src,sizeof(src),"/mnt/shadowmnt/%s/sce_sys/icon0.png",de->d_name);sf=fopen(src,"rb");} + closedir(sd);} + } + if(sf){ + fseek(sf,0,SEEK_END);long isz=ftell(sf);fseek(sf,0,SEEK_SET); + if(isz>0&&isz<=524288){ + char *ibuf=malloc(isz); + 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); + free(ibuf);fclose(sf);return; + }free(ibuf); + }fclose(sf); + } + mg_http_reply(c,404,"","");return; + #undef SMG_IC2 + } + fseek(fi,0,SEEK_END);long sz2=ftell(fi);fseek(fi,0,SEEK_SET); + if(sz2<=0||sz2>524288){fclose(fi);mg_http_reply(c,404,"","");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); + free(buf2); + #undef SMG_IC2 + } else if(mg_match(hm->uri,mg_str("/api/game/icon-check"),NULL)){ char tid[64]={0}; mg_http_get_var(&hm->query,"title_id",tid,sizeof(tid)); for(int i=0;tid[i];i++) if(!isalnum((unsigned char)tid[i])){tid[0]=0;break;}