vendredi 11 septembre 2020

How can I dynamically generate a PWA manifest in PHP pulling data from the URL and from a publicly available JSON file?

I'm having issues setting up a Progressive Web App at the moment, here are the specifics:

Objective:

I am trying to set up a page that will allow for the installation of multiple PWAs based on URL parameters.

To be precise, I have created a set of icons for games available on the Google Stadia cloud gaming service and would like to allow users to create desktop/home screen icons for all those titles. The games can be accessed directly by simply opening the right URL.

Challenge

In order to allow users to have one PWA "installed" for each game/icon combo, I am trying to fill out the contents of the page with PHP.

Though I understand PWAs must be able to run client-side, it looks like as long as the initial PHP page is loaded, if the content is properly formatted and can run locally, it should be downloaded as-is and run properly; is that correct?

Problem:

The main problem I am currently facing is that browsers seem not to recognize my app.webmanifest file as valid JSON, whereas when I load the page in the browser, it spits out perfectly valid PHP.

Here is the specific error in the Chrome console: Manifest: Line: 1, column: 1, Syntax error.

Here is the code that gets displayed in the "Sources" tab in the Chrome dev tools, which is not what the page should be generating:

Note: I removed 3 strings that looked like uids (possibly linked to cookies?) just in case they were anything I shouldn't share.

<html>
   <body>
      <script type="text/javascript" src="/aes.js" ></script><script>
         function toNumbers(d) {
            var e = [];
            d.replace(/(..)/g, function(d) {
               e.push(parseInt(d, 16))
            });
            return e
         }

         function toHex() {
            for (var d = [], d = 1 == arguments.length && arguments[0].constructor == Array ? arguments[0] : arguments, e = "", f = 0; f < d.length; f++) e += (16 > d[f] ? "0" : "") + d[f].toString(16);
            return e.toLowerCase()
         }
         var a = toNumbers("UID_HERE"),
            b = toNumbers("UID_HERE"),
            c = toNumbers("UID_HERE");
         document.cookie = "__test=" + toHex(slowAES.decrypt(c, 2, a, b)) + "; expires=Thu, 31-Dec-37 23:55:55 GMT; path=/";
         location.href = "MY_APP_URL/app.webmanifest?fullName=Full Name&shortName=Short&uid=b17f16d4a4f94c0a85e07f54dbdedbb6rcp1&variant=2&i=1";
      </script>
      <noscript>This site requires Javascript to work, please enable Javascript in your browser or use a browser with Javascript support</noscript>
   </body>
</html>

Code Breakdown:

Context:

The PWA is being hosted on an InfinityFree web server.

EDIT: I did find this forum post that might be linked to the error I am getting, would that make sense? https://forum.infinityfree.net/t/extra-javascript-in-response/7031/2

Note: I've removed any direct URL references (such as the site I am running the app off of and a github repo).

The main page being called is MY_APP_URL/index.php?fullName=Full Name&shortName=Short&uid=b17f16d4a4f94c0a85e07f54dbdedbb6rcp1&variant=2

Main index.php

