#!/usr/bin/python3
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.

import sys
import getopt
import json
import os
import base64
from fcntl import flock, LOCK_EX, LOCK_UN


def main(argv):
    fpath = ''
    b64data = ''

    try:
        opts, args = getopt.getopt(argv, "f:d:")
    except getopt.GetoptError:
        print('params: -f <filename> -d <b64jsondata>')
        sys.exit(2)
    for opt, arg in opts:
        if opt == '-f':
            fpath = arg
        elif opt == '-d':
            b64data = arg

    json_data = ''
    if fpath != '':
        fh = open(fpath, 'r')
        json_data = json.loads(fh.read())
    elif b64data != '':
        json_data = json.loads(base64.b64decode(b64data))
    else:
        print('-f <filename> or -d <b64jsondata> required')
        sys.exit(2)

    for ip in json_data:
        for item in json_data[ip]:
            folder = item[0]
            file = item[1]
            data = item[2]

            # process only valid data
            if folder != "userdata" and folder != "metadata":
                continue

            if file == "":
                continue

            htaccess(ip, folder, file)

            if data == "":
                deletefile(ip, folder, file)
            else:
                createfile(ip, folder, file, data)

    if fpath != '':
        fh.close()
        os.remove(fpath)


def deletefile(ip, folder, file):
    datafile = "/var/www/html/" + folder + "/" + ip + "/" + file

    if os.path.exists(datafile):
        os.remove(datafile)


def createfile(ip, folder, file, data):
    dest = "/var/www/html/" + folder + "/" + ip + "/" + file
    metamanifestdir = "/var/www/html/" + folder + "/" + ip
    metamanifest = metamanifestdir + "/meta-data"

    # base64 decode userdata
    if folder == "userdata" or folder == "user-data":
        if data is not None:
            data = base64.b64decode(data)

    fh = open(dest, "w")
    exflock(fh)
    if data is not None:
        fh.write(data)
    else:
        fh.write("")
    unflock(fh)
    fh.close()
    os.chmod(dest, 0o644)

    if folder == "metadata" or folder == "meta-data":
        try:
            os.makedirs(metamanifestdir, 0o755)
        except OSError as e:
            # error 17 is already exists, we do it this way for concurrency
            if e.errno != 17:
                print("failed to make directories " + metamanifestdir + " due to :" + e.strerror)
                sys.exit(1)
        if os.path.exists(metamanifest):
            fh = open(metamanifest, "r+a")
            exflock(fh)
            if file not in fh.read():
                fh.write(file + '\n')
            unflock(fh)
            fh.close()
        else:
            fh = open(metamanifest, "w")
            exflock(fh)
            fh.write(file + '\n')
            unflock(fh)
            fh.close()

    if os.path.exists(metamanifest):
        os.chmod(metamanifest, 0o644)


def htaccess(ip, folder, file):
    entry = "Options -Indexes\nOrder Deny,Allow\nDeny from all\nAllow from " + ip
    htaccessFolder = "/var/www/html/" + folder + "/" + ip
    htaccessFile = htaccessFolder+"/.htaccess"

    try:
        os.makedirs(htaccessFolder, 0o755)
    except OSError as e:
        # error 17 is already exists, we do it this way for sake of concurrency
        if e.errno != 17:
            print("failed to make directories " + htaccessFolder + " due to :" + e.strerror)
            sys.exit(1)

    fh = open(htaccessFile, "w")
    exflock(fh)
    fh.write(entry + '\n')
    unflock(fh)
    fh.close()


def exflock(file):
    try:
        flock(file, LOCK_EX)
    except IOError as e:
        print("failed to lock file" + file.name + " due to : " + e.strerror)
        sys.exit(1)
    return True


def unflock(file):
    try:
        flock(file, LOCK_UN)
    except IOError as e:
        print("failed to unlock file" + file.name + " due to : " + e.strerror)
        sys.exit(1)
    return True


if __name__ == "__main__":
    main(sys.argv[1:])
