diff --git a/main.c b/main.c index 8e92288..d5222a8 100644 --- a/main.c +++ b/main.c @@ -1789,7 +1789,7 @@ static void fn(struct mg_connection *c, int ev, void *ev_data) { "var h='';window._smG=[];" "imgs.forEach(function(img,i){" "var tid=smTid(img.mount_point);" - "window._smG.push({tid:tid,path:img.path||'',mounted:img.mounted});" + "window._smG.push({tid:tid,path:img.path||'',mp:(img.mount_point||'').split('/').pop(),mounted:img.mounted});" "var fn=(img.path||'').split('/').pop();" "var sz=img.size?(img.size>1073741824?(img.size/1073741824).toFixed(2)+' GB':(img.size/1048576).toFixed(0)+' MB'):'?';" "var mn=img.mounted?'● aktiv'" @@ -1797,8 +1797,10 @@ static void fn(struct mg_connection *c, int ev, void *ev_data) { "var ba=img.mounted" "?''" ":'';" - /* CSS background-image: loads silently, no broken image icon if missing */ - "var icbg=tid?'background-image:url(/api/game/icon?title_id='+tid+');background-size:cover;':'';" + /* 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;':'';" "var ic='
'+(!img.mounted&&tid?tid.substring(0,4):'')+'
';" "h+='
'+ic;" "h+='
';" @@ -1806,6 +1808,9 @@ static void fn(struct mg_connection *c, int ev, void *ev_data) { "h+='
'+(tid||'–')+' — '+sz+'
';" "h+='
'+mn+ba+'
';" "});gl.innerHTML=h;" + /* auto-refresh once after 8s if all games still unmounted (SM still starting) */ + "if(_gpR===0&&imgs.length&&imgs.every(function(x){return !x.mounted;})){" + "setTimeout(function(){if(_gpR===0)loadGamePanel(1);},8000);}" "}else{" "gl.innerHTML=((!gd||gd.error||gd.status)?'

SM API nicht erreichbar — l\\u00e4uft ShadowMountPlus?

':'

Keine Spiele gefunden

');" "}});}" @@ -2919,15 +2924,26 @@ static void fn(struct mg_connection *c, int ev, void *ev_data) { } else if(mg_match(hm->uri,mg_str("/api/game/icon"),NULL)){ char tid[64]={0}; mg_http_get_var(&hm->query,"title_id",tid,sizeof(tid)); - /* sanitise: only alphanumeric title IDs allowed */ + char mp[128]={0}; mg_http_get_var(&hm->query,"mp",mp,sizeof(mp)); + /* sanitise mp: only alnum, dot, underscore */ + for(int i=0;mp[i];i++) if(!isalnum((unsigned char)mp[i])&&mp[i]!='_'&&mp[i]!='-'){mp[0]=0;break;} + /* sanitise tid: only alphanumeric */ for(int i=0;tid[i];i++) if(!isalnum((unsigned char)tid[i])){tid[0]=0;break;} - if(!tid[0]){mg_http_reply(c,404,"","");return;} + if(!tid[0]&&!mp[0]){mg_http_reply(c,404,"","");return;} #define SMG_ICON_CACHE "/data/SMPlusGui/icon-cache" - char cache[128]; snprintf(cache,sizeof(cache),SMG_ICON_CACHE "/%s.png",tid); + /* cache key: prefer mp over tid since mp is more specific */ + char ckey[128]; snprintf(ckey,sizeof(ckey),"%s",mp[0]?mp:tid); + char cache[256]; snprintf(cache,sizeof(cache),SMG_ICON_CACHE "/%s.png",ckey); /* serve from our own cache if available */ FILE *f=fopen(cache,"rb"); /* if not cached, try live mount paths and populate cache */ if(!f){ + char src[256]; FILE *sf=NULL; + /* try mount_point path first (most direct) */ + if(mp[0]&&!sf){ + snprintf(src,sizeof(src),"/mnt/shadowmnt/%s/sce_sys/icon0.png",mp); + sf=fopen(src,"rb"); + } static const char *icon_tpl[]={ "/data/homebrew/%s/sce_sys/icon0.png", "/data/etaHEN/games/%s/sce_sys/icon0.png", @@ -2937,13 +2953,12 @@ static void fn(struct mg_connection *c, int ev, void *ev_data) { "/system_data/priv/appmeta/%s/icon0.png", NULL }; - char src[256]; FILE *sf=NULL; - for(int i=0;icon_tpl[i]&&!sf;i++){ + if(tid[0]) for(int i=0;icon_tpl[i]&&!sf;i++){ snprintf(src,sizeof(src),icon_tpl[i],tid); sf=fopen(src,"rb"); } - /* scan /mnt/shadowmnt/ for {titleId}_* (SM's actual mount location) */ - if(!sf){ + /* scan /mnt/shadowmnt/ for {titleId}_* if no direct mp hit */ + if(!sf&&tid[0]){ DIR *sd=opendir("/mnt/shadowmnt"); if(sd){ struct dirent *de; size_t tlen=strlen(tid);