<?php
    if( !$fullName = filter_var ( $_GET['fullName'], FILTER_SANITIZE_STRING ) ) {
        $fullName = null;
    }
    if( !$shortName = filter_var ( $_GET['shortName'], FILTER_SANITIZE_STRING ) ) {
        $shortName = null;
    }
    if( !$uid = filter_var ( $_GET['uid'], FILTER_SANITIZE_STRING ) ) {
        $uid = null;
    }
    if( !$variant = filter_var ( $_GET['variant'], FILTER_SANITIZE_NUMBER_INT ) ) {
        $variant = 0;
    }
    if( !$alt = filter_var ( $_GET['alt'], FILTER_SANITIZE_STRING ) ) {
        $alt = '';
    }
    
    $data = json_decode( file_get_contents( "GITHUB_REPO_URL/refs.json" ) );
    
    if ($fullName != null && $shortName != null && $uid != null && $data != null)
    {
?>
<!DOCTYPE HTML>
<html lang="en">
    <head>
        <title>Game – <?php echo $fullName ?></title>
        <link rel="manifest" href="app.webmanifest?fullName=<?php
            echo $fullName . '&shortName=' . $shortName . '&uid=' . $uid;
            if ($variant != 0)
            {
                echo '&variant=' . $variant;
            }
            if ($alt != '')
            {
                echo '&alt=' . $alt;
            }
        ?>">
        <meta name="Description" content="This page will allow you to install <?php echo $fullName ?> as a Progressive Web App.">
        <meta name="mobile-web-app-capable" content="yes">
        <meta name="apple-mobile-web-app-capable" content="yes">
        <meta name="application-name" content="<?php echo $fullName ?>">
        <meta name="apple-mobile-web-app-title" content="<?php echo $shortName ?>">
        <meta name="theme-color" content="#202124">
        <meta name="msapplication-navbutton-color" content="#202124">
        <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
        <meta name="msapplication-starturl" content="https://stadia.google.com/player/<?php echo $uid ?>">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
        <meta name="theme-color" content="#202124">

        <?php
            echo '<link rel="icon" type="image/x-icon" sizes="16x16 32x32 48x48 64x64 128x128 256x256" href="' . $data->datasets->icons->uri . $data->uids->$uid->$variant . $alt . $data->datasets->icons->extension . '">' . "\n\t\t";
            echo '<link rel="icon" type="image/png" sizes="128x128" href="' . $data->datasets->{'images-128'}->uri . $data->uids->$uid->$variant . $alt . $data->datasets->{'images-128'}->extension . '">' . "\n\t\t";
            echo '<link rel="icon" type="image/png" sizes="192x192" href="' . $data->datasets->{'images-192'}->uri . $data->uids->$uid->$variant . $alt . $data->datasets->{'images-192'}->extension . '">' . "\n\t\t";
            echo '<link rel="icon" type="image/png" sizes="512x512" href="' . $data->datasets->{'images-512'}->uri . $data->uids->$uid->$variant . $alt . $data->datasets->{'images-512'}->extension . '">' . "\n\t\t";
            echo '<link rel="icon" type="image/png" sizes="1024x1024" href="' . $data->datasets->images->uri . $data->uids->$uid->$variant . $alt . $data->datasets->images->extension . '">' . "\n\t\t";
            echo '<link rel="icon" type="image/webp" sizes="1024x1024" href="' . $data->datasets->webp->uri . $data->uids->$uid->$variant . $alt . $data->datasets->webp->extension . '">' . "\n";
            echo '<link rel="apple-touch-icon" href="' . $data->datasets->{'images-192'}->uri . $data->uids->$uid->$variant . $alt . $data->datasets->{'images-192'}->extension . '">' . "\n\t\t";
        ?>
    </head>
    <body>
        <?php echo '<p>Hello World</p>'; ?> 
    </body>
</html>
<?php
    }
    else
    {
        echo "ERROR";
    }
?>

The app.webmanifest File:

Note, this file is run as PHP using the following code in the folder's .htaccess file: AddType application/x-httpd-php5 .webmanifest

<?php
    header('Content-Type: manifest/json');

    if( !$fullName = filter_var ( $_GET['fullName'], FILTER_SANITIZE_STRING ) ) {
        $fullName = null;
    }
    if( !$shortName = filter_var ( $_GET['shortName'], FILTER_SANITIZE_STRING ) ) {
        $shortName = null;
    }
    if( !$uid = filter_var ( $_GET['uid'], FILTER_SANITIZE_STRING ) ) {
        $uid = null;
    }
    if( !$variant = filter_var ( $_GET['variant'], FILTER_SANITIZE_NUMBER_INT ) ) {
        $variant = 0;
    }
    if( !$alt = filter_var ( $_GET['alt'], FILTER_SANITIZE_STRING ) ) {
        $alt = '';
    }
    
    $data = json_decode( file_get_contents( "GITHUB_REPO_URL/refs.json" ) );
    
