Introduction

Since some time our kids to to daycare, and the occassionaly place photos on the secured environment. It’s a bit problematic to download the photos. On the phone it feels a bit weird how that works and online you can only fetch one photo at at time. But since they are there for a longer period already, that would mean manually download a lot of photos.

So, I decided to write a little python wrapper. Using proxyman in between I analyzed the requests and contents and was able to determine how the login procedure works. We first POST a request to the LOGIN URL and bind a session to the ‘requests’ structure , which we will use later to POST to the album URL (you need to do that first, it seems that the PHPSESSID is then placed on the allowed list or something), which will result in a list of available photos. We can then fetch the items by iterating over the dict and nested list and download the images. We do our best to not overload the server so we delay every other request like a regular browser would also do.

If you are not on the session allow list or do not have the Cookie, then you will get images of ‘378’ bytes big, which looks like an unallowed image. From limited testing you are not able to download photos which is not in your list and/or belong to you. It is not a guarantee though!

Ofcourse there are probably easier or better methods. Please let me know in that case, so that I can learn from it ;-)

Note that you need the loadenv plugin to get variables from the environment. They are recorded as “VARIABLE=VALUE” items and work like BASH.

The Python Code used:

below is the code that I used to obtain the currently available photos. Adopt as you need it.

#!/usr/bin/env python3

import requests, json, time, os
from dotenv import load_dotenv

load_dotenv()

# URL Contructs
base_url = os.getenv('BASE_URL')
image_url = base_url + '/ouder/media/download/media/'
login_url = base_url + '/login/login'
album_url = base_url + '/ouder/fotoalbum/standaardalbum'

# private settings from environment file
username = os.getenv('USERNAME')
password = os.getenv('PASSWORD')
photo_path = os.getenv('PHOTO_PATH')

# Range between which period we should search for photos
year_start = yyyy
month_start = mm
year_end = yyyy
month_end = mm
# End of range selection

# Login needs a username, password and role
# role: 7 = login as parent(/ouder)
params = {
        'username': username,
        'password': password,
        'role': '7'
}

# Pretend we are a real browser, if there are checks for user agent, we can work around this.
headers = {
        'User-Agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Safari/605.1.15"
}

# assign the start year and month to the work variables.
year = year_start
month = month_start

with requests.Session() as session:
    post = session.post(login_url, headers=headers, data=params)

    # Variable setting
    # use the PHPSESSID header and assign it the set-Cookie parameter.
    headers["PHPSESSID"] = post.headers['set-Cookie']

    # Loop through year/month cycle (between range).
    while True:

        # Folder definition which will be reset every month and year and seen whether the folder exists. If not create it.
        folder = photo_path + str(year) + '/' + str(month) + '/'
        if not os.path.exists(folder):
                os.makedirs(folder)

        # assign the year month dict, this will be used to post to the correct page where we can fetch the resulting image list.
        year_month = { "year": year, "month": month }

        # Post the year month dict, in response we will receive a list of available photoids.
        post = session.post(album_url, headers=headers, data=year_month)

        # The results of the album post is a json structure with "FOTOS" and a list of the available photos.
        json_response = post.json()

        # Loop through the list in the json FOTOS structure
        for photo in json_response["FOTOS"]:

            # Construct the photo url
            photo_source_big =  image_url + photo

            # Obtain the photo
            r = session.get(photo_source_big, headers=headers)

            # For every result, write the file to the structure (yyyy/mm) with the obtained name.
            with open(folder + photo + '.jpg', 'wb') as handler:
                handler.write(r.content)

                # Sleep 10 seconds between requests to not overload the service.
                time.sleep(10)

        # After doing the loop if we match the end year and month, break out.
        if year == year_end and month == month_end:
            break

        # If the month is January, decrement the year and reset the month to 12.
        if month == 1:
            year = year - 1
            month = 12

        else:
            # If the month is not 1, we can decrement it with 1.
            month = month - 1
# end