?>{
    "name": "<?php echo $fullName ?>",
    "short_name": "<?php echo $shortName ?>",
    "lang": "en-US",
    "start_url": "https://stadia.google.com/player/<?php echo $uid ?>",
    "scope": "https://stadia.google.com/",
    "display": "standalone",
    "theme_color": "#202124",
    "icons": [
        {
            "src": "<?php echo $data->datasets->{'images-128'}->uri . $data->uids->$uid->$variant . $alt . $data->datasets->{'images-128'}->extension; ?>",
            "type": "image/png",
            "sizes": "128x128"
        },
        {
            "src": "<?php echo $data->datasets->{'images-192'}->uri . $data->uids->$uid->$variant . $alt . $data->datasets->{'images-192'}->extension; ?>",
            "type": "image/png",
            "sizes": "192x192"
        },
        {
            "src": "<?php echo $data->datasets->{'images-512'}->uri . $data->uids->$uid->$variant . $alt . $data->datasets->{'images-512'}->extension; ?>",
            "type": "image/png",
            "sizes": "512x512"
        },
        {
            "src": "<?php echo $data->datasets->images->uri . $data->uids->$uid->$variant . $alt . $data->datasets->images->extension; ?>",
            "type": "image/png",
            "sizes": "1024x1024"
        },
        {
            "src": "<?php echo $data->datasets->webp->uri . $data->uids->$uid->$variant . $alt . $data->datasets->webp->extension; ?>",
            "type": "image/webp",
            "sizes": "1024x1024"
        },
        {
            "src": "<?php echo $data->datasets->icons->uri . $data->uids->$uid->$variant . $alt . $data->datasets->icons->extension; ?>",
            "type": "image/x-icon",
            "sizes": "16x16 32x32 48x48 64x64 128x128 256x256"
        }
    ],
    "background_color": "#202124",
    "related_applications": [
        {
            "platform": "play",
            "id": "com.google.stadia.android",
            "url": "https://play.google.com/store/apps/details?id=com.google.stadia.android"
        }
    ],
    "prefer_related_applications": false
}

The output of this is the following:

{
    "name": "Long Name",
    "short_name": "Short",
    "lang": "en-US",
    "start_url": "https://stadia.google.com/player/b17f16d4a4f94c0a85e07f54dbdedbb6rcp1",
    "scope": "https://stadia.google.com/",
    "display": "standalone",
    "theme_color": "#202124",
    "icons": [
        {
            "src": "GITHUB_REPO_URL/Images/128/The Elder Scrolls – Online-Summerset.png",
            "type": "image/png",
            "sizes": "128x128"
        },
        {
            "src": "GITHUB_REPO_URL/Images/192/The Elder Scrolls – Online-Summerset.png",
            "type": "image/png",
            "sizes": "192x192"
        },
        {
            "src": "GITHUB_REPO_URL/Images/512/The Elder Scrolls – Online-Summerset.png",
            "type": "image/png",
            "sizes": "512x512"
        },
        {
            "src": "GITHUB_REPO_URL/Images/The Elder Scrolls – Online-Summerset.png",
            "type": "image/png",
            "sizes": "1024x1024"
        },
        {
            "src": "GITHUB_REPO_URL/WebP/The Elder Scrolls – Online-Summerset.webp",
            "type": "image/webp",
            "sizes": "1024x1024"
        },
        {
            "src": "GITHUB_REPO_URL/Icons/The Elder Scrolls – Online-Summerset.ico",
            "type": "image/x-icon",
            "sizes": "16x16 32x32 48x48 64x64 128x128 256x256"
        }
    ],
    "background_color": "#202124",
    "related_applications": [
        {
            "platform": "play",
            "id": "com.google.stadia.android",
            "url": "https://play.google.com/store/apps/details?id=com.google.stadia.android"
        }
    ],
    "prefer_related_applications": false
}

Github Repo "refs.json" file being referenced:

I've simplified this with only one entry in "uids" to keep it shorter.

{
    "datasets":{
        "icons":{
            "uri":"GITHUB_REPO_URL/Icons/",
            "extension":".ico"
        },
        "images":{
            "uri":"GITHUB_REPO_URL/Images/",
            "extension":".png"
        },
        "images-512":{
            "uri":"GITHUB_REPO_URL/Images/512/",
            "extension":".png"
        },
        "images-192":{
            "uri":"GITHUB_REPO_URL/Images/192/",
            "extension":".png"
        },
        "images-128":{
            "uri":"GITHUB_REPO_URL/Images/128/",
            "extension":".png"
        },
        "webp":{
            "uri":"GITHUB_REPO_URL/WebP/",
            "extension":".webp"
        }
    },
    "other":{
        "altSuffix":"_alt"
    },
    "uids":{
        "b17f16d4a4f94c0a85e07f54dbdedbb6rcp1":{
            "0":"The Elder Scrolls – Online",
            "1":"The Elder Scrolls – Online-Morrowind",
            "2":"The Elder Scrolls – Online-Summerset",
            "3":"The Elder Scrolls – Online-Elsweyr",
            "4":"The Elder Scrolls – Online-Greymoor"
        },
    }
}




Aucun commentaire:

Enregistrer un commentaire