From f9132f9934a74814f542f67ca993f9d3d683d258 Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Thu, 17 Feb 2022 15:29:03 -0500 Subject: [PATCH 001/160] adding new sqlite testing branch --- scripts/server-lite.py | 423 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 423 insertions(+) create mode 100755 scripts/server-lite.py diff --git a/scripts/server-lite.py b/scripts/server-lite.py new file mode 100755 index 0000000..e1787d5 --- /dev/null +++ b/scripts/server-lite.py @@ -0,0 +1,423 @@ +#!/home/pi/BirdNET-Pi/birdnet/bin/python3 +import socket +import threading +import os +os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' +os.environ['CUDA_VISIBLE_DEVICES'] = '' + +try: + import tflite_runtime.interpreter as tflite +except: + from tensorflow import lite as tflite + +import argparse +import operator +import librosa +import numpy as np +import math +import time +from decimal import Decimal +import json +import requests +import sqlite3 +import datetime +from time import sleep +import pytz +from tzlocal import get_localzone +from pathlib import Path + + +HEADER = 64 +PORT = 5050 +SERVER = socket.gethostbyname(socket.gethostname()) +ADDR = (SERVER, PORT) +FORMAT = 'utf-8' +DISCONNECT_MESSAGE = "!DISCONNECT" + +server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +try: + server.bind(ADDR) +except: + print("Waiting on socket") + time.sleep(5) + + + +# Open most recent Configuration and grab DB_PWD as a python variable +with open('/home/pi/BirdNET-Pi/thisrun.txt', 'r') as f: + this_run = f.readlines() + db_pwd = str(str(str([i for i in this_run if i.startswith('DB_PWD')]).split('=')[1]).split('\\')[0]) + + +def loadModel(): + + global INPUT_LAYER_INDEX + global OUTPUT_LAYER_INDEX + global MDATA_INPUT_INDEX + global CLASSES + + print('LOADING TF LITE MODEL...', end=' ') + + # Load TFLite model and allocate tensors. + myinterpreter = tflite.Interpreter(model_path='/home/pi/BirdNET-Pi/model/BirdNET_6K_GLOBAL_MODEL.tflite',num_threads=2) + myinterpreter.allocate_tensors() + + # Get input and output tensors. + input_details = myinterpreter.get_input_details() + output_details = myinterpreter.get_output_details() + + # Get input tensor index + INPUT_LAYER_INDEX = input_details[0]['index'] + MDATA_INPUT_INDEX = input_details[1]['index'] + OUTPUT_LAYER_INDEX = output_details[0]['index'] + + # Load labels + CLASSES = [] + with open('/home/pi/BirdNET-Pi/model/labels.txt', 'r') as lfile: + for line in lfile.readlines(): + CLASSES.append(line.replace('\n', '')) + + print('DONE!') + + return myinterpreter + +def loadCustomSpeciesList(path): + + slist = [] + if os.path.isfile(path): + with open(path, 'r') as csfile: + for line in csfile.readlines(): + slist.append(line.replace('\r', '').replace('\n', '')) + + return slist + +def splitSignal(sig, rate, overlap, seconds=3.0, minlen=1.5): + + # Split signal with overlap + sig_splits = [] + for i in range(0, len(sig), int((seconds - overlap) * rate)): + split = sig[i:i + int(seconds * rate)] + + # End of signal? + if len(split) < int(minlen * rate): + break + + # Signal chunk too short? Fill with zeros. + if len(split) < int(rate * seconds): + temp = np.zeros((int(rate * seconds))) + temp[:len(split)] = split + split = temp + + sig_splits.append(split) + + return sig_splits + +def readAudioData(path, overlap, sample_rate=48000): + + print('READING AUDIO DATA...', end=' ', flush=True) + + # Open file with librosa (uses ffmpeg or libav) + sig, rate = librosa.load(path, sr=sample_rate, mono=True, res_type='kaiser_fast') + + # Split audio into 3-second chunks + chunks = splitSignal(sig, rate, overlap) + + print('DONE! READ', str(len(chunks)), 'CHUNKS.') + + return chunks + +def convertMetadata(m): + + # Convert week to cosine + if m[2] >= 1 and m[2] <= 48: + m[2] = math.cos(math.radians(m[2] * 7.5)) + 1 + else: + m[2] = -1 + + # Add binary mask + mask = np.ones((3,)) + if m[0] == -1 or m[1] == -1: + mask = np.zeros((3,)) + if m[2] == -1: + mask[2] = 0.0 + + return np.concatenate([m, mask]) + +def custom_sigmoid(x, sensitivity=1.0): + return 1 / (1.0 + np.exp(-sensitivity * x)) + +def predict(sample, sensitivity): + global INTERPRETER + # Make a prediction + INTERPRETER.set_tensor(INPUT_LAYER_INDEX, np.array(sample[0], dtype='float32')) + INTERPRETER.set_tensor(MDATA_INPUT_INDEX, np.array(sample[1], dtype='float32')) + INTERPRETER.invoke() + prediction = INTERPRETER.get_tensor(OUTPUT_LAYER_INDEX)[0] + + # Apply custom sigmoid + p_sigmoid = custom_sigmoid(prediction, sensitivity) + + # Get label and scores for pooled predictions + p_labels = dict(zip(CLASSES, p_sigmoid)) + + # Sort by score + p_sorted = sorted(p_labels.items(), key=operator.itemgetter(1), reverse=True) + + # Remove species that are on blacklist + for i in range(min(10, len(p_sorted))): + if p_sorted[i][0] in ['Human_Human', 'Non-bird_Non-bird', 'Noise_Noise']: + p_sorted[i] = (p_sorted[i][0], 0.0) + + # Only return first the top ten results + return p_sorted[:10] + +def analyzeAudioData(chunks, lat, lon, week, sensitivity, overlap,): + global INTERPRETER + + detections = {} + start = time.time() + print('ANALYZING AUDIO...', end=' ', flush=True) + + # Convert and prepare metadata + mdata = convertMetadata(np.array([lat, lon, week])) + mdata = np.expand_dims(mdata, 0) + + # Parse every chunk + pred_start = 0.0 + for c in chunks: + + # Prepare as input signal + sig = np.expand_dims(c, 0) + + # Make prediction + p = predict([sig, mdata], sensitivity) + + # Save result and timestamp + pred_end = pred_start + 3.0 + detections[str(pred_start) + ';' + str(pred_end)] = p + pred_start = pred_end - overlap + + print('DONE! Time', int((time.time() - start) * 10) / 10.0, 'SECONDS') + + return detections + +def writeResultsToFile(detections, min_conf, path): + + print('WRITING RESULTS TO', path, '...', end=' ') + rcnt = 0 + with open(path, 'w') as rfile: + rfile.write('Start (s);End (s);Scientific name;Common name;Confidence\n') + for d in detections: + for entry in detections[d]: + if entry[1] >= min_conf and ((entry[0] in INCLUDE_LIST or len(INCLUDE_LIST) == 0) and (entry[0] not in EXCLUDE_LIST or len(EXCLUDE_LIST) == 0) ): + rfile.write(d + ';' + entry[0].replace('_', ';') + ';' + str(entry[1]) + '\n') + rcnt += 1 + print('DONE! WROTE', rcnt, 'RESULTS.') + return + +def handle_client(conn, addr): + global INCLUDE_LIST + global EXCLUDE_LIST + print(f"[NEW CONNECTION] {addr} connected.") + + connected = True + while connected: + msg_length = conn.recv(HEADER).decode(FORMAT) + if msg_length: + msg_length = int(msg_length) + msg = conn.recv(msg_length).decode(FORMAT) + if msg == DISCONNECT_MESSAGE: + connected = False + else: + #print(f"[{addr}] {msg}") + + args = type('', (), {})() + + args.i = '/home/pi/test.wav' + args.o = '/home/pi/test.wav.csv' + args.birdweather_id = '99999' + args.include_list = 'null' + args.exclude_list = 'null' + args.overlap = 0.0 + args.week = -1 + args.sensitivity = 1.25 + args.min_conf = 0.70 + args.lat = -1 + args.lon = -1 + + + for line in msg.split('||'): + inputvars = line.split('=') + if inputvars[0] == 'i': + args.i = inputvars[1] + elif inputvars[0] == 'o': + args.o = inputvars[1] + elif inputvars[0] == 'birdweather_id': + args.birdweather_id = inputvars[1] + elif inputvars[0] == 'include_list': + args.include_list = inputvars[1] + elif inputvars[0] == 'exclude_list': + args.exclude_list = inputvars[1] + elif inputvars[0] == 'overlap': + args.overlap = float(inputvars[1]) + elif inputvars[0] == 'week': + args.week = int(inputvars[1]) + elif inputvars[0] == 'sensitivity': + args.sensitivity = float(inputvars[1]) + elif inputvars[0] == 'min_conf': + args.min_conf = float(inputvars[1]) + elif inputvars[0] == 'lat': + args.lat = float(inputvars[1]) + elif inputvars[0] == 'lon': + args.lon = float(inputvars[1]) + + + + # Load custom species lists - INCLUDED and EXCLUDED + if not args.include_list == 'null': + INCLUDE_LIST = loadCustomSpeciesList(args.include_list) + else: + INCLUDE_LIST = [] + + if not args.exclude_list == 'null': + EXCLUDE_LIST = loadCustomSpeciesList(args.exclude_list) + else: + EXCLUDE_LIST = [] + + birdweather_id = args.birdweather_id + + # Read audio data + audioData = readAudioData(args.i, args.overlap) + + # Get Date/Time from filename in case Pi gets behind + #now = datetime.now() + full_file_name = args.i + print('FULL FILENAME: -' + full_file_name + '-') + file_name = Path(full_file_name).stem + file_date = file_name.split('-birdnet-')[0] + file_time = file_name.split('-birdnet-')[1] + date_time_str = file_date + ' ' + file_time + date_time_obj = datetime.datetime.strptime(date_time_str, '%Y-%m-%d %H:%M:%S') + #print('Date:', date_time_obj.date()) + #print('Time:', date_time_obj.time()) + print('Date-time:', date_time_obj) + now = date_time_obj + current_date = now.strftime("%Y/%m/%d") + current_time = now.strftime("%H:%M:%S") + current_iso8601 = now.astimezone(get_localzone()).isoformat() + + week_number = int(now.strftime("%V")) + week = max(1, min(week_number, 48)) + + sensitivity = max(0.5, min(1.0 - (args.sensitivity - 1.0), 1.5)) + + # Process audio data and get detections + detections = analyzeAudioData(audioData, args.lat, args.lon, week, sensitivity, args.overlap) + + # Write detections to output file + min_conf = max(0.01, min(args.min_conf, 0.99)) + writeResultsToFile(detections, min_conf, args.o) + + ############################################################################### + ############################################################################### + + soundscape_uploaded = False + + # Write detections to Database + myReturn = '' + for i in detections: + myReturn += str(i) + '-' + str(detections[i][0]) + '\n' + + + with open('/home/pi/BirdNET-Pi/BirdDB.txt', 'a') as rfile: + for d in detections: + for entry in detections[d]: + if entry[1] >= min_conf and ((entry[0] in INCLUDE_LIST or len(INCLUDE_LIST) == 0) and (entry[0] not in EXCLUDE_LIST or len(EXCLUDE_LIST) == 0) ): + rfile.write(str(current_date) + ';' + str(current_time) + ';' + entry[0].replace('_', ';') + ';' \ + + str(entry[1]) +";" + str(args.lat) + ';' + str(args.lon) + ';' + str(min_conf) + ';' + str(week) + ';' \ + + str(args.sensitivity) +';' + str(args.overlap) + '\n') + + Date = str(current_date) + Time = str(current_time) + species = entry[0] + Sci_Name,Com_Name = species.split('_') + score = entry[1] + Confidence = "{:.0%}".format(score) + Lat = str(args.lat) + Lon = str(args.lon) + Cutoff = str(args.min_conf) + Week = str(args.week) + Sens = str(args.sensitivity) + Overlap = str(args.overlap) + File_Name = Com_Name.replace(" ", "_") + '-' + Confidence + '-' + \ + Date.replace("/", "-") + '-birdnet-' + Time + '.mp3' + + #Connect to SQLite Database + con = sqlite3.connect('/home/pi/BirdNET-Pi/scripts/birds2.db') + cur = con.cursor() + cur.execute("INSERT INTO detections VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", (Date, Time, Sci_Name, Com_Name, str(score), Lat, Lon, Cutoff, Week, Sens, Overlap, File_Name)) + + con.commit() + con.close() + print(str(current_date) + ';' + str(current_time) + ';' + entry[0].replace('_', ';') + ';' + str(entry[1]) + ';' + str(args.lat) + ';' + str(args.lon) + ';' + str(min_conf) + ';' + str(week) + ';' + str(args.sensitivity) +';' + str(args.overlap) + Com_Name.replace(" ", "_") + '-' + str(score) + '-' + str(current_date) + '-birdnet-' + str(current_time) + '.mp3' + '\n') + + if birdweather_id != "99999": + + if soundscape_uploaded is False: + # POST soundscape to server + soundscape_url = "https://app.birdweather.com/api/v1/stations/" + birdweather_id + "/soundscapes" + "?timestamp=" + current_iso8601 + + with open(args.i, 'rb') as f: + wav_data = f.read() + response = requests.post(url=soundscape_url, data=wav_data, headers={'Content-Type': 'application/octet-stream'}) + print("Soundscape POST Response Status - ", response.status_code) + sdata = response.json() + soundscape_id = sdata['soundscape']['id'] + soundscape_uploaded = True + + # POST detection to server + detection_url = "https://app.birdweather.com/api/v1/stations/" + birdweather_id + "/detections" + start_time = d.split(';')[0] + end_time = d.split(';')[1] + post_begin = "{ " + now_p_start = now + datetime.timedelta(seconds=float(start_time)) + current_iso8601 = now_p_start.astimezone(get_localzone()).isoformat() + post_timestamp = "\"timestamp\": \"" + current_iso8601 + "\"," + post_lat = "\"lat\": " + str(args.lat) + "," + post_lon = "\"lon\": " + str(args.lon) + "," + post_soundscape_id = "\"soundscapeId\": " + str(soundscape_id) + "," + post_soundscape_start_time = "\"soundscapeStartTime\": " + start_time + "," + post_soundscape_end_time = "\"soundscapeEndTime\": " + end_time + "," + post_commonName = "\"commonName\": \"" + entry[0].split('_')[1] + "\"," + post_scientificName = "\"scientificName\": \"" + entry[0].split('_')[0] + "\"," + post_algorithm = "\"algorithm\": " + "\"alpha\"" + "," + post_confidence = "\"confidence\": " + str(entry[1]) + post_end = " }" + + post_json = post_begin + post_timestamp + post_lat + post_lon + post_soundscape_id + post_soundscape_start_time + post_soundscape_end_time + post_commonName + post_scientificName + post_algorithm + post_confidence + post_end + print(post_json) + response = requests.post(detection_url, json=json.loads(post_json)) + print("Detection POST Response Status - ", response.status_code) + + + conn.send(myReturn.encode(FORMAT)) + + #time.sleep(3) + + conn.close() + +def start(): + # Load model + global INTERPRETER, INCLUDE_LIST, EXCLUDE_LIST + INTERPRETER = loadModel() + server.listen() + print(f"[LISTENING] Server is listening on {SERVER}") + while True: + conn, addr = server.accept() + thread = threading.Thread(target=handle_client, args=(conn, addr)) + thread.start() + print(f"[ACTIVE CONNECTIONS] {threading.activeCount() - 1}") + + +print("[STARTING] server is starting...") +start() From a7351d63027e0049006341be38c8ecda2c20bdab Mon Sep 17 00:00:00 2001 From: Patrick McGuire <60325264+mcguirepr89@users.noreply.github.com> Date: Thu, 17 Feb 2022 16:54:42 -0500 Subject: [PATCH 002/160] Update newinstaller.sh --- newinstaller.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/newinstaller.sh b/newinstaller.sh index e89c8e6..c84c6a5 100644 --- a/newinstaller.sh +++ b/newinstaller.sh @@ -2,7 +2,7 @@ # Simple new installer HOME=/home/pi USER=pi -branch=main +branch=sqlite if ! which git &> /dev/null;then sudo apt update sudo apt -y install git From 7dda145f250a97ba05a8195f04d5a4861169d069 Mon Sep 17 00:00:00 2001 From: Patrick McGuire <60325264+mcguirepr89@users.noreply.github.com> Date: Thu, 17 Feb 2022 16:55:20 -0500 Subject: [PATCH 003/160] Delete server.py --- scripts/server.py | 436 ---------------------------------------------- 1 file changed, 436 deletions(-) delete mode 100755 scripts/server.py diff --git a/scripts/server.py b/scripts/server.py deleted file mode 100755 index fdc4a0b..0000000 --- a/scripts/server.py +++ /dev/null @@ -1,436 +0,0 @@ -#!/home/pi/BirdNET-Pi/birdnet/bin/python3 -import socket -import threading -import os -os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' -os.environ['CUDA_VISIBLE_DEVICES'] = '' - -try: - import tflite_runtime.interpreter as tflite -except: - from tensorflow import lite as tflite - -import argparse -import operator -import librosa -import numpy as np -import math -import time -from decimal import Decimal -import json -############################################################################### -import requests -import mysql.connector -############################################################################### -import datetime -from time import sleep -import pytz -from tzlocal import get_localzone -from pathlib import Path - - -HEADER = 64 -PORT = 5050 -SERVER = socket.gethostbyname(socket.gethostname()) -ADDR = (SERVER, PORT) -FORMAT = 'utf-8' -DISCONNECT_MESSAGE = "!DISCONNECT" - -server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) -try: - server.bind(ADDR) -except: - print("Waiting on socket") - time.sleep(5) - - - -# Open most recent Configuration and grab DB_PWD as a python variable -with open('/home/pi/BirdNET-Pi/thisrun.txt', 'r') as f: - this_run = f.readlines() - db_pwd = str(str(str([i for i in this_run if i.startswith('DB_PWD')]).split('=')[1]).split('\\')[0]) - - -def loadModel(): - - global INPUT_LAYER_INDEX - global OUTPUT_LAYER_INDEX - global MDATA_INPUT_INDEX - global CLASSES - - print('LOADING TF LITE MODEL...', end=' ') - - # Load TFLite model and allocate tensors. - myinterpreter = tflite.Interpreter(model_path='/home/pi/BirdNET-Pi/model/BirdNET_6K_GLOBAL_MODEL.tflite',num_threads=2) - myinterpreter.allocate_tensors() - - # Get input and output tensors. - input_details = myinterpreter.get_input_details() - output_details = myinterpreter.get_output_details() - - # Get input tensor index - INPUT_LAYER_INDEX = input_details[0]['index'] - MDATA_INPUT_INDEX = input_details[1]['index'] - OUTPUT_LAYER_INDEX = output_details[0]['index'] - - # Load labels - CLASSES = [] - with open('/home/pi/BirdNET-Pi/model/labels.txt', 'r') as lfile: - for line in lfile.readlines(): - CLASSES.append(line.replace('\n', '')) - - print('DONE!') - - return myinterpreter - -def loadCustomSpeciesList(path): - - slist = [] - if os.path.isfile(path): - with open(path, 'r') as csfile: - for line in csfile.readlines(): - slist.append(line.replace('\r', '').replace('\n', '')) - - return slist - -def splitSignal(sig, rate, overlap, seconds=3.0, minlen=1.5): - - # Split signal with overlap - sig_splits = [] - for i in range(0, len(sig), int((seconds - overlap) * rate)): - split = sig[i:i + int(seconds * rate)] - - # End of signal? - if len(split) < int(minlen * rate): - break - - # Signal chunk too short? Fill with zeros. - if len(split) < int(rate * seconds): - temp = np.zeros((int(rate * seconds))) - temp[:len(split)] = split - split = temp - - sig_splits.append(split) - - return sig_splits - -def readAudioData(path, overlap, sample_rate=48000): - - print('READING AUDIO DATA...', end=' ', flush=True) - - # Open file with librosa (uses ffmpeg or libav) - sig, rate = librosa.load(path, sr=sample_rate, mono=True, res_type='kaiser_fast') - - # Split audio into 3-second chunks - chunks = splitSignal(sig, rate, overlap) - - print('DONE! READ', str(len(chunks)), 'CHUNKS.') - - return chunks - -def convertMetadata(m): - - # Convert week to cosine - if m[2] >= 1 and m[2] <= 48: - m[2] = math.cos(math.radians(m[2] * 7.5)) + 1 - else: - m[2] = -1 - - # Add binary mask - mask = np.ones((3,)) - if m[0] == -1 or m[1] == -1: - mask = np.zeros((3,)) - if m[2] == -1: - mask[2] = 0.0 - - return np.concatenate([m, mask]) - -def custom_sigmoid(x, sensitivity=1.0): - return 1 / (1.0 + np.exp(-sensitivity * x)) - -def predict(sample, sensitivity): - global INTERPRETER - # Make a prediction - INTERPRETER.set_tensor(INPUT_LAYER_INDEX, np.array(sample[0], dtype='float32')) - INTERPRETER.set_tensor(MDATA_INPUT_INDEX, np.array(sample[1], dtype='float32')) - INTERPRETER.invoke() - prediction = INTERPRETER.get_tensor(OUTPUT_LAYER_INDEX)[0] - - # Apply custom sigmoid - p_sigmoid = custom_sigmoid(prediction, sensitivity) - - # Get label and scores for pooled predictions - p_labels = dict(zip(CLASSES, p_sigmoid)) - - # Sort by score - p_sorted = sorted(p_labels.items(), key=operator.itemgetter(1), reverse=True) - - # Remove species that are on blacklist - for i in range(min(10, len(p_sorted))): - if p_sorted[i][0] in ['Human_Human', 'Non-bird_Non-bird', 'Noise_Noise']: - p_sorted[i] = (p_sorted[i][0], 0.0) - - # Only return first the top ten results - return p_sorted[:10] - -def analyzeAudioData(chunks, lat, lon, week, sensitivity, overlap,): - global INTERPRETER - - detections = {} - start = time.time() - print('ANALYZING AUDIO...', end=' ', flush=True) - - # Convert and prepare metadata - mdata = convertMetadata(np.array([lat, lon, week])) - mdata = np.expand_dims(mdata, 0) - - # Parse every chunk - pred_start = 0.0 - for c in chunks: - - # Prepare as input signal - sig = np.expand_dims(c, 0) - - # Make prediction - p = predict([sig, mdata], sensitivity) - - # Save result and timestamp - pred_end = pred_start + 3.0 - detections[str(pred_start) + ';' + str(pred_end)] = p - pred_start = pred_end - overlap - - print('DONE! Time', int((time.time() - start) * 10) / 10.0, 'SECONDS') - - return detections - -def writeResultsToFile(detections, min_conf, path): - - print('WRITING RESULTS TO', path, '...', end=' ') - rcnt = 0 - with open(path, 'w') as rfile: - rfile.write('Start (s);End (s);Scientific name;Common name;Confidence\n') - for d in detections: - for entry in detections[d]: - if entry[1] >= min_conf and ((entry[0] in INCLUDE_LIST or len(INCLUDE_LIST) == 0) and (entry[0] not in EXCLUDE_LIST or len(EXCLUDE_LIST) == 0) ): - rfile.write(d + ';' + entry[0].replace('_', ';') + ';' + str(entry[1]) + '\n') - rcnt += 1 - print('DONE! WROTE', rcnt, 'RESULTS.') - return - -def handle_client(conn, addr): - global INCLUDE_LIST - global EXCLUDE_LIST - print(f"[NEW CONNECTION] {addr} connected.") - - connected = True - while connected: - msg_length = conn.recv(HEADER).decode(FORMAT) - if msg_length: - msg_length = int(msg_length) - msg = conn.recv(msg_length).decode(FORMAT) - if msg == DISCONNECT_MESSAGE: - connected = False - else: - #print(f"[{addr}] {msg}") - - args = type('', (), {})() - - args.i = '/home/pi/test.wav' - args.o = '/home/pi/test.wav.csv' - args.birdweather_id = '99999' - args.include_list = 'null' - args.exclude_list = 'null' - args.overlap = 0.0 - args.week = -1 - args.sensitivity = 1.25 - args.min_conf = 0.70 - args.lat = -1 - args.lon = -1 - - - for line in msg.split('||'): - inputvars = line.split('=') - if inputvars[0] == 'i': - args.i = inputvars[1] - elif inputvars[0] == 'o': - args.o = inputvars[1] - elif inputvars[0] == 'birdweather_id': - args.birdweather_id = inputvars[1] - elif inputvars[0] == 'include_list': - args.include_list = inputvars[1] - elif inputvars[0] == 'exclude_list': - args.exclude_list = inputvars[1] - elif inputvars[0] == 'overlap': - args.overlap = float(inputvars[1]) - elif inputvars[0] == 'week': - args.week = int(inputvars[1]) - elif inputvars[0] == 'sensitivity': - args.sensitivity = float(inputvars[1]) - elif inputvars[0] == 'min_conf': - args.min_conf = float(inputvars[1]) - elif inputvars[0] == 'lat': - args.lat = float(inputvars[1]) - elif inputvars[0] == 'lon': - args.lon = float(inputvars[1]) - - - - # Load custom species lists - INCLUDED and EXCLUDED - if not args.include_list == 'null': - INCLUDE_LIST = loadCustomSpeciesList(args.include_list) - else: - INCLUDE_LIST = [] - - if not args.exclude_list == 'null': - EXCLUDE_LIST = loadCustomSpeciesList(args.exclude_list) - else: - EXCLUDE_LIST = [] - - birdweather_id = args.birdweather_id - - # Read audio data - audioData = readAudioData(args.i, args.overlap) - - # Get Date/Time from filename in case Pi gets behind - #now = datetime.now() - full_file_name = args.i - print('FULL FILENAME: -' + full_file_name + '-') - file_name = Path(full_file_name).stem - file_date = file_name.split('-birdnet-')[0] - file_time = file_name.split('-birdnet-')[1] - date_time_str = file_date + ' ' + file_time - date_time_obj = datetime.datetime.strptime(date_time_str, '%Y-%m-%d %H:%M:%S') - #print('Date:', date_time_obj.date()) - #print('Time:', date_time_obj.time()) - print('Date-time:', date_time_obj) - now = date_time_obj - current_date = now.strftime("%Y/%m/%d") - current_time = now.strftime("%H:%M:%S") - current_iso8601 = now.astimezone(get_localzone()).isoformat() - - week_number = int(now.strftime("%V")) - week = max(1, min(week_number, 48)) - - sensitivity = max(0.5, min(1.0 - (args.sensitivity - 1.0), 1.5)) - - # Process audio data and get detections - detections = analyzeAudioData(audioData, args.lat, args.lon, week, sensitivity, args.overlap) - - # Write detections to output file - min_conf = max(0.01, min(args.min_conf, 0.99)) - writeResultsToFile(detections, min_conf, args.o) - - ############################################################################### - ############################################################################### - - soundscape_uploaded = False - - # Write detections to Database - myReturn = '' - for i in detections: - myReturn += str(i) + '-' + str(detections[i][0]) + '\n' - - - - - with open('/home/pi/BirdNET-Pi/BirdDB.txt', 'a') as rfile: - for d in detections: - for entry in detections[d]: - if entry[1] >= min_conf and ((entry[0] in INCLUDE_LIST or len(INCLUDE_LIST) == 0) and (entry[0] not in EXCLUDE_LIST or len(EXCLUDE_LIST) == 0) ): - rfile.write(str(current_date) + ';' + str(current_time) + ';' + entry[0].replace('_', ';') + ';' \ - + str(entry[1]) +";" + str(args.lat) + ';' + str(args.lon) + ';' + str(min_conf) + ';' + str(week) + ';' \ - + str(sensitivity) +';' + str(args.overlap) + '\n') - - def insert_variables_into_table(Date, Time, Sci_Name, Com_Name, Confidence, Lat, Lon, Cutoff, Week, Sens, Overlap): - try: - connection = mysql.connector.connect(host='localhost', - database='birds', - user='birder', - password=db_pwd) - cursor = connection.cursor() - mySql_insert_query = """INSERT INTO detections (Date, Time, Sci_Name, Com_Name, Confidence, Lat, Lon, Cutoff, Week, Sens, Overlap) - VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) """ - - record = (Date, Time, Sci_Name, Com_Name, Confidence, Lat, Lon, Cutoff, Week, Sens, Overlap) - - cursor.execute(mySql_insert_query, record) - connection.commit() - print("Record inserted successfully into detections table") - - - except mysql.connector.Error as error: - print("Failed to insert record into detections table {}".format(error)) - - finally: - if connection.is_connected(): - connection.close() - print("MySQL connection is closed") - - species = entry[0] - sci_name,com_name = species.split('_') - insert_variables_into_table(str(current_date), str(current_time), sci_name, com_name, \ - str(entry[1]), str(args.lat), str(args.lon), str(min_conf), str(week), \ - str(args.sensitivity), str(args.overlap)) - - print(str(current_date) + ';' + str(current_time) + ';' + entry[0].replace('_', ';') + ';' + str(entry[1]) +";" + str(args.lat) + ';' + str(args.lon) + ';' + str(min_conf) + ';' + str(week) + ';' + str(args.sensitivity) +';' + str(args.overlap) + '\n') - - if birdweather_id != "99999": - - if soundscape_uploaded is False: - # POST soundscape to server - soundscape_url = "https://app.birdweather.com/api/v1/stations/" + birdweather_id + "/soundscapes" + "?timestamp=" + current_iso8601 - - with open(args.i, 'rb') as f: - wav_data = f.read() - response = requests.post(url=soundscape_url, data=wav_data, headers={'Content-Type': 'application/octet-stream'}) - print("Soundscape POST Response Status - ", response.status_code) - sdata = response.json() - soundscape_id = sdata['soundscape']['id'] - soundscape_uploaded = True - - # POST detection to server - detection_url = "https://app.birdweather.com/api/v1/stations/" + birdweather_id + "/detections" - start_time = d.split(';')[0] - end_time = d.split(';')[1] - post_begin = "{ " - now_p_start = now + datetime.timedelta(seconds=float(start_time)) - current_iso8601 = now_p_start.astimezone(get_localzone()).isoformat() - post_timestamp = "\"timestamp\": \"" + current_iso8601 + "\"," - post_lat = "\"lat\": " + str(args.lat) + "," - post_lon = "\"lon\": " + str(args.lon) + "," - post_soundscape_id = "\"soundscapeId\": " + str(soundscape_id) + "," - post_soundscape_start_time = "\"soundscapeStartTime\": " + start_time + "," - post_soundscape_end_time = "\"soundscapeEndTime\": " + end_time + "," - post_commonName = "\"commonName\": \"" + entry[0].split('_')[1] + "\"," - post_scientificName = "\"scientificName\": \"" + entry[0].split('_')[0] + "\"," - post_algorithm = "\"algorithm\": " + "\"alpha\"" + "," - post_confidence = "\"confidence\": " + str(entry[1]) - post_end = " }" - - post_json = post_begin + post_timestamp + post_lat + post_lon + post_soundscape_id + post_soundscape_start_time + post_soundscape_end_time + post_commonName + post_scientificName + post_algorithm + post_confidence + post_end - print(post_json) - response = requests.post(detection_url, json=json.loads(post_json)) - print("Detection POST Response Status - ", response.status_code) - - - conn.send(myReturn.encode(FORMAT)) - - #time.sleep(3) - - conn.close() - -def start(): - # Load model - global INTERPRETER, INCLUDE_LIST, EXCLUDE_LIST - INTERPRETER = loadModel() - server.listen() - print(f"[LISTENING] Server is listening on {SERVER}") - while True: - conn, addr = server.accept() - thread = threading.Thread(target=handle_client, args=(conn, addr)) - thread.start() - print(f"[ACTIVE CONNECTIONS] {threading.activeCount() - 1}") - - -print("[STARTING] server is starting...") -start() From 95823a67ca75ce3961ddc309bcf387e97a5d5bb4 Mon Sep 17 00:00:00 2001 From: Patrick McGuire <60325264+mcguirepr89@users.noreply.github.com> Date: Thu, 17 Feb 2022 16:56:04 -0500 Subject: [PATCH 004/160] Rename server-lite.py to server.py --- scripts/{server-lite.py => server.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename scripts/{server-lite.py => server.py} (100%) diff --git a/scripts/server-lite.py b/scripts/server.py similarity index 100% rename from scripts/server-lite.py rename to scripts/server.py From eaf71eb6392fb595a0a69b575fadaf9decad6e1c Mon Sep 17 00:00:00 2001 From: Patrick McGuire <60325264+mcguirepr89@users.noreply.github.com> Date: Thu, 17 Feb 2022 16:58:21 -0500 Subject: [PATCH 005/160] Update createdb_bullseye.sh --- scripts/createdb_bullseye.sh | 28 +++------------------------- 1 file changed, 3 insertions(+), 25 deletions(-) diff --git a/scripts/createdb_bullseye.sh b/scripts/createdb_bullseye.sh index 8453358..45ea2b4 100755 --- a/scripts/createdb_bullseye.sh +++ b/scripts/createdb_bullseye.sh @@ -7,22 +7,7 @@ # If using this script to re-initialize (DROP then CREATE) # the DB, be sure to run this as root or with sudo source /etc/birdnet/birdnet.conf -mysql_secure_installation << EOF - -y -n -y -y -y -y -EOF - -mysql << EOF -DROP DATABASE IF EXISTS birds; -CREATE DATABASE IF NOT EXISTS birds; - -USE birds; - +sqlite3 /home/pi/BirdNET-Pi/scripts/birds.db << EOF CREATE TABLE IF NOT EXISTS detections ( Date DATE, Time TIME, @@ -34,13 +19,6 @@ CREATE TABLE IF NOT EXISTS detections ( Cutoff FLOAT, Week INT, Sens FLOAT, - Overlap FLOAT); -GRANT ALL ON birds.* TO 'birder'@'localhost' IDENTIFIED BY '${DB_PWD}' WITH GRANT OPTION; -FLUSH PRIVILEGES; -exit + Overlap FLOAT, + File_Name VARCHAR(100) NOT NULL); EOF -sudo -u${USER} sed -i "s/databasepassword/${DB_PWD}/g" /home/pi/BirdNET-Pi/scripts/server.py -sed -i "s/mysqli.default_host =.*/mysqli.default_host = localhost/g" /etc/php/7.4/fpm/php.ini -sed -i "s/mysqli.default_user =.*/mysqli.default_user = birder/g" /etc/php/7.4/fpm/php.ini -sed -i "s/mysqli.default_pw =.*/mysqli.default_pw = ${DB_PWD}/g" /etc/php/7.4/fpm/php.ini - From ba998a2c4fca46affadad7a54acacc2f3473befa Mon Sep 17 00:00:00 2001 From: Patrick McGuire <60325264+mcguirepr89@users.noreply.github.com> Date: Thu, 17 Feb 2022 17:06:57 -0500 Subject: [PATCH 006/160] Update install_config.sh --- scripts/install_config.sh | 373 +------------------------------------- 1 file changed, 2 insertions(+), 371 deletions(-) diff --git a/scripts/install_config.sh b/scripts/install_config.sh index a2559e2..7b97994 100755 --- a/scripts/install_config.sh +++ b/scripts/install_config.sh @@ -8,387 +8,18 @@ my_dir=$(realpath $(dirname $0)) birdnetpi_dir=$(realpath $(dirname $my_dir)) BIRDNET_CONF="$(dirname ${my_dir})/birdnet.conf" -get_RECS_DIR() { - read -p "What is the full path to your recordings directory (locally)? " RECS_DIR -} - -get_LATITUDE() { - read -p "What is the latitude where the recordings were made? " LATITUDE -} - -get_LONGITUDE() { - read -p "What is the longitude where the recordings were made? " LONGITUDE -} - -get_DO_EXTRACTIONS() { - while true; do - read -n1 -p "Do you want this device to perform the extractions? " DO_EXTRACTIONS - echo - case $DO_EXTRACTIONS in - [Yy] ) break;; - [Nn] ) break;; - * ) echo "You must answer with Yes or No (y or n)";; - esac - done -} - -get_DO_RECORDING() { - while true; do - read -n1 -p "Is this device also doing the recording? " DO_RECORDING - echo - case $DO_RECORDING in - [Yy] ) break;; - [Nn] ) break;; - * ) echo "You must answer with Yes or No (y or n)";; - esac - done -} - -get_BIRDNETPI_URL() { - while true;do - read -n1 -p "Would you like to access the extractions via a web browser? - - *Note: It is recommended, (but not required), that you run the web - server on the same host that does the extractions. If the extraction - service and web server are on different hosts, the \"By_Species\" and - \"Processed\" symbolic links won't work. The \"By-Date\" extractions, - however, will work as expected." CADDY_SERVICE - echo - case $CADDY_SERVICE in - [Yy] ) read -p "What URL would you like to publish the extractions to? - *Note: Set this to http://localhost if you do not want to make the - extractions publically available: " BIRDNETPI_URL - get_CADDY_PWD - get_ICE_PWD - break;; - [Nn] ) BIRDNETPI_URL= CADDY_PWD= ICE_PWD=;break;; - * ) echo "Please answer Yes or No";; - esac - done -} - -get_CADDY_PWD() { - if [ -z ${CADDY_PWD} ]; then - while true; do - read -p "Please set a password to protect your data: " CADDY_PWD - case $CADDY_PWD in - "" ) echo "The password cannot be empty. Please try again.";; - * ) break;; - esac - done - fi -} - -get_ICE_PWD() { - if [ ! -z ${CADDY_PWD} ] && [[ ${DO_RECORDING} =~ [Yy] ]];then - while true; do - read -n1 -p "Would you like to enable the live audio streaming service?" LIVE_STREAM - echo - case $LIVE_STREAM in - [Yy] ) - read -p "Please set the icecast password. Use only alphanumeric characters." ICE_PWD - echo - case ${ICE_PWD} in - "" ) echo "The password cannot be empty. Please try again.";; - *) break;; - esac - break;; - [Nn] ) break;; - * ) echo "You must answer Yes or No (y or n).";; - esac - done - fi -} - -get_DB_PWDS() { - if [ ! -z ${DB_PWD} ];then - read -p "Please set a password for your database: " DB_PWD - echo - fi -} - -get_PUSHED() { - while true; do - read -n1 -p "Do you have a free App key to receive mobile notifications via Pushed.co?" YN - echo - case $YN in - [Yy] ) read -p "Enter your Pushed.co App Key: " PUSHED_APP_KEY - read -p "Enter your Pushed.co App Key Secret: " PUSHED_APP_SECRET - break;; - [Nn] ) PUSHED_APP_KEY= - PUSHED_APP_SECRET= - break;; - * ) echo "A simple Yea or Nay will do";; - esac - done -} - -get_INSTALL_NOMACHINE() { - while true; do - read -n1 -p "Would you like to also install NoMachine for remote desktop access?" INSTALL_NOMACHINE - echo - case $INSTALL_NOMACHINE in - [Yy] ) break;; - [Nn] ) break;; - * ) echo "You must answer with Yes or No (y or n)";; - esac - done -} - -get_CHANNELS() { - REC_CARD="$(sudo -u pi aplay -L \ - | grep dsnoop \ - | cut -d, -f1 \ - | grep -ve 'vc4' -e 'Head' -e 'PCH' \ - | uniq)" - - [ -f $(dirname ${my_dir})/soundcard_params.txt ] || touch $(dirname ${my_dir})/soundcard_params.txt - SOUND_PARAMS=$(dirname ${my_dir})/soundcard_params.txt - SOUND_CARD="$(sudo -u ${USER} aplay -L \ - | awk -F, '/^hw:/ {print $1}' \ - | grep -ve 'vc4' -e 'Head' -e 'PCH' \ - | uniq)" - script -c "arecord -D ${SOUND_CARD} --dump-hw-params" -a "${SOUND_PARAMS}" &> /dev/null - CHANNELS=$(awk '/CHANN/ { print $2 }' "${SOUND_PARAMS}" | sed 's/\r$//') - [ -z REC_CARD ] && REC_CARD=default - [ -z CHANNELS ] && CHANNELS=2 - echo "REC_CARD variable set to ${REC_CARD}" - echo "Number of channels available: ${CHANNELS}" -} - - -configure() { - get_RECS_DIR - get_LATITUDE - get_LONGITUDE - get_DB_PWDS - get_DO_EXTRACTIONS - get_DO_RECORDING - get_BIRDNETPI_URL - get_PUSHED - get_INSTALL_NOMACHINE - get_CHANNELS -} - install_birdnet_conf() { cat << EOF > $(dirname ${my_dir})/birdnet.conf -################################################################################ -# Configuration settings for BirdNET-Pi # -################################################################################ - -############ CHANGE THE LATITUDE AND LONGITUDE TO STATIC VALUES ################ - - -## LATITUDE and LONGITUDE are self-explanatroy. Find them easily at -## maps.google.com. -## Example: these coordinates would indicate the Eiffel Tower in Paris, France. -## LATITUDE=48.858 -## LONGITUDE=2.294 - -## These are input as shell substitutions so that this will work out of the box. -## It guesses your latitude and longitude based off of your network information. -## THESE SHOULD BE CHANGED TO STATIC NUMBERS!!!! -LATITUDE=${LATITUDE} -LONGITUDE=${LONGITUDE} - -## RECS_DIR is the location birdnet_analysis.service will look for the data-set -## it needs to analyze. Be sure this directory is readable and writable for -## the BIRDNET_USER. If you are going to be accessing a remote data-set, you -## still need to set this, as this will be where the remote directory gets -## mounted locally. - -RECS_DIR=${RECS_DIR} - -#----------------------- Web Interface User Password ------------------------# -#____________________The variable below sets the 'birdnet'_____________________# -#___________________user password for the live audio stream,___________________# -#_________________web tools, system info, and processed files__________________# - -## CADDY_PWD is the plaintext password (that will be hashed) and used to access -## certain parts of the web interface - -CADDY_PWD=${CADDY_PWD} - -#------------------------- MariaDB User Passwords ---------------------------# -#_____________The variable below sets the password for the_____________________# -#_______________________'birder' user on the MariaDB___________________________# - -## DB_PWD is for the 'birder' user -DB_PWD=${DB_PWD} - -#------------------------- Live Audio Stream --------------------------------# -#_____________The variable below configures/enables the live___________________# -#_____________________________audio stream.____________________________________# - - -## ICE_PWD is the password that icecast2 will use to authenticate ffmpeg as a -## trusted source for the stream. You will never need to enter this manually -## anywhere other than here. - -ICE_PWD=${ICE_PWD} - -#----------------------- Web-hosting/Caddy File-server -----------------------# -#________The four variables below can be set to enable internet access_________# -#____________to your data,(e.g., extractions, raw data, live___________________# -#______________audio stream, BirdNET.selection.txt files)______________________# - - -## BIRDNETPI_URL is the URL where the extractions, data-set, and live-stream -## will be web-hosted. If you do not own a domain, or would just prefer to keep -## the BirdNET-Pi on your local network, keep this EMPTY. - -BIRDNETPI_URL=${BIRDNETPI_URL} -WEBTERMINAL_URL${WEBTERMINAL_URL} -BIRDNETLOG_URL=${BIRDNETLOG_URL} - - -#------------------- Mobile Notifications via Pushed.co ---------------------# -#____________The two variables below enable mobile notifications_______________# -#_____________See https://pushed.co/quick-start-guide to get___________________# -#_________________________these values for your app.___________________________# - -# Keep these EMPTY if haven't setup a Pushed.co App yet. # - -## Pushed.co App Key and App Secret - -PUSHED_APP_KEY=${PUSHED_APP_KEY} -PUSHED_APP_SECRET=${PUSHED_APP_SECRET} - -################################################################################ -#-------------------------------- Defaults ----------------------------------# -################################################################################ - -#------------------------------- NoMachine ----------------------------------# -#_____________The variable below can be set include NoMachine__________________# -#_________________remote desktop software to be installed._____________________# - -# Keep this EMPTY if you do not want to install NoMachine. # - -## INSTALL_NOMACHINE is simply a setting that can be enabled to install -## NoMachine alongside the BirdNET-Pi for remote desktop access. This in- -## staller assumes personal use. Please reference the LICENSE file included -## in this repository for more information. -## Set this to Y or y to install NoMachine alongside the BirdNET-Lite - -INSTALL_NOMACHINE=${INSTALL_NOMACHINE} - -# -#------------------------------ Extraction Service ---------------------------# - -## DO_EXTRACTIONS is simply a setting for enabling the extraction.service. -## Set this to Y or y to enable extractions. - -DO_EXTRACTIONS=${DO_EXTRACTIONS} - -#----------------------------- Recording Service ----------------------------# -#____________________The variable below can be set to enable __________________# -#________________________the birdnet_recording.service ________________________# - -## DO_RECORDING is simply a setting for enabling the 24/7 -## birdnet_recording.service. -## Set this to Y or y to enable recording. - -DO_RECORDING=${DO_RECORDING} - -## REC_CARD is the sound card you would want the birdnet_recording.service to -## use. This setting is irrelevant if you are not planning on doing data -## collection via recording on this machine. The command substitution below -## looks for a USB microphone's dsnoop alsa device. The dsnoop device lets -## birdnet_recording.service and livestream.service share the raw audio stream -## from the microphone. If you would like to use a different microphone than -## what this produces, or if your microphone does not support creating a -## dsnoop device, you can set this explicitly from a list of the available -## devices from the output of running 'aplay -L' - -REC_CARD=${REC_CARD} - -## PROCESSED is the directory where the formerly 'Analyzed' files are moved -## after extractions have been made from them. This includes both WAVE and -## BirdNET.selection.txt files. - -PROCESSED=${PROCESSED} - -## EXTRACTED is the directory where the extracted audio selections are moved. - -EXTRACTED=${EXTRACTED} - -## IDFILE is the file that keeps a complete list of every spececies that -## BirdNET has identified from your data-set. It is persistent across -## data-sets, so would need to be whiped clean through deleting or renaming -## it. A backup is automatically made from this variable each time it is -## updated (structure: ${IDFILE}.bak), and would also need to be removed -## or renamed to start a new file between data-sets. Alternately, you can -## change this variable between data-sets to preserve records of disparate -## data-sets according to name. - -IDFILE=${IDFILE} - -## OVERLAP is the value in seconds which BirdNET should use when analyzing -## the data. The values must be between 0.0-2.9. - -OVERLAP=${OVERLAP} - -## CONFIDENCE is the minimum confidence level from 0.0-1.0 BirdNET's analysis -## should reach before creating an entry in the BirdNET.selection.txt file. -## Don't set this to 1.0 or you won't have any results. - -CONFIDENCE=${CONFIDENCE} - -## SENSITIVITY is the detection sensitivity from 0.5-1.5. - -SENSITIVITY=${SENSITIVITY} - -## CHANNELS holds the variabel that corresponds to the number of channels the -## sound card supports. - -CHANNELS=${CHANNELS} - -## FULL_DISK can be set to configure how the system reacts to a full disk -## purge = Remove the oldest day's worth of recordings -## keep = Keep all data and 'stop_core_services.sh' - -FULL_DISK=purge - -## VENV is the virtual environment where the the BirdNET python build is found, -## i.e, VENV is the virtual environment miniforge built for BirdNET. - -VENV=/home/pi/BirdNET-Pi/birdnet - -## RECORDING_LENGTH sets the length of the recording that BirdNET-Lite will analyze. -RECORDING_LENGTH=${RECORDING_LENGTH} - -## EXTRACTION_LENGTH sets the length of the audio extractions that will be made -## from each BirdNET-Lite detection. -EXTRACTION_LENGTH=${EXTRACTION_LENGTH} - -## BIRDNET_USER should be the non-root user systemd should use to execute each -## service. - -BIRDNET_USER=pi - -## These are just for debugging -LAST_RUN=${LAST_RUN} -THIS_RUN=${THIS_RUN} EOF } -# Checks for a birdnet.conf file in the BirdNET-Pi directory for a -# non-interactive installation. Otherwise,the installation is interactive. +# Checks for a birdnet.conf file if [ -f ${BIRDNET_CONF} ];then source ${BIRDNET_CONF} chmod g+w ${BIRDNET_CONF} - sed -i "s/LATITUDE=.*/LATITUDE=${LATITUDE}/g" ${BIRDNET_CONF} - sed -i "s/LONGITUDE=.*/LONGITUDE=${LONGITUDE}/g" ${BIRDNET_CONF} - sed -i "s/DB_PWD=.*/DB_PWD=${DB_PWD}/g" ${BIRDNET_CONF} - #install_birdnet_conf [ -d /etc/birdnet ] || sudo mkdir /etc/birdnet sudo ln -sf $(dirname ${my_dir})/birdnet.conf /etc/birdnet/birdnet.conf grep -ve '^#' -e '^$' /etc/birdnet/birdnet.conf > ${birdnetpi_dir}/firstrun.ini else - configure - install_birdnet_conf - chmod g+w ${BIRDNET_CONF} - [ -d /etc/birdnet ] || sudo mkdir /etc/birdnet - sudo ln -sf $(dirname ${my_dir})/birdnet.conf /etc/birdnet/birdnet.conf - grep -ve '^#' -e '^$' /etc/birdnet/birdnet.conf > ${birdnetpi_dir}/firstrun.ini + echo "No birdnet.conf"; exit 1 fi From 5455a682cd9919e1891a7ddd49e410601c670adc Mon Sep 17 00:00:00 2001 From: Patrick McGuire <60325264+mcguirepr89@users.noreply.github.com> Date: Thu, 17 Feb 2022 17:07:37 -0500 Subject: [PATCH 007/160] Update birdnet.conf-defaults --- birdnet.conf-defaults | 8 -------- 1 file changed, 8 deletions(-) diff --git a/birdnet.conf-defaults b/birdnet.conf-defaults index 0513576..afe90b3 100644 --- a/birdnet.conf-defaults +++ b/birdnet.conf-defaults @@ -28,14 +28,6 @@ BIRDWEATHER_ID= CADDY_PWD= -#------------------------- MariaDB User Passwords ---------------------------# -#_____________The variable below sets the password for the_____________________# -#_______________________'birder' user on the MariaDB___________________________# - -## DB_PWD is for the 'birder' user. The shell substitution below sets a random -## password for you during installation. -DB_PWD=$(< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c${1:-32};echo;) - #------------------------- Live Audio Stream --------------------------------# #_____________The variable below configures/enables the live___________________# #_____________________________audio stream.____________________________________# From 3ec62479fbdf72f8411461014fe717cff343a6de Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Thu, 17 Feb 2022 17:28:32 -0500 Subject: [PATCH 008/160] test new install --- scripts/{createdb_bullseye.sh => createdb.sh} | 0 scripts/install_birdnet.sh | 52 +---- scripts/install_config.sh | 198 +++++++++++++++++- scripts/install_services.sh | 96 +++------ 4 files changed, 227 insertions(+), 119 deletions(-) rename scripts/{createdb_bullseye.sh => createdb.sh} (100%) diff --git a/scripts/createdb_bullseye.sh b/scripts/createdb.sh similarity index 100% rename from scripts/createdb_bullseye.sh rename to scripts/createdb.sh diff --git a/scripts/install_birdnet.sh b/scripts/install_birdnet.sh index 16a821e..13df62c 100755 --- a/scripts/install_birdnet.sh +++ b/scripts/install_birdnet.sh @@ -20,27 +20,26 @@ fi sudo ./install_services.sh || exit 1 source /etc/birdnet/birdnet.conf -APT_DEPS=(swig ffmpeg wget unzip curl cmake make bc) -LIBS_MODULES=(libjpeg-dev zlib1g-dev python3-dev python3-pip python3-venv) +apt_deps=(swig ffmpeg wget unzip curl cmake make bc) +libs_modules=(libjpeg-dev zlib1g-dev python3-dev python3-pip python3-venv) install_deps() { - echo " Checking dependencies" - sudo apt update &> /dev/null - for i in "${LIBS_MODULES[@]}";do + echo "Checking dependencies" + for i in "${libs_modules[@]}";do if [ $(apt list --installed 2>/dev/null | grep "$i" | wc -l) -le 0 ];then echo " Installing $i" sudo apt -y install ${i} &> /dev/null else - echo " $i is installed!" + echo "$i is installed!" fi done - for i in "${APT_DEPS[@]}";do + for i in "${apt_deps[@]}";do if ! which $i &>/dev/null ;then - echo " Installing $i" + echo "Installing $i" sudo apt -y install ${i} &> /dev/null else - echo " $i is installed!" + echo "$i is installed!" fi done } @@ -51,21 +50,10 @@ install_birdnet() { python3 -m venv birdnet source ./birdnet/bin/activate echo "Upgrading pip, wheel, and setuptools" - pip3 install --upgrade pip~=21.0.0 wheel setuptools - python_version="$(awk -F. '{print $2}' <(ls -l $(which /usr/bin/python3)))" - echo "python_version=${python_version}" + pip3 install --upgrade pip wheel setuptools # TFLite Pre-built binaires from https://github.com/PINTO0309/TensorflowLite-bin - # Python 3.7 - if [[ "$python_version" == 7 ]];then - echo "Installing the TFLite bin wheel" - pip3 install --upgrade tflite_runtime-2.6.0-cp37-none-linux_aarch64.whl - fi - - # Python 3.9 - if [[ "$python_version" == 9 ]];then echo "Installing the TFLite bin wheel" pip3 install --upgrade tflite_runtime-2.6.0-cp39-none-linux_aarch64.whl - fi echo "Making sure everything else is installed" pip3 install -U -r /home/pi/BirdNET-Pi/requirements.txt } @@ -76,24 +64,4 @@ install_deps if [ ! -d ${VENV} ];then install_birdnet fi - -echo " BirdNet is installed!! - - To start the service manually, issue: - 'sudo systemctl start birdnet_analysis' - To monitor the service logs, issue: - 'journalctl -fu birdnet_analysis' - To stop the service manually, issue: - 'sudo systemctl stop birdnet_analysis' - To stop and disable the service, issue: - 'sudo systemctl disable --now birdnet_analysis.service' - - Visit - the BirdNET-Pi homepage at http://birdnetpi.local" - echo -case $YN in - [Yy] ) sudo systemctl start birdnet_analysis.service \ - && journalctl -fu birdnet_analysis;; -* ) echo " Thanks for installing BirdNET-Pi!! - I hope it was helpful!";; -esac +exit 0 diff --git a/scripts/install_config.sh b/scripts/install_config.sh index 7b97994..5c9fd16 100755 --- a/scripts/install_config.sh +++ b/scripts/install_config.sh @@ -6,20 +6,198 @@ trap 'exit 1' SIGINT SIGHUP my_dir=$(realpath $(dirname $0)) birdnetpi_dir=$(realpath $(dirname $my_dir)) -BIRDNET_CONF="$(dirname ${my_dir})/birdnet.conf" +birdnet_conf="$(dirname ${my_dir})/birdnet.conf" -install_birdnet_conf() { +install_config() { cat << EOF > $(dirname ${my_dir})/birdnet.conf +################################################################################ +# Configuration settings for BirdNET-Pi # +################################################################################ + +#--------------------- Required: Latitude, and Longitude ----------------------# + +## The shell substitution below guesses these based on your network. THESE NEED +## TO BE CHANGED TO STATIC VALUES +## Please only go to 4 decimal places. Example:43.3984 + +LATITUDE="$(curl -s4 ifconfig.co/json | awk '/lat/ {print $2}' | tr -d ',')" +LONGITUDE="$(curl -s4 ifconfig.co/json | awk '/lon/ {print $2}' | tr -d ',')" + + +#--------------------- BirdWeather Station Information -----------------------# +#_____________The variable below can be set to have your BirdNET-Pi____________# +#__________________also act as a BirdWeather listening station_________________# + +BIRDWEATHER_ID= + +#----------------------- Web Interface User Password ------------------------# +#____________________The variable below sets the 'birdnet'_____________________# +#___________________user password for the Live Audio Stream,___________________# +#_________________Tools, System Links, and the Processed files ________________# + +## CADDY_PWD is the plaintext password (that will be hashed) and used to access +## certain parts of the web interface + +CADDY_PWD= + +#------------------------- Live Audio Stream --------------------------------# +#_____________The variable below configures/enables the live___________________# +#_____________________________audio stream.____________________________________# + + +## ICE_PWD is the password that icecast2 will use to authenticate ffmpeg as a +## trusted source for the stream. You will never need to enter this manually +## anywhere other than here and it stays on 'localhost.' + +ICE_PWD=birdnetpi + +#----------------------- Web-hosting/Caddy File-server -----------------------# +#_______The three variables below can be set to enable internet access_________# +#____________to your data,(e.g., extractions, raw data, live___________________# +#______________audio stream, BirdNET.selection.txt files)______________________# + + +## BIRDNETPI_URL is the URL where the extractions, data-set, and live-stream +## will be web-hosted. If you do not own a domain, or would just prefer to keep +## the BirdNET-Pi on your local network, keep this EMPTY. + +BIRDNETPI_URL= +BIRDNETLOG_URL= +WEBTERMINAL_URL= + + +#------------------- Mobile Notifications via Pushed.co ---------------------# +#____________The two variables below enable mobile notifications_______________# +#_____________See https://pushed.co/quick-start-guide to get___________________# +#_________________________these values for your app.___________________________# + +# Keep these EMPTY if haven't setup a Pushed.co App yet. # + +## Pushed.co App Key and App Secret + +PUSHED_APP_KEY= +PUSHED_APP_SECRET= + +################################################################################ +#-------------------------------- Defaults ----------------------------------# +################################################################################ + +## RECS_DIR is the location birdnet_analysis.service will look for the data-set +## it needs to analyze. Be sure this directory is readable and writable for +## the BIRDNET_USER. + +RECS_DIR=/home/pi/BirdSongs + + +#------------------------------ Extraction Service ---------------------------# + +## DO_EXTRACTIONS is simply a setting for enabling the extraction.service. +## Set this to Y or y to enable extractions. + +DO_EXTRACTIONS=y + +#----------------------------- Recording Service ----------------------------# +#____________________The variable below can be set to enable __________________# +#________________________the birdnet_recording.service ________________________# + +## DO_RECORDING is simply a setting for enabling the 24/7 +## birdnet_recording.service. +## Set this to Y or y to enable recording. + +DO_RECORDING=y + +## REC_CARD is the sound card you would want the birdnet_recording.service to +## use. Leave this as "default" to use PulseAudio (recommended), or use +## the output from "aplay -L" to specify an ALSA device. + +REC_CARD=default + +## PROCESSED is the directory where the formerly 'Analyzed' files are moved +## after extractions have been made from them. This includes both WAVE and +## BirdNET.selection.txt files. + +PROCESSED=${RECS_DIR}/Processed + +## EXTRACTED is the directory where the extracted audio selections are moved. + +EXTRACTED=${RECS_DIR}/Extracted + +## IDFILE is the file that keeps a complete list of every spececies that +## BirdNET has identified from your data-set. It is a relic and not really +## used anymore. + +IDFILE=${HOME}/BirdNET-Pi/IdentifiedSoFar.txt + +## OVERLAP is the value in seconds which BirdNET should use when analyzing +## the data. The values must be between 0.0-2.9. + +OVERLAP=0.0 + +## CONFIDENCE is the minimum confidence level from 0.0-1.0 BirdNET's analysis +## should reach before creating an entry in the BirdNET.selection.txt file. +## Don't set this to 1.0 or you won't have any results. + +CONFIDENCE=0.7 + +## SENSITIVITY is the detection sensitivity from 0.5-1.5. + +SENSITIVITY=1.25 + +## CHANNELS holds the variable that corresponds to the number of channels the +## sound card supports. + +CHANNELS=2 + +## FULL_DISK can be set to configure how the system reacts to a full disk +## purge = Remove the oldest day's worth of recordings +## keep = Keep all data and 'stop_core_services.sh' + +FULL_DISK=purge + +## VENV is the python virtual environment wherein all modules and site-packages +## have been installed. + +VENV=/home/pi/BirdNET-Pi/birdnet + +## RECORDING_LENGTH sets the length of the recording that BirdNET-Lite will +## analyze. + +RECORDING_LENGTH=15 + +## EXTRACTION_LENGTH sets the length of the audio extractions that will be made +## from each BirdNET-Lite detection. An empty value will use the default of 6 +## seconds. + +EXTRACTION_LENGTH= + +## AUDIOFMT set the audio format that sox should use for the extractions. +## The default is mp3. Available formats are: 8svx aif aifc aiff aiffc al amb +## amr-nb amr-wb anb au avr awb caf cdda cdr cvs cvsd cvu dat dvms f32 f4 f64 f8 +## fap flac fssd gsm gsrt hcom htk ima ircam la lpc lpc10 lu mat mat4 mat5 maud +## mp2 mp3 nist ogg paf prc pvf raw s1 s16 s2 s24 s3 s32 s4 s8 sb sd2 sds sf sl +## sln smp snd sndfile sndr sndt sou sox sph sw txw u1 u16 u2 u24 u3 u32 u4 u8 +## ub ul uw vms voc vorbis vox w64 wav wavpcm wv wve xa xi +## Note: Most have not been tested. + +AUDIOFMT=mp3 + +## BIRDNET_USER should be the non-root user systemd should use to execute each +## service. + +BIRDNET_USER=pi + +## These are just for debugging +LAST_RUN= +THIS_RUN= + EOF } # Checks for a birdnet.conf file -if [ -f ${BIRDNET_CONF} ];then - source ${BIRDNET_CONF} - chmod g+w ${BIRDNET_CONF} - [ -d /etc/birdnet ] || sudo mkdir /etc/birdnet - sudo ln -sf $(dirname ${my_dir})/birdnet.conf /etc/birdnet/birdnet.conf - grep -ve '^#' -e '^$' /etc/birdnet/birdnet.conf > ${birdnetpi_dir}/firstrun.ini -else - echo "No birdnet.conf"; exit 1 +if ! [ -f ${birdnet_conf} ];then + install_config fi +chmod g+w ${birdnet_conf} +[ -d /etc/birdnet ] || sudo mkdir /etc/birdnet +sudo ln -sf $(dirname ${my_dir})/birdnet.conf /etc/birdnet/birdnet.conf +grep -ve '^#' -e '^$' /etc/birdnet/birdnet.conf > ${birdnetpi_dir}/firstrun.ini diff --git a/scripts/install_services.sh b/scripts/install_services.sh index 447b573..993f71d 100755 --- a/scripts/install_services.sh +++ b/scripts/install_services.sh @@ -11,6 +11,11 @@ nomachine_url="https://download.nomachine.com/download/7.7/Arm/nomachine_7.7.4_1 gotty_url="https://github.com/yudai/gotty/releases/download/v1.0.1/gotty_linux_arm.tar.gz" config_file="$(dirname ${my_dir})/birdnet.conf" + +update_system() { + apt update && apt -y upgrade +} + set_hostname() { if [ "$(hostname)" == "raspberrypi" ];then echo "Setting hostname to 'birdnetpi'" @@ -31,10 +36,6 @@ install_ftpd() { fi } -update_system() { - apt update && apt -y upgrade -} - install_scripts() { echo "Installing BirdNET-Pi scripts to /usr/local/bin" ln -sf ${my_dir}/* /usr/local/bin/ @@ -42,20 +43,13 @@ install_scripts() { } install_mariadb() { - if ! which mysql &> /dev/null;then - echo "Installing MariaDB Server" - apt -qqy update - apt -qqy install mariadb-server - echo "MariaDB Installed" + if ! which sqlite3 &> /dev/null;then + echo "Installing SQLite3" + apt -qqy install sqlite3 php-sqlite3 + echo "SQLite Installed" fi echo "Initializing the database" - source /etc/os-release - if [[ "${VERSION_CODENAME}" == "buster" ]];then - USER=${USER} ${my_dir}/createdb_buster.sh - elif [[ "${VERSION_CODENAME}" == "bullseye" ]];then - USER=${USER} ${my_dir}/createdb_bullseye.sh - fi - systemctl restart php${php_version}-fpm + ${my_dir}/createdb.sh } install_birdnet_analysis() { @@ -186,7 +180,6 @@ create_necessary_dirs() { fi sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/spectrogram.php ${EXTRACTED} - sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/viewday.php ${EXTRACTED} sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/overview.php ${EXTRACTED} sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/stats.php ${EXTRACTED} sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/viewdb.php ${EXTRACTED} @@ -212,7 +205,7 @@ generate_BirdDB() { sudo -u ${USER} sed -i '1 i\Date;Time;Sci_Name;Com_Name;Confidence;Lat;Lon;Cutoff;Week;Sens;Overlap' $(dirname ${my_dir})/BirdDB.txt fi ln -sf $(dirname ${my_dir})/BirdDB.txt ${my_dir}/BirdDB.txt && - chown pi:pi ${my_dir}/BirdDB.txt && chmod g+rw ${my_dir}/BirdDB.txt + chown pi:pi ${my_dir}/BirdDB.txt && chmod g+rw ${my_dir}/BirdDB.txt } install_alsa() { @@ -221,7 +214,6 @@ install_alsa() { echo "alsa-utils installed" else echo "Installing alsa-utils" - apt -qqq update apt install -qqy alsa-utils echo "alsa-utils installed" fi @@ -229,7 +221,6 @@ install_alsa() { echo "PulseAudio installed" else echo "Installing pulseaudio" - apt -qqq update apt install -qqy pulseaudio echo "PulseAudio installed" fi @@ -285,7 +276,6 @@ install_Caddyfile() { if [ -f /etc/caddy/Caddyfile ];then cp /etc/caddy/Caddyfile{,.original} fi - php_version="$(awk -F'php' '{print $3}' <(ls -l $(which /etc/alternatives/php)))" if ! [ -z ${CADDY_PWD} ];then HASHWORD=$(caddy hash-password -plaintext ${CADDY_PWD}) cat << EOF > /etc/caddy/Caddyfile @@ -305,7 +295,7 @@ http://localhost http://$(hostname).local ${BIRDNETPI_URL} { birdnet ${HASHWORD} } reverse_proxy /stream localhost:8000 - php_fastcgi unix//run/php/php${php_version}-fpm.sock + php_fastcgi unix//run/php/php7.4-fpm.sock } EOF else @@ -314,7 +304,7 @@ http://localhost http://$(hostname).local ${BIRDNETPI_URL} { root * ${EXTRACTED} file_server browse reverse_proxy /stream localhost:8000 - php_fastcgi unix//run/php/php${php_version}-fpm.sock + php_fastcgi unix//run/php/php7.4-fpm.sock } EOF fi @@ -453,7 +443,6 @@ install_sox() { echo "Sox is installed" else echo "Installing sox" - apt -qq update apt install -y sox libsox-fmt-mp3 echo "Sox installed" fi @@ -485,7 +474,6 @@ EOF install_icecast() { if ! which icecast2;then echo "Installing IceCast2" - apt -qq update echo "icecast2 icecast2/icecast-setup boolean false" | debconf-set-selections apt install -qqy icecast2 config_icecast @@ -530,17 +518,6 @@ EOF systemctl enable livestream.service } -install_nomachine() { - if [ ! -d /usr/share/NX ] && [ -d /etc/lightdm ];then - echo "Installing NoMachine" - curl -s -o ${HOME}/nomachine.deb -O "${nomachine_url}" - apt install -y ${HOME}/nomachine.deb - rm -f ${HOME}/nomachine.deb - echo "Enabling VNC" - systemctl enable --now vncserver-x11-serviced.service - fi -} - install_cleanup_cron() { echo "Installing the cleanup.cron" cat $(dirname ${my_dir})/templates/cleanup.cron >> /etc/crontab @@ -552,37 +529,22 @@ install_selected_services() { install_scripts install_birdnet_analysis install_birdnet_server - - if [[ "${DO_EXTRACTIONS}" =~ [Yy] ]];then - install_extraction_service - fi - - if [[ "${DO_RECORDING}" =~ [Yy] ]];then - install_alsa - install_recording_service - fi - - install_php - install_caddy - install_Caddyfile - update_etc_hosts - install_avahi_aliases - install_gotty_logs - install_sox - install_mariadb - install_spectrogram_service - install_chart_viewer_service - install_pushed_notifications - - if [ ! -z "${ICE_PWD}" ];then - install_icecast - install_livestream_service - fi - - if [[ "${INSTALL_NOMACHINE}" =~ [Yy] ]];then - install_nomachine - fi - + install_extraction_service + install_alsa + install_recording_service + install_php + install_caddy + install_Caddyfile + update_etc_hosts + install_avahi_aliases + install_gotty_logs + install_sox + install_mariadb + install_spectrogram_service + install_chart_viewer_service + install_pushed_notifications + install_icecast + install_livestream_service create_necessary_dirs generate_BirdDB install_cleanup_cron From bab57620bf4823fe082076392015d557e922c948 Mon Sep 17 00:00:00 2001 From: Patrick McGuire <60325264+mcguirepr89@users.noreply.github.com> Date: Thu, 17 Feb 2022 17:37:38 -0500 Subject: [PATCH 009/160] Update install_services.sh --- scripts/install_services.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/install_services.sh b/scripts/install_services.sh index 993f71d..2b40b0b 100755 --- a/scripts/install_services.sh +++ b/scripts/install_services.sh @@ -451,7 +451,6 @@ install_sox() { install_php() { if ! which php &> /dev/null || ! which php-fpm || ! apt list --installed | grep php-xml;then echo "Installing PHP modules" - apt -qq update apt install -qqy php php-fpm php-mysql php-xml php-zip else echo "PHP and PHP-FPM installed" From 8143feefc72511d96f2f0e79b364c41492743e08 Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Fri, 18 Feb 2022 08:55:28 -0500 Subject: [PATCH 010/160] silent bit errors --- scripts/extra_info.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/scripts/extra_info.sh b/scripts/extra_info.sh index dce9466..68cada6 100755 --- a/scripts/extra_info.sh +++ b/scripts/extra_info.sh @@ -12,28 +12,28 @@ echo "Binary: $binary"; revbinary=$(echo $binary|rev) if echo $binary | grep 1 ;then echo "ISSUES DETECTED" - if [ ${revbinary:0:1} -eq 1 ];then + if [ ${revbinary:0:1} -eq 1 &>/dev/null ];then echo "Under-voltage detected" fi - if [ ${revbinary:1:1} -eq 1 ];then + if [ ${revbinary:1:1} -eq 1 &>/dev/null ];then echo "Arm frequency capped" fi - if [ ${revbinary:2:1} -eq 1 ];then + if [ ${revbinary:2:1} -eq 1 &>/dev/null ];then echo "Currently Throttled" fi - if [ ${revbinary:3:1} -eq 1 ];then + if [ ${revbinary:3:1} -eq 1 &>/dev/null ];then echo "Soft temperatue limit active" fi - if [ ${revbinary:16:1} -eq 1 ];then + if [ ${revbinary:16:1} -eq 1 &>/dev/null ];then echo "Under-voltage has occurred" fi - if [ ${revbinary:17:1} -eq 1 ];then + if [ ${revbinary:17:1} -eq 1 &>/dev/null ];then echo "Arm frequency capping has occurred" fi - if [ ${revbinary:18:1} -eq 1 ];then + if [ ${revbinary:18:1} -eq 1 &>/dev/null ];then echo "Throttling has occurred" fi - if [ ${revbinary:19:1} -eq 1 ];then + if [ ${revbinary:19:1} -eq 1 &>/dev/null ];then echo "Soft temperature limit has occurred" fi fi From a0722fbf0f77497abaa0bd7ab1ddc073e120c7f3 Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Fri, 18 Feb 2022 12:47:17 -0500 Subject: [PATCH 011/160] more testing --- scripts/adminer-de.php | 908 +++++++++++++++ scripts/adminer-fr.php | 908 +++++++++++++++ scripts/adminer.php | 2205 +++++++++++------------------------ scripts/analyze.py | 1 + scripts/birdnet_analysis.sh | 35 +- scripts/createdb.sh | 2 + scripts/extra_info.sh | 16 +- scripts/history.php | 24 +- scripts/index.html | 2 +- scripts/install_services.sh | 37 +- scripts/overview.php | 59 +- scripts/server.py | 8 +- scripts/stats.php | 88 +- scripts/viewdb.php | 78 +- 14 files changed, 2537 insertions(+), 1834 deletions(-) create mode 100644 scripts/adminer-de.php create mode 100644 scripts/adminer-fr.php mode change 100644 => 100755 scripts/analyze.py diff --git a/scripts/adminer-de.php b/scripts/adminer-de.php new file mode 100644 index 0000000..729d48d --- /dev/null +++ b/scripts/adminer-de.php @@ -0,0 +1,908 @@ +_findRootClass($Ja),'Adminer'))$Ge[$Ja]=new$Ja;}}$this->plugins=$Ge;}function +_callParent($s,$c){return +call_user_func_array(array('parent',$s),$c);}function +_applyPlugin($s,$c){foreach($this->plugins +as$Fe){if(method_exists($Fe,$s)){switch(count($c)){case +0:$K=$Fe->$s();break;case +1:$K=$Fe->$s($c[0]);break;case +2:$K=$Fe->$s($c[0],$c[1]);break;case +3:$K=$Fe->$s($c[0],$c[1],$c[2]);break;case +4:$K=$Fe->$s($c[0],$c[1],$c[2],$c[3]);break;case +5:$K=$Fe->$s($c[0],$c[1],$c[2],$c[3],$c[4]);break;case +6:$K=$Fe->$s($c[0],$c[1],$c[2],$c[3],$c[4],$c[5]);break;default:trigger_error('Too many parameters.',E_USER_WARNING);}if($K!==null)return$K;}}return$this->_callParent($s,$c);}function +_appendPlugin($s,$c){$K=$this->_callParent($s,$c);foreach($this->plugins +as$Fe){if(method_exists($Fe,$s)){$Y=call_user_func_array(array($Fe,$s),$c);if($Y)$K+=$Y;}}return$K;}function +dumpFormat(){$c=func_get_args();return$this->_appendPlugin(__FUNCTION__,$c);}function +dumpOutput(){$c=func_get_args();return$this->_appendPlugin(__FUNCTION__,$c);}function +editRowPrint($R,$n,$L,$Kg){$c=func_get_args();return$this->_appendPlugin(__FUNCTION__,$c);}function +editFunctions($m){$c=func_get_args();return$this->_appendPlugin(__FUNCTION__,$c);}function +name(){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +credentials(){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +connectSsl(){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +permanentLogin($h=false){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +bruteForceKey(){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +serverName($O){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +database(){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +schemas(){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +databases($mc=true){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +queryTimeout(){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +headers(){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +csp(){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +head(){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +css(){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +loginForm(){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +loginFormField($F,$Ec,$Y){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +login($rd,$_e){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +tableName($Vf){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +fieldName($m,$fe=0){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +selectLinks($Vf,$P=""){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +foreignKeys($R){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +backwardKeys($R,$Uf){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +backwardKeysPrint($va,$L){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +selectQuery($I,$Lf,$fc=false){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +sqlCommandQuery($I){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +rowDescription($R){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +rowDescriptions($M,$pc){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +selectLink($X,$m){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +selectVal($X,$A,$m,$ne){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +editVal($X,$m){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +tableStructurePrint($n){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +tableIndexesPrint($x){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +selectColumnsPrint($N,$e){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +selectSearchPrint($Z,$e,$x){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +selectOrderPrint($fe,$e,$x){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +selectLimitPrint($_){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +selectLengthPrint($ig){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +selectActionPrint($x){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +selectCommandPrint(){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +selectImportPrint(){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +selectEmailPrint($Lb,$e){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +selectColumnsProcess($e,$x){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +selectSearchProcess($n,$x){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +selectOrderProcess($n,$x){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +selectLimitProcess(){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +selectLengthProcess(){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +selectEmailProcess($Z,$pc){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +selectQueryBuild($N,$Z,$t,$fe,$_,$G){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +messageQuery($I,$jg,$fc=false){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +editInput($R,$m,$ra,$Y){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +editHint($R,$m,$Y){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +processInput($m,$Y,$s=""){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +dumpDatabase($j){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +dumpTable($R,$Pf,$Yc=0){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +dumpData($R,$Pf,$I){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +dumpFilename($Jc){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +dumpHeaders($Jc,$Id=false){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +importServerPath(){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +homepage(){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +navigation($Hd){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +databasesPrint($Hd){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}function +tablesPrint($T){$c=func_get_args();return$this->_applyPlugin(__FUNCTION__,$c);}}class +FCSqliteConnectionWithoutCredentials{function +loginForm(){$b=adminer();echo'
'.'Warnung: Verwenden Sie es nicht in einer Produktionsumgebung!'.'
',"\n",'',$b->loginFormField('db','
'.'Datenbank'.'',''."\n"),"
\n","

\n";return +true;}function +login($rd,$_e){return +true;}}function +adminer_object(){$Ge=array(new +FCSqliteConnectionWithoutCredentials());return +new +AdminerPlugin($Ge);}function +adminer_errors($Rb,$Tb){return!!preg_match('~^(Trying to access array offset on value of type null|Undefined array key)~',$Tb);}error_reporting(6135);set_error_handler('adminer_errors',E_WARNING);$kc=!preg_match('~^(unsafe_raw)?$~',ini_get("filter.default"));if($kc||ini_get("filter.default_flags")){foreach(array('_GET','_POST','_COOKIE','_SERVER')as$X){$Hg=filter_input_array(constant("INPUT$X"),FILTER_UNSAFE_RAW);if($Hg)$$X=$Hg;}}if(function_exists("mb_internal_encoding"))mb_internal_encoding("8bit");function +connection(){global$f;return$f;}function +adminer(){global$b;return$b;}function +version(){global$da;return$da;}function +idf_unescape($Kc){if(!preg_match('~^[`\'"]~',$Kc))return$Kc;$hd=substr($Kc,-1);return +str_replace($hd.$hd,$hd,substr($Kc,1,-1));}function +escape_string($X){return +substr(q($X),1,-1);}function +number($X){return +preg_replace('~[^0-9]+~','',$X);}function +number_type(){return'((?$W){unset($Te[$z][$ad]);if(is_array($W)){$Te[$z][stripslashes($ad)]=$W;$Te[]=&$Te[$z][stripslashes($ad)];}else$Te[$z][stripslashes($ad)]=($kc?$W:stripslashes($W));}}}}function +bracket_escape($Kc,$ua=false){static$vg=array(':'=>':1',']'=>':2','['=>':3','"'=>':4');return +strtr($Kc,($ua?array_flip($vg):$vg));}function +min_version($Xg,$td="",$g=null){global$f;if(!$g)$g=$f;$yf=$g->server_info;if($td&&preg_match('~([\d.]+)-MariaDB~',$yf,$C)){$yf=$C[1];$Xg=$td;}return(version_compare($yf,$Xg)>=0);}function +charset($f){return(min_version("5.5.3",0,$f)?"utf8mb4":"utf8");}function +script($Ff,$ug="\n"){return"$Ff$ug";}function +script_src($Mg){return"\n";}function +nonce(){return' nonce="'.get_nonce().'"';}function +target_blank(){return' target="_blank" rel="noreferrer noopener"';}function +h($Q){return +str_replace("\0","�",htmlspecialchars($Q,ENT_QUOTES,'utf-8'));}function +nl_br($Q){return +str_replace("\n","
",$Q);}function +checkbox($F,$Y,$Fa,$ed="",$Yd="",$Ja="",$fd=""){$K="".($Yd?script("qsl('input').onclick = function () { $Yd };",""):"");return($ed!=""||$Ja?"$K".h($ed)."":$K);}function +optionlist($de,$tf=null,$Qg=false){$K="";foreach($de +as$ad=>$W){$ee=array($ad=>$W);if(is_array($W)){$K.='';$ee=$W;}foreach($ee +as$z=>$X)$K.=''.h($X);if(is_array($W))$K.='';}return$K;}function +html_select($F,$de,$Y="",$Xd=true,$fd=""){if($Xd)return"".(is_string($Xd)?script("qsl('select').onchange = function () { $Xd };",""):"");$K="";foreach($de +as$z=>$X)$K.="";return$K;}function +select_input($ra,$de,$Y="",$Xd="",$Ee=""){$cg=($de?"select":"input");return"<$cg$ra".($de?">

","$md",script("qsl('a').onclick = partial(toggle, 'fieldset-$v');",""),"","
\n";}function +selectSearchPrint($Z,$e,$x){print_fieldset("search",'Suchen',$Z);foreach($x +as$u=>$w){if($w["type"]=="FULLTEXT"){echo"
(".implode(", ",array_map('h',$w["columns"])).") AGAINST"," ",script("qsl('input').oninput = selectFieldChange;",""),checkbox("boolean[$u]",1,isset($_GET["boolean"][$u]),"BOOL"),"
\n";}}$Da="this.parentNode.firstChild.onchange();";foreach(array_merge((array)$_GET["where"],array(array()))as$u=>$X){if(!$X||("$X[col]$X[val]"!=""&&in_array($X["op"],$this->operators))){echo"
".select_input(" name='where[$u][col]'",$e,$X["col"],($X?"selectFieldChange":"selectAddRow"),"(".'beliebig'.")"),html_select("where[$u][op]",$this->operators,$X["op"],$Da),"",script("mixin(qsl('input'), {oninput: function () { $Da }, onkeydown: selectSearchKeydown, onsearch: selectSearchSearch});",""),"
\n";}}echo"\n";}function +selectOrderPrint($fe,$e,$x){print_fieldset("sort",'Ordnen',$fe);$u=0;foreach((array)$_GET["order"]as$z=>$X){if($X!=""){echo"
".select_input(" name='order[$u]'",$e,$X,"selectFieldChange"),checkbox("desc[$u]",1,isset($_GET["desc"][$z]),'absteigend')."
\n";$u++;}}echo"
".select_input(" name='order[$u]'",$e,"","selectAddRow"),checkbox("desc[$u]",1,false,'absteigend')."
\n","\n";}function +selectLimitPrint($_){echo"
".'Begrenzung'."
";echo"",script("qsl('input').oninput = selectFieldChange;",""),"
\n";}function +selectLengthPrint($ig){if($ig!==null){echo"
".'Textlänge'."
","","
\n";}}function +selectActionPrint($x){echo"
".'Aktion'."
",""," ","\n","var indexColumns = ";$e=array();foreach($x +as$w){$gb=reset($w["columns"]);if($w["type"]!="FULLTEXT"&&$gb)$e[$gb]=1;}$e[""]=1;foreach($e +as$z=>$X)json_row($z);echo";\n","selectFieldChange.call(qs('#form')['select']);\n","\n","
\n";}function +selectCommandPrint(){return!information_schema(DB);}function +selectImportPrint(){return!information_schema(DB);}function +selectEmailPrint($Lb,$e){}function +selectColumnsProcess($e,$x){global$uc,$yc;$N=array();$t=array();foreach((array)$_GET["columns"]as$z=>$X){if($X["fun"]=="count"||($X["col"]!=""&&(!$X["fun"]||in_array($X["fun"],$uc)||in_array($X["fun"],$yc)))){$N[$z]=apply_sql_function($X["fun"],($X["col"]!=""?idf_escape($X["col"]):"*"));if(!in_array($X["fun"],$yc))$t[]=$N[$z];}}return +array($N,$t);}function +selectSearchProcess($n,$x){global$f,$k;$K=array();foreach($x +as$u=>$w){if($w["type"]=="FULLTEXT"&&$_GET["fulltext"][$u]!="")$K[]="MATCH (".implode(", ",array_map('idf_escape',$w["columns"])).") AGAINST (".q($_GET["fulltext"][$u]).(isset($_GET["boolean"][$u])?" IN BOOLEAN MODE":"").")";}foreach((array)$_GET["where"]as$z=>$X){if("$X[col]$X[val]"!=""&&in_array($X["op"],$this->operators)){$Me="";$Va=" $X[op]";if(preg_match('~IN$~',$X["op"])){$Nc=process_length($X["val"]);$Va.=" ".($Nc!=""?$Nc:"(NULL)");}elseif($X["op"]=="SQL")$Va=" $X[val]";elseif($X["op"]=="LIKE %%")$Va=" LIKE ".$this->processInput($n[$X["col"]],"%$X[val]%");elseif($X["op"]=="ILIKE %%")$Va=" ILIKE ".$this->processInput($n[$X["col"]],"%$X[val]%");elseif($X["op"]=="FIND_IN_SET"){$Me="$X[op](".q($X["val"]).", ";$Va=")";}elseif(!preg_match('~NULL$~',$X["op"]))$Va.=" ".$this->processInput($n[$X["col"]],$X["val"]);if($X["col"]!="")$K[]=$Me.$k->convertSearch(idf_escape($X["col"]),$X,$n[$X["col"]]).$Va;else{$Qa=array();foreach($n +as$F=>$m){if((preg_match('~^[-\d.'.(preg_match('~IN$~',$X["op"])?',':'').']+$~',$X["val"])||!preg_match('~'.number_type().'|bit~',$m["type"]))&&(!preg_match("~[\x80-\xFF]~",$X["val"])||preg_match('~char|text|enum|set~',$m["type"]))&&(!preg_match('~date|timestamp~',$m["type"])||preg_match('~^\d+-\d+-\d+~',$X["val"])))$Qa[]=$Me.$k->convertSearch(idf_escape($F),$X,$m).$Va;}$K[]=($Qa?"(".implode(" OR ",$Qa).")":"1 = 0");}}}return$K;}function +selectOrderProcess($n,$x){$K=array();foreach((array)$_GET["order"]as$z=>$X){if($X!="")$K[]=(preg_match('~^((COUNT\(DISTINCT |[A-Z0-9_]+\()(`(?:[^`]|``)+`|"(?:[^"]|"")+")\)|COUNT\(\*\))$~',$X)?$X:idf_escape($X)).(isset($_GET["desc"][$z])?" DESC":"");}return$K;}function +selectLimitProcess(){return(isset($_GET["limit"])?$_GET["limit"]:"50");}function +selectLengthProcess(){return(isset($_GET["text_length"])?$_GET["text_length"]:"100");}function +selectEmailProcess($Z,$pc){return +false;}function +selectQueryBuild($N,$Z,$t,$fe,$_,$G){return"";}function +messageQuery($I,$jg,$fc=false){global$y,$k;restart_session();$Fc=&get_session("queries");if(!$Fc[$_GET["db"]])$Fc[$_GET["db"]]=array();if(strlen($I)>1e6)$I=preg_replace('~[\x80-\xFF]+$~','',substr($I,0,1e6))."\n…";$Fc[$_GET["db"]][]=array($I,time(),$jg);$Jf="sql-".count($Fc[$_GET["db"]]);$K="".'SQL-Kommando'."\n";if(!$fc&&($ch=$k->warnings())){$v="warnings-".count($Fc[$_GET["db"]]);$K="".'Warnings'.", $K\n";}return" ".@date("H:i:s").""." $K';}function +editRowPrint($R,$n,$L,$Kg){}function +editFunctions($m){global$Gb;$K=($m["null"]?"NULL/":"");$Kg=isset($_GET["select"])||where($_GET);foreach($Gb +as$z=>$uc){if(!$z||(!isset($_GET["call"])&&$Kg)){foreach($uc +as$Be=>$X){if(!$Be||preg_match("~$Be~",$m["type"]))$K.="/$X";}}if($z&&!preg_match('~set|blob|bytea|raw|file|bool~',$m["type"]))$K.="/SQL";}if($m["auto_increment"]&&!$Kg)$K='Auto-Inkrement';return +explode("/",$K);}function +editInput($R,$m,$ra,$Y){if($m["type"]=="enum")return(isset($_GET["select"])?" ":"").($m["null"]?" ":"").enum_input("radio",$ra,$m,$Y,0);return"";}function +editHint($R,$m,$Y){return"";}function +processInput($m,$Y,$s=""){if($s=="SQL")return$Y;$F=$m["field"];$K=q($Y);if(preg_match('~^(now|getdate|uuid)$~',$s))$K="$s()";elseif(preg_match('~^current_(date|timestamp)$~',$s))$K=$s;elseif(preg_match('~^([+-]|\|\|)$~',$s))$K=idf_escape($F)." $s $K";elseif(preg_match('~^[+-] interval$~',$s))$K=idf_escape($F)." $s ".(preg_match("~^(\\d+|'[0-9.: -]') [A-Z_]+\$~i",$Y)?$Y:$K);elseif(preg_match('~^(addtime|subtime|concat)$~',$s))$K="$s(".idf_escape($F).", $K)";elseif(preg_match('~^(md5|sha1|password|encrypt)$~',$s))$K="$s($K)";return +unconvert_field($m,$K);}function +dumpOutput(){$K=array('text'=>'anzeigen','file'=>'Datei');if(function_exists('gzencode'))$K['gz']='gzip';return$K;}function +dumpFormat(){return +array('sql'=>'SQL','csv'=>'CSV,','csv;'=>'CSV;','tsv'=>'TSV');}function +dumpDatabase($j){}function +dumpTable($R,$Pf,$Yc=0){if($_POST["format"]!="sql"){echo"\xef\xbb\xbf";if($Pf)dump_csv(array_keys(fields($R)));}else{if($Yc==2){$n=array();foreach(fields($R)as$F=>$m)$n[]=idf_escape($F)." $m[full_type]";$h="CREATE TABLE ".table($R)." (".implode(", ",$n).")";}else$h=create_sql($R,$_POST["auto_increment"],$Pf);set_utf8mb4($h);if($Pf&&$h){if($Pf=="DROP+CREATE"||$Yc==1)echo"DROP ".($Yc==2?"VIEW":"TABLE")." IF EXISTS ".table($R).";\n";if($Yc==1)$h=remove_definer($h);echo"$h;\n\n";}}}function +dumpData($R,$Pf,$I){global$f,$y;$wd=($y=="sqlite"?0:1048576);if($Pf){if($_POST["format"]=="sql"){if($Pf=="TRUNCATE+INSERT")echo +truncate_sql($R).";\n";$n=fields($R);}$J=$f->query($I,1);if($J){$Sc="";$Ca="";$cd=array();$Rf="";$ic=($R!=''?'fetch_assoc':'fetch_row');while($L=$J->$ic()){if(!$cd){$Ug=array();foreach($L +as$X){$m=$J->fetch_field();$cd[]=$m->name;$z=idf_escape($m->name);$Ug[]="$z = VALUES($z)";}$Rf=($Pf=="INSERT+UPDATE"?"\nON DUPLICATE KEY UPDATE ".implode(", ",$Ug):"").";\n";}if($_POST["format"]!="sql"){if($Pf=="table"){dump_csv($cd);$Pf="INSERT";}dump_csv($L);}else{if(!$Sc)$Sc="INSERT INTO ".table($R)." (".implode(", ",array_map('idf_escape',$cd)).") VALUES";foreach($L +as$z=>$X){$m=$n[$z];$L[$z]=($X!==null?unconvert_field($m,preg_match(number_type(),$m["type"])&&!preg_match('~\[~',$m["full_type"])&&is_numeric($X)?$X:q(($X===false?0:$X))):"NULL");}$pf=($wd?"\n":" ")."(".implode(",\t",$L).")";if(!$Ca)$Ca=$Sc.$pf;elseif(strlen($Ca)+4+strlen($pf)+strlen($Rf)<$wd)$Ca.=",$pf";else{echo$Ca.$Rf;$Ca=$Sc.$pf;}}}if($Ca)echo$Ca.$Rf;}elseif($_POST["format"]=="sql")echo"-- ".str_replace("\n"," ",$f->error)."\n";}}function +dumpFilename($Jc){return +friendly_url($Jc!=""?$Jc:(SERVER!=""?SERVER:"localhost"));}function +dumpHeaders($Jc,$Id=false){$qe=$_POST["output"];$bc=(preg_match('~sql~',$_POST["format"])?"sql":($Id?"tar":"csv"));header("Content-Type: ".($qe=="gz"?"application/x-gzip":($bc=="tar"?"application/x-tar":($bc=="sql"||$qe!="file"?"text/plain":"text/csv")."; charset=utf-8")));if($qe=="gz")ob_start('ob_gzencode',1e6);return$bc;}function +importServerPath(){return"adminer.sql";}function +homepage(){echo'

+',$this->name(),' ',$da,' +',(version_compare($da,$_COOKIE["adminer_version"])<0?h($_COOKIE["adminer_version"]):""),' +

+';if($Hd=="auth"){$qe="";foreach((array)$_SESSION["pwds"]as$Wg=>$zf){foreach($zf +as$O=>$Sg){foreach($Sg +as$Rg=>$_e){if($_e!==null){$mb=$_SESSION["db"][$Wg][$O][$Rg];foreach(($mb?array_keys($mb):array(""))as$j)$qe.="
  • ($zb[$Wg]) ".h($Rg.($O!=""?"@".$this->serverName($O):"").($j!=""?" - $j":""))."\n";}}}}if($qe)echo"
      \n$qe
    \n".script("mixin(qs('#logins'), {onmouseover: menuOver, onmouseout: menuOut});");}else{$T=array();if($_GET["ns"]!==""&&!$Hd&&DB!=""){$f->select_db(DB);$T=table_status('',true);}echo +script_src(preg_replace("~\\?.*~","",ME)."?file=jush.js&version=4.8.1");if(support("sql")){echo' +';if($T){$qd=array();foreach($T +as$R=>$V)$qd[]=preg_quote($R,'/');echo"var jushLinks = { $y: [ '".js_escape(ME).(support("table")?"table=":"select=")."\$&', /\\b(".implode("|",$qd).")\\b/g ] };\n";foreach(array("bac","bra","sqlite_quo","mssql_bra")as$X)echo"jushLinks.$X = jushLinks.$y;\n";}$yf=$f->server_info;echo'bodyLoad(\'',(is_object($f)?preg_replace('~^(\d\.?\d).*~s','\1',$yf):""),'\'',(preg_match('~MariaDB~',$yf)?", true":""),'); + +';}$this->databasesPrint($Hd);if(DB==""||!$Hd){echo"

    ".'Keine Tabellen.'."\n";else$this->tablesPrint($T);}}}function +databasesPrint($Hd){global$b,$f;$i=$this->databases();if(DB&&$i&&!in_array(DB,$i))array_unshift($i,DB);echo'

    +

    +';hidden_fields_get();$kb=script("mixin(qsl('select'), {onmousedown: dbMouseDown, onchange: dbChange});");echo"".'DB'.": ".($i?"$kb":"\n"),"\n";foreach(array("import","sql","schema","dump","privileges")as$X){if(isset($_GET[$X])){echo"";break;}}echo"

    \n";}function +tablesPrint($T){echo"
      ".script("mixin(qs('#tables'), {onmouseover: menuOver, onmouseout: menuOut});");foreach($T +as$R=>$Mf){$F=$this->tableName($Mf);if($F!=""){echo'
    • ".'zeigen'." ",(support("table")||support("indexes")?'$F":"$F")."\n";}}echo"
    \n";}}$b=(function_exists('adminer_object')?adminer_object():new +Adminer);$Wa=driver_config();$Le=$Wa['possible_drivers'];$y=$Wa['jush'];$Cg=$Wa['types'];$Of=$Wa['structured_types'];$Jg=$Wa['unsigned'];$ae=$Wa['operators'];$uc=$Wa['functions'];$yc=$Wa['grouping'];$Gb=$Wa['edit_functions'];if($b->operators===null)$b->operators=$ae;define("SERVER",$_GET[DRIVER]);define("DB",$_GET["db"]);define("ME",preg_replace('~\?.*~','',relative_uri()).'?'.(sid()?SID.'&':'').(SERVER!==null?DRIVER."=".urlencode(SERVER).'&':'').(isset($_GET["username"])?"username=".urlencode($_GET["username"]).'&':'').(DB!=""?'db='.urlencode(DB).'&'.(isset($_GET["ns"])?"ns=".urlencode($_GET["ns"])."&":""):''));$da="4.8.1";function +page_header($mg,$l="",$Ba=array(),$ng=""){global$ba,$da,$b,$zb,$y;page_headers();if(is_ajax()&&$l){page_messages($l);exit;}$og=$mg.($ng!=""?": $ng":"");$pg=strip_tags($og.(SERVER!=""&&SERVER!="localhost"?h(" - ".SERVER):"")." - ".$b->name());echo' + + + +',$pg,' + +',script_src(preg_replace("~\\?.*~","",ME)."?file=functions.js&version=4.8.1");if($b->head()){echo' + +';foreach($b->css()as$eb){echo' +';}}echo' + +';$o=get_temp_dir()."/adminer.version";if(!$_COOKIE["adminer_version"]&&function_exists('openssl_verify')&&file_exists($o)&&filemtime($o)+86400>time()){$Xg=unserialize(file_get_contents($o));$Ve="-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwqWOVuF5uw7/+Z70djoK +RlHIZFZPO0uYRezq90+7Amk+FDNd7KkL5eDve+vHRJBLAszF/7XKXe11xwliIsFs +DFWQlsABVZB3oisKCBEuI71J4kPH8dKGEWR9jDHFw3cWmoH3PmqImX6FISWbG3B8 +h7FIx3jEaw5ckVPVTeo5JRm/1DZzJxjyDenXvBQ/6o9DgZKeNDgxwKzH+sw9/YCO +jHnq1cFpOIISzARlrHMa/43YfeNRAm/tsBXjSxembBPo7aQZLAWHmaj5+K19H10B +nCpz9Y++cipkVEiKRGih4ZEvjoFysEOdRLj6WiD/uUNky4xGeA6LaJqh5XpkFkcQ +fQIDAQAB +-----END PUBLIC KEY----- +";if(openssl_verify($Xg["version"],base64_decode($Xg["signature"]),$Ve)==1)$_COOKIE["adminer_version"]=$Xg["version"];}echo' +mixin(document.body, {onkeydown: bodyKeydown, onclick: bodyClick',(isset($_COOKIE["adminer_version"])?"":", onload: partial(verifyVersion, '$da', '".js_escape(ME)."', '".get_token()."')");?>}); +document.body.className = document.body.className.replace(/ nojs/, ' js'); +var offlineMessage = ' + + +',script("mixin(qs('#help'), {onmouseover: function () { helpOpen = 1; }, onmouseout: helpMouseout});"),' +
    +';if($Ba!==null){$A=substr(preg_replace('~\b(username|db|ns)=[^&]*&~','',ME),0,-1);echo'

    $og

    \n","\n";restart_session();page_messages($l);$i=&get_session("dbs");if(DB!=""&&$i&&!in_array(DB,$i,true))$i=null;stop_session();define("PAGE_HEADER",1);}function +page_headers(){global$b;header("Content-Type: text/html; charset=utf-8");header("Cache-Control: no-cache");header("X-Frame-Options: deny");header("X-XSS-Protection: 0");header("X-Content-Type-Options: nosniff");header("Referrer-Policy: origin-when-cross-origin");foreach($b->csp()as$db){$Dc=array();foreach($db +as$z=>$X)$Dc[]="$z $X";header("Content-Security-Policy: ".implode("; ",$Dc));}$b->headers();}function +csp(){return +array(array("script-src"=>"'self' 'unsafe-inline' 'nonce-".get_nonce()."' 'strict-dynamic'","connect-src"=>"'self'","frame-src"=>"https://www.adminer.org","object-src"=>"'none'","base-uri"=>"'none'","form-action"=>"'self'",),);}function +get_nonce(){static$Nd;if(!$Nd)$Nd=base64_encode(rand_string());return$Nd;}function +page_messages($l){$Lg=preg_replace('~^[^?]*~','',$_SERVER["REQUEST_URI"]);$Ed=$_SESSION["messages"][$Lg];if($Ed){echo"
    ".implode("
    \n
    ",$Ed)."
    ".script("messagesPrint();");unset($_SESSION["messages"][$Lg]);}if($l)echo"
    $l
    \n";}function +page_footer($Hd=""){global$b,$U;echo'
    + +';if($Hd!="auth"){echo'
    +

    + + +

    +
    +';}echo' +',script("setupSubmitHighlight(document);");}function +int32($E){while($E>=2147483648)$E-=4294967296;while($E<=-2147483649)$E+=4294967296;return(int)$E;}function +long2str($W,$bh){$pf='';foreach($W +as$X)$pf.=pack('V',$X);if($bh)return +substr($pf,0,end($W));return$pf;}function +str2long($pf,$bh){$W=array_values(unpack('V*',str_pad($pf,4*ceil(strlen($pf)/4),"\0")));if($bh)$W[]=strlen($pf);return$W;}function +xxtea_mx($ih,$hh,$Sf,$ad){return +int32((($ih>>5&0x7FFFFFF)^$hh<<2)+(($hh>>3&0x1FFFFFFF)^$ih<<4))^int32(($Sf^$hh)+($ad^$ih));}function +encrypt_string($Nf,$z){if($Nf=="")return"";$z=array_values(unpack("V*",pack("H*",md5($z))));$W=str2long($Nf,true);$E=count($W)-1;$ih=$W[$E];$hh=$W[0];$H=floor(6+52/($E+1));$Sf=0;while($H-->0){$Sf=int32($Sf+0x9E3779B9);$Fb=$Sf>>2&3;for($re=0;$re<$E;$re++){$hh=$W[$re+1];$Jd=xxtea_mx($ih,$hh,$Sf,$z[$re&3^$Fb]);$ih=int32($W[$re]+$Jd);$W[$re]=$ih;}$hh=$W[0];$Jd=xxtea_mx($ih,$hh,$Sf,$z[$re&3^$Fb]);$ih=int32($W[$E]+$Jd);$W[$E]=$ih;}return +long2str($W,false);}function +decrypt_string($Nf,$z){if($Nf=="")return"";if(!$z)return +false;$z=array_values(unpack("V*",pack("H*",md5($z))));$W=str2long($Nf,false);$E=count($W)-1;$ih=$W[$E];$hh=$W[0];$H=floor(6+52/($E+1));$Sf=int32($H*0x9E3779B9);while($Sf){$Fb=$Sf>>2&3;for($re=$E;$re>0;$re--){$ih=$W[$re-1];$Jd=xxtea_mx($ih,$hh,$Sf,$z[$re&3^$Fb]);$hh=int32($W[$re]-$Jd);$W[$re]=$hh;}$ih=$W[$E];$Jd=xxtea_mx($ih,$hh,$Sf,$z[$re&3^$Fb]);$hh=int32($W[0]-$Jd);$W[0]=$hh;$Sf=int32($Sf-0x9E3779B9);}return +long2str($W,true);}$f='';$Cc=$_SESSION["token"];if(!$Cc)$_SESSION["token"]=rand(1,1e6);$U=get_token();$De=array();if($_COOKIE["adminer_permanent"]){foreach(explode(" ",$_COOKIE["adminer_permanent"])as$X){list($z)=explode(":",$X);$De[$z]=$X;}}function +add_invalid_login(){global$b;$r=file_open_lock(get_temp_dir()."/adminer.invalid");if(!$r)return;$Uc=unserialize(stream_get_contents($r));$jg=time();if($Uc){foreach($Uc +as$Vc=>$X){if($X[0]<$jg)unset($Uc[$Vc]);}}$Tc=&$Uc[$b->bruteForceKey()];if(!$Tc)$Tc=array($jg+30*60,0);$Tc[1]++;file_write_unlock($r,serialize($Uc));}function +check_invalid_login(){global$b;$Uc=unserialize(@file_get_contents(get_temp_dir()."/adminer.invalid"));$Tc=($Uc?$Uc[$b->bruteForceKey()]:array());$Md=($Tc[1]>29?$Tc[0]-time():0);if($Md>0)auth_error(lang(array('Zu viele erfolglose Login-Versuche. Bitte probieren Sie es in %d Minute noch einmal.','Zu viele erfolglose Login-Versuche. Bitte probieren Sie es in %d Minuten noch einmal.'),ceil($Md/60)));}$sa=$_POST["auth"];if($sa){session_regenerate_id();$Wg=$sa["driver"];$O=$sa["server"];$Rg=$sa["username"];$_e=(string)$sa["password"];$j=$sa["db"];set_password($Wg,$O,$Rg,$_e);$_SESSION["db"][$Wg][$O][$Rg][$j]=true;if($sa["permanent"]){$z=base64_encode($Wg)."-".base64_encode($O)."-".base64_encode($Rg)."-".base64_encode($j);$Re=$b->permanentLogin(true);$De[$z]="$z:".base64_encode($Re?encrypt_string($_e,$Re):"");cookie("adminer_permanent",implode(" ",$De));}if(count($_POST)==1||DRIVER!=$Wg||SERVER!=$O||$_GET["username"]!==$Rg||DB!=$j)redirect(auth_url($Wg,$O,$Rg,$j));}elseif($_POST["logout"]&&(!$Cc||verify_token())){foreach(array("pwds","db","dbs","queries")as$z)set_session($z,null);unset_permanent();redirect(substr(preg_replace('~\b(username|db|ns)=[^&]*&~','',ME),0,-1),'Abmeldung erfolgreich.'.' '.'Danke, dass Sie Adminer genutzt haben. Spenden willkommen!');}elseif($De&&!$_SESSION["pwds"]){session_regenerate_id();$Re=$b->permanentLogin();foreach($De +as$z=>$X){list(,$Ia)=explode(":",$X);list($Wg,$O,$Rg,$j)=array_map('base64_decode',explode("-",$z));set_password($Wg,$O,$Rg,decrypt_string(base64_decode($Ia),$Re));$_SESSION["db"][$Wg][$O][$Rg][$j]=true;}}function +unset_permanent(){global$De;foreach($De +as$z=>$X){list($Wg,$O,$Rg,$j)=array_map('base64_decode',explode("-",$z));if($Wg==DRIVER&&$O==SERVER&&$Rg==$_GET["username"]&&$j==DB)unset($De[$z]);}cookie("adminer_permanent",implode(" ",$De));}function +auth_error($l){global$b,$Cc;$_f=session_name();if(isset($_GET["username"])){header("HTTP/1.1 403 Forbidden");if(($_COOKIE[$_f]||$_GET[$_f])&&!$Cc)$l='Sitzungsdauer abgelaufen, bitte erneut anmelden.';else{restart_session();add_invalid_login();$_e=get_password();if($_e!==null){if($_e===false)$l.=($l?'
    ':'').sprintf('Das Master-Passwort ist abgelaufen. Implementieren Sie die %s Methode, um es permanent zu machen.',target_blank(),'permanentLogin()');set_password(DRIVER,SERVER,$_GET["username"],null);}unset_permanent();}}if(!$_COOKIE[$_f]&&$_GET[$_f]&&ini_bool("session.use_only_cookies"))$l='Unterstüzung für PHP-Sessions muss aktiviert sein.';$ue=session_get_cookie_params();cookie("adminer_key",($_COOKIE["adminer_key"]?$_COOKIE["adminer_key"]:rand_string()),$ue["lifetime"]);page_header('Login',$l,null);echo"
    \n","
    ";if(hidden_fields($_POST,array("auth")))echo"

    ".'The action will be performed after successful login with the same credentials.'."\n";echo"

    \n";$b->loginForm();echo"
    \n";page_footer("auth");exit;}if(isset($_GET["username"])&&!class_exists("Min_DB")){unset($_SESSION["pwds"][DRIVER]);unset_permanent();page_header('Keine Erweiterungen installiert',sprintf('Keine der unterstützten PHP-Erweiterungen (%s) ist vorhanden.',implode(", ",$Le)),false);page_footer("auth");exit;}stop_session(true);if(isset($_GET["username"])&&is_string(get_password())){list($Hc,$He)=explode(":",SERVER,2);if(preg_match('~^\s*([-+]?\d+)~',$He,$C)&&($C[1]<1024||$C[1]>65535))auth_error('Connecting to privileged ports is not allowed.');check_invalid_login();$f=connect();$k=new +Min_Driver($f);}$rd=null;if(!is_object($f)||($rd=$b->login($_GET["username"],get_password()))!==true){$l=(is_string($f)?h($f):(is_string($rd)?$rd:'Ungültige Anmelde-Informationen.'));auth_error($l.(preg_match('~^ | $~',get_password())?'
    '.'There is a space in the input password which might be the cause.':''));}if($_POST["logout"]&&$Cc&&!verify_token()){page_header('Abmelden','CSRF Token ungültig. Bitte die Formulardaten erneut abschicken.');page_footer("db");exit;}if($sa&&$_POST["token"])$_POST["token"]=$U;$l='';if($_POST){if(!verify_token()){$Pc="max_input_vars";$_d=ini_get($Pc);if(extension_loaded("suhosin")){foreach(array("suhosin.request.max_vars","suhosin.post.max_vars")as$z){$X=ini_get($z);if($X&&(!$_d||$X<$_d)){$Pc=$z;$_d=$X;}}}$l=(!$_POST["token"]&&$_d?sprintf('Die maximal erlaubte Anzahl der Felder ist überschritten. Bitte %s erhöhen.',"'$Pc'"):'CSRF Token ungültig. Bitte die Formulardaten erneut abschicken.'.' '.'Wenn Sie diese Anfrage nicht von Adminer gesendet haben, schließen Sie diese Seite.');}}elseif($_SERVER["REQUEST_METHOD"]=="POST"){$l=sprintf('POST-Daten sind zu groß. Reduzieren Sie die Größe oder vergrößern Sie den Wert %s in der Konfiguration.',"'post_max_size'");if(isset($_GET["sql"]))$l.=' '.'Sie können eine große SQL-Datei per FTP hochladen und dann vom Server importieren.';}function +select($J,$g=null,$ie=array(),$_=0){global$y;$qd=array();$x=array();$e=array();$_a=array();$Cg=array();$K=array();odd('');for($u=0;(!$_||$u<$_)&&($L=$J->fetch_row());$u++){if(!$u){echo"
    \n","\n","";for($Zc=0;$Zcfetch_field();$F=$m->name;$he=$m->orgtable;$ge=$m->orgname;$K[$m->table]=$he;if($ie&&$y=="sql")$qd[$Zc]=($F=="table"?"table=":($F=="possible_keys"?"indexes=":null));elseif($he!=""){if(!isset($x[$he])){$x[$he]=array();foreach(indexes($he,$g)as$w){if($w["type"]=="PRIMARY"){$x[$he]=array_flip($w["columns"]);break;}}$e[$he]=$x[$he];}if(isset($e[$he][$ge])){unset($e[$he][$ge]);$x[$he][$ge]=$Zc;$qd[$Zc]=$he;}}if($m->charsetnr==63)$_a[$Zc]=true;$Cg[$Zc]=$m->type;echo"name!=$ge?" title='".h(($he!=""?"$he.":"").$ge)."'":"").">".h($F).($ie?'':"");}echo"\n";}echo"";foreach($L +as$z=>$X){$A="";if(isset($qd[$z])&&!$e[$qd[$z]]){if($ie&&$y=="sql"){$R=$L[array_search("table=",$qd)];$A=ME.$qd[$z].urlencode($ie[$R]!=""?$ie[$R]:$R);}else{$A=ME."edit=".urlencode($qd[$z]);foreach($x[$qd[$z]]as$Ma=>$Zc)$A.="&where".urlencode("[".bracket_escape($Ma)."]")."=".urlencode($L[$Zc]);}}elseif(is_url($X))$A=$X;if($X===null)$X="NULL";elseif($_a[$z]&&!is_utf8($X))$X="".lang(array('%d Byte','%d Bytes'),strlen($X))."";else{$X=h($X);if($Cg[$z]==254)$X="$X";}if($A)$X="$X";echo"
    $X";}}echo($u?"
    \n
    ":"

    ".'Keine Datensätze.')."\n";return$K;}function +referencable_primary($vf){$K=array();foreach(table_status('',true)as$Wf=>$R){if($Wf!=$vf&&fk_support($R)){foreach(fields($Wf)as$m){if($m["primary"]){if($K[$Wf]){unset($K[$Wf]);break;}$K[$Wf]=$m;}}}}return$K;}function +adminer_settings(){parse_str($_COOKIE["adminer_settings"],$Bf);return$Bf;}function +adminer_setting($z){$Bf=adminer_settings();return$Bf[$z];}function +set_adminer_settings($Bf){return +cookie("adminer_settings",http_build_query($Bf+adminer_settings()));}function +textarea($F,$Y,$M=10,$Qa=80){global$y;echo"";}function +edit_type($z,$m,$Pa,$q=array(),$ec=array()){global$Of,$Cg,$Jg,$Wd;$V=$m["type"];echo'',"',($Jg?"':''),(isset($m['on_update'])?"':''),($q?" ":" ");}function +process_length($nd){global$Qb;return(preg_match("~^\\s*\\(?\\s*$Qb(?:\\s*,\\s*$Qb)*+\\s*\\)?\\s*\$~",$nd)&&preg_match_all("~$Qb~",$nd,$ud)?"(".implode(",",$ud[0]).")":preg_replace('~^[0-9].*~','(\0)',preg_replace('~[^-0-9,+()[\]]~','',$nd)));}function +process_type($m,$Na="COLLATE"){global$Jg;return" $m[type]".process_length($m["length"]).(preg_match(number_type(),$m["type"])&&in_array($m["unsigned"],$Jg)?" $m[unsigned]":"").(preg_match('~char|text|enum|set~',$m["type"])&&$m["collation"]?" $Na ".q($m["collation"]):"");}function +process_field($m,$Bg){return +array(idf_escape(trim($m["field"])),process_type($Bg),($m["null"]?" NULL":" NOT NULL"),default_value($m),(preg_match('~timestamp|datetime~',$m["type"])&&$m["on_update"]?" ON UPDATE $m[on_update]":""),(support("comment")&&$m["comment"]!=""?" COMMENT ".q($m["comment"]):""),($m["auto_increment"]?auto_increment():null),);}function +default_value($m){$ob=$m["default"];return($ob===null?"":" DEFAULT ".(preg_match('~char|binary|text|enum|set~',$m["type"])||preg_match('~^(?![a-z])~i',$ob)?q($ob):$ob));}function +type_class($V){foreach(array('char'=>'text','date'=>'time|year','binary'=>'blob','enum'=>'set',)as$z=>$X){if(preg_match("~$z|$X~",$V))return" class='$z'";}}function +edit_fields($n,$Pa,$V="TABLE",$q=array()){global$Qc;$n=array_values($n);$pb=(($_POST?$_POST["defaults"]:adminer_setting("defaults"))?"":" class='hidden'");$Ua=(($_POST?$_POST["comments"]:adminer_setting("comments"))?"":" class='hidden'");echo' +';if($V=="PROCEDURE"){echo'';}echo'',($V=="TABLE"?'Spaltenname':'Name des Parameters'),'Typ',script("qs('#enum-edit').onblur = editingLengthBlur;"),'Länge +','Optionen';if($V=="TABLE"){echo'NULL +AI',doc_link(array('sqlite'=>"autoinc.html",)),'Vorgabewert festlegen +',(support("comment")?"".'Kommentar':"");}echo'',"".script("row_count = ".count($n).";"),' + +',script("mixin(qsl('tbody'), {onclick: editingClick, onkeydown: editingKeydown, oninput: editingInput});");foreach($n +as$u=>$m){$u++;$je=$m[($_POST?"orig":"field")];$wb=(isset($_POST["add"][$u-1])||(isset($m["field"])&&!$_POST["drop_col"][$u]))&&(support("drop_col")||$je=="");echo' +',($V=="PROCEDURE"?"".html_select("fields[$u][inout]",explode("|",$Qc),$m["inout"]):""),'';if($wb){echo'';}echo'';edit_type("fields[$u]",$m,$Pa,$q);if($V=="TABLE"){echo'',checkbox("fields[$u][null]",1,$m["null"],"","","block","label-null"),'',checkbox("fields[$u][has_default]",1,$m["has_default"],"","","","label-default"),'',(support("comment")?"":"");}echo"",(support("move_col")?" "." "." ":""),($je==""||support("drop_col")?"":"");}}function +process_fields(&$n){$Sd=0;if($_POST["up"]){$hd=0;foreach($n +as$z=>$m){if(key($_POST["up"])==$z){unset($n[$z]);array_splice($n,$hd,0,array($m));break;}if(isset($m["field"]))$hd=$Sd;$Sd++;}}elseif($_POST["down"]){$rc=false;foreach($n +as$z=>$m){if(isset($m["field"])&&$rc){unset($n[key($_POST["down"])]);array_splice($n,$Sd,0,array($rc));break;}if(key($_POST["down"])==$z)$rc=$m;$Sd++;}}elseif($_POST["add"]){$n=array_values($n);array_splice($n,key($_POST["add"]),0,array(array()));}elseif(!$_POST["drop_col"])return +false;return +true;}function +normalize_enum($C){return"'".str_replace("'","''",addcslashes(stripcslashes(str_replace($C[0][0].$C[0][0],$C[0][0],substr($C[0],1,-1))),'\\'))."'";}function +grant($vc,$Se,$e,$Vd){if(!$Se)return +true;if($Se==array("ALL PRIVILEGES","GRANT OPTION"))return($vc=="GRANT"?queries("$vc ALL PRIVILEGES$Vd WITH GRANT OPTION"):queries("$vc ALL PRIVILEGES$Vd")&&queries("$vc GRANT OPTION$Vd"));return +queries("$vc ".preg_replace('~(GRANT OPTION)\([^)]*\)~','\1',implode("$e, ",$Se).$e).$Vd);}function +drop_create($_b,$h,$Ab,$gg,$Cb,$B,$Dd,$Bd,$Cd,$Ud,$Ld){if($_POST["drop"])query_redirect($_b,$B,$Dd);elseif($Ud=="")query_redirect($h,$B,$Cd);elseif($Ud!=$Ld){$cb=queries($h);queries_redirect($B,$Bd,$cb&&queries($_b));if($cb)queries($Ab);}else +queries_redirect($B,$Bd,queries($gg)&&queries($Cb)&&queries($_b)&&queries($h));}function +create_trigger($Vd,$L){global$y;$lg=" $L[Timing] $L[Event]".(preg_match('~ OF~',$L["Event"])?" $L[Of]":"");return"CREATE TRIGGER ".idf_escape($L["Trigger"]).($y=="mssql"?$Vd.$lg:$lg.$Vd).rtrim(" $L[Type]\n$L[Statement]",";").";";}function +create_routine($nf,$L){global$Qc,$y;$P=array();$n=(array)$L["fields"];ksort($n);foreach($n +as$m){if($m["field"]!="")$P[]=(preg_match("~^($Qc)\$~",$m["inout"])?"$m[inout] ":"").idf_escape($m["field"]).process_type($m,"CHARACTER SET");}$qb=rtrim("\n$L[definition]",";");return"CREATE $nf ".idf_escape(trim($L["name"]))." (".implode(", ",$P).")".(isset($_GET["function"])?" RETURNS".process_type($L["returns"],"CHARACTER SET"):"").($L["language"]?" LANGUAGE $L[language]":"").($y=="pgsql"?" AS ".q($qb):"$qb;");}function +remove_definer($I){return +preg_replace('~^([A-Z =]+) DEFINER=`'.preg_replace('~@(.*)~','`@`(%|\1)',logged_user()).'`~','\1',$I);}function +format_foreign_key($p){global$Wd;$j=$p["db"];$Od=$p["ns"];return" FOREIGN KEY (".implode(", ",array_map('idf_escape',$p["source"])).") REFERENCES ".($j!=""&&$j!=$_GET["db"]?idf_escape($j).".":"").($Od!=""&&$Od!=$_GET["ns"]?idf_escape($Od).".":"").table($p["table"])." (".implode(", ",array_map('idf_escape',$p["target"])).")".(preg_match("~^($Wd)\$~",$p["on_delete"])?" ON DELETE $p[on_delete]":"").(preg_match("~^($Wd)\$~",$p["on_update"])?" ON UPDATE $p[on_update]":"");}function +tar_file($o,$qg){$K=pack("a100a8a8a8a12a12",$o,644,0,0,decoct($qg->size),decoct(time()));$Ha=8*32;for($u=0;$usend();echo +str_repeat("\0",511-($qg->size+511)%512);}function +ini_bytes($Pc){$X=ini_get($Pc);switch(strtolower(substr($X,-1))){case'g':$X*=1024;case'm':$X*=1024;case'k':$X*=1024;}return$X;}function +doc_link($Ae,$hg="?"){global$y,$f;$yf=$f->server_info;$Xg=preg_replace('~^(\d\.?\d).*~s','\1',$yf);$Ng=array('sql'=>"https://dev.mysql.com/doc/refman/$Xg/en/",'sqlite'=>"https://www.sqlite.org/",'pgsql'=>"https://www.postgresql.org/docs/$Xg/",'mssql'=>"https://msdn.microsoft.com/library/",'oracle'=>"https://www.oracle.com/pls/topic/lookup?ctx=db".preg_replace('~^.* (\d+)\.(\d+)\.\d+\.\d+\.\d+.*~s','\1\2',$yf)."&id=",);if(preg_match('~MariaDB~',$yf)){$Ng['sql']="https://mariadb.com/kb/en/library/";$Ae['sql']=(isset($Ae['mariadb'])?$Ae['mariadb']:str_replace(".html","/",$Ae['sql']));}return($Ae[$y]?"$hg":"");}function +ob_gzencode($Q){return +gzencode($Q);}function +db_size($j){global$f;if(!$f->select_db($j))return"?";$K=0;foreach(table_status()as$S)$K+=$S["Data_length"]+$S["Index_length"];return +format_number($K);}function +set_utf8mb4($h){global$f;static$P=false;if(!$P&&preg_match('~\butf8mb4~i',$h)){$P=true;echo"SET NAMES ".charset($f).";\n\n";}}function +connect_error(){global$b,$f,$U,$l,$zb;if(DB!=""){header("HTTP/1.1 404 Not Found");page_header('Datenbank'.": ".h(DB),'Datenbank ungültig.',true);}else{if($_POST["db"]&&!$l)queries_redirect(substr(ME,0,-1),'Datenbanken wurden entfernt.',drop_databases($_POST["db"]));page_header('Datenbank auswählen',$l,false);echo"

    ".sprintf('Version %s: %s mit PHP-Erweiterung %s',$zb[DRIVER],"".h($f->server_info)."","$f->extension")."\n","

    ".sprintf('Angemeldet als: %s',"".h(logged_user())."")."\n";$i=$b->databases();if($i){$rf=support("scheme");$Pa=collations();echo"

    \n","\n",script("mixin(qsl('table'), {onclick: tableClick, ondblclick: partialArg(tableClick, true)});"),"".(support("database")?"\n";$i=($_GET["dbsize"]?count_tables($i):array_flip($i));foreach($i +as$j=>$T){$mf=h(ME)."db=".urlencode($j);$v=h("Db-".$j);echo"".(support("database")?"
    ":"")."".'Datenbank'." - ".'Aktualisieren'.""."".'Kollation'."".'Tabellen'."".'Größe'." - ".'kalkulieren'."".script("qsl('a').onclick = partial(ajaxSetHtml, '".js_escape(ME)."script=connect');","")."
    ".checkbox("db[]",$j,in_array($j,(array)$_POST["db"]),"","","",$v):""),"".h($j)."";$Oa=h(db_collation($j,$Pa));echo"".(support("database")?"$Oa":$Oa),"".($_GET["dbsize"]?$T:"?")."","".($_GET["dbsize"]?db_size($j):"?"),"\n";}echo"
    \n",(support("database")?"\n":""),"\n","
    \n",script("tableCheck();");}}page_footer("db");}if(isset($_GET["status"]))$_GET["variables"]=$_GET["status"];if(isset($_GET["import"]))$_GET["sql"]=$_GET["import"];if(!(DB!=""?$f->select_db(DB):isset($_GET["sql"])||isset($_GET["dump"])||isset($_GET["database"])||isset($_GET["processlist"])||isset($_GET["privileges"])||isset($_GET["user"])||isset($_GET["variables"])||$_GET["script"]=="connect"||$_GET["script"]=="kill")){if(DB!=""||$_GET["refresh"]){restart_session();set_session("dbs",null);}connect_error();exit;}$Wd="RESTRICT|NO ACTION|CASCADE|SET NULL|SET DEFAULT";class +TmpFile{var$handler;var$size;function +__construct(){$this->handler=tmpfile();}function +write($Za){$this->size+=strlen($Za);fwrite($this->handler,$Za);}function +send(){fseek($this->handler,0);fpassthru($this->handler);fclose($this->handler);}}$Qb="'(?:''|[^'\\\\]|\\\\.)*'";$Qc="IN|OUT|INOUT";if(isset($_GET["select"])&&($_POST["edit"]||$_POST["clone"])&&!$_POST["save"])$_GET["edit"]=$_GET["select"];if(isset($_GET["download"])){$a=$_GET["download"];$n=fields($a);header("Content-Type: application/octet-stream");header("Content-Disposition: attachment; filename=".friendly_url("$a-".implode("_",$_GET["where"])).".".friendly_url($_GET["field"]));$N=array(idf_escape($_GET["field"]));$J=$k->select($a,$N,array(where($_GET,$n)),$N);$L=($J?$J->fetch_row():array());echo$k->value($L[0],$n[$_GET["field"]]);exit;}elseif(isset($_GET["table"])){$a=$_GET["table"];$n=fields($a);if(!$n)$l=error();$S=table_status1($a,true);$F=$b->tableName($S);page_header(($n&&is_view($S)?$S['Engine']=='materialized view'?'Materialized view':'View':'Tabelle').": ".($F!=""?$F:h($a)),$l);$b->selectLinks($S);$Ta=$S["Comment"];if($Ta!="")echo"

    ".'Kommentar'.": ".h($Ta)."\n";if($n)$b->tableStructurePrint($n);if(!is_view($S)){if(support("indexes")){echo"

    ".'Indizes'."

    \n";$x=indexes($a);if($x)$b->tableIndexesPrint($x);echo'

    ".'Fremdschlüssel'."

    \n";$q=foreign_keys($a);if($q){echo"\n","\n";foreach($q +as$F=>$p){echo"","
    ".'Ursprung'."".'Ziel'."".'ON DELETE'."".'ON UPDATE'."
    ".implode(", ",array_map('h',$p["source"]))."","".($p["db"]!=""?"".h($p["db"]).".":"").($p["ns"]!=""?"".h($p["ns"]).".":"").h($p["table"])."","(".implode(", ",array_map('h',$p["target"])).")","".h($p["on_delete"])."\n","".h($p["on_update"])."\n",''.'Ändern'.'';}echo"
    \n";}echo'

    ".'Trigger'."

    \n";$Ag=triggers($a);if($Ag){echo"\n";foreach($Ag +as$z=>$X)echo"
    ".h($X[0])."".h($X[1])."".h($z)."".'Ändern'."\n";echo"
    \n";}echo'
    + +qs(\'#schema\').onselectstart = function () { return false; }; +var tablePos = {',implode(",",$Yf)."\n",'}; +var em = qs(\'#schema\').offsetHeight / ',$sg,'; +document.onmousemove = schemaMousemove; +document.onmouseup = partialArg(schemaMouseup, \'',js_escape(DB),'\'); + +';foreach($qf +as$F=>$R){echo"
    ",''.h($F)."",script("qsl('div').onmousedown = schemaMousedown;");foreach($R["fields"]as$m){$X=''.h($m["field"]).'';echo"
    ".($m["primary"]?"$X":$X);}foreach((array)$R["references"]as$eg=>$gf){foreach($gf +as$jd=>$cf){$kd=$jd-$Xf[$F][1];$u=0;foreach($cf[0]as$Ff)echo"\n
    ";}}foreach((array)$ff[$F]as$eg=>$gf){foreach($gf +as$jd=>$e){$kd=$jd-$Xf[$F][1];$u=0;foreach($e +as$dg)echo"\n
    ";}}echo"\n
    \n";}foreach($qf +as$F=>$R){foreach((array)$R["references"]as$eg=>$gf){foreach($gf +as$jd=>$cf){$Gd=$sg;$yd=-10;foreach($cf[0]as$z=>$Ff){$Je=$R["pos"][0]+$R["fields"][$Ff]["pos"];$Ke=$qf[$eg]["pos"][0]+$qf[$eg]["fields"][$cf[1][$z]]["pos"];$Gd=min($Gd,$Je,$Ke);$yd=max($yd,$Je,$Ke);}echo"
    \n";}}}echo'
    +
    + +';$lb=array('','USE','DROP+CREATE','CREATE');$Zf=array('','DROP+CREATE','CREATE');$ib=array('','TRUNCATE+INSERT','INSERT');if($y=="sql")$ib[]='INSERT+UPDATE';parse_str($_COOKIE["adminer_export"],$L);if(!$L)$L=array("output"=>"text","format"=>"sql","db_style"=>(DB!=""?"":"CREATE"),"table_style"=>"DROP+CREATE","data_style"=>"INSERT");if(!isset($L["events"])){$L["routines"]=$L["events"]=($_GET["dump"]=="");$L["triggers"]=$L["table_style"];}echo"
    ".'Ergebnis'."".html_select("output",$b->dumpOutput(),$L["output"],0)."\n";echo"
    ".'Format'."".html_select("format",$b->dumpFormat(),$L["format"],0)."\n";echo($y=="sqlite"?"":"
    ".'Datenbank'."".html_select('db_style',$lb,$L["db_style"]).(support("routine")?checkbox("routines",1,$L["routines"],'Routinen'):"").(support("event")?checkbox("events",1,$L["events"],'Ereignisse'):"")),"
    ".'Tabellen'."".html_select('table_style',$Zf,$L["table_style"]).checkbox("auto_increment",1,$L["auto_increment"],'Auto-Inkrement').(support("trigger")?checkbox("triggers",1,$L["triggers"],'Trigger'):""),"
    ".'Daten'."".html_select('data_style',$ib,$L["data_style"]),'
    +

    + + + +',script("qsl('table').onclick = dumpClick;");$Ne=array();if(DB!=""){$Fa=($a!=""?"":" checked");echo"","\n";$Zg="";$ag=tables_list();foreach($ag +as$F=>$V){$Me=preg_replace('~_.*~','',$F);$Fa=($a==""||$a==(substr($a,-1)=="%"?"$Me%":$F));$Qe="\n";$i=$b->databases();if($i){foreach($i +as$j){if(!information_schema($j)){$Me=preg_replace('~_.*~','',$j);echo"
    ".script("qs('#check-tables').onclick = partial(formCheck, /^tables\\[/);",""),"".script("qs('#check-data').onclick = partial(formCheck, /^data\\[/);",""),"
    ".checkbox("tables[]",$F,$Fa,$F,"","block");if($V!==null&&!preg_match('~table~i',$V))$Zg.="$Qe\n";else +echo"$Qe\n";$Ne[$Me]++;}echo$Zg;if($ag)echo +script("ajaxSetHtml('".js_escape(ME)."script=db');");}else{echo"
    ","",script("qs('#check-databases').onclick = partial(formCheck, /^databases\\[/);",""),"
    ".checkbox("databases[]",$j,$a==""||$a=="$Me%",$j,"","block")."\n";$Ne[$Me]++;}}}else +echo"
    ";}echo'
    +

    +';$lc=true;foreach($Ne +as$z=>$X){if($z!=""&&$X>1){echo($lc?"

    ":" ")."".h($z)."";$lc=false;}}}elseif(isset($_GET["sql"])){if(!$l&&$_POST["export"]){dump_headers("sql");$b->dumpTable("","");$b->dumpData("","table",$_POST["query"]);exit;}restart_session();$Gc=&get_session("queries");$Fc=&$Gc[DB];if(!$l&&$_POST["clear"]){$Fc=array();redirect(remove_from_uri("history"));}page_header((isset($_GET["import"])?'Importieren':'SQL-Kommando'),$l);if(!$l&&$_POST){$r=false;if(!isset($_GET["import"]))$I=$_POST["query"];elseif($_POST["webfile"]){$If=$b->importServerPath();$r=@fopen((file_exists($If)?$If:"compress.zlib://$If.gz"),"rb");$I=($r?fread($r,1e6):false);}else$I=get_file("sql_file",true);if(is_string($I)){if(function_exists('memory_get_usage'))@ini_set("memory_limit",max(ini_bytes("memory_limit"),2*strlen($I)+memory_get_usage()+8e6));if($I!=""&&strlen($I)<1e6){$H=$I.(preg_match("~;[ \t\r\n]*\$~",$I)?"":";");if(!$Fc||reset(end($Fc))!=$H){restart_session();$Fc[]=array($H,time());set_session("queries",$Gc);stop_session();}}$Gf="(?:\\s|/\\*[\s\S]*?\\*/|(?:#|-- )[^\n]*\n?|--\r?\n)";$rb=";";$Sd=0;$Nb=true;$g=connect();if(is_object($g)&&DB!=""){$g->select_db(DB);if($_GET["ns"]!="")set_schema($_GET["ns"],$g);}$Sa=0;$Sb=array();$ve='[\'"'.($y=="sql"?'`#':($y=="sqlite"?'`[':($y=="mssql"?'[':''))).']|/\*|-- |$'.($y=="pgsql"?'|\$[^$]*\$':'');$tg=microtime(true);parse_str($_COOKIE["adminer_export"],$ia);$Eb=$b->dumpFormat();unset($Eb["sql"]);while($I!=""){if(!$Sd&&preg_match("~^$Gf*+DELIMITER\\s+(\\S+)~i",$I,$C)){$rb=$C[1];$I=substr($I,strlen($C[0]));}else{preg_match('('.preg_quote($rb)."\\s*|$ve)",$I,$C,PREG_OFFSET_CAPTURE,$Sd);list($rc,$Ie)=$C[0];if(!$rc&&$r&&!feof($r))$I.=fread($r,1e5);else{if(!$rc&&rtrim($I)=="")break;$Sd=$Ie+strlen($rc);if($rc&&rtrim($rc)!=$rb){while(preg_match('('.($rc=='/*'?'\*/':($rc=='['?']':(preg_match('~^-- |^#~',$rc)?"\n":preg_quote($rc)."|\\\\."))).'|$)s',$I,$C,PREG_OFFSET_CAPTURE,$Sd)){$pf=$C[0][0];if(!$pf&&$r&&!feof($r))$I.=fread($r,1e5);else{$Sd=$C[0][1]+strlen($pf);if($pf[0]!="\\")break;}}}else{$Nb=false;$H=substr($I,0,$Ie);$Sa++;$Qe="

    ".$b->sqlCommandQuery($H)."
    \n";if($y=="sqlite"&&preg_match("~^$Gf*+ATTACH\\b~i",$H,$C)){echo$Qe,"

    ".'ATTACH queries are not supported.'."\n";$Sb[]=" $Sa";if($_POST["error_stops"])break;}else{if(!$_POST["only_errors"]){echo$Qe;ob_flush();flush();}$Lf=microtime(true);if($f->multi_query($H)&&is_object($g)&&preg_match("~^$Gf*+USE\\b~i",$H))$g->query($H);do{$J=$f->store_result();if($f->error){echo($_POST["only_errors"]?$Qe:""),"

    ".'Fehler in der SQL-Abfrage'.($f->errno?" ($f->errno)":"").": ".error()."\n";$Sb[]=" $Sa";if($_POST["error_stops"])break +2;}else{$jg=" (".format_time($Lf).")".(strlen($H)<1000?" ".'Bearbeiten'."":"");$ka=$f->affected_rows;$ch=($_POST["only_errors"]?"":$k->warnings());$dh="warnings-$Sa";if($ch)$jg.=", ".'Warnings'."".script("qsl('a').onclick = partial(toggle, '$dh');","");$Zb=null;$ac="explain-$Sa";if(is_object($J)){$_=$_POST["limit"];$ie=select($J,$g,array(),$_);if(!$_POST["only_errors"]){echo"

    \n";$Pd=$J->num_rows;echo"

    ".($Pd?($_&&$Pd>$_?sprintf('%d / ',$_):"").lang(array('%d Datensatz','%d Datensätze'),$Pd):""),$jg;if($g&&preg_match("~^($Gf|\\()*+SELECT\\b~i",$H)&&($Zb=explain($g,$H)))echo", Explain".script("qsl('a').onclick = partial(toggle, '$ac');","");$v="export-$Sa";echo", ".'Exportieren'."".script("qsl('a').onclick = partial(toggle, '$v');","")."\n"."

    \n";}}else{if(preg_match("~^$Gf*+(CREATE|DROP|ALTER)$Gf++(DATABASE|SCHEMA)\\b~i",$H)){restart_session();set_session("dbs",null);stop_session();}if(!$_POST["only_errors"])echo"

    ".lang(array('Abfrage ausgeführt, %d Datensatz betroffen.','Abfrage ausgeführt, %d Datensätze betroffen.'),$ka)."$jg\n";}echo($ch?"

    \n":"");if($Zb){echo"\n";}}$Lf=microtime(true);}while($f->next_result());}$I=substr($I,$Sd);$Sd=0;}}}}if($Nb)echo"

    ".'Kein Kommando vorhanden.'."\n";elseif($_POST["only_errors"]){echo"

    ".lang(array('SQL-Abfrage erfolgreich ausgeführt.','%d SQL-Abfragen erfolgreich ausgeführt.'),$Sa-count($Sb))," (".format_time($tg).")\n";}elseif($Sb&&$Sa>1)echo"

    ".'Fehler in der SQL-Abfrage'.": ".implode("",$Sb)."\n";}else +echo"

    ".upload_error($I)."\n";}echo' +

    +';$Xb="";if(!isset($_GET["import"])){$H=$_GET["sql"];if($_POST)$H=$_POST["query"];elseif($_GET["history"]=="all")$H=$Fc;elseif($_GET["history"]!="")$H=$Fc[$_GET["history"]][0];echo"

    ";textarea("query",$H,20);echo +script(($_POST?"":"qs('textarea').focus();\n")."qs('#form').onsubmit = partial(sqlSubmit, qs('#form'), '".js_escape(remove_from_uri("sql|limit|error_stops|only_errors|history"))."');"),"

    $Xb\n",'Datensätze begrenzen'.": \n";}else{echo"

    ".'Datei importieren'."
    ";$zc=(extension_loaded("zlib")?"[.gz]":"");echo(ini_bool("file_uploads")?"SQL$zc (< ".ini_get("upload_max_filesize")."B): \n$Xb":'Importieren von Dateien abgeschaltet.'),"
    \n";$Mc=$b->importServerPath();if($Mc){echo"
    ".'Vom Server'."
    ",sprintf('Webserver Datei %s',"".h($Mc)."$zc"),' ',"
    \n";}echo"

    ";}echo +checkbox("error_stops",1,($_POST?$_POST["error_stops"]:isset($_GET["import"])||$_GET["error_stops"]),'Bei Fehler anhalten')."\n",checkbox("only_errors",1,($_POST?$_POST["only_errors"]:isset($_GET["import"])||$_GET["only_errors"]),'Nur Fehler anzeigen')."\n","\n";if(!isset($_GET["import"])&&$Fc){print_fieldset("history",'History',$_GET["history"]!="");for($X=end($Fc);$X;$X=prev($Fc)){$z=key($Fc);list($H,$jg,$Ib)=$X;echo''.'Bearbeiten'.""." ".@date("H:i:s",$jg).""." ".shorten_utf8(ltrim(str_replace("\n"," ",str_replace("\r","",preg_replace('~^(#|-- ).*~m','',$H)))),80,"").($Ib?" ($Ib)":"")."
    \n";}echo"\n","".'Alle bearbeiten'."\n","\n";}echo'

    +';}elseif(isset($_GET["edit"])){$a=$_GET["edit"];$n=fields($a);$Z=(isset($_GET["select"])?($_POST["check"]&&count($_POST["check"])==1?where_check($_POST["check"][0],$n):""):where($_GET,$n));$Kg=(isset($_GET["select"])?$_POST["edit"]:$Z);foreach($n +as$F=>$m){if(!isset($m["privileges"][$Kg?"update":"insert"])||$b->fieldName($m)==""||$m["generated"])unset($n[$F]);}if($_POST&&!$l&&!isset($_GET["select"])){$B=$_POST["referer"];if($_POST["insert"])$B=($Kg?null:$_SERVER["REQUEST_URI"]);elseif(!preg_match('~^.+&select=.+$~',$B))$B=ME."select=".urlencode($a);$x=indexes($a);$Fg=unique_array($_GET["where"],$x);$Ye="\nWHERE $Z";if(isset($_POST["delete"]))queries_redirect($B,'Datensatz wurde gelöscht.',$k->delete($a,$Ye,!$Fg));else{$P=array();foreach($n +as$F=>$m){$X=process_input($m);if($X!==false&&$X!==null)$P[idf_escape($F)]=$X;}if($Kg){if(!$P)redirect($B);queries_redirect($B,'Datensatz wurde geändert.',$k->update($a,$P,$Ye,!$Fg));if(is_ajax()){page_headers();page_messages($l);exit;}}else{$J=$k->insert($a,$P);$id=($J?last_id():0);queries_redirect($B,sprintf('Datensatz%s wurde eingefügt.',($id?" $id":"")),$J);}}}$L=null;if($_POST["save"])$L=(array)$_POST["fields"];elseif($Z){$N=array();foreach($n +as$F=>$m){if(isset($m["privileges"]["select"])){$pa=convert_field($m);if($_POST["clone"]&&$m["auto_increment"])$pa="''";if($y=="sql"&&preg_match("~enum|set~",$m["type"]))$pa="1*".idf_escape($F);$N[]=($pa?"$pa AS ":"").idf_escape($F);}}$L=array();if(!support("table"))$N=array("*");if($N){$J=$k->select($a,$N,array($Z),$N,array(),(isset($_GET["select"])?2:1));if(!$J)$l=error();else{$L=$J->fetch_assoc();if(!$L)$L=false;}if(isset($_GET["select"])&&(!$L||$J->fetch_assoc()))$L=null;}}if(!support("table")&&!$n){if(!$Z){$J=$k->select($a,array("*"),$Z,array("*"));$L=($J?$J->fetch_assoc():false);if(!$L)$L=array($k->primary=>"");}if($L){foreach($L +as$z=>$X){if(!$Z)$L[$z]=null;$n[$z]=array("field"=>$z,"null"=>($z!=$k->primary),"auto_increment"=>($z==$k->primary));}}}edit_form($a,$n,$L,$Kg);}elseif(isset($_GET["create"])){$a=$_GET["create"];$we=array();foreach(array('HASH','LINEAR HASH','KEY','LINEAR KEY','RANGE','LIST')as$z)$we[$z]=$z;$ef=referencable_primary($a);$q=array();foreach($ef +as$Wf=>$m)$q[str_replace("`","``",$Wf)."`".str_replace("`","``",$m["field"])]=$Wf;$le=array();$S=array();if($a!=""){$le=fields($a);$S=table_status($a);if(!$S)$l='Keine Tabellen.';}$L=$_POST;$L["fields"]=(array)$L["fields"];if($L["auto_increment_col"])$L["fields"][$L["auto_increment_col"]]["auto_increment"]=true;if($_POST)set_adminer_settings(array("comments"=>$_POST["comments"],"defaults"=>$_POST["defaults"]));if($_POST&&!process_fields($L["fields"])&&!$l){if($_POST["drop"])queries_redirect(substr(ME,0,-1),'Tabelle wurde entfernt.',drop_tables(array($a)));else{$n=array();$na=array();$Og=false;$oc=array();$ke=reset($le);$ma=" FIRST";foreach($L["fields"]as$z=>$m){$p=$q[$m["type"]];$Bg=($p!==null?$ef[$p]:$m);if($m["field"]!=""){if(!$m["has_default"])$m["default"]=null;if($z==$L["auto_increment_col"])$m["auto_increment"]=true;$Ue=process_field($m,$Bg);$na[]=array($m["orig"],$Ue,$ma);if(!$ke||$Ue!=process_field($ke,$ke)){$n[]=array($m["orig"],$Ue,$ma);if($m["orig"]!=""||$ma)$Og=true;}if($p!==null)$oc[idf_escape($m["field"])]=($a!=""&&$y!="sqlite"?"ADD":" ").format_foreign_key(array('table'=>$q[$m["type"]],'source'=>array($m["field"]),'target'=>array($Bg["field"]),'on_delete'=>$m["on_delete"],));$ma=" AFTER ".idf_escape($m["field"]);}elseif($m["orig"]!=""){$Og=true;$n[]=array($m["orig"]);}if($m["orig"]!=""){$ke=next($le);if(!$ke)$ma="";}}$ye="";if($we[$L["partition_by"]]){$ze=array();if($L["partition_by"]=='RANGE'||$L["partition_by"]=='LIST'){foreach(array_filter($L["partition_names"])as$z=>$X){$Y=$L["partition_values"][$z];$ze[]="\n PARTITION ".idf_escape($X)." VALUES ".($L["partition_by"]=='RANGE'?"LESS THAN":"IN").($Y!=""?" ($Y)":" MAXVALUE");}}$ye.="\nPARTITION BY $L[partition_by]($L[partition])".($ze?" (".implode(",",$ze)."\n)":($L["partitions"]?" PARTITIONS ".(+$L["partitions"]):""));}elseif(support("partitioning")&&preg_match("~partitioned~",$S["Create_options"]))$ye.="\nREMOVE PARTITIONING";$D='Tabelle wurde geändert.';if($a==""){cookie("adminer_engine",$L["Engine"]);$D='Tabelle wurde erstellt.';}$F=trim($L["name"]);queries_redirect(ME.(support("table")?"table=":"select=").urlencode($F),$D,alter_table($a,$F,($y=="sqlite"&&($Og||$oc)?$na:$n),$oc,($L["Comment"]!=$S["Comment"]?$L["Comment"]:null),($L["Engine"]&&$L["Engine"]!=$S["Engine"]?$L["Engine"]:""),($L["Collation"]&&$L["Collation"]!=$S["Collation"]?$L["Collation"]:""),($L["Auto_increment"]!=""?number($L["Auto_increment"]):""),$ye));}}page_header(($a!=""?'Tabelle ändern':'Tabelle erstellen'),$l,array("table"=>$a),h($a));if(!$_POST){$L=array("Engine"=>$_COOKIE["adminer_engine"],"fields"=>array(array("field"=>"","type"=>(isset($Cg["int"])?"int":(isset($Cg["integer"])?"integer":"")),"on_update"=>"")),"partition_names"=>array(""),);if($a!=""){$L=$S;$L["name"]=$a;$L["fields"]=array();if(!$_GET["auto_increment"])$L["Auto_increment"]="";foreach($le +as$m){$m["has_default"]=isset($m["default"]);$L["fields"][]=$m;}if(support("partitioning")){$tc="FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = ".q(DB)." AND TABLE_NAME = ".q($a);$J=$f->query("SELECT PARTITION_METHOD, PARTITION_ORDINAL_POSITION, PARTITION_EXPRESSION $tc ORDER BY PARTITION_ORDINAL_POSITION DESC LIMIT 1");list($L["partition_by"],$L["partitions"],$L["partition"])=$J->fetch_row();$ze=get_key_vals("SELECT PARTITION_NAME, PARTITION_DESCRIPTION $tc AND PARTITION_NAME != '' ORDER BY PARTITION_ORDINAL_POSITION");$ze[""]="";$L["partition_names"]=array_keys($ze);$L["partition_values"]=array_values($ze);}}}$Pa=collations();$Pb=engines();foreach($Pb +as$Ob){if(!strcasecmp($Ob,$L["Engine"])){$L["Engine"]=$Ob;break;}}echo' +
    +

    +';if(support("columns")||$a==""){echo'Name der Tabelle: +';if($a==""&&!$_POST)echo +script("focus(qs('#form')['name']);");echo($Pb?"".on_help("getTarget(event).value",1).script("qsl('select').onchange = helpClose;"):""),' ',($Pa&&!preg_match("~sqlite|mssql~",$y)?html_select("Collation",array(""=>"(".'Kollation'.")")+$Pa,$L["Collation"]):""),' +';}echo' +';if(support("columns")){echo'

    + +';edit_fields($L["fields"],$Pa,"TABLE",$q);echo'
    +',script("editFields();"),'
    +

    +Auto-Inkrement: +',checkbox("defaults",1,($_POST?$_POST["defaults"]:adminer_setting("defaults")),'Vorgabewerte festlegen',"columnShow(this.checked, 5)","jsonly"),(support("comment")?checkbox("comments",1,($_POST?$_POST["comments"]:adminer_setting("comments")),'Kommentar',"editingCommentsClick(this, true);","jsonly").' ':''),'

    + +';}echo' +';if($a!=""){echo'',confirm(sprintf('Drop %s?',$a));}if(support("partitioning")){$xe=preg_match('~RANGE|LIST~',$L["partition_by"]);print_fieldset("partition",'Partitionieren um',$L["partition_by"]);echo'

    +',"".on_help("getTarget(event).value.replace(/./, 'PARTITION BY \$&')",1).script("qsl('select').onchange = partitionByChange;"),'() +Partitionen: + + +';foreach($L["partition_names"]as$z=>$X){echo'',' + +';}echo' +

    +';}elseif(isset($_GET["indexes"])){$a=$_GET["indexes"];$Oc=array("PRIMARY","UNIQUE","INDEX");$S=table_status($a,true);if(preg_match('~MyISAM|M?aria'.(min_version(5.6,'10.0.5')?'|InnoDB':'').'~i',$S["Engine"]))$Oc[]="FULLTEXT";if(preg_match('~MyISAM|M?aria'.(min_version(5.7,'10.2.2')?'|InnoDB':'').'~i',$S["Engine"]))$Oc[]="SPATIAL";$x=indexes($a);$Oe=array();if($y=="mongo"){$Oe=$x["_id_"];unset($Oc[0]);unset($x["_id_"]);}$L=$_POST;if($_POST&&!$l&&!$_POST["add"]&&!$_POST["drop_col"]){$oa=array();foreach($L["indexes"]as$w){$F=$w["name"];if(in_array($w["type"],$Oc)){$e=array();$od=array();$tb=array();$P=array();ksort($w["columns"]);foreach($w["columns"]as$z=>$d){if($d!=""){$nd=$w["lengths"][$z];$sb=$w["descs"][$z];$P[]=idf_escape($d).($nd?"(".(+$nd).")":"").($sb?" DESC":"");$e[]=$d;$od[]=($nd?$nd:null);$tb[]=$sb;}}if($e){$Yb=$x[$F];if($Yb){ksort($Yb["columns"]);ksort($Yb["lengths"]);ksort($Yb["descs"]);if($w["type"]==$Yb["type"]&&array_values($Yb["columns"])===$e&&(!$Yb["lengths"]||array_values($Yb["lengths"])===$od)&&array_values($Yb["descs"])===$tb){unset($x[$F]);continue;}}$oa[]=array($w["type"],$F,$P);}}}foreach($x +as$F=>$Yb)$oa[]=array($Yb["type"],$F,"DROP");if(!$oa)redirect(ME."table=".urlencode($a));queries_redirect(ME."table=".urlencode($a),'Indizes geändert.',alter_indexes($a,$oa));}page_header('Indizes',$l,array("table"=>$a),h($a));$n=array_keys(fields($a));if($_POST["add"]){foreach($L["indexes"]as$z=>$w){if($w["columns"][count($w["columns"])]!="")$L["indexes"][$z]["columns"][]="";}$w=end($L["indexes"]);if($w["type"]||array_filter($w["columns"],'strlen'))$L["indexes"][]=array("columns"=>array(1=>""));}if(!$L){foreach($x +as$z=>$w){$x[$z]["name"]=$z;$x[$z]["columns"][]="";}$x[]=array("columns"=>array(1=>""));$L["indexes"]=$x;}echo' +
    +
    + + + +';if($Oe){echo"
    Index-Typ +Spalte (Länge) +Name + +
    PRIMARY";foreach($Oe["columns"]as$z=>$d){echo +select_input(" disabled",$n,$d)," ";}echo"\n";}$Zc=1;foreach($L["indexes"]as$w){if(!$_POST["drop_col"]||$Zc!=key($_POST["drop_col"])){echo"
    ".html_select("indexes[$Zc][type]",array(-1=>"")+$Oc,$w["type"],($Zc==count($L["indexes"])?"indexesAddRow.call(this);":1),"label-type"),"";ksort($w["columns"]);$u=1;foreach($w["columns"]as$z=>$d){echo"".select_input(" name='indexes[$Zc][columns][$u]' title='".'Spalte'."'",($n?array_combine($n,$n):$n),$d,"partial(".($u==count($w["columns"])?"indexesAddColumn":"indexesChangeColumn").", '".js_escape($y=="sql"?"":$_GET["indexes"]."_")."')"),($y=="sql"||$y=="mssql"?"":""),(support("descidx")?checkbox("indexes[$Zc][descs][$u]",1,$w["descs"][$z],'absteigend'):"")," ";$u++;}echo"\n","".script("qsl('input').onclick = partial(editingRemoveRow, 'indexes\$1[type]');");}$Zc++;}echo'
    +
    +

    + + +

    +';}elseif(isset($_GET["database"])){$L=$_POST;if($_POST&&!$l&&!isset($_POST["add_x"])){$F=trim($L["name"]);if($_POST["drop"]){$_GET["db"]="";queries_redirect(remove_from_uri("db|database"),'Datenbank wurde entfernt.',drop_databases(array(DB)));}elseif(DB!==$F){if(DB!=""){$_GET["db"]=$F;queries_redirect(preg_replace('~\bdb=[^&]*&~','',ME)."db=".urlencode($F),'Datenbank wurde umbenannt.',rename_database($F,$L["collation"]));}else{$i=explode("\n",str_replace("\r","",$F));$Qf=true;$hd="";foreach($i +as$j){if(count($i)==1||$j!=""){if(!create_database($j,$L["collation"]))$Qf=false;$hd=$j;}}restart_session();set_session("dbs",null);queries_redirect(ME."db=".urlencode($hd),'Datenbank wurde erstellt.',$Qf);}}else{if(!$L["collation"])redirect(substr(ME,0,-1));query_redirect("ALTER DATABASE ".idf_escape($F).(preg_match('~^[a-z0-9_]+$~i',$L["collation"])?" COLLATE $L[collation]":""),substr(ME,0,-1),'Datenbank wurde geändert.');}}page_header(DB!=""?'Datenbank ändern':'Datenbank erstellen',$l,array(),h(DB));$Pa=collations();$F=DB;if($_POST)$F=$L["name"];elseif(DB!="")$L["collation"]=db_collation(DB,$Pa);elseif($y=="sql"){foreach(get_vals("SHOW GRANTS")as$vc){if(preg_match('~ ON (`(([^\\\\`]|``|\\\\.)*)%`\.\*)?~',$vc,$C)&&$C[1]){$F=stripcslashes(idf_unescape("`$C[2]`"));break;}}}echo' +
    +

    +',($_POST["add_x"]||strpos($F,"\n")?'
    ':'')."\n".($Pa?html_select("collation",array(""=>"(".'Kollation'.")")+$Pa,$L["collation"]).'':""),script("focus(qs('#name'));"),' +';if(DB!="")echo"".confirm(sprintf('Drop %s?',DB))."\n";elseif(!$_POST["add_x"]&&$_GET["db"]=="")echo"\n";echo' +

    +';}elseif(isset($_GET["foreign"])){$a=$_GET["foreign"];$F=$_GET["name"];$L=$_POST;if($_POST&&!$l&&!$_POST["add"]&&!$_POST["change"]&&!$_POST["change-js"]){$D=($_POST["drop"]?'Fremdschlüssel wurde entfernt.':($F!=""?'Fremdschlüssel wurde geändert.':'Fremdschlüssel wurde erstellt.'));$B=ME."table=".urlencode($a);if(!$_POST["drop"]){$L["source"]=array_filter($L["source"],'strlen');ksort($L["source"]);$dg=array();foreach($L["source"]as$z=>$X)$dg[$z]=$L["target"][$z];$L["target"]=$dg;}if($y=="sqlite")queries_redirect($B,$D,recreate_table($a,$a,array(),array(),array(" $F"=>($_POST["drop"]?"":" ".format_foreign_key($L)))));else{$oa="ALTER TABLE ".table($a);$_b="\nDROP ".($y=="sql"?"FOREIGN KEY ":"CONSTRAINT ").idf_escape($F);if($_POST["drop"])query_redirect($oa.$_b,$B,$D);else{query_redirect($oa.($F!=""?"$_b,":"")."\nADD".format_foreign_key($L),$B,$D);$l='Quell- und Zielspalten müssen vom gleichen Datentyp sein, es muss unter den Zielspalten ein Index existieren und die referenzierten Daten müssen existieren.'."
    $l";}}}page_header('Fremdschlüssel',$l,array("table"=>$a),h($a));if($_POST){ksort($L["source"]);if($_POST["add"])$L["source"][]="";elseif($_POST["change"]||$_POST["change-js"])$L["target"]=array();}elseif($F!=""){$q=foreign_keys($a);$L=$q[$F];$L["source"][]="";}else{$L["table"]=$a;$L["source"]=array("");}echo' +
    +';$Ff=array_keys(fields($a));if($L["db"]!="")$f->select_db($L["db"]);if($L["ns"]!="")set_schema($L["ns"]);$df=array_keys(array_filter(table_status('',true),'fk_support'));$dg=array_keys(fields(in_array($L["table"],$df)?$L["table"]:reset($df)));$Xd="this.form['change-js'].value = '1'; this.form.submit();";echo"

    ".'Zieltabelle'.": ".html_select("table",$df,$L["table"],$Xd)."\n";if($y=="pgsql")echo'Schema'.": ".html_select("ns",$b->schemas(),$L["ns"]!=""?$L["ns"]:$_GET["ns"],$Xd);elseif($y!="sqlite"){$mb=array();foreach($b->databases()as$j){if(!information_schema($j))$mb[]=$j;}echo'DB'.": ".html_select("db",$mb,$L["db"]!=""?$L["db"]:$_GET["db"],$Xd);}echo' +

    + + +';$Zc=0;foreach($L["source"]as$z=>$X){echo"","
    UrsprungZiel
    ".html_select("source[".(+$z)."]",array(-1=>"")+$Ff,$X,($Zc==count($L["source"])-1?"foreignAddRow.call(this);":1),"label-source"),"".html_select("target[".(+$z)."]",$dg,$L["target"][$z],1,"label-target");$Zc++;}echo'
    +

    +ON DELETE: ',html_select("on_delete",array(-1=>"")+explode("|",$Wd),$L["on_delete"]),' ON UPDATE: ',html_select("on_update",array(-1=>"")+explode("|",$Wd),$L["on_update"]),'','

    + +

    +';if($F!=""){echo'',confirm(sprintf('Drop %s?',$F));}echo' +

    +';}elseif(isset($_GET["view"])){$a=$_GET["view"];$L=$_POST;$me="VIEW";if($y=="pgsql"&&$a!=""){$Mf=table_status($a);$me=strtoupper($Mf["Engine"]);}if($_POST&&!$l){$F=trim($L["name"]);$pa=" AS\n$L[select]";$B=ME."table=".urlencode($F);$D='View wurde geändert.';$V=($_POST["materialized"]?"MATERIALIZED VIEW":"VIEW");if(!$_POST["drop"]&&$a==$F&&$y!="sqlite"&&$V=="VIEW"&&$me=="VIEW")query_redirect(($y=="mssql"?"ALTER":"CREATE OR REPLACE")." VIEW ".table($F).$pa,$B,$D);else{$fg=$F."_adminer_".uniqid();drop_create("DROP $me ".table($a),"CREATE $V ".table($F).$pa,"DROP $V ".table($F),"CREATE $V ".table($fg).$pa,"DROP $V ".table($fg),($_POST["drop"]?substr(ME,0,-1):$B),'View wurde entfernt.',$D,'View wurde erstellt.',$a,$F);}}if(!$_POST&&$a!=""){$L=view($a);$L["name"]=$a;$L["materialized"]=($me!="VIEW");if(!$l)$l=error();}page_header(($a!=""?'View ändern':'View erstellen'),$l,array("table"=>$a),h($a));echo' +
    +

    Name: +',(support("materializedview")?" ".checkbox("materialized",1,$L["materialized"],'Materialized view'):""),'

    ';textarea("select",$L["select"]);echo'

    + +';if($a!=""){echo'',confirm(sprintf('Drop %s?',$a));}echo' +

    +';}elseif(isset($_GET["trigger"])){$a=$_GET["trigger"];$F=$_GET["name"];$_g=trigger_options();$L=(array)trigger($F,$a)+array("Trigger"=>$a."_bi");if($_POST){if(!$l&&in_array($_POST["Timing"],$_g["Timing"])&&in_array($_POST["Event"],$_g["Event"])&&in_array($_POST["Type"],$_g["Type"])){$Vd=" ON ".table($a);$_b="DROP TRIGGER ".idf_escape($F).($y=="pgsql"?$Vd:"");$B=ME."table=".urlencode($a);if($_POST["drop"])query_redirect($_b,$B,'Trigger wurde entfernt.');else{if($F!="")queries($_b);queries_redirect($B,($F!=""?'Trigger wurde geändert.':'Trigger wurde erstellt.'),queries(create_trigger($Vd,$_POST)));if($F!="")queries(create_trigger($Vd,$L+array("Type"=>reset($_g["Type"]))));}}$L=$_POST;}page_header(($F!=""?'Trigger ändern'.": ".h($F):'Trigger erstellen'),$l,array("table"=>$a));echo' +
    + +
    Zeitpunkt',html_select("Timing",$_g["Timing"],$L["Timing"],"triggerChange(/^".preg_quote($a,"/")."_[ba][iud]$/, '".js_escape($a)."', this.form);"),'
    Ereignis',html_select("Event",$_g["Event"],$L["Event"],"this.form['Timing'].onchange();"),(in_array("UPDATE OF",$_g["Event"])?" ":""),'
    Typ',html_select("Type",$_g["Type"],$L["Type"]),'
    +

    Name: +',script("qs('#form')['Timing'].onchange();"),'

    ';textarea("Statement",$L["Statement"]);echo'

    + +';if($F!=""){echo'',confirm(sprintf('Drop %s?',$F));}echo' +

    +';}elseif(isset($_GET["select"])){$a=$_GET["select"];$S=table_status1($a);$x=indexes($a);$n=fields($a);$q=column_foreign_keys($a);$Td=$S["Oid"];parse_str($_COOKIE["adminer_import"],$ja);$lf=array();$e=array();$ig=null;foreach($n +as$z=>$m){$F=$b->fieldName($m);if(isset($m["privileges"]["select"])&&$F!=""){$e[$z]=html_entity_decode(strip_tags($F),ENT_QUOTES);if(is_shortable($m))$ig=$b->selectLengthProcess();}$lf+=$m["privileges"];}list($N,$t)=$b->selectColumnsProcess($e,$x);$Wc=count($t)selectSearchProcess($n,$x);$fe=$b->selectOrderProcess($n,$x);$_=$b->selectLimitProcess();if($_GET["val"]&&is_ajax()){header("Content-Type: text/plain; charset=utf-8");foreach($_GET["val"]as$Gg=>$L){$pa=convert_field($n[key($L)]);$N=array($pa?$pa:idf_escape(key($L)));$Z[]=where_check($Gg,$n);$K=$k->select($a,$N,$Z,$N);if($K)echo +reset($K->fetch_row());}exit;}$Oe=$Ig=null;foreach($x +as$w){if($w["type"]=="PRIMARY"){$Oe=array_flip($w["columns"]);$Ig=($N?$Oe:array());foreach($Ig +as$z=>$X){if(in_array(idf_escape($z),$N))unset($Ig[$z]);}break;}}if($Td&&!$Oe){$Oe=$Ig=array($Td=>0);$x[]=array("type"=>"PRIMARY","columns"=>array($Td));}if($_POST&&!$l){$fh=$Z;if(!$_POST["all"]&&is_array($_POST["check"])){$Ga=array();foreach($_POST["check"]as$Ea)$Ga[]=where_check($Ea,$n);$fh[]="((".implode(") OR (",$Ga)."))";}$fh=($fh?"\nWHERE ".implode(" AND ",$fh):"");if($_POST["export"]){cookie("adminer_import","output=".urlencode($_POST["output"])."&format=".urlencode($_POST["format"]));dump_headers($a);$b->dumpTable($a,"");$tc=($N?implode(", ",$N):"*").convert_fields($e,$n,$N)."\nFROM ".table($a);$xc=($t&&$Wc?"\nGROUP BY ".implode(", ",$t):"").($fe?"\nORDER BY ".implode(", ",$fe):"");if(!is_array($_POST["check"])||$Oe)$I="SELECT $tc$fh$xc";else{$Eg=array();foreach($_POST["check"]as$X)$Eg[]="(SELECT".limit($tc,"\nWHERE ".($Z?implode(" AND ",$Z)." AND ":"").where_check($X,$n).$xc,1).")";$I=implode(" UNION ALL ",$Eg);}$b->dumpData($a,"table",$I);exit;}if(!$b->selectEmailProcess($Z,$q)){if($_POST["save"]||$_POST["delete"]){$J=true;$ka=0;$P=array();if(!$_POST["delete"]){foreach($e +as$F=>$X){$X=process_input($n[$F]);if($X!==null&&($_POST["clone"]||$X!==false))$P[idf_escape($F)]=($X!==false?$X:idf_escape($F));}}if($_POST["delete"]||$P){if($_POST["clone"])$I="INTO ".table($a)." (".implode(", ",array_keys($P)).")\nSELECT ".implode(", ",$P)."\nFROM ".table($a);if($_POST["all"]||($Oe&&is_array($_POST["check"]))||$Wc){$J=($_POST["delete"]?$k->delete($a,$fh):($_POST["clone"]?queries("INSERT $I$fh"):$k->update($a,$P,$fh)));$ka=$f->affected_rows;}else{foreach((array)$_POST["check"]as$X){$eh="\nWHERE ".($Z?implode(" AND ",$Z)." AND ":"").where_check($X,$n);$J=($_POST["delete"]?$k->delete($a,$eh,1):($_POST["clone"]?queries("INSERT".limit1($a,$I,$eh)):$k->update($a,$P,$eh,1)));if(!$J)break;$ka+=$f->affected_rows;}}}$D=sprintf('%d Artikel betroffen.',$ka);if($_POST["clone"]&&$J&&$ka==1){$id=last_id();if($id)$D=sprintf('Datensatz%s wurde eingefügt.'," $id");}queries_redirect(remove_from_uri($_POST["all"]&&$_POST["delete"]?"page":""),$D,$J);if(!$_POST["delete"]){edit_form($a,$n,(array)$_POST["fields"],!$_POST["clone"]);page_footer();exit;}}elseif(!$_POST["import"]){if(!$_POST["val"])$l='Ctrl+Klick zum Bearbeiten des Wertes.';else{$J=true;$ka=0;foreach($_POST["val"]as$Gg=>$L){$P=array();foreach($L +as$z=>$X){$z=bracket_escape($z,1);$P[idf_escape($z)]=(preg_match('~char|text~',$n[$z]["type"])||$X!=""?$b->processInput($n[$z],$X):"NULL");}$J=$k->update($a,$P," WHERE ".($Z?implode(" AND ",$Z)." AND ":"").where_check($Gg,$n),!$Wc&&!$Oe," ");if(!$J)break;$ka+=$f->affected_rows;}queries_redirect(remove_from_uri(),sprintf('%d Artikel betroffen.',$ka),$J);}}elseif(!is_string($jc=get_file("csv_file",true)))$l=upload_error($jc);elseif(!preg_match('~~u',$jc))$l='Die Datei muss UTF-8 kodiert sein.';else{cookie("adminer_import","output=".urlencode($ja["output"])."&format=".urlencode($_POST["separator"]));$J=true;$Qa=array_keys($n);preg_match_all('~(?>"[^"]*"|[^"\r\n]+)+~',$jc,$ud);$ka=count($ud[0]);$k->begin();$xf=($_POST["separator"]=="csv"?",":($_POST["separator"]=="tsv"?"\t":";"));$M=array();foreach($ud[0]as$z=>$X){preg_match_all("~((?>\"[^\"]*\")+|[^$xf]*)$xf~",$X.$xf,$vd);if(!$z&&!array_diff($vd[1],$Qa)){$Qa=$vd[1];$ka--;}else{$P=array();foreach($vd[1]as$u=>$Ma)$P[idf_escape($Qa[$u])]=($Ma==""&&$n[$Qa[$u]]["null"]?"NULL":q(str_replace('""','"',preg_replace('~^"|"$~','',$Ma))));$M[]=$P;}}$J=(!$M||$k->insertUpdate($a,$M,$Oe));if($J)$J=$k->commit();queries_redirect(remove_from_uri("page"),lang(array('%d Datensatz wurde importiert.','%d Datensätze wurden importiert.'),$ka),$J);$k->rollback();}}}$Wf=$b->tableName($S);if(is_ajax()){page_headers();ob_start();}else +page_header('Daten zeigen von'.": $Wf",$l);$P=null;if(isset($lf["insert"])||!support("table")){$P="";foreach((array)$_GET["where"]as$X){if($q[$X["col"]]&&count($q[$X["col"]])==1&&($X["op"]=="="||(!$X["op"]&&!preg_match('~[_%]~',$X["val"]))))$P.="&set".urlencode("[".bracket_escape($X["col"])."]")."=".urlencode($X["val"]);}}$b->selectLinks($S,$P);if(!$e&&support("table"))echo"

    ".'Auswahl der Tabelle fehlgeschlagen'.($n?".":": ".error())."\n";else{echo"

    \n","
    ";hidden_fields_get();echo(DB!=""?''.(isset($_GET["ns"])?'':""):"");echo'',"
    \n";$b->selectColumnsPrint($N,$e);$b->selectSearchPrint($Z,$e,$x);$b->selectOrderPrint($fe,$e,$x);$b->selectLimitPrint($_);$b->selectLengthPrint($ig);$b->selectActionPrint($x);echo"
    \n";$G=$_GET["page"];if($G=="last"){$sc=$f->result(count_rows($a,$Z,$Wc,$t));$G=floor(max(0,$sc-1)/$_);}$sf=$N;$wc=$t;if(!$sf){$sf[]="*";$ab=convert_fields($e,$n,$N);if($ab)$sf[]=substr($ab,2);}foreach($N +as$z=>$X){$m=$n[idf_unescape($X)];if($m&&($pa=convert_field($m)))$sf[$z]="$pa AS $X";}if(!$Wc&&$Ig){foreach($Ig +as$z=>$X){$sf[]=idf_escape($z);if($wc)$wc[]=idf_escape($z);}}$J=$k->select($a,$sf,$Z,$wc,$fe,$_,$G,true);if(!$J)echo"

    ".error()."\n";else{if($y=="mssql"&&$G)$J->seek($_*$G);$Mb=array();echo"

    \n";$M=array();while($L=$J->fetch_assoc()){if($G&&$y=="oracle")unset($L["RNUM"]);$M[]=$L;}if($_GET["page"]!="last"&&$_!=""&&$t&&$Wc&&$y=="sql")$sc=$f->result(" SELECT FOUND_ROWS()");if(!$M)echo"

    ".'Keine Datensätze.'."\n";else{$wa=$b->backwardKeys($a,$Wf);echo"

    ","",script("mixin(qs('#table'), {onclick: tableClick, ondblclick: partialArg(tableClick, true), onkeydown: editingKeydown});"),"".(!$t&&$N?"":"\n";if(is_ajax()){if($_%2==1&&$G%2==1)odd();ob_end_clean();}foreach($b->rowDescriptions($M,$q)as$E=>$L){$Fg=unique_array($M[$E],$x);if(!$Fg){$Fg=array();foreach($M[$E]as$z=>$X){if(!preg_match('~^(COUNT\((\*|(DISTINCT )?`(?:[^`]|``)+`)\)|(AVG|GROUP_CONCAT|MAX|MIN|SUM)\(`(?:[^`]|``)+`\))$~',$z))$Fg[$z]=$X;}}$Gg="";foreach($Fg +as$z=>$X){if(($y=="sql"||$y=="pgsql")&&preg_match('~char|text|enum|set~',$n[$z]["type"])&&strlen($X)>64){$z=(strpos($z,'(')?$z:idf_escape($z));$z="MD5(".($y!='sql'||preg_match("~^utf8~",$n[$z]["collation"])?$z:"CONVERT($z USING ".charset($f).")").")";$X=md5($X);}$Gg.="&".($X!==null?urlencode("where[".bracket_escape($z)."]")."=".urlencode($X):"null%5B%5D=".urlencode($z));}echo"".(!$t&&$N?"":"";}}}if($wa)echo"\n";}if(is_ajax())exit;echo"
    ".script("qs('#all-page').onclick = partial(formCheck, /check/);","")." ".'Ändern'."");$Kd=array();$uc=array();reset($N);$af=1;foreach($M[0]as$z=>$X){if(!isset($Ig[$z])){$X=$_GET["columns"][key($N)];$m=$n[$N?($X?$X["col"]:current($N)):$z];$F=($m?$b->fieldName($m,$af):($X["fun"]?"*":$z));if($F!=""){$af++;$Kd[$z]=$F;$d=idf_escape($z);$Ic=remove_from_uri('(order|desc)[^=]*|page').'&order%5B0%5D='.urlencode($z);$sb="&desc%5B0%5D=1";echo"".script("mixin(qsl('th'), {onmouseover: partial(columnMouse), onmouseout: partial(columnMouse, ' hidden')});",""),'';echo +apply_sql_function($X["fun"],$F)."";echo"";}$uc[$z]=$X["fun"];next($N);}}$od=array();if($_GET["modify"]){foreach($M +as$L){foreach($L +as$z=>$X)$od[$z]=max($od[$z],min(40,strlen(utf8_decode($X))));}}echo($wa?"".'Relationen':"")."
    ".checkbox("check[]",substr($Gg,1),in_array(substr($Gg,1),(array)$_POST["check"])).($Wc||information_schema(DB)?"":" ".'bearbeiten'.""));foreach($L +as$z=>$X){if(isset($Kd[$z])){$m=$n[$z];$X=$k->value($X,$m);if($X!=""&&(!isset($Mb[$z])||$Mb[$z]!=""))$Mb[$z]=(is_mail($X)?$Kd[$z]:"");$A="";if(preg_match('~blob|bytea|raw|file~',$m["type"])&&$X!="")$A=ME.'download='.urlencode($a).'&field='.urlencode($z).$Gg;if(!$A&&$X!==null){foreach((array)$q[$z]as$p){if(count($q[$z])==1||end($p["source"])==$z){$A="";foreach($p["source"]as$u=>$Ff)$A.=where_link($u,$p["target"][$u],$M[$E][$Ff]);$A=($p["db"]!=""?preg_replace('~([?&]db=)[^&]+~','\1'.urlencode($p["db"]),ME):ME).'select='.urlencode($p["table"]).$A;if($p["ns"])$A=preg_replace('~([?&]ns=)[^&]+~','\1'.urlencode($p["ns"]),$A);if(count($p["source"])==1)break;}}}if($z=="COUNT(*)"){$A=ME."select=".urlencode($a);$u=0;foreach((array)$_GET["where"]as$W){if(!array_key_exists($W["col"],$Fg))$A.=where_link($u++,$W["col"],$W["val"],$W["op"]);}foreach($Fg +as$ad=>$W)$A.=where_link($u++,$ad,$W);}$X=select_value($X,$A,$m,$ig);$v=h("val[$Gg][".bracket_escape($z)."]");$Y=$_POST["val"][$Gg][bracket_escape($z)];$Hb=!is_array($L[$z])&&is_utf8($X)&&$M[$E][$z]==$L[$z]&&!$uc[$z];$hg=preg_match('~text|lob~',$m["type"]);echo"".($hg?"":"");}else{$sd=strpos($X,"");echo" data-text='".($sd?2:($hg?1:0))."'".($Hb?"":" data-warning='".h('Benutzen Sie den Link zum Bearbeiten dieses Wertes.')."'").">$X";$b->backwardKeysPrint($wa,$M[$E]);echo"
    \n","
    \n";}if(!is_ajax()){if($M||$G){$Wb=true;if($_GET["page"]!="last"){if($_==""||(count($M)<$_&&($M||!$G)))$sc=($G?$G*$_:0)+count($M);elseif($y!="sql"||!$Wc){$sc=($Wc?false:found_rows($S,$Z));if($sc$_||$G));if($se){echo(($sc===false?count($M)+1:$sc-$G*$_)>$_?'

    '.'Mehr Daten laden'.''.script("qsl('a').onclick = partial(selectLoadMore, ".(+$_).", '".'Lade'."…');",""):''),"\n";}}echo"

    \n";if($b->selectImportPrint()){echo"
    ","".'Importieren'."",script("qsl('a').onclick = partial(toggle, 'import');",""),"","
    ";}echo"\n","\n",(!$t&&$N?"":script("tableCheck();"));}}}if(is_ajax()){ob_end_clean();exit;}}elseif(isset($_GET["variables"])){$Mf=isset($_GET["status"]);page_header($Mf?'Status':'Variablen');$Vg=($Mf?show_status():show_variables());if(!$Vg)echo"

    ".'Keine Datensätze.'."\n";else{echo"\n";foreach($Vg +as$z=>$X){echo"","
    ".h($z)."","".h($X);}echo"
    \n";}}elseif(isset($_GET["script"])){header("Content-Type: text/javascript; charset=utf-8");if($_GET["script"]=="db"){$Tf=array("Data_length"=>0,"Index_length"=>0,"Data_free"=>0);foreach(table_status()as$F=>$S){json_row("Comment-$F",h($S["Comment"]));if(!is_view($S)){foreach(array("Engine","Collation")as$z)json_row("$z-$F",h($S[$z]));foreach($Tf+array("Auto_increment"=>0,"Rows"=>0)as$z=>$X){if($S[$z]!=""){$X=format_number($S[$z]);json_row("$z-$F",($z=="Rows"&&$X&&$S["Engine"]==($Hf=="pgsql"?"table":"InnoDB")?"~ $X":$X));if(isset($Tf[$z]))$Tf[$z]+=($S["Engine"]!="InnoDB"||$z!="Data_free"?$S[$z]:0);}elseif(array_key_exists($z,$S))json_row("$z-$F");}}}foreach($Tf +as$z=>$X)json_row("sum-$z",format_number($X));json_row("");}elseif($_GET["script"]=="kill")$f->query("KILL ".number($_POST["kill"]));else{foreach(count_tables($b->databases())as$j=>$X){json_row("tables-$j",$X);json_row("size-$j",db_size($j));}json_row("");}exit;}else{$bg=array_merge((array)$_POST["tables"],(array)$_POST["views"]);if($bg&&!$l&&!$_POST["search"]){$J=true;$D="";if($y=="sql"&&$_POST["tables"]&&count($_POST["tables"])>1&&($_POST["drop"]||$_POST["truncate"]||$_POST["copy"]))queries("SET foreign_key_checks = 0");if($_POST["truncate"]){if($_POST["tables"])$J=truncate_tables($_POST["tables"]);$D='Tabellen wurden geleert (truncate).';}elseif($_POST["move"]){$J=move_tables((array)$_POST["tables"],(array)$_POST["views"],$_POST["target"]);$D='Tabellen verschoben.';}elseif($_POST["copy"]){$J=copy_tables((array)$_POST["tables"],(array)$_POST["views"],$_POST["target"]);$D='Tabellen wurden kopiert.';}elseif($_POST["drop"]){if($_POST["views"])$J=drop_views($_POST["views"]);if($J&&$_POST["tables"])$J=drop_tables($_POST["tables"]);$D='Tabellen wurden entfernt (drop).';}elseif($y!="sql"){$J=($y=="sqlite"?queries("VACUUM"):apply_queries("VACUUM".($_POST["optimize"]?"":" ANALYZE"),$_POST["tables"]));$D='Tabellen wurden optimiert.';}elseif(!$_POST["tables"])$D='Keine Tabellen.';elseif($J=queries(($_POST["optimize"]?"OPTIMIZE":($_POST["check"]?"CHECK":($_POST["repair"]?"REPAIR":"ANALYZE")))." TABLE ".implode(", ",array_map('idf_escape',$_POST["tables"])))){while($L=$J->fetch_assoc())$D.="".h($L["Table"]).": ".h($L["Msg_text"])."
    ";}queries_redirect(substr(ME,0,-1),$D,$J);}page_header(($_GET["ns"]==""?'Datenbank'.": ".h(DB):'Schema'.": ".h($_GET["ns"])),$l,true);if($b->homepage()){if($_GET["ns"]!==""){echo"

    ".'Tabellen und Views'."

    \n";$ag=tables_list();if(!$ag)echo"

    ".'Keine Tabellen.'."\n";else{echo"

    \n";if(support("table")){echo"
    ".'Suche in Tabellen'."
    ","",script("qsl('input').onkeydown = partialArg(bodyKeydown, 'search');","")," \n","
    \n";if($_POST["search"]&&$_POST["query"]!=""){$_GET["where"][0]["op"]="LIKE %%";search_tables();}}echo"
    \n","\n",script("mixin(qsl('table'), {onclick: tableClick, ondblclick: partialArg(tableClick, true)});"),'','\n";$T=0;foreach($ag +as$F=>$V){$Yg=($V!==null&&!preg_match('~table|sequence~i',$V));$v=h("Table-".$F);echo'
    '.script("qs('#check-all').onclick = partial(formCheck, /^(tables|views)\[/);",""),''.'Tabelle',''.'Speicher-Engine'.'',''.'Kollation'.'',''.'Datengröße'.'',''.'Indexgröße'.'',''.'Freier Bereich'.'',''.'Auto-Inkrement'.'',''.'Datensätze'.'',(support("comment")?''.'Kommentar'.'':''),"
    '.checkbox(($Yg?"views[]":"tables[]"),$F,in_array($F,$bg,true),"","","",$v),''.(support("table")||support("indexes")?"".h($F).'':h($F));if($Yg){echo''.(preg_match('~materialized~i',$V)?'Materialized view':'View').'','?';}else{foreach(array("Engine"=>array(),"Collation"=>array(),"Data_length"=>array("create",'Tabelle ändern'),"Index_length"=>array("indexes",'Indizes ändern'),"Data_free"=>array("edit",'Neuer Datensatz'),"Auto_increment"=>array("auto_increment=1&create",'Tabelle ändern'),"Rows"=>array("select",'Daten auswählen'),)as$z=>$A){$v=" id='$z-".h($F)."'";echo($A?"".(support("table")||$z=="Rows"||(support("indexes")&&$z!="Data_length")?"?":"?"):"");}$T++;}echo(support("comment")?"":"");}echo"
    ".sprintf('%d insgesamt',count($ag)),"".h($y=="sql"?$f->result("SELECT @@default_storage_engine"):""),"".h(db_collation(DB,collations()));foreach(array("Data_length","Index_length","Data_free")as$z)echo"";echo"
    \n","
    \n";if(!information_schema(DB)){echo"\n";}echo"
    \n",script("tableCheck();");}echo'
    '.'Attention : ne l\'utilisez pas dans un environnement de production !'.'
    ',"\n",'',$b->loginFormField('db','
    '.'Base de données'.'',''."\n"),"
    \n","

    \n";return +true;}function +login($rd,$_e){return +true;}}function +adminer_object(){$Ge=array(new +FCSqliteConnectionWithoutCredentials());return +new +AdminerPlugin($Ge);}function +adminer_errors($Rb,$Tb){return!!preg_match('~^(Trying to access array offset on value of type null|Undefined array key)~',$Tb);}error_reporting(6135);set_error_handler('adminer_errors',E_WARNING);$kc=!preg_match('~^(unsafe_raw)?$~',ini_get("filter.default"));if($kc||ini_get("filter.default_flags")){foreach(array('_GET','_POST','_COOKIE','_SERVER')as$X){$Hg=filter_input_array(constant("INPUT$X"),FILTER_UNSAFE_RAW);if($Hg)$$X=$Hg;}}if(function_exists("mb_internal_encoding"))mb_internal_encoding("8bit");function +connection(){global$f;return$f;}function +adminer(){global$b;return$b;}function +version(){global$da;return$da;}function +idf_unescape($Kc){if(!preg_match('~^[`\'"]~',$Kc))return$Kc;$hd=substr($Kc,-1);return +str_replace($hd.$hd,$hd,substr($Kc,1,-1));}function +escape_string($X){return +substr(q($X),1,-1);}function +number($X){return +preg_replace('~[^0-9]+~','',$X);}function +number_type(){return'((?$W){unset($Te[$z][$ad]);if(is_array($W)){$Te[$z][stripslashes($ad)]=$W;$Te[]=&$Te[$z][stripslashes($ad)];}else$Te[$z][stripslashes($ad)]=($kc?$W:stripslashes($W));}}}}function +bracket_escape($Kc,$ua=false){static$vg=array(':'=>':1',']'=>':2','['=>':3','"'=>':4');return +strtr($Kc,($ua?array_flip($vg):$vg));}function +min_version($Xg,$td="",$g=null){global$f;if(!$g)$g=$f;$yf=$g->server_info;if($td&&preg_match('~([\d.]+)-MariaDB~',$yf,$C)){$yf=$C[1];$Xg=$td;}return(version_compare($yf,$Xg)>=0);}function +charset($f){return(min_version("5.5.3",0,$f)?"utf8mb4":"utf8");}function +script($Ff,$ug="\n"){return"$Ff$ug";}function +script_src($Mg){return"\n";}function +nonce(){return' nonce="'.get_nonce().'"';}function +target_blank(){return' target="_blank" rel="noreferrer noopener"';}function +h($Q){return +str_replace("\0","�",htmlspecialchars($Q,ENT_QUOTES,'utf-8'));}function +nl_br($Q){return +str_replace("\n","
    ",$Q);}function +checkbox($F,$Y,$Fa,$ed="",$Yd="",$Ja="",$fd=""){$K="".($Yd?script("qsl('input').onclick = function () { $Yd };",""):"");return($ed!=""||$Ja?"$K".h($ed)."":$K);}function +optionlist($de,$tf=null,$Qg=false){$K="";foreach($de +as$ad=>$W){$ee=array($ad=>$W);if(is_array($W)){$K.='';$ee=$W;}foreach($ee +as$z=>$X)$K.=''.h($X);if(is_array($W))$K.='';}return$K;}function +html_select($F,$de,$Y="",$Xd=true,$fd=""){if($Xd)return"".(is_string($Xd)?script("qsl('select').onchange = function () { $Xd };",""):"");$K="";foreach($de +as$z=>$X)$K.="";return$K;}function +select_input($ra,$de,$Y="",$Xd="",$Ee=""){$cg=($de?"select":"input");return"<$cg$ra".($de?">

    ","$md",script("qsl('a').onclick = partial(toggle, 'fieldset-$v');",""),"","
    \n";}function +selectSearchPrint($Z,$e,$x){print_fieldset("search",'Rechercher',$Z);foreach($x +as$u=>$w){if($w["type"]=="FULLTEXT"){echo"
    (".implode(", ",array_map('h',$w["columns"])).") AGAINST"," ",script("qsl('input').oninput = selectFieldChange;",""),checkbox("boolean[$u]",1,isset($_GET["boolean"][$u]),"BOOL"),"
    \n";}}$Da="this.parentNode.firstChild.onchange();";foreach(array_merge((array)$_GET["where"],array(array()))as$u=>$X){if(!$X||("$X[col]$X[val]"!=""&&in_array($X["op"],$this->operators))){echo"
    ".select_input(" name='where[$u][col]'",$e,$X["col"],($X?"selectFieldChange":"selectAddRow"),"(".'n\'importe où'.")"),html_select("where[$u][op]",$this->operators,$X["op"],$Da),"",script("mixin(qsl('input'), {oninput: function () { $Da }, onkeydown: selectSearchKeydown, onsearch: selectSearchSearch});",""),"
    \n";}}echo"\n";}function +selectOrderPrint($fe,$e,$x){print_fieldset("sort",'Trier',$fe);$u=0;foreach((array)$_GET["order"]as$z=>$X){if($X!=""){echo"
    ".select_input(" name='order[$u]'",$e,$X,"selectFieldChange"),checkbox("desc[$u]",1,isset($_GET["desc"][$z]),'décroissant')."
    \n";$u++;}}echo"
    ".select_input(" name='order[$u]'",$e,"","selectAddRow"),checkbox("desc[$u]",1,false,'décroissant')."
    \n","\n";}function +selectLimitPrint($_){echo"
    ".'Limite'."
    ";echo"",script("qsl('input').oninput = selectFieldChange;",""),"
    \n";}function +selectLengthPrint($ig){if($ig!==null){echo"
    ".'Longueur du texte'."
    ","","
    \n";}}function +selectActionPrint($x){echo"
    ".'Action'."
    ",""," ","\n","var indexColumns = ";$e=array();foreach($x +as$w){$gb=reset($w["columns"]);if($w["type"]!="FULLTEXT"&&$gb)$e[$gb]=1;}$e[""]=1;foreach($e +as$z=>$X)json_row($z);echo";\n","selectFieldChange.call(qs('#form')['select']);\n","\n","
    \n";}function +selectCommandPrint(){return!information_schema(DB);}function +selectImportPrint(){return!information_schema(DB);}function +selectEmailPrint($Lb,$e){}function +selectColumnsProcess($e,$x){global$uc,$yc;$N=array();$t=array();foreach((array)$_GET["columns"]as$z=>$X){if($X["fun"]=="count"||($X["col"]!=""&&(!$X["fun"]||in_array($X["fun"],$uc)||in_array($X["fun"],$yc)))){$N[$z]=apply_sql_function($X["fun"],($X["col"]!=""?idf_escape($X["col"]):"*"));if(!in_array($X["fun"],$yc))$t[]=$N[$z];}}return +array($N,$t);}function +selectSearchProcess($n,$x){global$f,$k;$K=array();foreach($x +as$u=>$w){if($w["type"]=="FULLTEXT"&&$_GET["fulltext"][$u]!="")$K[]="MATCH (".implode(", ",array_map('idf_escape',$w["columns"])).") AGAINST (".q($_GET["fulltext"][$u]).(isset($_GET["boolean"][$u])?" IN BOOLEAN MODE":"").")";}foreach((array)$_GET["where"]as$z=>$X){if("$X[col]$X[val]"!=""&&in_array($X["op"],$this->operators)){$Me="";$Va=" $X[op]";if(preg_match('~IN$~',$X["op"])){$Nc=process_length($X["val"]);$Va.=" ".($Nc!=""?$Nc:"(NULL)");}elseif($X["op"]=="SQL")$Va=" $X[val]";elseif($X["op"]=="LIKE %%")$Va=" LIKE ".$this->processInput($n[$X["col"]],"%$X[val]%");elseif($X["op"]=="ILIKE %%")$Va=" ILIKE ".$this->processInput($n[$X["col"]],"%$X[val]%");elseif($X["op"]=="FIND_IN_SET"){$Me="$X[op](".q($X["val"]).", ";$Va=")";}elseif(!preg_match('~NULL$~',$X["op"]))$Va.=" ".$this->processInput($n[$X["col"]],$X["val"]);if($X["col"]!="")$K[]=$Me.$k->convertSearch(idf_escape($X["col"]),$X,$n[$X["col"]]).$Va;else{$Qa=array();foreach($n +as$F=>$m){if((preg_match('~^[-\d.'.(preg_match('~IN$~',$X["op"])?',':'').']+$~',$X["val"])||!preg_match('~'.number_type().'|bit~',$m["type"]))&&(!preg_match("~[\x80-\xFF]~",$X["val"])||preg_match('~char|text|enum|set~',$m["type"]))&&(!preg_match('~date|timestamp~',$m["type"])||preg_match('~^\d+-\d+-\d+~',$X["val"])))$Qa[]=$Me.$k->convertSearch(idf_escape($F),$X,$m).$Va;}$K[]=($Qa?"(".implode(" OR ",$Qa).")":"1 = 0");}}}return$K;}function +selectOrderProcess($n,$x){$K=array();foreach((array)$_GET["order"]as$z=>$X){if($X!="")$K[]=(preg_match('~^((COUNT\(DISTINCT |[A-Z0-9_]+\()(`(?:[^`]|``)+`|"(?:[^"]|"")+")\)|COUNT\(\*\))$~',$X)?$X:idf_escape($X)).(isset($_GET["desc"][$z])?" DESC":"");}return$K;}function +selectLimitProcess(){return(isset($_GET["limit"])?$_GET["limit"]:"50");}function +selectLengthProcess(){return(isset($_GET["text_length"])?$_GET["text_length"]:"100");}function +selectEmailProcess($Z,$pc){return +false;}function +selectQueryBuild($N,$Z,$t,$fe,$_,$G){return"";}function +messageQuery($I,$jg,$fc=false){global$y,$k;restart_session();$Fc=&get_session("queries");if(!$Fc[$_GET["db"]])$Fc[$_GET["db"]]=array();if(strlen($I)>1e6)$I=preg_replace('~[\x80-\xFF]+$~','',substr($I,0,1e6))."\n…";$Fc[$_GET["db"]][]=array($I,time(),$jg);$Jf="sql-".count($Fc[$_GET["db"]]);$K="".'Requête SQL'."\n";if(!$fc&&($ch=$k->warnings())){$v="warnings-".count($Fc[$_GET["db"]]);$K="".'Warnings'.", $K\n";}return" ".@date("H:i:s").""." $K';}function +editRowPrint($R,$n,$L,$Kg){}function +editFunctions($m){global$Gb;$K=($m["null"]?"NULL/":"");$Kg=isset($_GET["select"])||where($_GET);foreach($Gb +as$z=>$uc){if(!$z||(!isset($_GET["call"])&&$Kg)){foreach($uc +as$Be=>$X){if(!$Be||preg_match("~$Be~",$m["type"]))$K.="/$X";}}if($z&&!preg_match('~set|blob|bytea|raw|file|bool~',$m["type"]))$K.="/SQL";}if($m["auto_increment"]&&!$Kg)$K='Incrément automatique';return +explode("/",$K);}function +editInput($R,$m,$ra,$Y){if($m["type"]=="enum")return(isset($_GET["select"])?" ":"").($m["null"]?" ":"").enum_input("radio",$ra,$m,$Y,0);return"";}function +editHint($R,$m,$Y){return"";}function +processInput($m,$Y,$s=""){if($s=="SQL")return$Y;$F=$m["field"];$K=q($Y);if(preg_match('~^(now|getdate|uuid)$~',$s))$K="$s()";elseif(preg_match('~^current_(date|timestamp)$~',$s))$K=$s;elseif(preg_match('~^([+-]|\|\|)$~',$s))$K=idf_escape($F)." $s $K";elseif(preg_match('~^[+-] interval$~',$s))$K=idf_escape($F)." $s ".(preg_match("~^(\\d+|'[0-9.: -]') [A-Z_]+\$~i",$Y)?$Y:$K);elseif(preg_match('~^(addtime|subtime|concat)$~',$s))$K="$s(".idf_escape($F).", $K)";elseif(preg_match('~^(md5|sha1|password|encrypt)$~',$s))$K="$s($K)";return +unconvert_field($m,$K);}function +dumpOutput(){$K=array('text'=>'ouvrir','file'=>'enregistrer');if(function_exists('gzencode'))$K['gz']='gzip';return$K;}function +dumpFormat(){return +array('sql'=>'SQL','csv'=>'CSV,','csv;'=>'CSV;','tsv'=>'TSV');}function +dumpDatabase($j){}function +dumpTable($R,$Pf,$Yc=0){if($_POST["format"]!="sql"){echo"\xef\xbb\xbf";if($Pf)dump_csv(array_keys(fields($R)));}else{if($Yc==2){$n=array();foreach(fields($R)as$F=>$m)$n[]=idf_escape($F)." $m[full_type]";$h="CREATE TABLE ".table($R)." (".implode(", ",$n).")";}else$h=create_sql($R,$_POST["auto_increment"],$Pf);set_utf8mb4($h);if($Pf&&$h){if($Pf=="DROP+CREATE"||$Yc==1)echo"DROP ".($Yc==2?"VIEW":"TABLE")." IF EXISTS ".table($R).";\n";if($Yc==1)$h=remove_definer($h);echo"$h;\n\n";}}}function +dumpData($R,$Pf,$I){global$f,$y;$wd=($y=="sqlite"?0:1048576);if($Pf){if($_POST["format"]=="sql"){if($Pf=="TRUNCATE+INSERT")echo +truncate_sql($R).";\n";$n=fields($R);}$J=$f->query($I,1);if($J){$Sc="";$Ca="";$cd=array();$Rf="";$ic=($R!=''?'fetch_assoc':'fetch_row');while($L=$J->$ic()){if(!$cd){$Ug=array();foreach($L +as$X){$m=$J->fetch_field();$cd[]=$m->name;$z=idf_escape($m->name);$Ug[]="$z = VALUES($z)";}$Rf=($Pf=="INSERT+UPDATE"?"\nON DUPLICATE KEY UPDATE ".implode(", ",$Ug):"").";\n";}if($_POST["format"]!="sql"){if($Pf=="table"){dump_csv($cd);$Pf="INSERT";}dump_csv($L);}else{if(!$Sc)$Sc="INSERT INTO ".table($R)." (".implode(", ",array_map('idf_escape',$cd)).") VALUES";foreach($L +as$z=>$X){$m=$n[$z];$L[$z]=($X!==null?unconvert_field($m,preg_match(number_type(),$m["type"])&&!preg_match('~\[~',$m["full_type"])&&is_numeric($X)?$X:q(($X===false?0:$X))):"NULL");}$pf=($wd?"\n":" ")."(".implode(",\t",$L).")";if(!$Ca)$Ca=$Sc.$pf;elseif(strlen($Ca)+4+strlen($pf)+strlen($Rf)<$wd)$Ca.=",$pf";else{echo$Ca.$Rf;$Ca=$Sc.$pf;}}}if($Ca)echo$Ca.$Rf;}elseif($_POST["format"]=="sql")echo"-- ".str_replace("\n"," ",$f->error)."\n";}}function +dumpFilename($Jc){return +friendly_url($Jc!=""?$Jc:(SERVER!=""?SERVER:"localhost"));}function +dumpHeaders($Jc,$Id=false){$qe=$_POST["output"];$bc=(preg_match('~sql~',$_POST["format"])?"sql":($Id?"tar":"csv"));header("Content-Type: ".($qe=="gz"?"application/x-gzip":($bc=="tar"?"application/x-tar":($bc=="sql"||$qe!="file"?"text/plain":"text/csv")."; charset=utf-8")));if($qe=="gz")ob_start('ob_gzencode',1e6);return$bc;}function +importServerPath(){return"adminer.sql";}function +homepage(){echo'

    +',$this->name(),' ',$da,' +',(version_compare($da,$_COOKIE["adminer_version"])<0?h($_COOKIE["adminer_version"]):""),' +

    +';if($Hd=="auth"){$qe="";foreach((array)$_SESSION["pwds"]as$Wg=>$zf){foreach($zf +as$O=>$Sg){foreach($Sg +as$Rg=>$_e){if($_e!==null){$mb=$_SESSION["db"][$Wg][$O][$Rg];foreach(($mb?array_keys($mb):array(""))as$j)$qe.="
  • ($zb[$Wg]) ".h($Rg.($O!=""?"@".$this->serverName($O):"").($j!=""?" - $j":""))."\n";}}}}if($qe)echo"
      \n$qe
    \n".script("mixin(qs('#logins'), {onmouseover: menuOver, onmouseout: menuOut});");}else{$T=array();if($_GET["ns"]!==""&&!$Hd&&DB!=""){$f->select_db(DB);$T=table_status('',true);}echo +script_src(preg_replace("~\\?.*~","",ME)."?file=jush.js&version=4.8.1");if(support("sql")){echo' +';if($T){$qd=array();foreach($T +as$R=>$V)$qd[]=preg_quote($R,'/');echo"var jushLinks = { $y: [ '".js_escape(ME).(support("table")?"table=":"select=")."\$&', /\\b(".implode("|",$qd).")\\b/g ] };\n";foreach(array("bac","bra","sqlite_quo","mssql_bra")as$X)echo"jushLinks.$X = jushLinks.$y;\n";}$yf=$f->server_info;echo'bodyLoad(\'',(is_object($f)?preg_replace('~^(\d\.?\d).*~s','\1',$yf):""),'\'',(preg_match('~MariaDB~',$yf)?", true":""),'); + +';}$this->databasesPrint($Hd);if(DB==""||!$Hd){echo"

    ".'Aucune table.'."\n";else$this->tablesPrint($T);}}}function +databasesPrint($Hd){global$b,$f;$i=$this->databases();if(DB&&$i&&!in_array(DB,$i))array_unshift($i,DB);echo'

    +

    +';hidden_fields_get();$kb=script("mixin(qsl('select'), {onmousedown: dbMouseDown, onchange: dbChange});");echo"".'DB'.": ".($i?"$kb":"\n"),"\n";foreach(array("import","sql","schema","dump","privileges")as$X){if(isset($_GET[$X])){echo"";break;}}echo"

    \n";}function +tablesPrint($T){echo"
      ".script("mixin(qs('#tables'), {onmouseover: menuOver, onmouseout: menuOut});");foreach($T +as$R=>$Mf){$F=$this->tableName($Mf);if($F!=""){echo'
    • ".'select'." ",(support("table")||support("indexes")?'$F":"$F")."\n";}}echo"
    \n";}}$b=(function_exists('adminer_object')?adminer_object():new +Adminer);$Wa=driver_config();$Le=$Wa['possible_drivers'];$y=$Wa['jush'];$Cg=$Wa['types'];$Of=$Wa['structured_types'];$Jg=$Wa['unsigned'];$ae=$Wa['operators'];$uc=$Wa['functions'];$yc=$Wa['grouping'];$Gb=$Wa['edit_functions'];if($b->operators===null)$b->operators=$ae;define("SERVER",$_GET[DRIVER]);define("DB",$_GET["db"]);define("ME",preg_replace('~\?.*~','',relative_uri()).'?'.(sid()?SID.'&':'').(SERVER!==null?DRIVER."=".urlencode(SERVER).'&':'').(isset($_GET["username"])?"username=".urlencode($_GET["username"]).'&':'').(DB!=""?'db='.urlencode(DB).'&'.(isset($_GET["ns"])?"ns=".urlencode($_GET["ns"])."&":""):''));$da="4.8.1";function +page_header($mg,$l="",$Ba=array(),$ng=""){global$ba,$da,$b,$zb,$y;page_headers();if(is_ajax()&&$l){page_messages($l);exit;}$og=$mg.($ng!=""?": $ng":"");$pg=strip_tags($og.(SERVER!=""&&SERVER!="localhost"?h(" - ".SERVER):"")." - ".$b->name());echo' + + + +',$pg,' + +',script_src(preg_replace("~\\?.*~","",ME)."?file=functions.js&version=4.8.1");if($b->head()){echo' + +';foreach($b->css()as$eb){echo' +';}}echo' + +';$o=get_temp_dir()."/adminer.version";if(!$_COOKIE["adminer_version"]&&function_exists('openssl_verify')&&file_exists($o)&&filemtime($o)+86400>time()){$Xg=unserialize(file_get_contents($o));$Ve="-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwqWOVuF5uw7/+Z70djoK +RlHIZFZPO0uYRezq90+7Amk+FDNd7KkL5eDve+vHRJBLAszF/7XKXe11xwliIsFs +DFWQlsABVZB3oisKCBEuI71J4kPH8dKGEWR9jDHFw3cWmoH3PmqImX6FISWbG3B8 +h7FIx3jEaw5ckVPVTeo5JRm/1DZzJxjyDenXvBQ/6o9DgZKeNDgxwKzH+sw9/YCO +jHnq1cFpOIISzARlrHMa/43YfeNRAm/tsBXjSxembBPo7aQZLAWHmaj5+K19H10B +nCpz9Y++cipkVEiKRGih4ZEvjoFysEOdRLj6WiD/uUNky4xGeA6LaJqh5XpkFkcQ +fQIDAQAB +-----END PUBLIC KEY----- +";if(openssl_verify($Xg["version"],base64_decode($Xg["signature"]),$Ve)==1)$_COOKIE["adminer_version"]=$Xg["version"];}echo' +mixin(document.body, {onkeydown: bodyKeydown, onclick: bodyClick',(isset($_COOKIE["adminer_version"])?"":", onload: partial(verifyVersion, '$da', '".js_escape(ME)."', '".get_token()."')");?>}); +document.body.className = document.body.className.replace(/ nojs/, ' js'); +var offlineMessage = ' + + +',script("mixin(qs('#help'), {onmouseover: function () { helpOpen = 1; }, onmouseout: helpMouseout});"),' +
    +';if($Ba!==null){$A=substr(preg_replace('~\b(username|db|ns)=[^&]*&~','',ME),0,-1);echo'

    $og

    \n","\n";restart_session();page_messages($l);$i=&get_session("dbs");if(DB!=""&&$i&&!in_array(DB,$i,true))$i=null;stop_session();define("PAGE_HEADER",1);}function +page_headers(){global$b;header("Content-Type: text/html; charset=utf-8");header("Cache-Control: no-cache");header("X-Frame-Options: deny");header("X-XSS-Protection: 0");header("X-Content-Type-Options: nosniff");header("Referrer-Policy: origin-when-cross-origin");foreach($b->csp()as$db){$Dc=array();foreach($db +as$z=>$X)$Dc[]="$z $X";header("Content-Security-Policy: ".implode("; ",$Dc));}$b->headers();}function +csp(){return +array(array("script-src"=>"'self' 'unsafe-inline' 'nonce-".get_nonce()."' 'strict-dynamic'","connect-src"=>"'self'","frame-src"=>"https://www.adminer.org","object-src"=>"'none'","base-uri"=>"'none'","form-action"=>"'self'",),);}function +get_nonce(){static$Nd;if(!$Nd)$Nd=base64_encode(rand_string());return$Nd;}function +page_messages($l){$Lg=preg_replace('~^[^?]*~','',$_SERVER["REQUEST_URI"]);$Ed=$_SESSION["messages"][$Lg];if($Ed){echo"
    ".implode("
    \n
    ",$Ed)."
    ".script("messagesPrint();");unset($_SESSION["messages"][$Lg]);}if($l)echo"
    $l
    \n";}function +page_footer($Hd=""){global$b,$U;echo'
    + +';if($Hd!="auth"){echo'
    +

    + + +

    +
    +';}echo' +',script("setupSubmitHighlight(document);");}function +int32($E){while($E>=2147483648)$E-=4294967296;while($E<=-2147483649)$E+=4294967296;return(int)$E;}function +long2str($W,$bh){$pf='';foreach($W +as$X)$pf.=pack('V',$X);if($bh)return +substr($pf,0,end($W));return$pf;}function +str2long($pf,$bh){$W=array_values(unpack('V*',str_pad($pf,4*ceil(strlen($pf)/4),"\0")));if($bh)$W[]=strlen($pf);return$W;}function +xxtea_mx($ih,$hh,$Sf,$ad){return +int32((($ih>>5&0x7FFFFFF)^$hh<<2)+(($hh>>3&0x1FFFFFFF)^$ih<<4))^int32(($Sf^$hh)+($ad^$ih));}function +encrypt_string($Nf,$z){if($Nf=="")return"";$z=array_values(unpack("V*",pack("H*",md5($z))));$W=str2long($Nf,true);$E=count($W)-1;$ih=$W[$E];$hh=$W[0];$H=floor(6+52/($E+1));$Sf=0;while($H-->0){$Sf=int32($Sf+0x9E3779B9);$Fb=$Sf>>2&3;for($re=0;$re<$E;$re++){$hh=$W[$re+1];$Jd=xxtea_mx($ih,$hh,$Sf,$z[$re&3^$Fb]);$ih=int32($W[$re]+$Jd);$W[$re]=$ih;}$hh=$W[0];$Jd=xxtea_mx($ih,$hh,$Sf,$z[$re&3^$Fb]);$ih=int32($W[$E]+$Jd);$W[$E]=$ih;}return +long2str($W,false);}function +decrypt_string($Nf,$z){if($Nf=="")return"";if(!$z)return +false;$z=array_values(unpack("V*",pack("H*",md5($z))));$W=str2long($Nf,false);$E=count($W)-1;$ih=$W[$E];$hh=$W[0];$H=floor(6+52/($E+1));$Sf=int32($H*0x9E3779B9);while($Sf){$Fb=$Sf>>2&3;for($re=$E;$re>0;$re--){$ih=$W[$re-1];$Jd=xxtea_mx($ih,$hh,$Sf,$z[$re&3^$Fb]);$hh=int32($W[$re]-$Jd);$W[$re]=$hh;}$ih=$W[$E];$Jd=xxtea_mx($ih,$hh,$Sf,$z[$re&3^$Fb]);$hh=int32($W[0]-$Jd);$W[0]=$hh;$Sf=int32($Sf-0x9E3779B9);}return +long2str($W,true);}$f='';$Cc=$_SESSION["token"];if(!$Cc)$_SESSION["token"]=rand(1,1e6);$U=get_token();$De=array();if($_COOKIE["adminer_permanent"]){foreach(explode(" ",$_COOKIE["adminer_permanent"])as$X){list($z)=explode(":",$X);$De[$z]=$X;}}function +add_invalid_login(){global$b;$r=file_open_lock(get_temp_dir()."/adminer.invalid");if(!$r)return;$Uc=unserialize(stream_get_contents($r));$jg=time();if($Uc){foreach($Uc +as$Vc=>$X){if($X[0]<$jg)unset($Uc[$Vc]);}}$Tc=&$Uc[$b->bruteForceKey()];if(!$Tc)$Tc=array($jg+30*60,0);$Tc[1]++;file_write_unlock($r,serialize($Uc));}function +check_invalid_login(){global$b;$Uc=unserialize(@file_get_contents(get_temp_dir()."/adminer.invalid"));$Tc=($Uc?$Uc[$b->bruteForceKey()]:array());$Md=($Tc[1]>29?$Tc[0]-time():0);if($Md>0)auth_error(lang(array('Trop de connexions échouées, essayez à nouveau dans %d minute.','Trop de connexions échouées, essayez à nouveau dans %d minutes.'),ceil($Md/60)));}$sa=$_POST["auth"];if($sa){session_regenerate_id();$Wg=$sa["driver"];$O=$sa["server"];$Rg=$sa["username"];$_e=(string)$sa["password"];$j=$sa["db"];set_password($Wg,$O,$Rg,$_e);$_SESSION["db"][$Wg][$O][$Rg][$j]=true;if($sa["permanent"]){$z=base64_encode($Wg)."-".base64_encode($O)."-".base64_encode($Rg)."-".base64_encode($j);$Re=$b->permanentLogin(true);$De[$z]="$z:".base64_encode($Re?encrypt_string($_e,$Re):"");cookie("adminer_permanent",implode(" ",$De));}if(count($_POST)==1||DRIVER!=$Wg||SERVER!=$O||$_GET["username"]!==$Rg||DB!=$j)redirect(auth_url($Wg,$O,$Rg,$j));}elseif($_POST["logout"]&&(!$Cc||verify_token())){foreach(array("pwds","db","dbs","queries")as$z)set_session($z,null);unset_permanent();redirect(substr(preg_replace('~\b(username|db|ns)=[^&]*&~','',ME),0,-1),'Au revoir !'.' '.'Thanks for using Adminer, consider donating.');}elseif($De&&!$_SESSION["pwds"]){session_regenerate_id();$Re=$b->permanentLogin();foreach($De +as$z=>$X){list(,$Ia)=explode(":",$X);list($Wg,$O,$Rg,$j)=array_map('base64_decode',explode("-",$z));set_password($Wg,$O,$Rg,decrypt_string(base64_decode($Ia),$Re));$_SESSION["db"][$Wg][$O][$Rg][$j]=true;}}function +unset_permanent(){global$De;foreach($De +as$z=>$X){list($Wg,$O,$Rg,$j)=array_map('base64_decode',explode("-",$z));if($Wg==DRIVER&&$O==SERVER&&$Rg==$_GET["username"]&&$j==DB)unset($De[$z]);}cookie("adminer_permanent",implode(" ",$De));}function +auth_error($l){global$b,$Cc;$_f=session_name();if(isset($_GET["username"])){header("HTTP/1.1 403 Forbidden");if(($_COOKIE[$_f]||$_GET[$_f])&&!$Cc)$l='Session expirée, veuillez vous authentifier à nouveau.';else{restart_session();add_invalid_login();$_e=get_password();if($_e!==null){if($_e===false)$l.=($l?'
    ':'').sprintf('Le mot de passe a expiré. Implémentez la méthode %s afin de le rendre permanent.',target_blank(),'permanentLogin()');set_password(DRIVER,SERVER,$_GET["username"],null);}unset_permanent();}}if(!$_COOKIE[$_f]&&$_GET[$_f]&&ini_bool("session.use_only_cookies"))$l='Veuillez activer les sessions.';$ue=session_get_cookie_params();cookie("adminer_key",($_COOKIE["adminer_key"]?$_COOKIE["adminer_key"]:rand_string()),$ue["lifetime"]);page_header('Authentification',$l,null);echo"
    \n","
    ";if(hidden_fields($_POST,array("auth")))echo"

    ".'The action will be performed after successful login with the same credentials.'."\n";echo"

    \n";$b->loginForm();echo"
    \n";page_footer("auth");exit;}if(isset($_GET["username"])&&!class_exists("Min_DB")){unset($_SESSION["pwds"][DRIVER]);unset_permanent();page_header('Extension introuvable',sprintf('Aucune des extensions PHP supportées (%s) n\'est disponible.',implode(", ",$Le)),false);page_footer("auth");exit;}stop_session(true);if(isset($_GET["username"])&&is_string(get_password())){list($Hc,$He)=explode(":",SERVER,2);if(preg_match('~^\s*([-+]?\d+)~',$He,$C)&&($C[1]<1024||$C[1]>65535))auth_error('Connecting to privileged ports is not allowed.');check_invalid_login();$f=connect();$k=new +Min_Driver($f);}$rd=null;if(!is_object($f)||($rd=$b->login($_GET["username"],get_password()))!==true){$l=(is_string($f)?h($f):(is_string($rd)?$rd:'Authentification échouée.'));auth_error($l.(preg_match('~^ | $~',get_password())?'
    '.'There is a space in the input password which might be the cause.':''));}if($_POST["logout"]&&$Cc&&!verify_token()){page_header('Déconnexion','Token CSRF invalide. Veuillez renvoyer le formulaire.');page_footer("db");exit;}if($sa&&$_POST["token"])$_POST["token"]=$U;$l='';if($_POST){if(!verify_token()){$Pc="max_input_vars";$_d=ini_get($Pc);if(extension_loaded("suhosin")){foreach(array("suhosin.request.max_vars","suhosin.post.max_vars")as$z){$X=ini_get($z);if($X&&(!$_d||$X<$_d)){$Pc=$z;$_d=$X;}}}$l=(!$_POST["token"]&&$_d?sprintf('Le nombre maximum de champs est dépassé. Veuillez augmenter %s.',"'$Pc'"):'Token CSRF invalide. Veuillez renvoyer le formulaire.'.' '.'Si vous n\'avez pas envoyé cette requête depuis Adminer, alors fermez cette page.');}}elseif($_SERVER["REQUEST_METHOD"]=="POST"){$l=sprintf('Données POST trop grandes. Réduisez la taille des données ou augmentez la valeur de %s dans la configuration de PHP.',"'post_max_size'");if(isset($_GET["sql"]))$l.=' '.'Vous pouvez uploader un gros fichier SQL par FTP et ensuite l\'importer depuis le serveur.';}function +select($J,$g=null,$ie=array(),$_=0){global$y;$qd=array();$x=array();$e=array();$_a=array();$Cg=array();$K=array();odd('');for($u=0;(!$_||$u<$_)&&($L=$J->fetch_row());$u++){if(!$u){echo"
    \n","\n","";for($Zc=0;$Zcfetch_field();$F=$m->name;$he=$m->orgtable;$ge=$m->orgname;$K[$m->table]=$he;if($ie&&$y=="sql")$qd[$Zc]=($F=="table"?"table=":($F=="possible_keys"?"indexes=":null));elseif($he!=""){if(!isset($x[$he])){$x[$he]=array();foreach(indexes($he,$g)as$w){if($w["type"]=="PRIMARY"){$x[$he]=array_flip($w["columns"]);break;}}$e[$he]=$x[$he];}if(isset($e[$he][$ge])){unset($e[$he][$ge]);$x[$he][$ge]=$Zc;$qd[$Zc]=$he;}}if($m->charsetnr==63)$_a[$Zc]=true;$Cg[$Zc]=$m->type;echo"name!=$ge?" title='".h(($he!=""?"$he.":"").$ge)."'":"").">".h($F).($ie?'':"");}echo"\n";}echo"";foreach($L +as$z=>$X){$A="";if(isset($qd[$z])&&!$e[$qd[$z]]){if($ie&&$y=="sql"){$R=$L[array_search("table=",$qd)];$A=ME.$qd[$z].urlencode($ie[$R]!=""?$ie[$R]:$R);}else{$A=ME."edit=".urlencode($qd[$z]);foreach($x[$qd[$z]]as$Ma=>$Zc)$A.="&where".urlencode("[".bracket_escape($Ma)."]")."=".urlencode($L[$Zc]);}}elseif(is_url($X))$A=$X;if($X===null)$X="NULL";elseif($_a[$z]&&!is_utf8($X))$X="".lang(array('%d octet','%d octets'),strlen($X))."";else{$X=h($X);if($Cg[$z]==254)$X="$X";}if($A)$X="$X";echo"
    $X";}}echo($u?"
    \n
    ":"

    ".'Aucun résultat.')."\n";return$K;}function +referencable_primary($vf){$K=array();foreach(table_status('',true)as$Wf=>$R){if($Wf!=$vf&&fk_support($R)){foreach(fields($Wf)as$m){if($m["primary"]){if($K[$Wf]){unset($K[$Wf]);break;}$K[$Wf]=$m;}}}}return$K;}function +adminer_settings(){parse_str($_COOKIE["adminer_settings"],$Bf);return$Bf;}function +adminer_setting($z){$Bf=adminer_settings();return$Bf[$z];}function +set_adminer_settings($Bf){return +cookie("adminer_settings",http_build_query($Bf+adminer_settings()));}function +textarea($F,$Y,$M=10,$Qa=80){global$y;echo"";}function +edit_type($z,$m,$Pa,$q=array(),$ec=array()){global$Of,$Cg,$Jg,$Wd;$V=$m["type"];echo'',"',($Jg?"':''),(isset($m['on_update'])?"':''),($q?" ":" ");}function +process_length($nd){global$Qb;return(preg_match("~^\\s*\\(?\\s*$Qb(?:\\s*,\\s*$Qb)*+\\s*\\)?\\s*\$~",$nd)&&preg_match_all("~$Qb~",$nd,$ud)?"(".implode(",",$ud[0]).")":preg_replace('~^[0-9].*~','(\0)',preg_replace('~[^-0-9,+()[\]]~','',$nd)));}function +process_type($m,$Na="COLLATE"){global$Jg;return" $m[type]".process_length($m["length"]).(preg_match(number_type(),$m["type"])&&in_array($m["unsigned"],$Jg)?" $m[unsigned]":"").(preg_match('~char|text|enum|set~',$m["type"])&&$m["collation"]?" $Na ".q($m["collation"]):"");}function +process_field($m,$Bg){return +array(idf_escape(trim($m["field"])),process_type($Bg),($m["null"]?" NULL":" NOT NULL"),default_value($m),(preg_match('~timestamp|datetime~',$m["type"])&&$m["on_update"]?" ON UPDATE $m[on_update]":""),(support("comment")&&$m["comment"]!=""?" COMMENT ".q($m["comment"]):""),($m["auto_increment"]?auto_increment():null),);}function +default_value($m){$ob=$m["default"];return($ob===null?"":" DEFAULT ".(preg_match('~char|binary|text|enum|set~',$m["type"])||preg_match('~^(?![a-z])~i',$ob)?q($ob):$ob));}function +type_class($V){foreach(array('char'=>'text','date'=>'time|year','binary'=>'blob','enum'=>'set',)as$z=>$X){if(preg_match("~$z|$X~",$V))return" class='$z'";}}function +edit_fields($n,$Pa,$V="TABLE",$q=array()){global$Qc;$n=array_values($n);$pb=(($_POST?$_POST["defaults"]:adminer_setting("defaults"))?"":" class='hidden'");$Ua=(($_POST?$_POST["comments"]:adminer_setting("comments"))?"":" class='hidden'");echo' +';if($V=="PROCEDURE"){echo'';}echo'',($V=="TABLE"?'Nom de la colonne':'Nom du paramètre'),'Type',script("qs('#enum-edit').onblur = editingLengthBlur;"),'Longueur +','Options';if($V=="TABLE"){echo'NULL +AI',doc_link(array('sqlite'=>"autoinc.html",)),'Valeur par défaut +',(support("comment")?"".'Commentaire':"");}echo'',"".script("row_count = ".count($n).";"),' + +',script("mixin(qsl('tbody'), {onclick: editingClick, onkeydown: editingKeydown, oninput: editingInput});");foreach($n +as$u=>$m){$u++;$je=$m[($_POST?"orig":"field")];$wb=(isset($_POST["add"][$u-1])||(isset($m["field"])&&!$_POST["drop_col"][$u]))&&(support("drop_col")||$je=="");echo' +',($V=="PROCEDURE"?"".html_select("fields[$u][inout]",explode("|",$Qc),$m["inout"]):""),'';if($wb){echo'';}echo'';edit_type("fields[$u]",$m,$Pa,$q);if($V=="TABLE"){echo'',checkbox("fields[$u][null]",1,$m["null"],"","","block","label-null"),'',checkbox("fields[$u][has_default]",1,$m["has_default"],"","","","label-default"),'',(support("comment")?"":"");}echo"",(support("move_col")?" "." "." ":""),($je==""||support("drop_col")?"":"");}}function +process_fields(&$n){$Sd=0;if($_POST["up"]){$hd=0;foreach($n +as$z=>$m){if(key($_POST["up"])==$z){unset($n[$z]);array_splice($n,$hd,0,array($m));break;}if(isset($m["field"]))$hd=$Sd;$Sd++;}}elseif($_POST["down"]){$rc=false;foreach($n +as$z=>$m){if(isset($m["field"])&&$rc){unset($n[key($_POST["down"])]);array_splice($n,$Sd,0,array($rc));break;}if(key($_POST["down"])==$z)$rc=$m;$Sd++;}}elseif($_POST["add"]){$n=array_values($n);array_splice($n,key($_POST["add"]),0,array(array()));}elseif(!$_POST["drop_col"])return +false;return +true;}function +normalize_enum($C){return"'".str_replace("'","''",addcslashes(stripcslashes(str_replace($C[0][0].$C[0][0],$C[0][0],substr($C[0],1,-1))),'\\'))."'";}function +grant($vc,$Se,$e,$Vd){if(!$Se)return +true;if($Se==array("ALL PRIVILEGES","GRANT OPTION"))return($vc=="GRANT"?queries("$vc ALL PRIVILEGES$Vd WITH GRANT OPTION"):queries("$vc ALL PRIVILEGES$Vd")&&queries("$vc GRANT OPTION$Vd"));return +queries("$vc ".preg_replace('~(GRANT OPTION)\([^)]*\)~','\1',implode("$e, ",$Se).$e).$Vd);}function +drop_create($_b,$h,$Ab,$gg,$Cb,$B,$Dd,$Bd,$Cd,$Ud,$Ld){if($_POST["drop"])query_redirect($_b,$B,$Dd);elseif($Ud=="")query_redirect($h,$B,$Cd);elseif($Ud!=$Ld){$cb=queries($h);queries_redirect($B,$Bd,$cb&&queries($_b));if($cb)queries($Ab);}else +queries_redirect($B,$Bd,queries($gg)&&queries($Cb)&&queries($_b)&&queries($h));}function +create_trigger($Vd,$L){global$y;$lg=" $L[Timing] $L[Event]".(preg_match('~ OF~',$L["Event"])?" $L[Of]":"");return"CREATE TRIGGER ".idf_escape($L["Trigger"]).($y=="mssql"?$Vd.$lg:$lg.$Vd).rtrim(" $L[Type]\n$L[Statement]",";").";";}function +create_routine($nf,$L){global$Qc,$y;$P=array();$n=(array)$L["fields"];ksort($n);foreach($n +as$m){if($m["field"]!="")$P[]=(preg_match("~^($Qc)\$~",$m["inout"])?"$m[inout] ":"").idf_escape($m["field"]).process_type($m,"CHARACTER SET");}$qb=rtrim("\n$L[definition]",";");return"CREATE $nf ".idf_escape(trim($L["name"]))." (".implode(", ",$P).")".(isset($_GET["function"])?" RETURNS".process_type($L["returns"],"CHARACTER SET"):"").($L["language"]?" LANGUAGE $L[language]":"").($y=="pgsql"?" AS ".q($qb):"$qb;");}function +remove_definer($I){return +preg_replace('~^([A-Z =]+) DEFINER=`'.preg_replace('~@(.*)~','`@`(%|\1)',logged_user()).'`~','\1',$I);}function +format_foreign_key($p){global$Wd;$j=$p["db"];$Od=$p["ns"];return" FOREIGN KEY (".implode(", ",array_map('idf_escape',$p["source"])).") REFERENCES ".($j!=""&&$j!=$_GET["db"]?idf_escape($j).".":"").($Od!=""&&$Od!=$_GET["ns"]?idf_escape($Od).".":"").table($p["table"])." (".implode(", ",array_map('idf_escape',$p["target"])).")".(preg_match("~^($Wd)\$~",$p["on_delete"])?" ON DELETE $p[on_delete]":"").(preg_match("~^($Wd)\$~",$p["on_update"])?" ON UPDATE $p[on_update]":"");}function +tar_file($o,$qg){$K=pack("a100a8a8a8a12a12",$o,644,0,0,decoct($qg->size),decoct(time()));$Ha=8*32;for($u=0;$usend();echo +str_repeat("\0",511-($qg->size+511)%512);}function +ini_bytes($Pc){$X=ini_get($Pc);switch(strtolower(substr($X,-1))){case'g':$X*=1024;case'm':$X*=1024;case'k':$X*=1024;}return$X;}function +doc_link($Ae,$hg="?"){global$y,$f;$yf=$f->server_info;$Xg=preg_replace('~^(\d\.?\d).*~s','\1',$yf);$Ng=array('sql'=>"https://dev.mysql.com/doc/refman/$Xg/en/",'sqlite'=>"https://www.sqlite.org/",'pgsql'=>"https://www.postgresql.org/docs/$Xg/",'mssql'=>"https://msdn.microsoft.com/library/",'oracle'=>"https://www.oracle.com/pls/topic/lookup?ctx=db".preg_replace('~^.* (\d+)\.(\d+)\.\d+\.\d+\.\d+.*~s','\1\2',$yf)."&id=",);if(preg_match('~MariaDB~',$yf)){$Ng['sql']="https://mariadb.com/kb/en/library/";$Ae['sql']=(isset($Ae['mariadb'])?$Ae['mariadb']:str_replace(".html","/",$Ae['sql']));}return($Ae[$y]?"$hg":"");}function +ob_gzencode($Q){return +gzencode($Q);}function +db_size($j){global$f;if(!$f->select_db($j))return"?";$K=0;foreach(table_status()as$S)$K+=$S["Data_length"]+$S["Index_length"];return +format_number($K);}function +set_utf8mb4($h){global$f;static$P=false;if(!$P&&preg_match('~\butf8mb4~i',$h)){$P=true;echo"SET NAMES ".charset($f).";\n\n";}}function +connect_error(){global$b,$f,$U,$l,$zb;if(DB!=""){header("HTTP/1.1 404 Not Found");page_header('Base de données'.": ".h(DB),'Base de données invalide.',true);}else{if($_POST["db"]&&!$l)queries_redirect(substr(ME,0,-1),'Les bases de données ont été supprimées.',drop_databases($_POST["db"]));page_header('Sélectionner la base de données',$l,false);echo"

    ".sprintf('Version de %s : %s via l\'extension PHP %s',$zb[DRIVER],"".h($f->server_info)."","$f->extension")."\n","

    ".sprintf('Authentifié en tant que : %s',"".h(logged_user())."")."\n";$i=$b->databases();if($i){$rf=support("scheme");$Pa=collations();echo"

    \n","\n",script("mixin(qsl('table'), {onclick: tableClick, ondblclick: partialArg(tableClick, true)});"),"".(support("database")?"\n";$i=($_GET["dbsize"]?count_tables($i):array_flip($i));foreach($i +as$j=>$T){$mf=h(ME)."db=".urlencode($j);$v=h("Db-".$j);echo"".(support("database")?"
    ":"")."".'Base de données'." - ".'Rafraîchir'.""."".'Interclassement'."".'Tables'."".'Taille'." - ".'Calcul'."".script("qsl('a').onclick = partial(ajaxSetHtml, '".js_escape(ME)."script=connect');","")."
    ".checkbox("db[]",$j,in_array($j,(array)$_POST["db"]),"","","",$v):""),"".h($j)."";$Oa=h(db_collation($j,$Pa));echo"".(support("database")?"$Oa":$Oa),"".($_GET["dbsize"]?$T:"?")."","".($_GET["dbsize"]?db_size($j):"?"),"\n";}echo"
    \n",(support("database")?"\n":""),"\n","
    \n",script("tableCheck();");}}page_footer("db");}if(isset($_GET["status"]))$_GET["variables"]=$_GET["status"];if(isset($_GET["import"]))$_GET["sql"]=$_GET["import"];if(!(DB!=""?$f->select_db(DB):isset($_GET["sql"])||isset($_GET["dump"])||isset($_GET["database"])||isset($_GET["processlist"])||isset($_GET["privileges"])||isset($_GET["user"])||isset($_GET["variables"])||$_GET["script"]=="connect"||$_GET["script"]=="kill")){if(DB!=""||$_GET["refresh"]){restart_session();set_session("dbs",null);}connect_error();exit;}$Wd="RESTRICT|NO ACTION|CASCADE|SET NULL|SET DEFAULT";class +TmpFile{var$handler;var$size;function +__construct(){$this->handler=tmpfile();}function +write($Za){$this->size+=strlen($Za);fwrite($this->handler,$Za);}function +send(){fseek($this->handler,0);fpassthru($this->handler);fclose($this->handler);}}$Qb="'(?:''|[^'\\\\]|\\\\.)*'";$Qc="IN|OUT|INOUT";if(isset($_GET["select"])&&($_POST["edit"]||$_POST["clone"])&&!$_POST["save"])$_GET["edit"]=$_GET["select"];if(isset($_GET["download"])){$a=$_GET["download"];$n=fields($a);header("Content-Type: application/octet-stream");header("Content-Disposition: attachment; filename=".friendly_url("$a-".implode("_",$_GET["where"])).".".friendly_url($_GET["field"]));$N=array(idf_escape($_GET["field"]));$J=$k->select($a,$N,array(where($_GET,$n)),$N);$L=($J?$J->fetch_row():array());echo$k->value($L[0],$n[$_GET["field"]]);exit;}elseif(isset($_GET["table"])){$a=$_GET["table"];$n=fields($a);if(!$n)$l=error();$S=table_status1($a,true);$F=$b->tableName($S);page_header(($n&&is_view($S)?$S['Engine']=='materialized view'?'Vue matérialisée':'Vue':'Table').": ".($F!=""?$F:h($a)),$l);$b->selectLinks($S);$Ta=$S["Comment"];if($Ta!="")echo"

    ".'Commentaire'.": ".h($Ta)."\n";if($n)$b->tableStructurePrint($n);if(!is_view($S)){if(support("indexes")){echo"

    ".'Index'."

    \n";$x=indexes($a);if($x)$b->tableIndexesPrint($x);echo'

    ".'Clés étrangères'."

    \n";$q=foreign_keys($a);if($q){echo"\n","\n";foreach($q +as$F=>$p){echo"","
    ".'Source'."".'Cible'."".'ON DELETE'."".'ON UPDATE'."
    ".implode(", ",array_map('h',$p["source"]))."","".($p["db"]!=""?"".h($p["db"]).".":"").($p["ns"]!=""?"".h($p["ns"]).".":"").h($p["table"])."","(".implode(", ",array_map('h',$p["target"])).")","".h($p["on_delete"])."\n","".h($p["on_update"])."\n",''.'Modifier'.'';}echo"
    \n";}echo'

    ".'Déclencheurs'."

    \n";$Ag=triggers($a);if($Ag){echo"\n";foreach($Ag +as$z=>$X)echo"
    ".h($X[0])."".h($X[1])."".h($z)."".'Modifier'."\n";echo"
    \n";}echo'
    + +qs(\'#schema\').onselectstart = function () { return false; }; +var tablePos = {',implode(",",$Yf)."\n",'}; +var em = qs(\'#schema\').offsetHeight / ',$sg,'; +document.onmousemove = schemaMousemove; +document.onmouseup = partialArg(schemaMouseup, \'',js_escape(DB),'\'); + +';foreach($qf +as$F=>$R){echo"
    ",''.h($F)."",script("qsl('div').onmousedown = schemaMousedown;");foreach($R["fields"]as$m){$X=''.h($m["field"]).'';echo"
    ".($m["primary"]?"$X":$X);}foreach((array)$R["references"]as$eg=>$gf){foreach($gf +as$jd=>$cf){$kd=$jd-$Xf[$F][1];$u=0;foreach($cf[0]as$Ff)echo"\n
    ";}}foreach((array)$ff[$F]as$eg=>$gf){foreach($gf +as$jd=>$e){$kd=$jd-$Xf[$F][1];$u=0;foreach($e +as$dg)echo"\n
    ";}}echo"\n
    \n";}foreach($qf +as$F=>$R){foreach((array)$R["references"]as$eg=>$gf){foreach($gf +as$jd=>$cf){$Gd=$sg;$yd=-10;foreach($cf[0]as$z=>$Ff){$Je=$R["pos"][0]+$R["fields"][$Ff]["pos"];$Ke=$qf[$eg]["pos"][0]+$qf[$eg]["fields"][$cf[1][$z]]["pos"];$Gd=min($Gd,$Je,$Ke);$yd=max($yd,$Je,$Ke);}echo"
    \n";}}}echo'
    +
    + +';$lb=array('','USE','DROP+CREATE','CREATE');$Zf=array('','DROP+CREATE','CREATE');$ib=array('','TRUNCATE+INSERT','INSERT');if($y=="sql")$ib[]='INSERT+UPDATE';parse_str($_COOKIE["adminer_export"],$L);if(!$L)$L=array("output"=>"text","format"=>"sql","db_style"=>(DB!=""?"":"CREATE"),"table_style"=>"DROP+CREATE","data_style"=>"INSERT");if(!isset($L["events"])){$L["routines"]=$L["events"]=($_GET["dump"]=="");$L["triggers"]=$L["table_style"];}echo"
    ".'Sortie'."".html_select("output",$b->dumpOutput(),$L["output"],0)."\n";echo"
    ".'Format'."".html_select("format",$b->dumpFormat(),$L["format"],0)."\n";echo($y=="sqlite"?"":"
    ".'Base de données'."".html_select('db_style',$lb,$L["db_style"]).(support("routine")?checkbox("routines",1,$L["routines"],'Routines'):"").(support("event")?checkbox("events",1,$L["events"],'Évènements'):"")),"
    ".'Tables'."".html_select('table_style',$Zf,$L["table_style"]).checkbox("auto_increment",1,$L["auto_increment"],'Incrément automatique').(support("trigger")?checkbox("triggers",1,$L["triggers"],'Déclencheurs'):""),"
    ".'Données'."".html_select('data_style',$ib,$L["data_style"]),'
    +

    + + + +',script("qsl('table').onclick = dumpClick;");$Ne=array();if(DB!=""){$Fa=($a!=""?"":" checked");echo"","\n";$Zg="";$ag=tables_list();foreach($ag +as$F=>$V){$Me=preg_replace('~_.*~','',$F);$Fa=($a==""||$a==(substr($a,-1)=="%"?"$Me%":$F));$Qe="\n";$i=$b->databases();if($i){foreach($i +as$j){if(!information_schema($j)){$Me=preg_replace('~_.*~','',$j);echo"
    ".script("qs('#check-tables').onclick = partial(formCheck, /^tables\\[/);",""),"".script("qs('#check-data').onclick = partial(formCheck, /^data\\[/);",""),"
    ".checkbox("tables[]",$F,$Fa,$F,"","block");if($V!==null&&!preg_match('~table~i',$V))$Zg.="$Qe\n";else +echo"$Qe\n";$Ne[$Me]++;}echo$Zg;if($ag)echo +script("ajaxSetHtml('".js_escape(ME)."script=db');");}else{echo"
    ","",script("qs('#check-databases').onclick = partial(formCheck, /^databases\\[/);",""),"
    ".checkbox("databases[]",$j,$a==""||$a=="$Me%",$j,"","block")."\n";$Ne[$Me]++;}}}else +echo"
    ";}echo'
    +

    +';$lc=true;foreach($Ne +as$z=>$X){if($z!=""&&$X>1){echo($lc?"

    ":" ")."".h($z)."";$lc=false;}}}elseif(isset($_GET["sql"])){if(!$l&&$_POST["export"]){dump_headers("sql");$b->dumpTable("","");$b->dumpData("","table",$_POST["query"]);exit;}restart_session();$Gc=&get_session("queries");$Fc=&$Gc[DB];if(!$l&&$_POST["clear"]){$Fc=array();redirect(remove_from_uri("history"));}page_header((isset($_GET["import"])?'Importer':'Requête SQL'),$l);if(!$l&&$_POST){$r=false;if(!isset($_GET["import"]))$I=$_POST["query"];elseif($_POST["webfile"]){$If=$b->importServerPath();$r=@fopen((file_exists($If)?$If:"compress.zlib://$If.gz"),"rb");$I=($r?fread($r,1e6):false);}else$I=get_file("sql_file",true);if(is_string($I)){if(function_exists('memory_get_usage'))@ini_set("memory_limit",max(ini_bytes("memory_limit"),2*strlen($I)+memory_get_usage()+8e6));if($I!=""&&strlen($I)<1e6){$H=$I.(preg_match("~;[ \t\r\n]*\$~",$I)?"":";");if(!$Fc||reset(end($Fc))!=$H){restart_session();$Fc[]=array($H,time());set_session("queries",$Gc);stop_session();}}$Gf="(?:\\s|/\\*[\s\S]*?\\*/|(?:#|-- )[^\n]*\n?|--\r?\n)";$rb=";";$Sd=0;$Nb=true;$g=connect();if(is_object($g)&&DB!=""){$g->select_db(DB);if($_GET["ns"]!="")set_schema($_GET["ns"],$g);}$Sa=0;$Sb=array();$ve='[\'"'.($y=="sql"?'`#':($y=="sqlite"?'`[':($y=="mssql"?'[':''))).']|/\*|-- |$'.($y=="pgsql"?'|\$[^$]*\$':'');$tg=microtime(true);parse_str($_COOKIE["adminer_export"],$ia);$Eb=$b->dumpFormat();unset($Eb["sql"]);while($I!=""){if(!$Sd&&preg_match("~^$Gf*+DELIMITER\\s+(\\S+)~i",$I,$C)){$rb=$C[1];$I=substr($I,strlen($C[0]));}else{preg_match('('.preg_quote($rb)."\\s*|$ve)",$I,$C,PREG_OFFSET_CAPTURE,$Sd);list($rc,$Ie)=$C[0];if(!$rc&&$r&&!feof($r))$I.=fread($r,1e5);else{if(!$rc&&rtrim($I)=="")break;$Sd=$Ie+strlen($rc);if($rc&&rtrim($rc)!=$rb){while(preg_match('('.($rc=='/*'?'\*/':($rc=='['?']':(preg_match('~^-- |^#~',$rc)?"\n":preg_quote($rc)."|\\\\."))).'|$)s',$I,$C,PREG_OFFSET_CAPTURE,$Sd)){$pf=$C[0][0];if(!$pf&&$r&&!feof($r))$I.=fread($r,1e5);else{$Sd=$C[0][1]+strlen($pf);if($pf[0]!="\\")break;}}}else{$Nb=false;$H=substr($I,0,$Ie);$Sa++;$Qe="

    ".$b->sqlCommandQuery($H)."
    \n";if($y=="sqlite"&&preg_match("~^$Gf*+ATTACH\\b~i",$H,$C)){echo$Qe,"

    ".'ATTACH queries are not supported.'."\n";$Sb[]=" $Sa";if($_POST["error_stops"])break;}else{if(!$_POST["only_errors"]){echo$Qe;ob_flush();flush();}$Lf=microtime(true);if($f->multi_query($H)&&is_object($g)&&preg_match("~^$Gf*+USE\\b~i",$H))$g->query($H);do{$J=$f->store_result();if($f->error){echo($_POST["only_errors"]?$Qe:""),"

    ".'Erreur dans la requête'.($f->errno?" ($f->errno)":"").": ".error()."\n";$Sb[]=" $Sa";if($_POST["error_stops"])break +2;}else{$jg=" (".format_time($Lf).")".(strlen($H)<1000?" ".'Modifier'."":"");$ka=$f->affected_rows;$ch=($_POST["only_errors"]?"":$k->warnings());$dh="warnings-$Sa";if($ch)$jg.=", ".'Warnings'."".script("qsl('a').onclick = partial(toggle, '$dh');","");$Zb=null;$ac="explain-$Sa";if(is_object($J)){$_=$_POST["limit"];$ie=select($J,$g,array(),$_);if(!$_POST["only_errors"]){echo"

    \n";$Pd=$J->num_rows;echo"

    ".($Pd?($_&&$Pd>$_?sprintf('%d / ',$_):"").lang(array('%d ligne','%d lignes'),$Pd):""),$jg;if($g&&preg_match("~^($Gf|\\()*+SELECT\\b~i",$H)&&($Zb=explain($g,$H)))echo", Explain".script("qsl('a').onclick = partial(toggle, '$ac');","");$v="export-$Sa";echo", ".'Exporter'."".script("qsl('a').onclick = partial(toggle, '$v');","")."\n"."

    \n";}}else{if(preg_match("~^$Gf*+(CREATE|DROP|ALTER)$Gf++(DATABASE|SCHEMA)\\b~i",$H)){restart_session();set_session("dbs",null);stop_session();}if(!$_POST["only_errors"])echo"

    ".lang(array('Requête exécutée avec succès, %d ligne modifiée.','Requête exécutée avec succès, %d lignes modifiées.'),$ka)."$jg\n";}echo($ch?"

    \n":"");if($Zb){echo"\n";}}$Lf=microtime(true);}while($f->next_result());}$I=substr($I,$Sd);$Sd=0;}}}}if($Nb)echo"

    ".'Aucune commande à exécuter.'."\n";elseif($_POST["only_errors"]){echo"

    ".lang(array('%d requête exécutée avec succès.','%d requêtes exécutées avec succès.'),$Sa-count($Sb))," (".format_time($tg).")\n";}elseif($Sb&&$Sa>1)echo"

    ".'Erreur dans la requête'.": ".implode("",$Sb)."\n";}else +echo"

    ".upload_error($I)."\n";}echo' +

    +';$Xb="";if(!isset($_GET["import"])){$H=$_GET["sql"];if($_POST)$H=$_POST["query"];elseif($_GET["history"]=="all")$H=$Fc;elseif($_GET["history"]!="")$H=$Fc[$_GET["history"]][0];echo"

    ";textarea("query",$H,20);echo +script(($_POST?"":"qs('textarea').focus();\n")."qs('#form').onsubmit = partial(sqlSubmit, qs('#form'), '".js_escape(remove_from_uri("sql|limit|error_stops|only_errors|history"))."');"),"

    $Xb\n",'Limiter les lignes'.": \n";}else{echo"

    ".'Importer un fichier'."
    ";$zc=(extension_loaded("zlib")?"[.gz]":"");echo(ini_bool("file_uploads")?"SQL$zc (< ".ini_get("upload_max_filesize")."B): \n$Xb":'L\'importation de fichier est désactivée.'),"
    \n";$Mc=$b->importServerPath();if($Mc){echo"
    ".'Depuis le serveur'."
    ",sprintf('Fichier %s du serveur Web',"".h($Mc)."$zc"),' ',"
    \n";}echo"

    ";}echo +checkbox("error_stops",1,($_POST?$_POST["error_stops"]:isset($_GET["import"])||$_GET["error_stops"]),'Arrêter en cas d\'erreur')."\n",checkbox("only_errors",1,($_POST?$_POST["only_errors"]:isset($_GET["import"])||$_GET["only_errors"]),'Montrer seulement les erreurs')."\n","\n";if(!isset($_GET["import"])&&$Fc){print_fieldset("history",'Historique',$_GET["history"]!="");for($X=end($Fc);$X;$X=prev($Fc)){$z=key($Fc);list($H,$jg,$Ib)=$X;echo''.'Modifier'.""." ".@date("H:i:s",$jg).""." ".shorten_utf8(ltrim(str_replace("\n"," ",str_replace("\r","",preg_replace('~^(#|-- ).*~m','',$H)))),80,"").($Ib?" ($Ib)":"")."
    \n";}echo"\n","".'Tout modifier'."\n","\n";}echo'

    +';}elseif(isset($_GET["edit"])){$a=$_GET["edit"];$n=fields($a);$Z=(isset($_GET["select"])?($_POST["check"]&&count($_POST["check"])==1?where_check($_POST["check"][0],$n):""):where($_GET,$n));$Kg=(isset($_GET["select"])?$_POST["edit"]:$Z);foreach($n +as$F=>$m){if(!isset($m["privileges"][$Kg?"update":"insert"])||$b->fieldName($m)==""||$m["generated"])unset($n[$F]);}if($_POST&&!$l&&!isset($_GET["select"])){$B=$_POST["referer"];if($_POST["insert"])$B=($Kg?null:$_SERVER["REQUEST_URI"]);elseif(!preg_match('~^.+&select=.+$~',$B))$B=ME."select=".urlencode($a);$x=indexes($a);$Fg=unique_array($_GET["where"],$x);$Ye="\nWHERE $Z";if(isset($_POST["delete"]))queries_redirect($B,'L\'élément a été supprimé.',$k->delete($a,$Ye,!$Fg));else{$P=array();foreach($n +as$F=>$m){$X=process_input($m);if($X!==false&&$X!==null)$P[idf_escape($F)]=$X;}if($Kg){if(!$P)redirect($B);queries_redirect($B,'L\'élément a été modifié.',$k->update($a,$P,$Ye,!$Fg));if(is_ajax()){page_headers();page_messages($l);exit;}}else{$J=$k->insert($a,$P);$id=($J?last_id():0);queries_redirect($B,sprintf('L\'élément%s a été inséré.',($id?" $id":"")),$J);}}}$L=null;if($_POST["save"])$L=(array)$_POST["fields"];elseif($Z){$N=array();foreach($n +as$F=>$m){if(isset($m["privileges"]["select"])){$pa=convert_field($m);if($_POST["clone"]&&$m["auto_increment"])$pa="''";if($y=="sql"&&preg_match("~enum|set~",$m["type"]))$pa="1*".idf_escape($F);$N[]=($pa?"$pa AS ":"").idf_escape($F);}}$L=array();if(!support("table"))$N=array("*");if($N){$J=$k->select($a,$N,array($Z),$N,array(),(isset($_GET["select"])?2:1));if(!$J)$l=error();else{$L=$J->fetch_assoc();if(!$L)$L=false;}if(isset($_GET["select"])&&(!$L||$J->fetch_assoc()))$L=null;}}if(!support("table")&&!$n){if(!$Z){$J=$k->select($a,array("*"),$Z,array("*"));$L=($J?$J->fetch_assoc():false);if(!$L)$L=array($k->primary=>"");}if($L){foreach($L +as$z=>$X){if(!$Z)$L[$z]=null;$n[$z]=array("field"=>$z,"null"=>($z!=$k->primary),"auto_increment"=>($z==$k->primary));}}}edit_form($a,$n,$L,$Kg);}elseif(isset($_GET["create"])){$a=$_GET["create"];$we=array();foreach(array('HASH','LINEAR HASH','KEY','LINEAR KEY','RANGE','LIST')as$z)$we[$z]=$z;$ef=referencable_primary($a);$q=array();foreach($ef +as$Wf=>$m)$q[str_replace("`","``",$Wf)."`".str_replace("`","``",$m["field"])]=$Wf;$le=array();$S=array();if($a!=""){$le=fields($a);$S=table_status($a);if(!$S)$l='Aucune table.';}$L=$_POST;$L["fields"]=(array)$L["fields"];if($L["auto_increment_col"])$L["fields"][$L["auto_increment_col"]]["auto_increment"]=true;if($_POST)set_adminer_settings(array("comments"=>$_POST["comments"],"defaults"=>$_POST["defaults"]));if($_POST&&!process_fields($L["fields"])&&!$l){if($_POST["drop"])queries_redirect(substr(ME,0,-1),'La table a été effacée.',drop_tables(array($a)));else{$n=array();$na=array();$Og=false;$oc=array();$ke=reset($le);$ma=" FIRST";foreach($L["fields"]as$z=>$m){$p=$q[$m["type"]];$Bg=($p!==null?$ef[$p]:$m);if($m["field"]!=""){if(!$m["has_default"])$m["default"]=null;if($z==$L["auto_increment_col"])$m["auto_increment"]=true;$Ue=process_field($m,$Bg);$na[]=array($m["orig"],$Ue,$ma);if(!$ke||$Ue!=process_field($ke,$ke)){$n[]=array($m["orig"],$Ue,$ma);if($m["orig"]!=""||$ma)$Og=true;}if($p!==null)$oc[idf_escape($m["field"])]=($a!=""&&$y!="sqlite"?"ADD":" ").format_foreign_key(array('table'=>$q[$m["type"]],'source'=>array($m["field"]),'target'=>array($Bg["field"]),'on_delete'=>$m["on_delete"],));$ma=" AFTER ".idf_escape($m["field"]);}elseif($m["orig"]!=""){$Og=true;$n[]=array($m["orig"]);}if($m["orig"]!=""){$ke=next($le);if(!$ke)$ma="";}}$ye="";if($we[$L["partition_by"]]){$ze=array();if($L["partition_by"]=='RANGE'||$L["partition_by"]=='LIST'){foreach(array_filter($L["partition_names"])as$z=>$X){$Y=$L["partition_values"][$z];$ze[]="\n PARTITION ".idf_escape($X)." VALUES ".($L["partition_by"]=='RANGE'?"LESS THAN":"IN").($Y!=""?" ($Y)":" MAXVALUE");}}$ye.="\nPARTITION BY $L[partition_by]($L[partition])".($ze?" (".implode(",",$ze)."\n)":($L["partitions"]?" PARTITIONS ".(+$L["partitions"]):""));}elseif(support("partitioning")&&preg_match("~partitioned~",$S["Create_options"]))$ye.="\nREMOVE PARTITIONING";$D='La table a été modifiée.';if($a==""){cookie("adminer_engine",$L["Engine"]);$D='La table a été créée.';}$F=trim($L["name"]);queries_redirect(ME.(support("table")?"table=":"select=").urlencode($F),$D,alter_table($a,$F,($y=="sqlite"&&($Og||$oc)?$na:$n),$oc,($L["Comment"]!=$S["Comment"]?$L["Comment"]:null),($L["Engine"]&&$L["Engine"]!=$S["Engine"]?$L["Engine"]:""),($L["Collation"]&&$L["Collation"]!=$S["Collation"]?$L["Collation"]:""),($L["Auto_increment"]!=""?number($L["Auto_increment"]):""),$ye));}}page_header(($a!=""?'Modifier la table':'Créer une table'),$l,array("table"=>$a),h($a));if(!$_POST){$L=array("Engine"=>$_COOKIE["adminer_engine"],"fields"=>array(array("field"=>"","type"=>(isset($Cg["int"])?"int":(isset($Cg["integer"])?"integer":"")),"on_update"=>"")),"partition_names"=>array(""),);if($a!=""){$L=$S;$L["name"]=$a;$L["fields"]=array();if(!$_GET["auto_increment"])$L["Auto_increment"]="";foreach($le +as$m){$m["has_default"]=isset($m["default"]);$L["fields"][]=$m;}if(support("partitioning")){$tc="FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = ".q(DB)." AND TABLE_NAME = ".q($a);$J=$f->query("SELECT PARTITION_METHOD, PARTITION_ORDINAL_POSITION, PARTITION_EXPRESSION $tc ORDER BY PARTITION_ORDINAL_POSITION DESC LIMIT 1");list($L["partition_by"],$L["partitions"],$L["partition"])=$J->fetch_row();$ze=get_key_vals("SELECT PARTITION_NAME, PARTITION_DESCRIPTION $tc AND PARTITION_NAME != '' ORDER BY PARTITION_ORDINAL_POSITION");$ze[""]="";$L["partition_names"]=array_keys($ze);$L["partition_values"]=array_values($ze);}}}$Pa=collations();$Pb=engines();foreach($Pb +as$Ob){if(!strcasecmp($Ob,$L["Engine"])){$L["Engine"]=$Ob;break;}}echo' +
    +

    +';if(support("columns")||$a==""){echo'Nom de la table: +';if($a==""&&!$_POST)echo +script("focus(qs('#form')['name']);");echo($Pb?"".on_help("getTarget(event).value",1).script("qsl('select').onchange = helpClose;"):""),' ',($Pa&&!preg_match("~sqlite|mssql~",$y)?html_select("Collation",array(""=>"(".'interclassement'.")")+$Pa,$L["Collation"]):""),' +';}echo' +';if(support("columns")){echo'

    + +';edit_fields($L["fields"],$Pa,"TABLE",$q);echo'
    +',script("editFields();"),'
    +

    +Incrément automatique: +',checkbox("defaults",1,($_POST?$_POST["defaults"]:adminer_setting("defaults")),'Valeurs par défaut',"columnShow(this.checked, 5)","jsonly"),(support("comment")?checkbox("comments",1,($_POST?$_POST["comments"]:adminer_setting("comments")),'Commentaire',"editingCommentsClick(this, true);","jsonly").' ':''),'

    + +';}echo' +';if($a!=""){echo'',confirm(sprintf('Drop %s?',$a));}if(support("partitioning")){$xe=preg_match('~RANGE|LIST~',$L["partition_by"]);print_fieldset("partition",'Partitionner par',$L["partition_by"]);echo'

    +',"".on_help("getTarget(event).value.replace(/./, 'PARTITION BY \$&')",1).script("qsl('select').onchange = partitionByChange;"),'() +Partitions: + + +';foreach($L["partition_names"]as$z=>$X){echo'',' + +';}echo' +

    +';}elseif(isset($_GET["indexes"])){$a=$_GET["indexes"];$Oc=array("PRIMARY","UNIQUE","INDEX");$S=table_status($a,true);if(preg_match('~MyISAM|M?aria'.(min_version(5.6,'10.0.5')?'|InnoDB':'').'~i',$S["Engine"]))$Oc[]="FULLTEXT";if(preg_match('~MyISAM|M?aria'.(min_version(5.7,'10.2.2')?'|InnoDB':'').'~i',$S["Engine"]))$Oc[]="SPATIAL";$x=indexes($a);$Oe=array();if($y=="mongo"){$Oe=$x["_id_"];unset($Oc[0]);unset($x["_id_"]);}$L=$_POST;if($_POST&&!$l&&!$_POST["add"]&&!$_POST["drop_col"]){$oa=array();foreach($L["indexes"]as$w){$F=$w["name"];if(in_array($w["type"],$Oc)){$e=array();$od=array();$tb=array();$P=array();ksort($w["columns"]);foreach($w["columns"]as$z=>$d){if($d!=""){$nd=$w["lengths"][$z];$sb=$w["descs"][$z];$P[]=idf_escape($d).($nd?"(".(+$nd).")":"").($sb?" DESC":"");$e[]=$d;$od[]=($nd?$nd:null);$tb[]=$sb;}}if($e){$Yb=$x[$F];if($Yb){ksort($Yb["columns"]);ksort($Yb["lengths"]);ksort($Yb["descs"]);if($w["type"]==$Yb["type"]&&array_values($Yb["columns"])===$e&&(!$Yb["lengths"]||array_values($Yb["lengths"])===$od)&&array_values($Yb["descs"])===$tb){unset($x[$F]);continue;}}$oa[]=array($w["type"],$F,$P);}}}foreach($x +as$F=>$Yb)$oa[]=array($Yb["type"],$F,"DROP");if(!$oa)redirect(ME."table=".urlencode($a));queries_redirect(ME."table=".urlencode($a),'Index modifiés.',alter_indexes($a,$oa));}page_header('Index',$l,array("table"=>$a),h($a));$n=array_keys(fields($a));if($_POST["add"]){foreach($L["indexes"]as$z=>$w){if($w["columns"][count($w["columns"])]!="")$L["indexes"][$z]["columns"][]="";}$w=end($L["indexes"]);if($w["type"]||array_filter($w["columns"],'strlen'))$L["indexes"][]=array("columns"=>array(1=>""));}if(!$L){foreach($x +as$z=>$w){$x[$z]["name"]=$z;$x[$z]["columns"][]="";}$x[]=array("columns"=>array(1=>""));$L["indexes"]=$x;}echo' +
    +
    + + + +';if($Oe){echo"
    Type d\'index +Colonne (longueur) +Nom + +
    PRIMARY";foreach($Oe["columns"]as$z=>$d){echo +select_input(" disabled",$n,$d)," ";}echo"\n";}$Zc=1;foreach($L["indexes"]as$w){if(!$_POST["drop_col"]||$Zc!=key($_POST["drop_col"])){echo"
    ".html_select("indexes[$Zc][type]",array(-1=>"")+$Oc,$w["type"],($Zc==count($L["indexes"])?"indexesAddRow.call(this);":1),"label-type"),"";ksort($w["columns"]);$u=1;foreach($w["columns"]as$z=>$d){echo"".select_input(" name='indexes[$Zc][columns][$u]' title='".'Colonne'."'",($n?array_combine($n,$n):$n),$d,"partial(".($u==count($w["columns"])?"indexesAddColumn":"indexesChangeColumn").", '".js_escape($y=="sql"?"":$_GET["indexes"]."_")."')"),($y=="sql"||$y=="mssql"?"":""),(support("descidx")?checkbox("indexes[$Zc][descs][$u]",1,$w["descs"][$z],'décroissant'):"")," ";$u++;}echo"\n","".script("qsl('input').onclick = partial(editingRemoveRow, 'indexes\$1[type]');");}$Zc++;}echo'
    +
    +

    + + +

    +';}elseif(isset($_GET["database"])){$L=$_POST;if($_POST&&!$l&&!isset($_POST["add_x"])){$F=trim($L["name"]);if($_POST["drop"]){$_GET["db"]="";queries_redirect(remove_from_uri("db|database"),'La base de données a été supprimée.',drop_databases(array(DB)));}elseif(DB!==$F){if(DB!=""){$_GET["db"]=$F;queries_redirect(preg_replace('~\bdb=[^&]*&~','',ME)."db=".urlencode($F),'La base de données a été renommée.',rename_database($F,$L["collation"]));}else{$i=explode("\n",str_replace("\r","",$F));$Qf=true;$hd="";foreach($i +as$j){if(count($i)==1||$j!=""){if(!create_database($j,$L["collation"]))$Qf=false;$hd=$j;}}restart_session();set_session("dbs",null);queries_redirect(ME."db=".urlencode($hd),'La base de données a été créée.',$Qf);}}else{if(!$L["collation"])redirect(substr(ME,0,-1));query_redirect("ALTER DATABASE ".idf_escape($F).(preg_match('~^[a-z0-9_]+$~i',$L["collation"])?" COLLATE $L[collation]":""),substr(ME,0,-1),'La base de données a été modifiée.');}}page_header(DB!=""?'Modifier la base de données':'Créer une base de données',$l,array(),h(DB));$Pa=collations();$F=DB;if($_POST)$F=$L["name"];elseif(DB!="")$L["collation"]=db_collation(DB,$Pa);elseif($y=="sql"){foreach(get_vals("SHOW GRANTS")as$vc){if(preg_match('~ ON (`(([^\\\\`]|``|\\\\.)*)%`\.\*)?~',$vc,$C)&&$C[1]){$F=stripcslashes(idf_unescape("`$C[2]`"));break;}}}echo' +
    +

    +',($_POST["add_x"]||strpos($F,"\n")?'
    ':'')."\n".($Pa?html_select("collation",array(""=>"(".'interclassement'.")")+$Pa,$L["collation"]).'':""),script("focus(qs('#name'));"),' +';if(DB!="")echo"".confirm(sprintf('Drop %s?',DB))."\n";elseif(!$_POST["add_x"]&&$_GET["db"]=="")echo"\n";echo' +

    +';}elseif(isset($_GET["foreign"])){$a=$_GET["foreign"];$F=$_GET["name"];$L=$_POST;if($_POST&&!$l&&!$_POST["add"]&&!$_POST["change"]&&!$_POST["change-js"]){$D=($_POST["drop"]?'La clé étrangère a été effacée.':($F!=""?'La clé étrangère a été modifiée.':'La clé étrangère a été créée.'));$B=ME."table=".urlencode($a);if(!$_POST["drop"]){$L["source"]=array_filter($L["source"],'strlen');ksort($L["source"]);$dg=array();foreach($L["source"]as$z=>$X)$dg[$z]=$L["target"][$z];$L["target"]=$dg;}if($y=="sqlite")queries_redirect($B,$D,recreate_table($a,$a,array(),array(),array(" $F"=>($_POST["drop"]?"":" ".format_foreign_key($L)))));else{$oa="ALTER TABLE ".table($a);$_b="\nDROP ".($y=="sql"?"FOREIGN KEY ":"CONSTRAINT ").idf_escape($F);if($_POST["drop"])query_redirect($oa.$_b,$B,$D);else{query_redirect($oa.($F!=""?"$_b,":"")."\nADD".format_foreign_key($L),$B,$D);$l='Les colonnes de source et de destination doivent être du même type, il doit y avoir un index sur les colonnes de destination et les données référencées doivent exister.'."
    $l";}}}page_header('Clé étrangère',$l,array("table"=>$a),h($a));if($_POST){ksort($L["source"]);if($_POST["add"])$L["source"][]="";elseif($_POST["change"]||$_POST["change-js"])$L["target"]=array();}elseif($F!=""){$q=foreign_keys($a);$L=$q[$F];$L["source"][]="";}else{$L["table"]=$a;$L["source"]=array("");}echo' +
    +';$Ff=array_keys(fields($a));if($L["db"]!="")$f->select_db($L["db"]);if($L["ns"]!="")set_schema($L["ns"]);$df=array_keys(array_filter(table_status('',true),'fk_support'));$dg=array_keys(fields(in_array($L["table"],$df)?$L["table"]:reset($df)));$Xd="this.form['change-js'].value = '1'; this.form.submit();";echo"

    ".'Table visée'.": ".html_select("table",$df,$L["table"],$Xd)."\n";if($y=="pgsql")echo'Schéma'.": ".html_select("ns",$b->schemas(),$L["ns"]!=""?$L["ns"]:$_GET["ns"],$Xd);elseif($y!="sqlite"){$mb=array();foreach($b->databases()as$j){if(!information_schema($j))$mb[]=$j;}echo'DB'.": ".html_select("db",$mb,$L["db"]!=""?$L["db"]:$_GET["db"],$Xd);}echo' +

    + + +';$Zc=0;foreach($L["source"]as$z=>$X){echo"","
    SourceCible
    ".html_select("source[".(+$z)."]",array(-1=>"")+$Ff,$X,($Zc==count($L["source"])-1?"foreignAddRow.call(this);":1),"label-source"),"".html_select("target[".(+$z)."]",$dg,$L["target"][$z],1,"label-target");$Zc++;}echo'
    +

    +ON DELETE: ',html_select("on_delete",array(-1=>"")+explode("|",$Wd),$L["on_delete"]),' ON UPDATE: ',html_select("on_update",array(-1=>"")+explode("|",$Wd),$L["on_update"]),'','

    + +

    +';if($F!=""){echo'',confirm(sprintf('Drop %s?',$F));}echo' +

    +';}elseif(isset($_GET["view"])){$a=$_GET["view"];$L=$_POST;$me="VIEW";if($y=="pgsql"&&$a!=""){$Mf=table_status($a);$me=strtoupper($Mf["Engine"]);}if($_POST&&!$l){$F=trim($L["name"]);$pa=" AS\n$L[select]";$B=ME."table=".urlencode($F);$D='La vue a été modifiée.';$V=($_POST["materialized"]?"MATERIALIZED VIEW":"VIEW");if(!$_POST["drop"]&&$a==$F&&$y!="sqlite"&&$V=="VIEW"&&$me=="VIEW")query_redirect(($y=="mssql"?"ALTER":"CREATE OR REPLACE")." VIEW ".table($F).$pa,$B,$D);else{$fg=$F."_adminer_".uniqid();drop_create("DROP $me ".table($a),"CREATE $V ".table($F).$pa,"DROP $V ".table($F),"CREATE $V ".table($fg).$pa,"DROP $V ".table($fg),($_POST["drop"]?substr(ME,0,-1):$B),'La vue a été effacée.',$D,'La vue a été créée.',$a,$F);}}if(!$_POST&&$a!=""){$L=view($a);$L["name"]=$a;$L["materialized"]=($me!="VIEW");if(!$l)$l=error();}page_header(($a!=""?'Modifier une vue':'Créer une vue'),$l,array("table"=>$a),h($a));echo' +
    +

    Nom: +',(support("materializedview")?" ".checkbox("materialized",1,$L["materialized"],'Vue matérialisée'):""),'

    ';textarea("select",$L["select"]);echo'

    + +';if($a!=""){echo'',confirm(sprintf('Drop %s?',$a));}echo' +

    +';}elseif(isset($_GET["trigger"])){$a=$_GET["trigger"];$F=$_GET["name"];$_g=trigger_options();$L=(array)trigger($F,$a)+array("Trigger"=>$a."_bi");if($_POST){if(!$l&&in_array($_POST["Timing"],$_g["Timing"])&&in_array($_POST["Event"],$_g["Event"])&&in_array($_POST["Type"],$_g["Type"])){$Vd=" ON ".table($a);$_b="DROP TRIGGER ".idf_escape($F).($y=="pgsql"?$Vd:"");$B=ME."table=".urlencode($a);if($_POST["drop"])query_redirect($_b,$B,'Le déclencheur a été supprimé.');else{if($F!="")queries($_b);queries_redirect($B,($F!=""?'Le déclencheur a été modifié.':'Le déclencheur a été créé.'),queries(create_trigger($Vd,$_POST)));if($F!="")queries(create_trigger($Vd,$L+array("Type"=>reset($_g["Type"]))));}}$L=$_POST;}page_header(($F!=""?'Modifier un déclencheur'.": ".h($F):'Ajouter un déclencheur'),$l,array("table"=>$a));echo' +
    + +
    Temps',html_select("Timing",$_g["Timing"],$L["Timing"],"triggerChange(/^".preg_quote($a,"/")."_[ba][iud]$/, '".js_escape($a)."', this.form);"),'
    Évènement',html_select("Event",$_g["Event"],$L["Event"],"this.form['Timing'].onchange();"),(in_array("UPDATE OF",$_g["Event"])?" ":""),'
    Type',html_select("Type",$_g["Type"],$L["Type"]),'
    +

    Nom: +',script("qs('#form')['Timing'].onchange();"),'

    ';textarea("Statement",$L["Statement"]);echo'

    + +';if($F!=""){echo'',confirm(sprintf('Drop %s?',$F));}echo' +

    +';}elseif(isset($_GET["select"])){$a=$_GET["select"];$S=table_status1($a);$x=indexes($a);$n=fields($a);$q=column_foreign_keys($a);$Td=$S["Oid"];parse_str($_COOKIE["adminer_import"],$ja);$lf=array();$e=array();$ig=null;foreach($n +as$z=>$m){$F=$b->fieldName($m);if(isset($m["privileges"]["select"])&&$F!=""){$e[$z]=html_entity_decode(strip_tags($F),ENT_QUOTES);if(is_shortable($m))$ig=$b->selectLengthProcess();}$lf+=$m["privileges"];}list($N,$t)=$b->selectColumnsProcess($e,$x);$Wc=count($t)selectSearchProcess($n,$x);$fe=$b->selectOrderProcess($n,$x);$_=$b->selectLimitProcess();if($_GET["val"]&&is_ajax()){header("Content-Type: text/plain; charset=utf-8");foreach($_GET["val"]as$Gg=>$L){$pa=convert_field($n[key($L)]);$N=array($pa?$pa:idf_escape(key($L)));$Z[]=where_check($Gg,$n);$K=$k->select($a,$N,$Z,$N);if($K)echo +reset($K->fetch_row());}exit;}$Oe=$Ig=null;foreach($x +as$w){if($w["type"]=="PRIMARY"){$Oe=array_flip($w["columns"]);$Ig=($N?$Oe:array());foreach($Ig +as$z=>$X){if(in_array(idf_escape($z),$N))unset($Ig[$z]);}break;}}if($Td&&!$Oe){$Oe=$Ig=array($Td=>0);$x[]=array("type"=>"PRIMARY","columns"=>array($Td));}if($_POST&&!$l){$fh=$Z;if(!$_POST["all"]&&is_array($_POST["check"])){$Ga=array();foreach($_POST["check"]as$Ea)$Ga[]=where_check($Ea,$n);$fh[]="((".implode(") OR (",$Ga)."))";}$fh=($fh?"\nWHERE ".implode(" AND ",$fh):"");if($_POST["export"]){cookie("adminer_import","output=".urlencode($_POST["output"])."&format=".urlencode($_POST["format"]));dump_headers($a);$b->dumpTable($a,"");$tc=($N?implode(", ",$N):"*").convert_fields($e,$n,$N)."\nFROM ".table($a);$xc=($t&&$Wc?"\nGROUP BY ".implode(", ",$t):"").($fe?"\nORDER BY ".implode(", ",$fe):"");if(!is_array($_POST["check"])||$Oe)$I="SELECT $tc$fh$xc";else{$Eg=array();foreach($_POST["check"]as$X)$Eg[]="(SELECT".limit($tc,"\nWHERE ".($Z?implode(" AND ",$Z)." AND ":"").where_check($X,$n).$xc,1).")";$I=implode(" UNION ALL ",$Eg);}$b->dumpData($a,"table",$I);exit;}if(!$b->selectEmailProcess($Z,$q)){if($_POST["save"]||$_POST["delete"]){$J=true;$ka=0;$P=array();if(!$_POST["delete"]){foreach($e +as$F=>$X){$X=process_input($n[$F]);if($X!==null&&($_POST["clone"]||$X!==false))$P[idf_escape($F)]=($X!==false?$X:idf_escape($F));}}if($_POST["delete"]||$P){if($_POST["clone"])$I="INTO ".table($a)." (".implode(", ",array_keys($P)).")\nSELECT ".implode(", ",$P)."\nFROM ".table($a);if($_POST["all"]||($Oe&&is_array($_POST["check"]))||$Wc){$J=($_POST["delete"]?$k->delete($a,$fh):($_POST["clone"]?queries("INSERT $I$fh"):$k->update($a,$P,$fh)));$ka=$f->affected_rows;}else{foreach((array)$_POST["check"]as$X){$eh="\nWHERE ".($Z?implode(" AND ",$Z)." AND ":"").where_check($X,$n);$J=($_POST["delete"]?$k->delete($a,$eh,1):($_POST["clone"]?queries("INSERT".limit1($a,$I,$eh)):$k->update($a,$P,$eh,1)));if(!$J)break;$ka+=$f->affected_rows;}}}$D=lang(array('%d élément a été modifié.','%d éléments ont été modifiés.'),$ka);if($_POST["clone"]&&$J&&$ka==1){$id=last_id();if($id)$D=sprintf('L\'élément%s a été inséré.'," $id");}queries_redirect(remove_from_uri($_POST["all"]&&$_POST["delete"]?"page":""),$D,$J);if(!$_POST["delete"]){edit_form($a,$n,(array)$_POST["fields"],!$_POST["clone"]);page_footer();exit;}}elseif(!$_POST["import"]){if(!$_POST["val"])$l='Ctrl+cliquez sur une valeur pour la modifier.';else{$J=true;$ka=0;foreach($_POST["val"]as$Gg=>$L){$P=array();foreach($L +as$z=>$X){$z=bracket_escape($z,1);$P[idf_escape($z)]=(preg_match('~char|text~',$n[$z]["type"])||$X!=""?$b->processInput($n[$z],$X):"NULL");}$J=$k->update($a,$P," WHERE ".($Z?implode(" AND ",$Z)." AND ":"").where_check($Gg,$n),!$Wc&&!$Oe," ");if(!$J)break;$ka+=$f->affected_rows;}queries_redirect(remove_from_uri(),lang(array('%d élément a été modifié.','%d éléments ont été modifiés.'),$ka),$J);}}elseif(!is_string($jc=get_file("csv_file",true)))$l=upload_error($jc);elseif(!preg_match('~~u',$jc))$l='Les fichiers doivent être encodés en UTF-8.';else{cookie("adminer_import","output=".urlencode($ja["output"])."&format=".urlencode($_POST["separator"]));$J=true;$Qa=array_keys($n);preg_match_all('~(?>"[^"]*"|[^"\r\n]+)+~',$jc,$ud);$ka=count($ud[0]);$k->begin();$xf=($_POST["separator"]=="csv"?",":($_POST["separator"]=="tsv"?"\t":";"));$M=array();foreach($ud[0]as$z=>$X){preg_match_all("~((?>\"[^\"]*\")+|[^$xf]*)$xf~",$X.$xf,$vd);if(!$z&&!array_diff($vd[1],$Qa)){$Qa=$vd[1];$ka--;}else{$P=array();foreach($vd[1]as$u=>$Ma)$P[idf_escape($Qa[$u])]=($Ma==""&&$n[$Qa[$u]]["null"]?"NULL":q(str_replace('""','"',preg_replace('~^"|"$~','',$Ma))));$M[]=$P;}}$J=(!$M||$k->insertUpdate($a,$M,$Oe));if($J)$J=$k->commit();queries_redirect(remove_from_uri("page"),lang(array('%d ligne a été importée.','%d lignes ont été importées.'),$ka),$J);$k->rollback();}}}$Wf=$b->tableName($S);if(is_ajax()){page_headers();ob_start();}else +page_header('Sélectionner'.": $Wf",$l);$P=null;if(isset($lf["insert"])||!support("table")){$P="";foreach((array)$_GET["where"]as$X){if($q[$X["col"]]&&count($q[$X["col"]])==1&&($X["op"]=="="||(!$X["op"]&&!preg_match('~[_%]~',$X["val"]))))$P.="&set".urlencode("[".bracket_escape($X["col"])."]")."=".urlencode($X["val"]);}}$b->selectLinks($S,$P);if(!$e&&support("table"))echo"

    ".'Impossible de sélectionner la table'.($n?".":": ".error())."\n";else{echo"

    \n","
    ";hidden_fields_get();echo(DB!=""?''.(isset($_GET["ns"])?'':""):"");echo'',"
    \n";$b->selectColumnsPrint($N,$e);$b->selectSearchPrint($Z,$e,$x);$b->selectOrderPrint($fe,$e,$x);$b->selectLimitPrint($_);$b->selectLengthPrint($ig);$b->selectActionPrint($x);echo"
    \n";$G=$_GET["page"];if($G=="last"){$sc=$f->result(count_rows($a,$Z,$Wc,$t));$G=floor(max(0,$sc-1)/$_);}$sf=$N;$wc=$t;if(!$sf){$sf[]="*";$ab=convert_fields($e,$n,$N);if($ab)$sf[]=substr($ab,2);}foreach($N +as$z=>$X){$m=$n[idf_unescape($X)];if($m&&($pa=convert_field($m)))$sf[$z]="$pa AS $X";}if(!$Wc&&$Ig){foreach($Ig +as$z=>$X){$sf[]=idf_escape($z);if($wc)$wc[]=idf_escape($z);}}$J=$k->select($a,$sf,$Z,$wc,$fe,$_,$G,true);if(!$J)echo"

    ".error()."\n";else{if($y=="mssql"&&$G)$J->seek($_*$G);$Mb=array();echo"

    \n";$M=array();while($L=$J->fetch_assoc()){if($G&&$y=="oracle")unset($L["RNUM"]);$M[]=$L;}if($_GET["page"]!="last"&&$_!=""&&$t&&$Wc&&$y=="sql")$sc=$f->result(" SELECT FOUND_ROWS()");if(!$M)echo"

    ".'Aucun résultat.'."\n";else{$wa=$b->backwardKeys($a,$Wf);echo"

    ","",script("mixin(qs('#table'), {onclick: tableClick, ondblclick: partialArg(tableClick, true), onkeydown: editingKeydown});"),"".(!$t&&$N?"":"\n";if(is_ajax()){if($_%2==1&&$G%2==1)odd();ob_end_clean();}foreach($b->rowDescriptions($M,$q)as$E=>$L){$Fg=unique_array($M[$E],$x);if(!$Fg){$Fg=array();foreach($M[$E]as$z=>$X){if(!preg_match('~^(COUNT\((\*|(DISTINCT )?`(?:[^`]|``)+`)\)|(AVG|GROUP_CONCAT|MAX|MIN|SUM)\(`(?:[^`]|``)+`\))$~',$z))$Fg[$z]=$X;}}$Gg="";foreach($Fg +as$z=>$X){if(($y=="sql"||$y=="pgsql")&&preg_match('~char|text|enum|set~',$n[$z]["type"])&&strlen($X)>64){$z=(strpos($z,'(')?$z:idf_escape($z));$z="MD5(".($y!='sql'||preg_match("~^utf8~",$n[$z]["collation"])?$z:"CONVERT($z USING ".charset($f).")").")";$X=md5($X);}$Gg.="&".($X!==null?urlencode("where[".bracket_escape($z)."]")."=".urlencode($X):"null%5B%5D=".urlencode($z));}echo"".(!$t&&$N?"":"";}}}if($wa)echo"\n";}if(is_ajax())exit;echo"
    ".script("qs('#all-page').onclick = partial(formCheck, /check/);","")." ".'Modification'."");$Kd=array();$uc=array();reset($N);$af=1;foreach($M[0]as$z=>$X){if(!isset($Ig[$z])){$X=$_GET["columns"][key($N)];$m=$n[$N?($X?$X["col"]:current($N)):$z];$F=($m?$b->fieldName($m,$af):($X["fun"]?"*":$z));if($F!=""){$af++;$Kd[$z]=$F;$d=idf_escape($z);$Ic=remove_from_uri('(order|desc)[^=]*|page').'&order%5B0%5D='.urlencode($z);$sb="&desc%5B0%5D=1";echo"".script("mixin(qsl('th'), {onmouseover: partial(columnMouse), onmouseout: partial(columnMouse, ' hidden')});",""),'';echo +apply_sql_function($X["fun"],$F)."";echo"";}$uc[$z]=$X["fun"];next($N);}}$od=array();if($_GET["modify"]){foreach($M +as$L){foreach($L +as$z=>$X)$od[$z]=max($od[$z],min(40,strlen(utf8_decode($X))));}}echo($wa?"".'Relations':"")."
    ".checkbox("check[]",substr($Gg,1),in_array(substr($Gg,1),(array)$_POST["check"])).($Wc||information_schema(DB)?"":" ".'modifier'.""));foreach($L +as$z=>$X){if(isset($Kd[$z])){$m=$n[$z];$X=$k->value($X,$m);if($X!=""&&(!isset($Mb[$z])||$Mb[$z]!=""))$Mb[$z]=(is_mail($X)?$Kd[$z]:"");$A="";if(preg_match('~blob|bytea|raw|file~',$m["type"])&&$X!="")$A=ME.'download='.urlencode($a).'&field='.urlencode($z).$Gg;if(!$A&&$X!==null){foreach((array)$q[$z]as$p){if(count($q[$z])==1||end($p["source"])==$z){$A="";foreach($p["source"]as$u=>$Ff)$A.=where_link($u,$p["target"][$u],$M[$E][$Ff]);$A=($p["db"]!=""?preg_replace('~([?&]db=)[^&]+~','\1'.urlencode($p["db"]),ME):ME).'select='.urlencode($p["table"]).$A;if($p["ns"])$A=preg_replace('~([?&]ns=)[^&]+~','\1'.urlencode($p["ns"]),$A);if(count($p["source"])==1)break;}}}if($z=="COUNT(*)"){$A=ME."select=".urlencode($a);$u=0;foreach((array)$_GET["where"]as$W){if(!array_key_exists($W["col"],$Fg))$A.=where_link($u++,$W["col"],$W["val"],$W["op"]);}foreach($Fg +as$ad=>$W)$A.=where_link($u++,$ad,$W);}$X=select_value($X,$A,$m,$ig);$v=h("val[$Gg][".bracket_escape($z)."]");$Y=$_POST["val"][$Gg][bracket_escape($z)];$Hb=!is_array($L[$z])&&is_utf8($X)&&$M[$E][$z]==$L[$z]&&!$uc[$z];$hg=preg_match('~text|lob~',$m["type"]);echo"".($hg?"":"");}else{$sd=strpos($X,"");echo" data-text='".($sd?2:($hg?1:0))."'".($Hb?"":" data-warning='".h('Utilisez le lien "modifier" pour modifier cette valeur.')."'").">$X";$b->backwardKeysPrint($wa,$M[$E]);echo"
    \n","
    \n";}if(!is_ajax()){if($M||$G){$Wb=true;if($_GET["page"]!="last"){if($_==""||(count($M)<$_&&($M||!$G)))$sc=($G?$G*$_:0)+count($M);elseif($y!="sql"||!$Wc){$sc=($Wc?false:found_rows($S,$Z));if($sc$_||$G));if($se){echo(($sc===false?count($M)+1:$sc-$G*$_)>$_?'

    '.'Charger plus de données'.''.script("qsl('a').onclick = partial(selectLoadMore, ".(+$_).", '".'Chargement'."…');",""):''),"\n";}}echo"

    \n";if($b->selectImportPrint()){echo"
    ","".'Importer'."",script("qsl('a').onclick = partial(toggle, 'import');",""),"","
    ";}echo"\n","\n",(!$t&&$N?"":script("tableCheck();"));}}}if(is_ajax()){ob_end_clean();exit;}}elseif(isset($_GET["variables"])){$Mf=isset($_GET["status"]);page_header($Mf?'Statut':'Variables');$Vg=($Mf?show_status():show_variables());if(!$Vg)echo"

    ".'Aucun résultat.'."\n";else{echo"\n";foreach($Vg +as$z=>$X){echo"","
    ".h($z)."","".h($X);}echo"
    \n";}}elseif(isset($_GET["script"])){header("Content-Type: text/javascript; charset=utf-8");if($_GET["script"]=="db"){$Tf=array("Data_length"=>0,"Index_length"=>0,"Data_free"=>0);foreach(table_status()as$F=>$S){json_row("Comment-$F",h($S["Comment"]));if(!is_view($S)){foreach(array("Engine","Collation")as$z)json_row("$z-$F",h($S[$z]));foreach($Tf+array("Auto_increment"=>0,"Rows"=>0)as$z=>$X){if($S[$z]!=""){$X=format_number($S[$z]);json_row("$z-$F",($z=="Rows"&&$X&&$S["Engine"]==($Hf=="pgsql"?"table":"InnoDB")?"~ $X":$X));if(isset($Tf[$z]))$Tf[$z]+=($S["Engine"]!="InnoDB"||$z!="Data_free"?$S[$z]:0);}elseif(array_key_exists($z,$S))json_row("$z-$F");}}}foreach($Tf +as$z=>$X)json_row("sum-$z",format_number($X));json_row("");}elseif($_GET["script"]=="kill")$f->query("KILL ".number($_POST["kill"]));else{foreach(count_tables($b->databases())as$j=>$X){json_row("tables-$j",$X);json_row("size-$j",db_size($j));}json_row("");}exit;}else{$bg=array_merge((array)$_POST["tables"],(array)$_POST["views"]);if($bg&&!$l&&!$_POST["search"]){$J=true;$D="";if($y=="sql"&&$_POST["tables"]&&count($_POST["tables"])>1&&($_POST["drop"]||$_POST["truncate"]||$_POST["copy"]))queries("SET foreign_key_checks = 0");if($_POST["truncate"]){if($_POST["tables"])$J=truncate_tables($_POST["tables"]);$D='Les tables ont été tronquées.';}elseif($_POST["move"]){$J=move_tables((array)$_POST["tables"],(array)$_POST["views"],$_POST["target"]);$D='Les tables ont été déplacées.';}elseif($_POST["copy"]){$J=copy_tables((array)$_POST["tables"],(array)$_POST["views"],$_POST["target"]);$D='Les tables ont été copiées.';}elseif($_POST["drop"]){if($_POST["views"])$J=drop_views($_POST["views"]);if($J&&$_POST["tables"])$J=drop_tables($_POST["tables"]);$D='Les tables ont été effacées.';}elseif($y!="sql"){$J=($y=="sqlite"?queries("VACUUM"):apply_queries("VACUUM".($_POST["optimize"]?"":" ANALYZE"),$_POST["tables"]));$D='Les tables ont bien été optimisées.';}elseif(!$_POST["tables"])$D='Aucune table.';elseif($J=queries(($_POST["optimize"]?"OPTIMIZE":($_POST["check"]?"CHECK":($_POST["repair"]?"REPAIR":"ANALYZE")))." TABLE ".implode(", ",array_map('idf_escape',$_POST["tables"])))){while($L=$J->fetch_assoc())$D.="".h($L["Table"]).": ".h($L["Msg_text"])."
    ";}queries_redirect(substr(ME,0,-1),$D,$J);}page_header(($_GET["ns"]==""?'Base de données'.": ".h(DB):'Schéma'.": ".h($_GET["ns"])),$l,true);if($b->homepage()){if($_GET["ns"]!==""){echo"

    ".'Tables et vues'."

    \n";$ag=tables_list();if(!$ag)echo"

    ".'Aucune table.'."\n";else{echo"

    \n";if(support("table")){echo"
    ".'Rechercher dans les tables'."
    ","",script("qsl('input').onkeydown = partialArg(bodyKeydown, 'search');","")," \n","
    \n";if($_POST["search"]&&$_POST["query"]!=""){$_GET["where"][0]["op"]="LIKE %%";search_tables();}}echo"
    \n","\n",script("mixin(qsl('table'), {onclick: tableClick, ondblclick: partialArg(tableClick, true)});"),'','\n";$T=0;foreach($ag +as$F=>$V){$Yg=($V!==null&&!preg_match('~table|sequence~i',$V));$v=h("Table-".$F);echo'
    '.script("qs('#check-all').onclick = partial(formCheck, /^(tables|views)\[/);",""),''.'Table',''.'Moteur'.'',''.'Interclassement'.'',''.'Longueur des données'.'',''.'Longueur de l\'index'.'',''.'Espace inutilisé'.'',''.'Incrément automatique'.'',''.'Lignes'.'',(support("comment")?''.'Commentaire'.'':''),"
    '.checkbox(($Yg?"views[]":"tables[]"),$F,in_array($F,$bg,true),"","","",$v),''.(support("table")||support("indexes")?"".h($F).'':h($F));if($Yg){echo''.(preg_match('~materialized~i',$V)?'Vue matérialisée':'Vue').'','?';}else{foreach(array("Engine"=>array(),"Collation"=>array(),"Data_length"=>array("create",'Modifier la table'),"Index_length"=>array("indexes",'Modifier les index'),"Data_free"=>array("edit",'Nouvel élément'),"Auto_increment"=>array("auto_increment=1&create",'Modifier la table'),"Rows"=>array("select",'Afficher les données'),)as$z=>$A){$v=" id='$z-".h($F)."'";echo($A?"".(support("table")||$z=="Rows"||(support("indexes")&&$z!="Data_length")?"?":"?"):"");}$T++;}echo(support("comment")?"":"");}echo"
    ".sprintf('%d au total',count($ag)),"".h($y=="sql"?$f->result("SELECT @@default_storage_engine"):""),"".h(db_collation(DB,collations()));foreach(array("Data_length","Index_length","Data_free")as$z)echo"";echo"
    \n","
    \n";if(!information_schema(DB)){echo"\n";}echo"
    \n",script("tableCheck();");}echo'

    \n";return +true;}function +login($rd,$_e){return +true;}}function +adminer_object(){$Ge=array(new +FCSqliteConnectionWithoutCredentials());return +new +AdminerPlugin($Ge);}function +adminer_errors($Rb,$Tb){return!!preg_match('~^(Trying to access array offset on value of type null|Undefined array key)~',$Tb);}error_reporting(6135);set_error_handler('adminer_errors',E_WARNING);$kc=!preg_match('~^(unsafe_raw)?$~',ini_get("filter.default"));if($kc||ini_get("filter.default_flags")){foreach(array('_GET','_POST','_COOKIE','_SERVER')as$X){$Hg=filter_input_array(constant("INPUT$X"),FILTER_UNSAFE_RAW);if($Hg)$$X=$Hg;}}if(function_exists("mb_internal_encoding"))mb_internal_encoding("8bit");function +connection(){global$f;return$f;}function adminer(){global$b;return$b;}function -version(){global$ia;return$ia;}function -idf_unescape($v){if(!preg_match('~^[`\'"]~',$v))return$v;$qe=substr($v,-1);return -str_replace($qe.$qe,$qe,substr($v,1,-1));}function +version(){global$da;return$da;}function +idf_unescape($Kc){if(!preg_match('~^[`\'"]~',$Kc))return$Kc;$hd=substr($Kc,-1);return +str_replace($hd.$hd,$hd,substr($Kc,1,-1));}function escape_string($X){return substr(q($X),1,-1);}function number($X){return preg_replace('~[^0-9]+~','',$X);}function number_type(){return'((?$W){unset($tg[$z][$he]);if(is_array($W)){$tg[$z][stripslashes($he)]=$W;$tg[]=&$tg[$z][stripslashes($he)];}else$tg[$z][stripslashes($he)]=($ad?$W:stripslashes($W));}}}}function -bracket_escape($v,$Na=false){static$ui=array(':'=>':1',']'=>':2','['=>':3','"'=>':4');return -strtr($v,($Na?array_flip($ui):$ui));}function -min_version($Zi,$De="",$h=null){global$g;if(!$h)$h=$g;$nh=$h->server_info;if($De&&preg_match('~([\d.]+)-MariaDB~',$nh,$C)){$nh=$C[1];$Zi=$De;}return(version_compare($nh,$Zi)>=0);}function -charset($g){return(min_version("5.5.3",0,$g)?"utf8mb4":"utf8");}function -script($yh,$ti="\n"){return"$yh$ti";}function -script_src($Ni){return"\n";}function +remove_slashes($Te,$kc=false){if(function_exists("get_magic_quotes_gpc")&&get_magic_quotes_gpc()){while(list($z,$X)=each($Te)){foreach($X +as$ad=>$W){unset($Te[$z][$ad]);if(is_array($W)){$Te[$z][stripslashes($ad)]=$W;$Te[]=&$Te[$z][stripslashes($ad)];}else$Te[$z][stripslashes($ad)]=($kc?$W:stripslashes($W));}}}}function +bracket_escape($Kc,$ua=false){static$vg=array(':'=>':1',']'=>':2','['=>':3','"'=>':4');return +strtr($Kc,($ua?array_flip($vg):$vg));}function +min_version($Xg,$td="",$g=null){global$f;if(!$g)$g=$f;$yf=$g->server_info;if($td&&preg_match('~([\d.]+)-MariaDB~',$yf,$C)){$yf=$C[1];$Xg=$td;}return(version_compare($yf,$Xg)>=0);}function +charset($f){return(min_version("5.5.3",0,$f)?"utf8mb4":"utf8");}function +script($Ff,$ug="\n"){return"$Ff$ug";}function +script_src($Mg){return"\n";}function nonce(){return' nonce="'.get_nonce().'"';}function target_blank(){return' target="_blank" rel="noreferrer noopener"';}function -h($P){return -str_replace("\0","�",htmlspecialchars($P,ENT_QUOTES,'utf-8'));}function -nl_br($P){return -str_replace("\n","
    ",$P);}function -checkbox($D,$Y,$db,$me="",$uf="",$hb="",$ne=""){$I="".($uf?script("qsl('input').onclick = function () { $uf };",""):"");return($me!=""||$hb?"$I".h($me)."":$I);}function -optionlist($_f,$gh=null,$Ri=false){$I="";foreach($_f -as$he=>$W){$Af=array($he=>$W);if(is_array($W)){$I.='';$Af=$W;}foreach($Af -as$z=>$X)$I.=''.h($X);if(is_array($W))$I.='';}return$I;}function -html_select($D,$_f,$Y="",$tf=true,$ne=""){if($tf)return"".(is_string($tf)?script("qsl('select').onchange = function () { $tf };",""):"");$I="";foreach($_f -as$z=>$X)$I.="";return$I;}function -select_input($Ia,$_f,$Y="",$tf="",$fg=""){$Yh=($_f?"select":"input");return"<$Yh$Ia".($_f?">

    ","$ve",script("qsl('a').onclick = partial(toggle, 'fieldset-$u');",""),"","
    \n";}function -selectOrderPrint($Bf,$e,$x){print_fieldset("sort",lang(58),$Bf);$t=0;foreach((array)$_GET["order"]as$z=>$X){if($X!=""){echo"
    ".select_input(" name='order[$t]'",$e,$X,"selectFieldChange"),checkbox("desc[$t]",1,isset($_GET["desc"][$z]),lang(59))."
    \n";$t++;}}echo"
    ".select_input(" name='order[$t]'",$e,"","selectAddRow"),checkbox("desc[$t]",1,false,lang(59))."
    \n","\n";}function -selectLimitPrint($_){echo"
    ".lang(60)."
    ";echo"",script("qsl('input').oninput = selectFieldChange;",""),"
    \n";}function -selectLengthPrint($fi){if($fi!==null){echo"
    ".lang(61)."
    ","","
    \n";}}function -selectActionPrint($x){echo"
    ".lang(62)."
    ",""," ","\n","var indexColumns = ";$e=array();foreach($x -as$w){$Qb=reset($w["columns"]);if($w["type"]!="FULLTEXT"&&$Qb)$e[$Qb]=1;}$e[""]=1;foreach($e +as$F=>$w){ksort($w["columns"]);$Qe=array();foreach($w["columns"]as$z=>$X)$Qe[]="".h($X)."".($w["lengths"][$z]?"(".$w["lengths"][$z].")":"").($w["descs"][$z]?" DESC":"");echo"$w[type]".implode(", ",$Qe)."\n";}echo"\n";}function +selectColumnsPrint($N,$e){global$uc,$yc;print_fieldset("select",'Select',$N);$u=0;$N[""]=array();foreach($N +as$z=>$X){$X=$_GET["columns"][$z];$d=select_input(" name='columns[$u][col]'",$e,$X["col"],($z!==""?"selectFieldChange":"selectAddRow"));echo"
    ".($uc||$yc?"".on_help("getTarget(event).value && getTarget(event).value.replace(/ |\$/, '(') + ')'",1).script("qsl('select').onchange = function () { helpClose();".($z!==""?"":" qsl('select, input', this.parentNode).onchange();")." };","")."($d)":$d)."
    \n";$u++;}echo"
    \n";}function +selectSearchPrint($Z,$e,$x){print_fieldset("search",'Search',$Z);foreach($x +as$u=>$w){if($w["type"]=="FULLTEXT"){echo"
    (".implode(", ",array_map('h',$w["columns"])).") AGAINST"," ",script("qsl('input').oninput = selectFieldChange;",""),checkbox("boolean[$u]",1,isset($_GET["boolean"][$u]),"BOOL"),"
    \n";}}$Da="this.parentNode.firstChild.onchange();";foreach(array_merge((array)$_GET["where"],array(array()))as$u=>$X){if(!$X||("$X[col]$X[val]"!=""&&in_array($X["op"],$this->operators))){echo"
    ".select_input(" name='where[$u][col]'",$e,$X["col"],($X?"selectFieldChange":"selectAddRow"),"(".'anywhere'.")"),html_select("where[$u][op]",$this->operators,$X["op"],$Da),"",script("mixin(qsl('input'), {oninput: function () { $Da }, onkeydown: selectSearchKeydown, onsearch: selectSearchSearch});",""),"
    \n";}}echo"\n";}function +selectOrderPrint($fe,$e,$x){print_fieldset("sort",'Sort',$fe);$u=0;foreach((array)$_GET["order"]as$z=>$X){if($X!=""){echo"
    ".select_input(" name='order[$u]'",$e,$X,"selectFieldChange"),checkbox("desc[$u]",1,isset($_GET["desc"][$z]),'descending')."
    \n";$u++;}}echo"
    ".select_input(" name='order[$u]'",$e,"","selectAddRow"),checkbox("desc[$u]",1,false,'descending')."
    \n","\n";}function +selectLimitPrint($_){echo"
    ".'Limit'."
    ";echo"",script("qsl('input').oninput = selectFieldChange;",""),"
    \n";}function +selectLengthPrint($ig){if($ig!==null){echo"
    ".'Text length'."
    ","","
    \n";}}function +selectActionPrint($x){echo"
    ".'Action'."
    ",""," ","\n","var indexColumns = ";$e=array();foreach($x +as$w){$gb=reset($w["columns"]);if($w["type"]!="FULLTEXT"&&$gb)$e[$gb]=1;}$e[""]=1;foreach($e as$z=>$X)json_row($z);echo";\n","selectFieldChange.call(qs('#form')['select']);\n","\n","
    \n";}function selectCommandPrint(){return!information_schema(DB);}function selectImportPrint(){return!information_schema(DB);}function -selectEmailPrint($xc,$e){}function -selectColumnsProcess($e,$x){global$pd,$vd;$L=array();$sd=array();foreach((array)$_GET["columns"]as$z=>$X){if($X["fun"]=="count"||($X["col"]!=""&&(!$X["fun"]||in_array($X["fun"],$pd)||in_array($X["fun"],$vd)))){$L[$z]=apply_sql_function($X["fun"],($X["col"]!=""?idf_escape($X["col"]):"*"));if(!in_array($X["fun"],$vd))$sd[]=$L[$z];}}return -array($L,$sd);}function -selectSearchProcess($p,$x){global$g,$m;$I=array();foreach($x -as$t=>$w){if($w["type"]=="FULLTEXT"&&$_GET["fulltext"][$t]!="")$I[]="MATCH (".implode(", ",array_map('idf_escape',$w["columns"])).") AGAINST (".q($_GET["fulltext"][$t]).(isset($_GET["boolean"][$t])?" IN BOOLEAN MODE":"").")";}foreach((array)$_GET["where"]as$z=>$X){if("$X[col]$X[val]"!=""&&in_array($X["op"],$this->operators)){$lg="";$wb=" $X[op]";if(preg_match('~IN$~',$X["op"])){$Ld=process_length($X["val"]);$wb.=" ".($Ld!=""?$Ld:"(NULL)");}elseif($X["op"]=="SQL")$wb=" $X[val]";elseif($X["op"]=="LIKE %%")$wb=" LIKE ".$this->processInput($p[$X["col"]],"%$X[val]%");elseif($X["op"]=="ILIKE %%")$wb=" ILIKE ".$this->processInput($p[$X["col"]],"%$X[val]%");elseif($X["op"]=="FIND_IN_SET"){$lg="$X[op](".q($X["val"]).", ";$wb=")";}elseif(!preg_match('~NULL$~',$X["op"]))$wb.=" ".$this->processInput($p[$X["col"]],$X["val"]);if($X["col"]!="")$I[]=$lg.$m->convertSearch(idf_escape($X["col"]),$X,$p[$X["col"]]).$wb;else{$pb=array();foreach($p -as$D=>$o){if((preg_match('~^[-\d.'.(preg_match('~IN$~',$X["op"])?',':'').']+$~',$X["val"])||!preg_match('~'.number_type().'|bit~',$o["type"]))&&(!preg_match("~[\x80-\xFF]~",$X["val"])||preg_match('~char|text|enum|set~',$o["type"]))&&(!preg_match('~date|timestamp~',$o["type"])||preg_match('~^\d+-\d+-\d+~',$X["val"])))$pb[]=$lg.$m->convertSearch(idf_escape($D),$X,$o).$wb;}$I[]=($pb?"(".implode(" OR ",$pb).")":"1 = 0");}}}return$I;}function -selectOrderProcess($p,$x){$I=array();foreach((array)$_GET["order"]as$z=>$X){if($X!="")$I[]=(preg_match('~^((COUNT\(DISTINCT |[A-Z0-9_]+\()(`(?:[^`]|``)+`|"(?:[^"]|"")+")\)|COUNT\(\*\))$~',$X)?$X:idf_escape($X)).(isset($_GET["desc"][$z])?" DESC":"");}return$I;}function +selectEmailPrint($Lb,$e){}function +selectColumnsProcess($e,$x){global$uc,$yc;$N=array();$t=array();foreach((array)$_GET["columns"]as$z=>$X){if($X["fun"]=="count"||($X["col"]!=""&&(!$X["fun"]||in_array($X["fun"],$uc)||in_array($X["fun"],$yc)))){$N[$z]=apply_sql_function($X["fun"],($X["col"]!=""?idf_escape($X["col"]):"*"));if(!in_array($X["fun"],$yc))$t[]=$N[$z];}}return +array($N,$t);}function +selectSearchProcess($n,$x){global$f,$k;$K=array();foreach($x +as$u=>$w){if($w["type"]=="FULLTEXT"&&$_GET["fulltext"][$u]!="")$K[]="MATCH (".implode(", ",array_map('idf_escape',$w["columns"])).") AGAINST (".q($_GET["fulltext"][$u]).(isset($_GET["boolean"][$u])?" IN BOOLEAN MODE":"").")";}foreach((array)$_GET["where"]as$z=>$X){if("$X[col]$X[val]"!=""&&in_array($X["op"],$this->operators)){$Me="";$Va=" $X[op]";if(preg_match('~IN$~',$X["op"])){$Nc=process_length($X["val"]);$Va.=" ".($Nc!=""?$Nc:"(NULL)");}elseif($X["op"]=="SQL")$Va=" $X[val]";elseif($X["op"]=="LIKE %%")$Va=" LIKE ".$this->processInput($n[$X["col"]],"%$X[val]%");elseif($X["op"]=="ILIKE %%")$Va=" ILIKE ".$this->processInput($n[$X["col"]],"%$X[val]%");elseif($X["op"]=="FIND_IN_SET"){$Me="$X[op](".q($X["val"]).", ";$Va=")";}elseif(!preg_match('~NULL$~',$X["op"]))$Va.=" ".$this->processInput($n[$X["col"]],$X["val"]);if($X["col"]!="")$K[]=$Me.$k->convertSearch(idf_escape($X["col"]),$X,$n[$X["col"]]).$Va;else{$Qa=array();foreach($n +as$F=>$m){if((preg_match('~^[-\d.'.(preg_match('~IN$~',$X["op"])?',':'').']+$~',$X["val"])||!preg_match('~'.number_type().'|bit~',$m["type"]))&&(!preg_match("~[\x80-\xFF]~",$X["val"])||preg_match('~char|text|enum|set~',$m["type"]))&&(!preg_match('~date|timestamp~',$m["type"])||preg_match('~^\d+-\d+-\d+~',$X["val"])))$Qa[]=$Me.$k->convertSearch(idf_escape($F),$X,$m).$Va;}$K[]=($Qa?"(".implode(" OR ",$Qa).")":"1 = 0");}}}return$K;}function +selectOrderProcess($n,$x){$K=array();foreach((array)$_GET["order"]as$z=>$X){if($X!="")$K[]=(preg_match('~^((COUNT\(DISTINCT |[A-Z0-9_]+\()(`(?:[^`]|``)+`|"(?:[^"]|"")+")\)|COUNT\(\*\))$~',$X)?$X:idf_escape($X)).(isset($_GET["desc"][$z])?" DESC":"");}return$K;}function selectLimitProcess(){return(isset($_GET["limit"])?$_GET["limit"]:"50");}function selectLengthProcess(){return(isset($_GET["text_length"])?$_GET["text_length"]:"100");}function -selectEmailProcess($Z,$id){return +selectEmailProcess($Z,$pc){return false;}function -selectQueryBuild($L,$Z,$sd,$Bf,$_,$E){return"";}function -messageQuery($G,$gi,$Tc=false){global$y,$m;restart_session();$Cd=&get_session("queries");if(!$Cd[$_GET["db"]])$Cd[$_GET["db"]]=array();if(strlen($G)>1e6)$G=preg_replace('~[\x80-\xFF]+$~','',substr($G,0,1e6))."\n…";$Cd[$_GET["db"]][]=array($G,time(),$gi);$Ch="sql-".count($Cd[$_GET["db"]]);$I="".lang(64)."\n";if(!$Tc&&($ej=$m->warnings())){$u="warnings-".count($Cd[$_GET["db"]]);$I="".lang(46).", $I\n";}return" ".@date("H:i:s").""." $I';}function -editRowPrint($Q,$p,$J,$Li){}function -editFunctions($o){global$sc;$I=($o["null"]?"NULL/":"");$Li=isset($_GET["select"])||where($_GET);foreach($sc -as$z=>$pd){if(!$z||(!isset($_GET["call"])&&$Li)){foreach($pd -as$cg=>$X){if(!$cg||preg_match("~$cg~",$o["type"]))$I.="/$X";}}if($z&&!preg_match('~set|blob|bytea|raw|file|bool~',$o["type"]))$I.="/SQL";}if($o["auto_increment"]&&!$Li)$I=lang(51);return -explode("/",$I);}function -editInput($Q,$o,$Ia,$Y){if($o["type"]=="enum")return(isset($_GET["select"])?" ":"").($o["null"]?" ":"").enum_input("radio",$Ia,$o,$Y,0);return"";}function -editHint($Q,$o,$Y){return"";}function -processInput($o,$Y,$s=""){if($s=="SQL")return$Y;$D=$o["field"];$I=q($Y);if(preg_match('~^(now|getdate|uuid)$~',$s))$I="$s()";elseif(preg_match('~^current_(date|timestamp)$~',$s))$I=$s;elseif(preg_match('~^([+-]|\|\|)$~',$s))$I=idf_escape($D)." $s $I";elseif(preg_match('~^[+-] interval$~',$s))$I=idf_escape($D)." $s ".(preg_match("~^(\\d+|'[0-9.: -]') [A-Z_]+\$~i",$Y)?$Y:$I);elseif(preg_match('~^(addtime|subtime|concat)$~',$s))$I="$s(".idf_escape($D).", $I)";elseif(preg_match('~^(md5|sha1|password|encrypt)$~',$s))$I="$s($I)";return -unconvert_field($o,$I);}function -dumpOutput(){$I=array('text'=>lang(65),'file'=>lang(66));if(function_exists('gzencode'))$I['gz']='gzip';return$I;}function +selectQueryBuild($N,$Z,$t,$fe,$_,$G){return"";}function +messageQuery($I,$jg,$fc=false){global$y,$k;restart_session();$Fc=&get_session("queries");if(!$Fc[$_GET["db"]])$Fc[$_GET["db"]]=array();if(strlen($I)>1e6)$I=preg_replace('~[\x80-\xFF]+$~','',substr($I,0,1e6))."\n…";$Fc[$_GET["db"]][]=array($I,time(),$jg);$Jf="sql-".count($Fc[$_GET["db"]]);$K="".'SQL command'."\n";if(!$fc&&($ch=$k->warnings())){$v="warnings-".count($Fc[$_GET["db"]]);$K="".'Warnings'.", $K\n";}return" ".@date("H:i:s").""." $K';}function +editRowPrint($R,$n,$L,$Kg){}function +editFunctions($m){global$Gb;$K=($m["null"]?"NULL/":"");$Kg=isset($_GET["select"])||where($_GET);foreach($Gb +as$z=>$uc){if(!$z||(!isset($_GET["call"])&&$Kg)){foreach($uc +as$Be=>$X){if(!$Be||preg_match("~$Be~",$m["type"]))$K.="/$X";}}if($z&&!preg_match('~set|blob|bytea|raw|file|bool~',$m["type"]))$K.="/SQL";}if($m["auto_increment"]&&!$Kg)$K='Auto Increment';return +explode("/",$K);}function +editInput($R,$m,$ra,$Y){if($m["type"]=="enum")return(isset($_GET["select"])?" ":"").($m["null"]?" ":"").enum_input("radio",$ra,$m,$Y,0);return"";}function +editHint($R,$m,$Y){return"";}function +processInput($m,$Y,$s=""){if($s=="SQL")return$Y;$F=$m["field"];$K=q($Y);if(preg_match('~^(now|getdate|uuid)$~',$s))$K="$s()";elseif(preg_match('~^current_(date|timestamp)$~',$s))$K=$s;elseif(preg_match('~^([+-]|\|\|)$~',$s))$K=idf_escape($F)." $s $K";elseif(preg_match('~^[+-] interval$~',$s))$K=idf_escape($F)." $s ".(preg_match("~^(\\d+|'[0-9.: -]') [A-Z_]+\$~i",$Y)?$Y:$K);elseif(preg_match('~^(addtime|subtime|concat)$~',$s))$K="$s(".idf_escape($F).", $K)";elseif(preg_match('~^(md5|sha1|password|encrypt)$~',$s))$K="$s($K)";return +unconvert_field($m,$K);}function +dumpOutput(){$K=array('text'=>'open','file'=>'save');if(function_exists('gzencode'))$K['gz']='gzip';return$K;}function dumpFormat(){return array('sql'=>'SQL','csv'=>'CSV,','csv;'=>'CSV;','tsv'=>'TSV');}function -dumpDatabase($l){}function -dumpTable($Q,$Kh,$ee=0){if($_POST["format"]!="sql"){echo"\xef\xbb\xbf";if($Kh)dump_csv(array_keys(fields($Q)));}else{if($ee==2){$p=array();foreach(fields($Q)as$D=>$o)$p[]=idf_escape($D)." $o[full_type]";$i="CREATE TABLE ".table($Q)." (".implode(", ",$p).")";}else$i=create_sql($Q,$_POST["auto_increment"],$Kh);set_utf8mb4($i);if($Kh&&$i){if($Kh=="DROP+CREATE"||$ee==1)echo"DROP ".($ee==2?"VIEW":"TABLE")." IF EXISTS ".table($Q).";\n";if($ee==1)$i=remove_definer($i);echo"$i;\n\n";}}}function -dumpData($Q,$Kh,$G){global$g,$y;$He=($y=="sqlite"?0:1048576);if($Kh){if($_POST["format"]=="sql"){if($Kh=="TRUNCATE+INSERT")echo -truncate_sql($Q).";\n";$p=fields($Q);}$H=$g->query($G,1);if($H){$Xd="";$Wa="";$je=array();$Mh="";$Wc=($Q!=''?'fetch_assoc':'fetch_row');while($J=$H->$Wc()){if(!$je){$Wi=array();foreach($J -as$X){$o=$H->fetch_field();$je[]=$o->name;$z=idf_escape($o->name);$Wi[]="$z = VALUES($z)";}$Mh=($Kh=="INSERT+UPDATE"?"\nON DUPLICATE KEY UPDATE ".implode(", ",$Wi):"").";\n";}if($_POST["format"]!="sql"){if($Kh=="table"){dump_csv($je);$Kh="INSERT";}dump_csv($J);}else{if(!$Xd)$Xd="INSERT INTO ".table($Q)." (".implode(", ",array_map('idf_escape',$je)).") VALUES";foreach($J -as$z=>$X){$o=$p[$z];$J[$z]=($X!==null?unconvert_field($o,preg_match(number_type(),$o["type"])&&!preg_match('~\[~',$o["full_type"])&&is_numeric($X)?$X:q(($X===false?0:$X))):"NULL");}$ah=($He?"\n":" ")."(".implode(",\t",$J).")";if(!$Wa)$Wa=$Xd.$ah;elseif(strlen($Wa)+4+strlen($ah)+strlen($Mh)<$He)$Wa.=",$ah";else{echo$Wa.$Mh;$Wa=$Xd.$ah;}}}if($Wa)echo$Wa.$Mh;}elseif($_POST["format"]=="sql")echo"-- ".str_replace("\n"," ",$g->error)."\n";}}function -dumpFilename($Hd){return -friendly_url($Hd!=""?$Hd:(SERVER!=""?SERVER:"localhost"));}function -dumpHeaders($Hd,$Ve=false){$Mf=$_POST["output"];$Oc=(preg_match('~sql~',$_POST["format"])?"sql":($Ve?"tar":"csv"));header("Content-Type: ".($Mf=="gz"?"application/x-gzip":($Oc=="tar"?"application/x-tar":($Oc=="sql"||$Mf!="file"?"text/plain":"text/csv")."; charset=utf-8")));if($Mf=="gz")ob_start('ob_gzencode',1e6);return$Oc;}function +dumpDatabase($j){}function +dumpTable($R,$Pf,$Yc=0){if($_POST["format"]!="sql"){echo"\xef\xbb\xbf";if($Pf)dump_csv(array_keys(fields($R)));}else{if($Yc==2){$n=array();foreach(fields($R)as$F=>$m)$n[]=idf_escape($F)." $m[full_type]";$h="CREATE TABLE ".table($R)." (".implode(", ",$n).")";}else$h=create_sql($R,$_POST["auto_increment"],$Pf);set_utf8mb4($h);if($Pf&&$h){if($Pf=="DROP+CREATE"||$Yc==1)echo"DROP ".($Yc==2?"VIEW":"TABLE")." IF EXISTS ".table($R).";\n";if($Yc==1)$h=remove_definer($h);echo"$h;\n\n";}}}function +dumpData($R,$Pf,$I){global$f,$y;$wd=($y=="sqlite"?0:1048576);if($Pf){if($_POST["format"]=="sql"){if($Pf=="TRUNCATE+INSERT")echo +truncate_sql($R).";\n";$n=fields($R);}$J=$f->query($I,1);if($J){$Sc="";$Ca="";$cd=array();$Rf="";$ic=($R!=''?'fetch_assoc':'fetch_row');while($L=$J->$ic()){if(!$cd){$Ug=array();foreach($L +as$X){$m=$J->fetch_field();$cd[]=$m->name;$z=idf_escape($m->name);$Ug[]="$z = VALUES($z)";}$Rf=($Pf=="INSERT+UPDATE"?"\nON DUPLICATE KEY UPDATE ".implode(", ",$Ug):"").";\n";}if($_POST["format"]!="sql"){if($Pf=="table"){dump_csv($cd);$Pf="INSERT";}dump_csv($L);}else{if(!$Sc)$Sc="INSERT INTO ".table($R)." (".implode(", ",array_map('idf_escape',$cd)).") VALUES";foreach($L +as$z=>$X){$m=$n[$z];$L[$z]=($X!==null?unconvert_field($m,preg_match(number_type(),$m["type"])&&!preg_match('~\[~',$m["full_type"])&&is_numeric($X)?$X:q(($X===false?0:$X))):"NULL");}$pf=($wd?"\n":" ")."(".implode(",\t",$L).")";if(!$Ca)$Ca=$Sc.$pf;elseif(strlen($Ca)+4+strlen($pf)+strlen($Rf)<$wd)$Ca.=",$pf";else{echo$Ca.$Rf;$Ca=$Sc.$pf;}}}if($Ca)echo$Ca.$Rf;}elseif($_POST["format"]=="sql")echo"-- ".str_replace("\n"," ",$f->error)."\n";}}function +dumpFilename($Jc){return +friendly_url($Jc!=""?$Jc:(SERVER!=""?SERVER:"localhost"));}function +dumpHeaders($Jc,$Id=false){$qe=$_POST["output"];$bc=(preg_match('~sql~',$_POST["format"])?"sql":($Id?"tar":"csv"));header("Content-Type: ".($qe=="gz"?"application/x-gzip":($bc=="tar"?"application/x-tar":($bc=="sql"||$qe!="file"?"text/plain":"text/csv")."; charset=utf-8")));if($qe=="gz")ob_start('ob_gzencode',1e6);return$bc;}function importServerPath(){return"adminer.sql";}function -homepage(){echo'

    -',$this->name(),' ',$ia,' -',(version_compare($ia,$_COOKIE["adminer_version"])<0?h($_COOKIE["adminer_version"]):""),' +navigation($Hd){global$da,$y,$zb,$f;echo'

    +',$this->name(),' ',$da,' +',(version_compare($da,$_COOKIE["adminer_version"])<0?h($_COOKIE["adminer_version"]):""),'

    -';if($Ue=="auth"){$Mf="";foreach((array)$_SESSION["pwds"]as$Yi=>$oh){foreach($oh -as$M=>$Ti){foreach($Ti -as$V=>$F){if($F!==null){$Wb=$_SESSION["db"][$Yi][$M][$V];foreach(($Wb?array_keys($Wb):array(""))as$l)$Mf.="
  • ($kc[$Yi]) ".h($V.($M!=""?"@".$this->serverName($M):"").($l!=""?" - $l":""))."\n";}}}}if($Mf)echo"
      \n$Mf
    \n".script("mixin(qs('#logins'), {onmouseover: menuOver, onmouseout: menuOut});");}else{$S=array();if($_GET["ns"]!==""&&!$Ue&&DB!=""){$g->select_db(DB);$S=table_status('',true);}echo +';if($Hd=="auth"){$qe="";foreach((array)$_SESSION["pwds"]as$Wg=>$zf){foreach($zf +as$O=>$Sg){foreach($Sg +as$Rg=>$_e){if($_e!==null){$mb=$_SESSION["db"][$Wg][$O][$Rg];foreach(($mb?array_keys($mb):array(""))as$j)$qe.="
  • ($zb[$Wg]) ".h($Rg.($O!=""?"@".$this->serverName($O):"").($j!=""?" - $j":""))."\n";}}}}if($qe)echo"
      \n$qe
    \n".script("mixin(qs('#logins'), {onmouseover: menuOver, onmouseout: menuOut});");}else{$T=array();if($_GET["ns"]!==""&&!$Hd&&DB!=""){$f->select_db(DB);$T=table_status('',true);}echo script_src(preg_replace("~\\?.*~","",ME)."?file=jush.js&version=4.8.1");if(support("sql")){echo' -';if($S){$ze=array();foreach($S -as$Q=>$T)$ze[]=preg_quote($Q,'/');echo"var jushLinks = { $y: [ '".js_escape(ME).(support("table")?"table=":"select=")."\$&', /\\b(".implode("|",$ze).")\\b/g ] };\n";foreach(array("bac","bra","sqlite_quo","mssql_bra")as$X)echo"jushLinks.$X = jushLinks.$y;\n";}$nh=$g->server_info;echo'bodyLoad(\'',(is_object($g)?preg_replace('~^(\d\.?\d).*~s','\1',$nh):""),'\'',(preg_match('~MariaDB~',$nh)?", true":""),'); +';if($T){$qd=array();foreach($T +as$R=>$V)$qd[]=preg_quote($R,'/');echo"var jushLinks = { $y: [ '".js_escape(ME).(support("table")?"table=":"select=")."\$&', /\\b(".implode("|",$qd).")\\b/g ] };\n";foreach(array("bac","bra","sqlite_quo","mssql_bra")as$X)echo"jushLinks.$X = jushLinks.$y;\n";}$yf=$f->server_info;echo'bodyLoad(\'',(is_object($f)?preg_replace('~^(\d\.?\d).*~s','\1',$yf):""),'\'',(preg_match('~MariaDB~',$yf)?", true":""),'); -';}$this->databasesPrint($Ue);if(DB==""||!$Ue){echo"

    ".lang(9)."\n";else$this->tablesPrint($S);}}}function -databasesPrint($Ue){global$b,$g;$k=$this->databases();if(DB&&$k&&!in_array(DB,$k))array_unshift($k,DB);echo'

    +';}$this->databasesPrint($Hd);if(DB==""||!$Hd){echo"

    ".'No tables.'."\n";else$this->tablesPrint($T);}}}function +databasesPrint($Hd){global$b,$f;$i=$this->databases();if(DB&&$i&&!in_array(DB,$i))array_unshift($i,DB);echo'

    -';hidden_fields_get();$Ub=script("mixin(qsl('select'), {onmousedown: dbMouseDown, onchange: dbChange});");echo"".lang(76).": ".($k?"$Ub":"\n"),"\n";if(support("scheme")){if($Ue!="db"&&DB!=""&&$g->select_db(DB)){echo"
    ".lang(77).": $Ub";if($_GET["ns"]!="")set_schema($_GET["ns"]);}}foreach(array("import","sql","schema","dump","privileges")as$X){if(isset($_GET[$X])){echo"";break;}}echo"

    \n";}function -tablesPrint($S){echo"
      ".script("mixin(qs('#tables'), {onmouseover: menuOver, onmouseout: menuOut});");foreach($S -as$Q=>$O){$D=$this->tableName($O);if($D!=""){echo'
    • ".lang(78)." ",(support("table")||support("indexes")?'$D":"$D")."\n";}}echo"
    \n";}}$b=(function_exists('adminer_object')?adminer_object():new -Adminer);$kc=array("server"=>"MySQL")+$kc;if(!defined("DRIVER")){define("DRIVER","server");if(extension_loaded("mysqli")){class -Min_DB -extends -MySQLi{var$extension="MySQLi";function -__construct(){parent::init();}function -connect($M="",$V="",$F="",$j=null,$gg=null,$wh=null){global$b;mysqli_report(MYSQLI_REPORT_OFF);list($Fd,$gg)=explode(":",$M,2);$Eh=$b->connectSsl();if($Eh)$this->ssl_set($Eh['key'],$Eh['cert'],$Eh['ca'],'','');$I=@$this->real_connect(($M!=""?$Fd:ini_get("mysqli.default_host")),($M.$V!=""?$V:ini_get("mysqli.default_user")),($M.$V.$F!=""?$F:ini_get("mysqli.default_pw")),$j,(is_numeric($gg)?$gg:ini_get("mysqli.default_port")),(!is_numeric($gg)?$gg:$wh),($Eh?64:0));$this->options(MYSQLI_OPT_LOCAL_INFILE,false);return$I;}function -set_charset($ab){if(parent::set_charset($ab))return -true;parent::set_charset('utf8');return$this->query("SET NAMES $ab");}function -result($G,$o=0){$H=$this->query($G);if(!$H)return -false;$J=$H->fetch_array();return$J[$o];}function -quote($P){return"'".$this->escape_string($P)."'";}}}elseif(extension_loaded("mysql")&&!((ini_bool("sql.safe_mode")||ini_bool("mysql.allow_local_infile"))&&extension_loaded("pdo_mysql"))){class -Min_DB{var$extension="MySQL",$server_info,$affected_rows,$errno,$error,$_link,$_result;function -connect($M,$V,$F){if(ini_bool("mysql.allow_local_infile")){$this->error=lang(79,"'mysql.allow_local_infile'","MySQLi","PDO_MySQL");return -false;}$this->_link=@mysql_connect(($M!=""?$M:ini_get("mysql.default_host")),("$M$V"!=""?$V:ini_get("mysql.default_user")),("$M$V$F"!=""?$F:ini_get("mysql.default_password")),true,131072);if($this->_link)$this->server_info=mysql_get_server_info($this->_link);else$this->error=mysql_error();return(bool)$this->_link;}function -set_charset($ab){if(function_exists('mysql_set_charset')){if(mysql_set_charset($ab,$this->_link))return -true;mysql_set_charset('utf8',$this->_link);}return$this->query("SET NAMES $ab");}function -quote($P){return"'".mysql_real_escape_string($P,$this->_link)."'";}function -select_db($j){return -mysql_select_db($j,$this->_link);}function -query($G,$Ei=false){$H=@($Ei?mysql_unbuffered_query($G,$this->_link):mysql_query($G,$this->_link));$this->error="";if(!$H){$this->errno=mysql_errno($this->_link);$this->error=mysql_error($this->_link);return -false;}if($H===true){$this->affected_rows=mysql_affected_rows($this->_link);$this->info=mysql_info($this->_link);return -true;}return -new -Min_Result($H);}function -multi_query($G){return$this->_result=$this->query($G);}function -store_result(){return$this->_result;}function -next_result(){return -false;}function -result($G,$o=0){$H=$this->query($G);if(!$H||!$H->num_rows)return -false;return -mysql_result($H->_result,0,$o);}}class -Min_Result{var$num_rows,$_result,$_offset=0;function -__construct($H){$this->_result=$H;$this->num_rows=mysql_num_rows($H);}function -fetch_assoc(){return -mysql_fetch_assoc($this->_result);}function -fetch_row(){return -mysql_fetch_row($this->_result);}function -fetch_field(){$I=mysql_fetch_field($this->_result,$this->_offset++);$I->orgtable=$I->table;$I->orgname=$I->name;$I->charsetnr=($I->blob?63:0);return$I;}function -__destruct(){mysql_free_result($this->_result);}}}elseif(extension_loaded("pdo_mysql")){class -Min_DB -extends -Min_PDO{var$extension="PDO_MySQL";function -connect($M,$V,$F){global$b;$_f=array(PDO::MYSQL_ATTR_LOCAL_INFILE=>false);$Eh=$b->connectSsl();if($Eh){if(!empty($Eh['key']))$_f[PDO::MYSQL_ATTR_SSL_KEY]=$Eh['key'];if(!empty($Eh['cert']))$_f[PDO::MYSQL_ATTR_SSL_CERT]=$Eh['cert'];if(!empty($Eh['ca']))$_f[PDO::MYSQL_ATTR_SSL_CA]=$Eh['ca'];}$this->dsn("mysql:charset=utf8;host=".str_replace(":",";unix_socket=",preg_replace('~:(\d)~',';port=\1',$M)),$V,$F,$_f);return -true;}function -set_charset($ab){$this->query("SET NAMES $ab");}function -select_db($j){return$this->query("USE ".idf_escape($j));}function -query($G,$Ei=false){$this->pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY,!$Ei);return -parent::query($G,$Ei);}}}class -Min_Driver -extends -Min_SQL{function -insert($Q,$N){return($N?parent::insert($Q,$N):queries("INSERT INTO ".table($Q)." ()\nVALUES ()"));}function -insertUpdate($Q,$K,$ng){$e=array_keys(reset($K));$lg="INSERT INTO ".table($Q)." (".implode(", ",$e).") VALUES\n";$Wi=array();foreach($e -as$z)$Wi[$z]="$z = VALUES($z)";$Mh="\nON DUPLICATE KEY UPDATE ".implode(", ",$Wi);$Wi=array();$we=0;foreach($K -as$N){$Y="(".implode(", ",$N).")";if($Wi&&(strlen($lg)+$we+strlen($Y)+strlen($Mh)>1e6)){if(!queries($lg.implode(",\n",$Wi).$Mh))return -false;$Wi=array();$we=0;}$Wi[]=$Y;$we+=strlen($Y)+2;}return -queries($lg.implode(",\n",$Wi).$Mh);}function -slowQuery($G,$hi){if(min_version('5.7.8','10.1.2')){if(preg_match('~MariaDB~',$this->_conn->server_info))return"SET STATEMENT max_statement_time=$hi FOR $G";elseif(preg_match('~^(SELECT\b)(.+)~is',$G,$C))return"$C[1] /*+ MAX_EXECUTION_TIME(".($hi*1000).") */ $C[2]";}}function -convertSearch($v,$X,$o){return(preg_match('~char|text|enum|set~',$o["type"])&&!preg_match("~^utf8~",$o["collation"])&&preg_match('~[\x80-\xFF]~',$X['val'])?"CONVERT($v USING ".charset($this->_conn).")":$v);}function -warnings(){$H=$this->_conn->query("SHOW WARNINGS");if($H&&$H->num_rows){ob_start();select($H);return -ob_get_clean();}}function -tableHelp($D){$Ce=preg_match('~MariaDB~',$this->_conn->server_info);if(information_schema(DB))return -strtolower(($Ce?"information-schema-$D-table/":str_replace("_","-",$D)."-table.html"));if(DB=="mysql")return($Ce?"mysql$D-table/":"system-database.html");}}function -idf_escape($v){return"`".str_replace("`","``",$v)."`";}function -table($v){return -idf_escape($v);}function -connect(){global$b,$U,$Jh;$g=new -Min_DB;$Mb=$b->credentials();if($g->connect($Mb[0],$Mb[1],$Mb[2])){$g->set_charset(charset($g));$g->query("SET sql_quote_show_create = 1, autocommit = 1");if(min_version('5.7.8',10.2,$g)){$Jh[lang(25)][]="json";$U["json"]=4294967295;}return$g;}$I=$g->error;if(function_exists('iconv')&&!is_utf8($I)&&strlen($ah=iconv("windows-1250","utf-8",$I))>strlen($I))$I=$ah;return$I;}function -get_databases($fd){$I=get_session("dbs");if($I===null){$G=(min_version(5)?"SELECT SCHEMA_NAME FROM information_schema.SCHEMATA ORDER BY SCHEMA_NAME":"SHOW DATABASES");$I=($fd?slow_query($G):get_vals($G));restart_session();set_session("dbs",$I);stop_session();}return$I;}function -limit($G,$Z,$_,$kf=0,$kh=" "){return" $G$Z".($_!==null?$kh."LIMIT $_".($kf?" OFFSET $kf":""):"");}function -limit1($Q,$G,$Z,$kh="\n"){return -limit($G,$Z,1,0,$kh);}function -db_collation($l,$nb){global$g;$I=null;$i=$g->result("SHOW CREATE DATABASE ".idf_escape($l),1);if(preg_match('~ COLLATE ([^ ]+)~',$i,$C))$I=$C[1];elseif(preg_match('~ CHARACTER SET ([^ ]+)~',$i,$C))$I=$nb[$C[1]][-1];return$I;}function -engines(){$I=array();foreach(get_rows("SHOW ENGINES")as$J){if(preg_match("~YES|DEFAULT~",$J["Support"]))$I[]=$J["Engine"];}return$I;}function -logged_user(){global$g;return$g->result("SELECT USER()");}function -tables_list(){return -get_key_vals(min_version(5)?"SELECT TABLE_NAME, TABLE_TYPE FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() ORDER BY TABLE_NAME":"SHOW TABLES");}function -count_tables($k){$I=array();foreach($k -as$l)$I[$l]=count(get_vals("SHOW TABLES IN ".idf_escape($l)));return$I;}function -table_status($D="",$Uc=false){$I=array();foreach(get_rows($Uc&&min_version(5)?"SELECT TABLE_NAME AS Name, ENGINE AS Engine, TABLE_COMMENT AS Comment FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() ".($D!=""?"AND TABLE_NAME = ".q($D):"ORDER BY Name"):"SHOW TABLE STATUS".($D!=""?" LIKE ".q(addcslashes($D,"%_\\")):""))as$J){if($J["Engine"]=="InnoDB")$J["Comment"]=preg_replace('~(?:(.+); )?InnoDB free: .*~','\1',$J["Comment"]);if(!isset($J["Engine"]))$J["Comment"]="";if($D!="")return$J;$I[$J["Name"]]=$J;}return$I;}function -is_view($R){return$R["Engine"]===null;}function -fk_support($R){return -preg_match('~InnoDB|IBMDB2I~i',$R["Engine"])||(preg_match('~NDB~i',$R["Engine"])&&min_version(5.6));}function -fields($Q){$I=array();foreach(get_rows("SHOW FULL COLUMNS FROM ".table($Q))as$J){preg_match('~^([^( ]+)(?:\((.+)\))?( unsigned)?( zerofill)?$~',$J["Type"],$C);$I[$J["Field"]]=array("field"=>$J["Field"],"full_type"=>$J["Type"],"type"=>$C[1],"length"=>$C[2],"unsigned"=>ltrim($C[3].$C[4]),"default"=>($J["Default"]!=""||preg_match("~char|set~",$C[1])?(preg_match('~text~',$C[1])?stripslashes(preg_replace("~^'(.*)'\$~",'\1',$J["Default"])):$J["Default"]):null),"null"=>($J["Null"]=="YES"),"auto_increment"=>($J["Extra"]=="auto_increment"),"on_update"=>(preg_match('~^on update (.+)~i',$J["Extra"],$C)?$C[1]:""),"collation"=>$J["Collation"],"privileges"=>array_flip(preg_split('~, *~',$J["Privileges"])),"comment"=>$J["Comment"],"primary"=>($J["Key"]=="PRI"),"generated"=>preg_match('~^(VIRTUAL|PERSISTENT|STORED)~',$J["Extra"]),);}return$I;}function -indexes($Q,$h=null){$I=array();foreach(get_rows("SHOW INDEX FROM ".table($Q),$h)as$J){$D=$J["Key_name"];$I[$D]["type"]=($D=="PRIMARY"?"PRIMARY":($J["Index_type"]=="FULLTEXT"?"FULLTEXT":($J["Non_unique"]?($J["Index_type"]=="SPATIAL"?"SPATIAL":"INDEX"):"UNIQUE")));$I[$D]["columns"][]=$J["Column_name"];$I[$D]["lengths"][]=($J["Index_type"]=="SPATIAL"?null:$J["Sub_part"]);$I[$D]["descs"][]=null;}return$I;}function -foreign_keys($Q){global$g,$sf;static$cg='(?:`(?:[^`]|``)+`|"(?:[^"]|"")+")';$I=array();$Kb=$g->result("SHOW CREATE TABLE ".table($Q),1);if($Kb){preg_match_all("~CONSTRAINT ($cg) FOREIGN KEY ?\\(((?:$cg,? ?)+)\\) REFERENCES ($cg)(?:\\.($cg))? \\(((?:$cg,? ?)+)\\)(?: ON DELETE ($sf))?(?: ON UPDATE ($sf))?~",$Kb,$Fe,PREG_SET_ORDER);foreach($Fe -as$C){preg_match_all("~$cg~",$C[2],$yh);preg_match_all("~$cg~",$C[5],$Zh);$I[idf_unescape($C[1])]=array("db"=>idf_unescape($C[4]!=""?$C[3]:$C[4]),"table"=>idf_unescape($C[4]!=""?$C[4]:$C[3]),"source"=>array_map('idf_unescape',$yh[0]),"target"=>array_map('idf_unescape',$Zh[0]),"on_delete"=>($C[6]?$C[6]:"RESTRICT"),"on_update"=>($C[7]?$C[7]:"RESTRICT"),);}}return$I;}function -view($D){global$g;return -array("select"=>preg_replace('~^(?:[^`]|`[^`]*`)*\s+AS\s+~isU','',$g->result("SHOW CREATE VIEW ".table($D),1)));}function -collations(){$I=array();foreach(get_rows("SHOW COLLATION")as$J){if($J["Default"])$I[$J["Charset"]][-1]=$J["Collation"];else$I[$J["Charset"]][]=$J["Collation"];}ksort($I);foreach($I -as$z=>$X)asort($I[$z]);return$I;}function -information_schema($l){return(min_version(5)&&$l=="information_schema")||(min_version(5.5)&&$l=="performance_schema");}function -error(){global$g;return -h(preg_replace('~^You have an error.*syntax to use~U',"Syntax error",$g->error));}function -create_database($l,$mb){return -queries("CREATE DATABASE ".idf_escape($l).($mb?" COLLATE ".q($mb):""));}function -drop_databases($k){$I=apply_queries("DROP DATABASE",$k,'idf_escape');restart_session();set_session("dbs",null);return$I;}function -rename_database($D,$mb){$I=false;if(create_database($D,$mb)){$S=array();$bj=array();foreach(tables_list()as$Q=>$T){if($T=='VIEW')$bj[]=$Q;else$S[]=$Q;}$I=(!$S&&!$bj)||move_tables($S,$bj,$D);drop_databases($I?array(DB):array());}return$I;}function -auto_increment(){$Ma=" PRIMARY KEY";if($_GET["create"]!=""&&$_POST["auto_increment_col"]){foreach(indexes($_GET["create"])as$w){if(in_array($_POST["fields"][$_POST["auto_increment_col"]]["orig"],$w["columns"],true)){$Ma="";break;}if($w["type"]=="PRIMARY")$Ma=" UNIQUE";}}return" AUTO_INCREMENT$Ma";}function -alter_table($Q,$D,$p,$hd,$tb,$_c,$mb,$La,$Wf){$c=array();foreach($p -as$o)$c[]=($o[1]?($Q!=""?($o[0]!=""?"CHANGE ".idf_escape($o[0]):"ADD"):" ")." ".implode($o[1]).($Q!=""?$o[2]:""):"DROP ".idf_escape($o[0]));$c=array_merge($c,$hd);$O=($tb!==null?" COMMENT=".q($tb):"").($_c?" ENGINE=".q($_c):"").($mb?" COLLATE ".q($mb):"").($La!=""?" AUTO_INCREMENT=$La":"");if($Q=="")return -queries("CREATE TABLE ".table($D)." (\n".implode(",\n",$c)."\n)$O$Wf");if($Q!=$D)$c[]="RENAME TO ".table($D);if($O)$c[]=ltrim($O);return($c||$Wf?queries("ALTER TABLE ".table($Q)."\n".implode(",\n",$c).$Wf):true);}function -alter_indexes($Q,$c){foreach($c -as$z=>$X)$c[$z]=($X[2]=="DROP"?"\nDROP INDEX ".idf_escape($X[1]):"\nADD $X[0] ".($X[0]=="PRIMARY"?"KEY ":"").($X[1]!=""?idf_escape($X[1])." ":"")."(".implode(", ",$X[2]).")");return -queries("ALTER TABLE ".table($Q).implode(",",$c));}function -truncate_tables($S){return -apply_queries("TRUNCATE TABLE",$S);}function -drop_views($bj){return -queries("DROP VIEW ".implode(", ",array_map('table',$bj)));}function -drop_tables($S){return -queries("DROP TABLE ".implode(", ",array_map('table',$S)));}function -move_tables($S,$bj,$Zh){global$g;$Mg=array();foreach($S -as$Q)$Mg[]=table($Q)." TO ".idf_escape($Zh).".".table($Q);if(!$Mg||queries("RENAME TABLE ".implode(", ",$Mg))){$bc=array();foreach($bj -as$Q)$bc[table($Q)]=view($Q);$g->select_db($Zh);$l=idf_escape(DB);foreach($bc -as$D=>$aj){if(!queries("CREATE VIEW $D AS ".str_replace(" $l."," ",$aj["select"]))||!queries("DROP VIEW $l.$D"))return -false;}return -true;}return -false;}function -copy_tables($S,$bj,$Zh){queries("SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO'");foreach($S -as$Q){$D=($Zh==DB?table("copy_$Q"):idf_escape($Zh).".".table($Q));if(($_POST["overwrite"]&&!queries("\nDROP TABLE IF EXISTS $D"))||!queries("CREATE TABLE $D LIKE ".table($Q))||!queries("INSERT INTO $D SELECT * FROM ".table($Q)))return -false;foreach(get_rows("SHOW TRIGGERS LIKE ".q(addcslashes($Q,"%_\\")))as$J){$zi=$J["Trigger"];if(!queries("CREATE TRIGGER ".($Zh==DB?idf_escape("copy_$zi"):idf_escape($Zh).".".idf_escape($zi))." $J[Timing] $J[Event] ON $D FOR EACH ROW\n$J[Statement];"))return -false;}}foreach($bj -as$Q){$D=($Zh==DB?table("copy_$Q"):idf_escape($Zh).".".table($Q));$aj=view($Q);if(($_POST["overwrite"]&&!queries("DROP VIEW IF EXISTS $D"))||!queries("CREATE VIEW $D AS $aj[select]"))return -false;}return -true;}function -trigger($D){if($D=="")return -array();$K=get_rows("SHOW TRIGGERS WHERE `Trigger` = ".q($D));return -reset($K);}function -triggers($Q){$I=array();foreach(get_rows("SHOW TRIGGERS LIKE ".q(addcslashes($Q,"%_\\")))as$J)$I[$J["Trigger"]]=array($J["Timing"],$J["Event"]);return$I;}function -trigger_options(){return -array("Timing"=>array("BEFORE","AFTER"),"Event"=>array("INSERT","UPDATE","DELETE"),"Type"=>array("FOR EACH ROW"),);}function -routine($D,$T){global$g,$Bc,$Vd,$U;$Ca=array("bool","boolean","integer","double precision","real","dec","numeric","fixed","national char","national varchar");$zh="(?:\\s|/\\*[\s\S]*?\\*/|(?:#|-- )[^\n]*\n?|--\r?\n)";$Di="((".implode("|",array_merge(array_keys($U),$Ca)).")\\b(?:\\s*\\(((?:[^'\")]|$Bc)++)\\))?\\s*(zerofill\\s*)?(unsigned(?:\\s+zerofill)?)?)(?:\\s*(?:CHARSET|CHARACTER\\s+SET)\\s*['\"]?([^'\"\\s,]+)['\"]?)?";$cg="$zh*(".($T=="FUNCTION"?"":$Vd).")?\\s*(?:`((?:[^`]|``)*)`\\s*|\\b(\\S+)\\s+)$Di";$i=$g->result("SHOW CREATE $T ".idf_escape($D),2);preg_match("~\\(((?:$cg\\s*,?)*)\\)\\s*".($T=="FUNCTION"?"RETURNS\\s+$Di\\s+":"")."(.*)~is",$i,$C);$p=array();preg_match_all("~$cg\\s*,?~is",$C[1],$Fe,PREG_SET_ORDER);foreach($Fe -as$Qf)$p[]=array("field"=>str_replace("``","`",$Qf[2]).$Qf[3],"type"=>strtolower($Qf[5]),"length"=>preg_replace_callback("~$Bc~s",'normalize_enum',$Qf[6]),"unsigned"=>strtolower(preg_replace('~\s+~',' ',trim("$Qf[8] $Qf[7]"))),"null"=>1,"full_type"=>$Qf[4],"inout"=>strtoupper($Qf[1]),"collation"=>strtolower($Qf[9]),);if($T!="FUNCTION")return -array("fields"=>$p,"definition"=>$C[11]);return -array("fields"=>$p,"returns"=>array("type"=>$C[12],"length"=>$C[13],"unsigned"=>$C[15],"collation"=>$C[16]),"definition"=>$C[17],"language"=>"SQL",);}function -routines(){return -get_rows("SELECT ROUTINE_NAME AS SPECIFIC_NAME, ROUTINE_NAME, ROUTINE_TYPE, DTD_IDENTIFIER FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = ".q(DB));}function -routine_languages(){return -array();}function -routine_id($D,$J){return -idf_escape($D);}function -last_id(){global$g;return$g->result("SELECT LAST_INSERT_ID()");}function -explain($g,$G){return$g->query("EXPLAIN ".(min_version(5.1)&&!min_version(5.7)?"PARTITIONS ":"").$G);}function -found_rows($R,$Z){return($Z||$R["Engine"]!="InnoDB"?null:$R["Rows"]);}function -types(){return -array();}function -schemas(){return -array();}function -get_schema(){return"";}function -set_schema($ch,$h=null){return -true;}function -create_sql($Q,$La,$Kh){global$g;$I=$g->result("SHOW CREATE TABLE ".table($Q),1);if(!$La)$I=preg_replace('~ AUTO_INCREMENT=\d+~','',$I);return$I;}function -truncate_sql($Q){return"TRUNCATE ".table($Q);}function -use_sql($j){return"USE ".idf_escape($j);}function -trigger_sql($Q){$I="";foreach(get_rows("SHOW TRIGGERS LIKE ".q(addcslashes($Q,"%_\\")),null,"-- ")as$J)$I.="\nCREATE TRIGGER ".idf_escape($J["Trigger"])." $J[Timing] $J[Event] ON ".table($J["Table"])." FOR EACH ROW\n$J[Statement];;\n";return$I;}function -show_variables(){return -get_key_vals("SHOW VARIABLES");}function -process_list(){return -get_rows("SHOW FULL PROCESSLIST");}function -show_status(){return -get_key_vals("SHOW STATUS");}function -convert_field($o){if(preg_match("~binary~",$o["type"]))return"HEX(".idf_escape($o["field"]).")";if($o["type"]=="bit")return"BIN(".idf_escape($o["field"])." + 0)";if(preg_match("~geometry|point|linestring|polygon~",$o["type"]))return(min_version(8)?"ST_":"")."AsWKT(".idf_escape($o["field"]).")";}function -unconvert_field($o,$I){if(preg_match("~binary~",$o["type"]))$I="UNHEX($I)";if($o["type"]=="bit")$I="CONV($I, 2, 10) + 0";if(preg_match("~geometry|point|linestring|polygon~",$o["type"]))$I=(min_version(8)?"ST_":"")."GeomFromText($I, SRID($o[field]))";return$I;}function -support($Vc){return!preg_match("~scheme|sequence|type|view_trigger|materializedview".(min_version(8)?"":"|descidx".(min_version(5.1)?"":"|event|partitioning".(min_version(5)?"":"|routine|trigger|view")))."~",$Vc);}function -kill_process($X){return -queries("KILL ".number($X));}function -connection_id(){return"SELECT CONNECTION_ID()";}function -max_connections(){global$g;return$g->result("SELECT @@max_connections");}function -driver_config(){$U=array();$Jh=array();foreach(array(lang(27)=>array("tinyint"=>3,"smallint"=>5,"mediumint"=>8,"int"=>10,"bigint"=>20,"decimal"=>66,"float"=>12,"double"=>21),lang(28)=>array("date"=>10,"datetime"=>19,"timestamp"=>19,"time"=>10,"year"=>4),lang(25)=>array("char"=>255,"varchar"=>65535,"tinytext"=>255,"text"=>65535,"mediumtext"=>16777215,"longtext"=>4294967295),lang(80)=>array("enum"=>65535,"set"=>64),lang(29)=>array("bit"=>20,"binary"=>255,"varbinary"=>65535,"tinyblob"=>255,"blob"=>65535,"mediumblob"=>16777215,"longblob"=>4294967295),lang(31)=>array("geometry"=>0,"point"=>0,"linestring"=>0,"polygon"=>0,"multipoint"=>0,"multilinestring"=>0,"multipolygon"=>0,"geometrycollection"=>0),)as$z=>$X){$U+=$X;$Jh[$z]=array_keys($X);}return -array('possible_drivers'=>array("MySQLi","MySQL","PDO_MySQL"),'jush'=>"sql",'types'=>$U,'structured_types'=>$Jh,'unsigned'=>array("unsigned","zerofill","unsigned zerofill"),'operators'=>array("=","<",">","<=",">=","!=","LIKE","LIKE %%","REGEXP","IN","FIND_IN_SET","IS NULL","NOT LIKE","NOT REGEXP","NOT IN","IS NOT NULL","SQL"),'functions'=>array("char_length","date","from_unixtime","lower","round","floor","ceil","sec_to_time","time_to_sec","upper"),'grouping'=>array("avg","count","count distinct","group_concat","max","min","sum"),'edit_functions'=>array(array("char"=>"md5/sha1/password/encrypt/uuid","binary"=>"md5/sha1","date|time"=>"now",),array(number_type()=>"+/-","date"=>"+ interval/- interval","time"=>"addtime/subtime","char|text"=>"concat",)),);}}$xb=driver_config();$kg=$xb['possible_drivers'];$y=$xb['jush'];$U=$xb['types'];$Jh=$xb['structured_types'];$Ki=$xb['unsigned'];$xf=$xb['operators'];$pd=$xb['functions'];$vd=$xb['grouping'];$sc=$xb['edit_functions'];if($b->operators===null)$b->operators=$xf;define("SERVER",$_GET[DRIVER]);define("DB",$_GET["db"]);define("ME",preg_replace('~\?.*~','',relative_uri()).'?'.(sid()?SID.'&':'').(SERVER!==null?DRIVER."=".urlencode(SERVER).'&':'').(isset($_GET["username"])?"username=".urlencode($_GET["username"]).'&':'').(DB!=""?'db='.urlencode(DB).'&'.(isset($_GET["ns"])?"ns=".urlencode($_GET["ns"])."&":""):''));$ia="4.8.1";function -page_header($ji,$n="",$Va=array(),$ki=""){global$ca,$ia,$b,$kc,$y;page_headers();if(is_ajax()&&$n){page_messages($n);exit;}$li=$ji.($ki!=""?": $ki":"");$mi=strip_tags($li.(SERVER!=""&&SERVER!="localhost"?h(" - ".SERVER):"")." - ".$b->name());echo' - +';hidden_fields_get();$kb=script("mixin(qsl('select'), {onmousedown: dbMouseDown, onchange: dbChange});");echo"".'DB'.": ".($i?"$kb":"\n"),"\n";foreach(array("import","sql","schema","dump","privileges")as$X){if(isset($_GET[$X])){echo"";break;}}echo"

    \n";}function +tablesPrint($T){echo"
      ".script("mixin(qs('#tables'), {onmouseover: menuOver, onmouseout: menuOut});");foreach($T +as$R=>$Mf){$F=$this->tableName($Mf);if($F!=""){echo'
    • ".'select'." ",(support("table")||support("indexes")?'$F":"$F")."\n";}}echo"
    \n";}}$b=(function_exists('adminer_object')?adminer_object():new +Adminer);$Wa=driver_config();$Le=$Wa['possible_drivers'];$y=$Wa['jush'];$Cg=$Wa['types'];$Of=$Wa['structured_types'];$Jg=$Wa['unsigned'];$ae=$Wa['operators'];$uc=$Wa['functions'];$yc=$Wa['grouping'];$Gb=$Wa['edit_functions'];if($b->operators===null)$b->operators=$ae;define("SERVER",$_GET[DRIVER]);define("DB",$_GET["db"]);define("ME",preg_replace('~\?.*~','',relative_uri()).'?'.(sid()?SID.'&':'').(SERVER!==null?DRIVER."=".urlencode(SERVER).'&':'').(isset($_GET["username"])?"username=".urlencode($_GET["username"]).'&':'').(DB!=""?'db='.urlencode(DB).'&'.(isset($_GET["ns"])?"ns=".urlencode($_GET["ns"])."&":""):''));$da="4.8.1";function +page_header($mg,$l="",$Ba=array(),$ng=""){global$ba,$da,$b,$zb,$y;page_headers();if(is_ajax()&&$l){page_messages($l);exit;}$og=$mg.($ng!=""?": $ng":"");$pg=strip_tags($og.(SERVER!=""&&SERVER!="localhost"?h(" - ".SERVER):"")." - ".$b->name());echo' + -',$mi,' +',$pg,' ',script_src(preg_replace("~\\?.*~","",ME)."?file=functions.js&version=4.8.1");if($b->head()){echo' -';foreach($b->css()as$Ob){echo' +';foreach($b->css()as$eb){echo' ';}}echo' - -';$q=get_temp_dir()."/adminer.version";if(!$_COOKIE["adminer_version"]&&function_exists('openssl_verify')&&file_exists($q)&&filemtime($q)+86400>time()){$Zi=unserialize(file_get_contents($q));$wg="-----BEGIN PUBLIC KEY----- + +';$o=get_temp_dir()."/adminer.version";if(!$_COOKIE["adminer_version"]&&function_exists('openssl_verify')&&file_exists($o)&&filemtime($o)+86400>time()){$Xg=unserialize(file_get_contents($o));$Ve="-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwqWOVuF5uw7/+Z70djoK RlHIZFZPO0uYRezq90+7Amk+FDNd7KkL5eDve+vHRJBLAszF/7XKXe11xwliIsFs DFWQlsABVZB3oisKCBEuI71J4kPH8dKGEWR9jDHFw3cWmoH3PmqImX6FISWbG3B8 @@ -1431,365 +626,283 @@ jHnq1cFpOIISzARlrHMa/43YfeNRAm/tsBXjSxembBPo7aQZLAWHmaj5+K19H10B nCpz9Y++cipkVEiKRGih4ZEvjoFysEOdRLj6WiD/uUNky4xGeA6LaJqh5XpkFkcQ fQIDAQAB -----END PUBLIC KEY----- -";if(openssl_verify($Zi["version"],base64_decode($Zi["signature"]),$wg)==1)$_COOKIE["adminer_version"]=$Zi["version"];}echo' -mixin(document.body, {onkeydown: bodyKeydown, onclick: bodyClick',(isset($_COOKIE["adminer_version"])?"":", onload: partial(verifyVersion, '$ia', '".js_escape(ME)."', '".get_token()."')");?>}); +";if(openssl_verify($Xg["version"],base64_decode($Xg["signature"]),$Ve)==1)$_COOKIE["adminer_version"]=$Xg["version"];}echo' +mixin(document.body, {onkeydown: bodyKeydown, onclick: bodyClick',(isset($_COOKIE["adminer_version"])?"":", onload: partial(verifyVersion, '$da', '".js_escape(ME)."', '".get_token()."')");?>}); document.body.className = document.body.className.replace(/ nojs/, ' js'); var offlineMessage = ' ',script("mixin(qs('#help'), {onmouseover: function () { helpOpen = 1; }, onmouseout: helpMouseout});"),'
    -';if($Va!==null){$A=substr(preg_replace('~\b(username|db|ns)=[^&]*&~','',ME),0,-1);echo'

    $li

    \n","\n";restart_session();page_messages($n);$k=&get_session("dbs");if(DB!=""&&$k&&!in_array(DB,$k,true))$k=null;stop_session();define("PAGE_HEADER",1);}function -page_headers(){global$b;header("Content-Type: text/html; charset=utf-8");header("Cache-Control: no-cache");header("X-Frame-Options: deny");header("X-XSS-Protection: 0");header("X-Content-Type-Options: nosniff");header("Referrer-Policy: origin-when-cross-origin");foreach($b->csp()as$Nb){$Ad=array();foreach($Nb -as$z=>$X)$Ad[]="$z $X";header("Content-Security-Policy: ".implode("; ",$Ad));}$b->headers();}function +';if($Ba!==null){$A=substr(preg_replace('~\b(username|db|ns)=[^&]*&~','',ME),0,-1);echo'

    $og

    \n","\n";restart_session();page_messages($l);$i=&get_session("dbs");if(DB!=""&&$i&&!in_array(DB,$i,true))$i=null;stop_session();define("PAGE_HEADER",1);}function +page_headers(){global$b;header("Content-Type: text/html; charset=utf-8");header("Cache-Control: no-cache");header("X-Frame-Options: deny");header("X-XSS-Protection: 0");header("X-Content-Type-Options: nosniff");header("Referrer-Policy: origin-when-cross-origin");foreach($b->csp()as$db){$Dc=array();foreach($db +as$z=>$X)$Dc[]="$z $X";header("Content-Security-Policy: ".implode("; ",$Dc));}$b->headers();}function csp(){return array(array("script-src"=>"'self' 'unsafe-inline' 'nonce-".get_nonce()."' 'strict-dynamic'","connect-src"=>"'self'","frame-src"=>"https://www.adminer.org","object-src"=>"'none'","base-uri"=>"'none'","form-action"=>"'self'",),);}function -get_nonce(){static$ef;if(!$ef)$ef=base64_encode(rand_string());return$ef;}function -page_messages($n){$Mi=preg_replace('~^[^?]*~','',$_SERVER["REQUEST_URI"]);$Re=$_SESSION["messages"][$Mi];if($Re){echo"
    ".implode("
    \n
    ",$Re)."
    ".script("messagesPrint();");unset($_SESSION["messages"][$Mi]);}if($n)echo"
    $n
    \n";}function -page_footer($Ue=""){global$b,$qi;echo'
    +get_nonce(){static$Nd;if(!$Nd)$Nd=base64_encode(rand_string());return$Nd;}function +page_messages($l){$Lg=preg_replace('~^[^?]*~','',$_SERVER["REQUEST_URI"]);$Ed=$_SESSION["messages"][$Lg];if($Ed){echo"
    ".implode("
    \n
    ",$Ed)."
    ".script("messagesPrint();");unset($_SESSION["messages"][$Lg]);}if($l)echo"
    $l
    \n";}function +page_footer($Hd=""){global$b,$U;echo' -';switch_lang();if($Ue!="auth"){echo'
    +';if($Hd!="auth"){echo'

    - - + +

    ';}echo' +';$b->navigation($Hd);echo' ',script("setupSubmitHighlight(document);");}function -int32($Xe){while($Xe>=2147483648)$Xe-=4294967296;while($Xe<=-2147483649)$Xe+=4294967296;return(int)$Xe;}function -long2str($W,$dj){$ah='';foreach($W -as$X)$ah.=pack('V',$X);if($dj)return -substr($ah,0,end($W));return$ah;}function -str2long($ah,$dj){$W=array_values(unpack('V*',str_pad($ah,4*ceil(strlen($ah)/4),"\0")));if($dj)$W[]=strlen($ah);return$W;}function -xxtea_mx($pj,$oj,$Nh,$he){return -int32((($pj>>5&0x7FFFFFF)^$oj<<2)+(($oj>>3&0x1FFFFFFF)^$pj<<4))^int32(($Nh^$oj)+($he^$pj));}function -encrypt_string($Ih,$z){if($Ih=="")return"";$z=array_values(unpack("V*",pack("H*",md5($z))));$W=str2long($Ih,true);$Xe=count($W)-1;$pj=$W[$Xe];$oj=$W[0];$xg=floor(6+52/($Xe+1));$Nh=0;while($xg-->0){$Nh=int32($Nh+0x9E3779B9);$rc=$Nh>>2&3;for($Of=0;$Of<$Xe;$Of++){$oj=$W[$Of+1];$We=xxtea_mx($pj,$oj,$Nh,$z[$Of&3^$rc]);$pj=int32($W[$Of]+$We);$W[$Of]=$pj;}$oj=$W[0];$We=xxtea_mx($pj,$oj,$Nh,$z[$Of&3^$rc]);$pj=int32($W[$Xe]+$We);$W[$Xe]=$pj;}return +int32($E){while($E>=2147483648)$E-=4294967296;while($E<=-2147483649)$E+=4294967296;return(int)$E;}function +long2str($W,$bh){$pf='';foreach($W +as$X)$pf.=pack('V',$X);if($bh)return +substr($pf,0,end($W));return$pf;}function +str2long($pf,$bh){$W=array_values(unpack('V*',str_pad($pf,4*ceil(strlen($pf)/4),"\0")));if($bh)$W[]=strlen($pf);return$W;}function +xxtea_mx($ih,$hh,$Sf,$ad){return +int32((($ih>>5&0x7FFFFFF)^$hh<<2)+(($hh>>3&0x1FFFFFFF)^$ih<<4))^int32(($Sf^$hh)+($ad^$ih));}function +encrypt_string($Nf,$z){if($Nf=="")return"";$z=array_values(unpack("V*",pack("H*",md5($z))));$W=str2long($Nf,true);$E=count($W)-1;$ih=$W[$E];$hh=$W[0];$H=floor(6+52/($E+1));$Sf=0;while($H-->0){$Sf=int32($Sf+0x9E3779B9);$Fb=$Sf>>2&3;for($re=0;$re<$E;$re++){$hh=$W[$re+1];$Jd=xxtea_mx($ih,$hh,$Sf,$z[$re&3^$Fb]);$ih=int32($W[$re]+$Jd);$W[$re]=$ih;}$hh=$W[0];$Jd=xxtea_mx($ih,$hh,$Sf,$z[$re&3^$Fb]);$ih=int32($W[$E]+$Jd);$W[$E]=$ih;}return long2str($W,false);}function -decrypt_string($Ih,$z){if($Ih=="")return"";if(!$z)return -false;$z=array_values(unpack("V*",pack("H*",md5($z))));$W=str2long($Ih,false);$Xe=count($W)-1;$pj=$W[$Xe];$oj=$W[0];$xg=floor(6+52/($Xe+1));$Nh=int32($xg*0x9E3779B9);while($Nh){$rc=$Nh>>2&3;for($Of=$Xe;$Of>0;$Of--){$pj=$W[$Of-1];$We=xxtea_mx($pj,$oj,$Nh,$z[$Of&3^$rc]);$oj=int32($W[$Of]-$We);$W[$Of]=$oj;}$pj=$W[$Xe];$We=xxtea_mx($pj,$oj,$Nh,$z[$Of&3^$rc]);$oj=int32($W[0]-$We);$W[0]=$oj;$Nh=int32($Nh-0x9E3779B9);}return -long2str($W,true);}$g='';$_d=$_SESSION["token"];if(!$_d)$_SESSION["token"]=rand(1,1e6);$qi=get_token();$eg=array();if($_COOKIE["adminer_permanent"]){foreach(explode(" ",$_COOKIE["adminer_permanent"])as$X){list($z)=explode(":",$X);$eg[$z]=$X;}}function -add_invalid_login(){global$b;$nd=file_open_lock(get_temp_dir()."/adminer.invalid");if(!$nd)return;$ae=unserialize(stream_get_contents($nd));$gi=time();if($ae){foreach($ae -as$be=>$X){if($X[0]<$gi)unset($ae[$be]);}}$Zd=&$ae[$b->bruteForceKey()];if(!$Zd)$Zd=array($gi+30*60,0);$Zd[1]++;file_write_unlock($nd,serialize($ae));}function -check_invalid_login(){global$b;$ae=unserialize(@file_get_contents(get_temp_dir()."/adminer.invalid"));$Zd=($ae?$ae[$b->bruteForceKey()]:array());$df=($Zd[1]>29?$Zd[0]-time():0);if($df>0)auth_error(lang(84,ceil($df/60)));}$Ja=$_POST["auth"];if($Ja){session_regenerate_id();$Yi=$Ja["driver"];$M=$Ja["server"];$V=$Ja["username"];$F=(string)$Ja["password"];$l=$Ja["db"];set_password($Yi,$M,$V,$F);$_SESSION["db"][$Yi][$M][$V][$l]=true;if($Ja["permanent"]){$z=base64_encode($Yi)."-".base64_encode($M)."-".base64_encode($V)."-".base64_encode($l);$qg=$b->permanentLogin(true);$eg[$z]="$z:".base64_encode($qg?encrypt_string($F,$qg):"");cookie("adminer_permanent",implode(" ",$eg));}if(count($_POST)==1||DRIVER!=$Yi||SERVER!=$M||$_GET["username"]!==$V||DB!=$l)redirect(auth_url($Yi,$M,$V,$l));}elseif($_POST["logout"]&&(!$_d||verify_token())){foreach(array("pwds","db","dbs","queries")as$z)set_session($z,null);unset_permanent();redirect(substr(preg_replace('~\b(username|db|ns)=[^&]*&~','',ME),0,-1),lang(85).' '.lang(86));}elseif($eg&&!$_SESSION["pwds"]){session_regenerate_id();$qg=$b->permanentLogin();foreach($eg -as$z=>$X){list(,$gb)=explode(":",$X);list($Yi,$M,$V,$l)=array_map('base64_decode',explode("-",$z));set_password($Yi,$M,$V,decrypt_string(base64_decode($gb),$qg));$_SESSION["db"][$Yi][$M][$V][$l]=true;}}function -unset_permanent(){global$eg;foreach($eg -as$z=>$X){list($Yi,$M,$V,$l)=array_map('base64_decode',explode("-",$z));if($Yi==DRIVER&&$M==SERVER&&$V==$_GET["username"]&&$l==DB)unset($eg[$z]);}cookie("adminer_permanent",implode(" ",$eg));}function -auth_error($n){global$b,$_d;$ph=session_name();if(isset($_GET["username"])){header("HTTP/1.1 403 Forbidden");if(($_COOKIE[$ph]||$_GET[$ph])&&!$_d)$n=lang(87);else{restart_session();add_invalid_login();$F=get_password();if($F!==null){if($F===false)$n.=($n?'
    ':'').lang(88,target_blank(),'permanentLogin()');set_password(DRIVER,SERVER,$_GET["username"],null);}unset_permanent();}}if(!$_COOKIE[$ph]&&$_GET[$ph]&&ini_bool("session.use_only_cookies"))$n=lang(89);$Rf=session_get_cookie_params();cookie("adminer_key",($_COOKIE["adminer_key"]?$_COOKIE["adminer_key"]:rand_string()),$Rf["lifetime"]);page_header(lang(38),$n,null);echo"
    \n","
    ";if(hidden_fields($_POST,array("auth")))echo"

    ".lang(90)."\n";echo"

    \n";$b->loginForm();echo"
    \n";page_footer("auth");exit;}if(isset($_GET["username"])&&!class_exists("Min_DB")){unset($_SESSION["pwds"][DRIVER]);unset_permanent();page_header(lang(91),lang(92,implode(", ",$kg)),false);page_footer("auth");exit;}stop_session(true);if(isset($_GET["username"])&&is_string(get_password())){list($Fd,$gg)=explode(":",SERVER,2);if(preg_match('~^\s*([-+]?\d+)~',$gg,$C)&&($C[1]<1024||$C[1]>65535))auth_error(lang(93));check_invalid_login();$g=connect();$m=new -Min_Driver($g);}$_e=null;if(!is_object($g)||($_e=$b->login($_GET["username"],get_password()))!==true){$n=(is_string($g)?h($g):(is_string($_e)?$_e:lang(32)));auth_error($n.(preg_match('~^ | $~',get_password())?'
    '.lang(94):''));}if($_POST["logout"]&&$_d&&!verify_token()){page_header(lang(83),lang(95));page_footer("db");exit;}if($Ja&&$_POST["token"])$_POST["token"]=$qi;$n='';if($_POST){if(!verify_token()){$Ud="max_input_vars";$Le=ini_get($Ud);if(extension_loaded("suhosin")){foreach(array("suhosin.request.max_vars","suhosin.post.max_vars")as$z){$X=ini_get($z);if($X&&(!$Le||$X<$Le)){$Ud=$z;$Le=$X;}}}$n=(!$_POST["token"]&&$Le?lang(96,"'$Ud'"):lang(95).' '.lang(97));}}elseif($_SERVER["REQUEST_METHOD"]=="POST"){$n=lang(98,"'post_max_size'");if(isset($_GET["sql"]))$n.=' '.lang(99);}function -select($H,$h=null,$Ef=array(),$_=0){global$y;$ze=array();$x=array();$e=array();$Ta=array();$U=array();$I=array();odd('');for($t=0;(!$_||$t<$_)&&($J=$H->fetch_row());$t++){if(!$t){echo"
    \n","\n","";for($ge=0;$gefetch_field();$D=$o->name;$Df=$o->orgtable;$Cf=$o->orgname;$I[$o->table]=$Df;if($Ef&&$y=="sql")$ze[$ge]=($D=="table"?"table=":($D=="possible_keys"?"indexes=":null));elseif($Df!=""){if(!isset($x[$Df])){$x[$Df]=array();foreach(indexes($Df,$h)as$w){if($w["type"]=="PRIMARY"){$x[$Df]=array_flip($w["columns"]);break;}}$e[$Df]=$x[$Df];}if(isset($e[$Df][$Cf])){unset($e[$Df][$Cf]);$x[$Df][$Cf]=$ge;$ze[$ge]=$Df;}}if($o->charsetnr==63)$Ta[$ge]=true;$U[$ge]=$o->type;echo"name!=$Cf?" title='".h(($Df!=""?"$Df.":"").$Cf)."'":"").">".h($D).($Ef?doc_link(array('sql'=>"explain-output.html#explain_".strtolower($D),'mariadb'=>"explain/#the-columns-in-explain-select",)):"");}echo"\n";}echo"";foreach($J -as$z=>$X){$A="";if(isset($ze[$z])&&!$e[$ze[$z]]){if($Ef&&$y=="sql"){$Q=$J[array_search("table=",$ze)];$A=ME.$ze[$z].urlencode($Ef[$Q]!=""?$Ef[$Q]:$Q);}else{$A=ME."edit=".urlencode($ze[$z]);foreach($x[$ze[$z]]as$kb=>$ge)$A.="&where".urlencode("[".bracket_escape($kb)."]")."=".urlencode($J[$ge]);}}elseif(is_url($X))$A=$X;if($X===null)$X="NULL";elseif($Ta[$z]&&!is_utf8($X))$X="".lang(47,strlen($X))."";else{$X=h($X);if($U[$z]==254)$X="$X";}if($A)$X="$X";echo"
    $X";}}echo($t?"
    \n
    ":"

    ".lang(12))."\n";return$I;}function -referencable_primary($ih){$I=array();foreach(table_status('',true)as$Rh=>$Q){if($Rh!=$ih&&fk_support($Q)){foreach(fields($Rh)as$o){if($o["primary"]){if($I[$Rh]){unset($I[$Rh]);break;}$I[$Rh]=$o;}}}}return$I;}function -adminer_settings(){parse_str($_COOKIE["adminer_settings"],$rh);return$rh;}function -adminer_setting($z){$rh=adminer_settings();return$rh[$z];}function -set_adminer_settings($rh){return -cookie("adminer_settings",http_build_query($rh+adminer_settings()));}function -textarea($D,$Y,$K=10,$pb=80){global$y;echo"";}function -edit_type($z,$o,$nb,$jd=array(),$Rc=array()){global$Jh,$U,$Ki,$sf;$T=$o["type"];echo'',"',($Ki?"':''),(isset($o['on_update'])?"':''),($jd?" ":" ");}function -process_length($we){global$Bc;return(preg_match("~^\\s*\\(?\\s*$Bc(?:\\s*,\\s*$Bc)*+\\s*\\)?\\s*\$~",$we)&&preg_match_all("~$Bc~",$we,$Fe)?"(".implode(",",$Fe[0]).")":preg_replace('~^[0-9].*~','(\0)',preg_replace('~[^-0-9,+()[\]]~','',$we)));}function -process_type($o,$lb="COLLATE"){global$Ki;return" $o[type]".process_length($o["length"]).(preg_match(number_type(),$o["type"])&&in_array($o["unsigned"],$Ki)?" $o[unsigned]":"").(preg_match('~char|text|enum|set~',$o["type"])&&$o["collation"]?" $lb ".q($o["collation"]):"");}function -process_field($o,$Ci){return -array(idf_escape(trim($o["field"])),process_type($Ci),($o["null"]?" NULL":" NOT NULL"),default_value($o),(preg_match('~timestamp|datetime~',$o["type"])&&$o["on_update"]?" ON UPDATE $o[on_update]":""),(support("comment")&&$o["comment"]!=""?" COMMENT ".q($o["comment"]):""),($o["auto_increment"]?auto_increment():null),);}function -default_value($o){$Yb=$o["default"];return($Yb===null?"":" DEFAULT ".(preg_match('~char|binary|text|enum|set~',$o["type"])||preg_match('~^(?![a-z])~i',$Yb)?q($Yb):$Yb));}function -type_class($T){foreach(array('char'=>'text','date'=>'time|year','binary'=>'blob','enum'=>'set',)as$z=>$X){if(preg_match("~$z|$X~",$T))return" class='$z'";}}function -edit_fields($p,$nb,$T="TABLE",$jd=array()){global$Vd;$p=array_values($p);$Zb=(($_POST?$_POST["defaults"]:adminer_setting("defaults"))?"":" class='hidden'");$ub=(($_POST?$_POST["comments"]:adminer_setting("comments"))?"":" class='hidden'");echo' -';if($T=="PROCEDURE"){echo'';}echo'',($T=="TABLE"?lang(104):lang(105)),'',lang(49),'',script("qs('#enum-edit').onblur = editingLengthBlur;"),'',lang(106),'',lang(107);if($T=="TABLE"){echo'NULL -AI',doc_link(array('sql'=>"example-auto-increment.html",'mariadb'=>"auto_increment/",'sqlite'=>"autoinc.html",'pgsql'=>"datatype.html#DATATYPE-SERIAL",'mssql'=>"ms186775.aspx",)),'',lang(52),(support("comment")?"".lang(50):"");}echo'',"".script("row_count = ".count($p).";"),' +edit_type($z,$m,$Pa,$q=array(),$ec=array()){global$Of,$Cg,$Jg,$Wd;$V=$m["type"];echo'',"',($Jg?"':''),(isset($m['on_update'])?"':''),($q?" ":" ");}function +process_length($nd){global$Qb;return(preg_match("~^\\s*\\(?\\s*$Qb(?:\\s*,\\s*$Qb)*+\\s*\\)?\\s*\$~",$nd)&&preg_match_all("~$Qb~",$nd,$ud)?"(".implode(",",$ud[0]).")":preg_replace('~^[0-9].*~','(\0)',preg_replace('~[^-0-9,+()[\]]~','',$nd)));}function +process_type($m,$Na="COLLATE"){global$Jg;return" $m[type]".process_length($m["length"]).(preg_match(number_type(),$m["type"])&&in_array($m["unsigned"],$Jg)?" $m[unsigned]":"").(preg_match('~char|text|enum|set~',$m["type"])&&$m["collation"]?" $Na ".q($m["collation"]):"");}function +process_field($m,$Bg){return +array(idf_escape(trim($m["field"])),process_type($Bg),($m["null"]?" NULL":" NOT NULL"),default_value($m),(preg_match('~timestamp|datetime~',$m["type"])&&$m["on_update"]?" ON UPDATE $m[on_update]":""),(support("comment")&&$m["comment"]!=""?" COMMENT ".q($m["comment"]):""),($m["auto_increment"]?auto_increment():null),);}function +default_value($m){$ob=$m["default"];return($ob===null?"":" DEFAULT ".(preg_match('~char|binary|text|enum|set~',$m["type"])||preg_match('~^(?![a-z])~i',$ob)?q($ob):$ob));}function +type_class($V){foreach(array('char'=>'text','date'=>'time|year','binary'=>'blob','enum'=>'set',)as$z=>$X){if(preg_match("~$z|$X~",$V))return" class='$z'";}}function +edit_fields($n,$Pa,$V="TABLE",$q=array()){global$Qc;$n=array_values($n);$pb=(($_POST?$_POST["defaults"]:adminer_setting("defaults"))?"":" class='hidden'");$Ua=(($_POST?$_POST["comments"]:adminer_setting("comments"))?"":" class='hidden'");echo' +';if($V=="PROCEDURE"){echo'';}echo'',($V=="TABLE"?'Column name':'Parameter name'),'Type',script("qs('#enum-edit').onblur = editingLengthBlur;"),'Length +','Options';if($V=="TABLE"){echo'NULL +AI',doc_link(array('sqlite'=>"autoinc.html",)),'Default value +',(support("comment")?"".'Comment':"");}echo'',"".script("row_count = ".count($n).";"),' -',script("mixin(qsl('tbody'), {onclick: editingClick, onkeydown: editingKeydown, oninput: editingInput});");foreach($p -as$t=>$o){$t++;$Ff=$o[($_POST?"orig":"field")];$hc=(isset($_POST["add"][$t-1])||(isset($o["field"])&&!$_POST["drop_col"][$t]))&&(support("drop_col")||$Ff=="");echo' -',($T=="PROCEDURE"?"".html_select("fields[$t][inout]",explode("|",$Vd),$o["inout"]):""),'';if($hc){echo'';}echo'';edit_type("fields[$t]",$o,$nb,$jd);if($T=="TABLE"){echo'',checkbox("fields[$t][null]",1,$o["null"],"","","block","label-null"),'',checkbox("fields[$t][has_default]",1,$o["has_default"],"","","","label-default"),'',(support("comment")?"":"");}echo"",(support("move_col")?" "." "." ":""),($Ff==""||support("drop_col")?"":"");}}function -process_fields(&$p){$kf=0;if($_POST["up"]){$qe=0;foreach($p -as$z=>$o){if(key($_POST["up"])==$z){unset($p[$z]);array_splice($p,$qe,0,array($o));break;}if(isset($o["field"]))$qe=$kf;$kf++;}}elseif($_POST["down"]){$ld=false;foreach($p -as$z=>$o){if(isset($o["field"])&&$ld){unset($p[key($_POST["down"])]);array_splice($p,$kf,0,array($ld));break;}if(key($_POST["down"])==$z)$ld=$o;$kf++;}}elseif($_POST["add"]){$p=array_values($p);array_splice($p,key($_POST["add"]),0,array(array()));}elseif(!$_POST["drop_col"])return +',script("mixin(qsl('tbody'), {onclick: editingClick, onkeydown: editingKeydown, oninput: editingInput});");foreach($n +as$u=>$m){$u++;$je=$m[($_POST?"orig":"field")];$wb=(isset($_POST["add"][$u-1])||(isset($m["field"])&&!$_POST["drop_col"][$u]))&&(support("drop_col")||$je=="");echo' +',($V=="PROCEDURE"?"".html_select("fields[$u][inout]",explode("|",$Qc),$m["inout"]):""),'';if($wb){echo'';}echo'';edit_type("fields[$u]",$m,$Pa,$q);if($V=="TABLE"){echo'',checkbox("fields[$u][null]",1,$m["null"],"","","block","label-null"),'',checkbox("fields[$u][has_default]",1,$m["has_default"],"","","","label-default"),'',(support("comment")?"":"");}echo"",(support("move_col")?" "." "." ":""),($je==""||support("drop_col")?"":"");}}function +process_fields(&$n){$Sd=0;if($_POST["up"]){$hd=0;foreach($n +as$z=>$m){if(key($_POST["up"])==$z){unset($n[$z]);array_splice($n,$hd,0,array($m));break;}if(isset($m["field"]))$hd=$Sd;$Sd++;}}elseif($_POST["down"]){$rc=false;foreach($n +as$z=>$m){if(isset($m["field"])&&$rc){unset($n[key($_POST["down"])]);array_splice($n,$Sd,0,array($rc));break;}if(key($_POST["down"])==$z)$rc=$m;$Sd++;}}elseif($_POST["add"]){$n=array_values($n);array_splice($n,key($_POST["add"]),0,array(array()));}elseif(!$_POST["drop_col"])return false;return true;}function normalize_enum($C){return"'".str_replace("'","''",addcslashes(stripcslashes(str_replace($C[0][0].$C[0][0],$C[0][0],substr($C[0],1,-1))),'\\'))."'";}function -grant($qd,$sg,$e,$rf){if(!$sg)return -true;if($sg==array("ALL PRIVILEGES","GRANT OPTION"))return($qd=="GRANT"?queries("$qd ALL PRIVILEGES$rf WITH GRANT OPTION"):queries("$qd ALL PRIVILEGES$rf")&&queries("$qd GRANT OPTION$rf"));return -queries("$qd ".preg_replace('~(GRANT OPTION)\([^)]*\)~','\1',implode("$e, ",$sg).$e).$rf);}function -drop_create($lc,$i,$mc,$di,$oc,$B,$Qe,$Oe,$Pe,$of,$bf){if($_POST["drop"])query_redirect($lc,$B,$Qe);elseif($of=="")query_redirect($i,$B,$Pe);elseif($of!=$bf){$Lb=queries($i);queries_redirect($B,$Oe,$Lb&&queries($lc));if($Lb)queries($mc);}else -queries_redirect($B,$Oe,queries($di)&&queries($oc)&&queries($lc)&&queries($i));}function -create_trigger($rf,$J){global$y;$ii=" $J[Timing] $J[Event]".(preg_match('~ OF~',$J["Event"])?" $J[Of]":"");return"CREATE TRIGGER ".idf_escape($J["Trigger"]).($y=="mssql"?$rf.$ii:$ii.$rf).rtrim(" $J[Type]\n$J[Statement]",";").";";}function -create_routine($Wg,$J){global$Vd,$y;$N=array();$p=(array)$J["fields"];ksort($p);foreach($p -as$o){if($o["field"]!="")$N[]=(preg_match("~^($Vd)\$~",$o["inout"])?"$o[inout] ":"").idf_escape($o["field"]).process_type($o,"CHARACTER SET");}$ac=rtrim("\n$J[definition]",";");return"CREATE $Wg ".idf_escape(trim($J["name"]))." (".implode(", ",$N).")".(isset($_GET["function"])?" RETURNS".process_type($J["returns"],"CHARACTER SET"):"").($J["language"]?" LANGUAGE $J[language]":"").($y=="pgsql"?" AS ".q($ac):"$ac;");}function -remove_definer($G){return -preg_replace('~^([A-Z =]+) DEFINER=`'.preg_replace('~@(.*)~','`@`(%|\1)',logged_user()).'`~','\1',$G);}function -format_foreign_key($r){global$sf;$l=$r["db"];$ff=$r["ns"];return" FOREIGN KEY (".implode(", ",array_map('idf_escape',$r["source"])).") REFERENCES ".($l!=""&&$l!=$_GET["db"]?idf_escape($l).".":"").($ff!=""&&$ff!=$_GET["ns"]?idf_escape($ff).".":"").table($r["table"])." (".implode(", ",array_map('idf_escape',$r["target"])).")".(preg_match("~^($sf)\$~",$r["on_delete"])?" ON DELETE $r[on_delete]":"").(preg_match("~^($sf)\$~",$r["on_update"])?" ON UPDATE $r[on_update]":"");}function -tar_file($q,$ni){$I=pack("a100a8a8a8a12a12",$q,644,0,0,decoct($ni->size),decoct(time()));$fb=8*32;for($t=0;$tsend();echo -str_repeat("\0",511-($ni->size+511)%512);}function -ini_bytes($Ud){$X=ini_get($Ud);switch(strtolower(substr($X,-1))){case'g':$X*=1024;case'm':$X*=1024;case'k':$X*=1024;}return$X;}function -doc_link($bg,$ei="?"){global$y,$g;$nh=$g->server_info;$Zi=preg_replace('~^(\d\.?\d).*~s','\1',$nh);$Oi=array('sql'=>"https://dev.mysql.com/doc/refman/$Zi/en/",'sqlite'=>"https://www.sqlite.org/",'pgsql'=>"https://www.postgresql.org/docs/$Zi/",'mssql'=>"https://msdn.microsoft.com/library/",'oracle'=>"https://www.oracle.com/pls/topic/lookup?ctx=db".preg_replace('~^.* (\d+)\.(\d+)\.\d+\.\d+\.\d+.*~s','\1\2',$nh)."&id=",);if(preg_match('~MariaDB~',$nh)){$Oi['sql']="https://mariadb.com/kb/en/library/";$bg['sql']=(isset($bg['mariadb'])?$bg['mariadb']:str_replace(".html","/",$bg['sql']));}return($bg[$y]?"$ei":"");}function -ob_gzencode($P){return -gzencode($P);}function -db_size($l){global$g;if(!$g->select_db($l))return"?";$I=0;foreach(table_status()as$R)$I+=$R["Data_length"]+$R["Index_length"];return -format_number($I);}function -set_utf8mb4($i){global$g;static$N=false;if(!$N&&preg_match('~\butf8mb4~i',$i)){$N=true;echo"SET NAMES ".charset($g).";\n\n";}}function -connect_error(){global$b,$g,$qi,$n,$kc;if(DB!=""){header("HTTP/1.1 404 Not Found");page_header(lang(37).": ".h(DB),lang(112),true);}else{if($_POST["db"]&&!$n)queries_redirect(substr(ME,0,-1),lang(113),drop_databases($_POST["db"]));page_header(lang(114),$n,false);echo"

    ".lang(119,$kc[DRIVER],"".h($g->server_info)."","$g->extension")."\n","

    ".lang(120,"".h(logged_user())."")."\n";$k=$b->databases();if($k){$dh=support("scheme");$nb=collations();echo"

    \n","\n",script("mixin(qsl('table'), {onclick: tableClick, ondblclick: partialArg(tableClick, true)});"),"".(support("database")?"\n";$k=($_GET["dbsize"]?count_tables($k):array_flip($k));foreach($k -as$l=>$S){$Vg=h(ME)."db=".urlencode($l);$u=h("Db-".$l);echo"".(support("database")?"
    ":"")."".lang(37)." - ".lang(121).""."".lang(122)."".lang(123)."".lang(124)." - ".lang(125)."".script("qsl('a').onclick = partial(ajaxSetHtml, '".js_escape(ME)."script=connect');","")."
    ".checkbox("db[]",$l,in_array($l,(array)$_POST["db"]),"","","",$u):""),"".h($l)."";$mb=h(db_collation($l,$nb));echo"".(support("database")?"$mb":$mb),"".($_GET["dbsize"]?$S:"?")."","".($_GET["dbsize"]?db_size($l):"?"),"\n";}echo"
    \n",(support("database")?"\n":""),"\n","
    \n",script("tableCheck();");}}page_footer("db");}if(isset($_GET["status"]))$_GET["variables"]=$_GET["status"];if(isset($_GET["import"]))$_GET["sql"]=$_GET["import"];if(!(DB!=""?$g->select_db(DB):isset($_GET["sql"])||isset($_GET["dump"])||isset($_GET["database"])||isset($_GET["processlist"])||isset($_GET["privileges"])||isset($_GET["user"])||isset($_GET["variables"])||$_GET["script"]=="connect"||$_GET["script"]=="kill")){if(DB!=""||$_GET["refresh"]){restart_session();set_session("dbs",null);}connect_error();exit;}if(support("scheme")){if(DB!=""&&$_GET["ns"]!==""){if(!isset($_GET["ns"]))redirect(preg_replace('~ns=[^&]*&~','',ME)."ns=".get_schema());if(!set_schema($_GET["ns"])){header("HTTP/1.1 404 Not Found");page_header(lang(77).": ".h($_GET["ns"]),lang(128),true);page_footer("ns");exit;}}}$sf="RESTRICT|NO ACTION|CASCADE|SET NULL|SET DEFAULT";class +grant($vc,$Se,$e,$Vd){if(!$Se)return +true;if($Se==array("ALL PRIVILEGES","GRANT OPTION"))return($vc=="GRANT"?queries("$vc ALL PRIVILEGES$Vd WITH GRANT OPTION"):queries("$vc ALL PRIVILEGES$Vd")&&queries("$vc GRANT OPTION$Vd"));return +queries("$vc ".preg_replace('~(GRANT OPTION)\([^)]*\)~','\1',implode("$e, ",$Se).$e).$Vd);}function +drop_create($_b,$h,$Ab,$gg,$Cb,$B,$Dd,$Bd,$Cd,$Ud,$Ld){if($_POST["drop"])query_redirect($_b,$B,$Dd);elseif($Ud=="")query_redirect($h,$B,$Cd);elseif($Ud!=$Ld){$cb=queries($h);queries_redirect($B,$Bd,$cb&&queries($_b));if($cb)queries($Ab);}else +queries_redirect($B,$Bd,queries($gg)&&queries($Cb)&&queries($_b)&&queries($h));}function +create_trigger($Vd,$L){global$y;$lg=" $L[Timing] $L[Event]".(preg_match('~ OF~',$L["Event"])?" $L[Of]":"");return"CREATE TRIGGER ".idf_escape($L["Trigger"]).($y=="mssql"?$Vd.$lg:$lg.$Vd).rtrim(" $L[Type]\n$L[Statement]",";").";";}function +create_routine($nf,$L){global$Qc,$y;$P=array();$n=(array)$L["fields"];ksort($n);foreach($n +as$m){if($m["field"]!="")$P[]=(preg_match("~^($Qc)\$~",$m["inout"])?"$m[inout] ":"").idf_escape($m["field"]).process_type($m,"CHARACTER SET");}$qb=rtrim("\n$L[definition]",";");return"CREATE $nf ".idf_escape(trim($L["name"]))." (".implode(", ",$P).")".(isset($_GET["function"])?" RETURNS".process_type($L["returns"],"CHARACTER SET"):"").($L["language"]?" LANGUAGE $L[language]":"").($y=="pgsql"?" AS ".q($qb):"$qb;");}function +remove_definer($I){return +preg_replace('~^([A-Z =]+) DEFINER=`'.preg_replace('~@(.*)~','`@`(%|\1)',logged_user()).'`~','\1',$I);}function +format_foreign_key($p){global$Wd;$j=$p["db"];$Od=$p["ns"];return" FOREIGN KEY (".implode(", ",array_map('idf_escape',$p["source"])).") REFERENCES ".($j!=""&&$j!=$_GET["db"]?idf_escape($j).".":"").($Od!=""&&$Od!=$_GET["ns"]?idf_escape($Od).".":"").table($p["table"])." (".implode(", ",array_map('idf_escape',$p["target"])).")".(preg_match("~^($Wd)\$~",$p["on_delete"])?" ON DELETE $p[on_delete]":"").(preg_match("~^($Wd)\$~",$p["on_update"])?" ON UPDATE $p[on_update]":"");}function +tar_file($o,$qg){$K=pack("a100a8a8a8a12a12",$o,644,0,0,decoct($qg->size),decoct(time()));$Ha=8*32;for($u=0;$usend();echo +str_repeat("\0",511-($qg->size+511)%512);}function +ini_bytes($Pc){$X=ini_get($Pc);switch(strtolower(substr($X,-1))){case'g':$X*=1024;case'm':$X*=1024;case'k':$X*=1024;}return$X;}function +doc_link($Ae,$hg="?"){global$y,$f;$yf=$f->server_info;$Xg=preg_replace('~^(\d\.?\d).*~s','\1',$yf);$Ng=array('sql'=>"https://dev.mysql.com/doc/refman/$Xg/en/",'sqlite'=>"https://www.sqlite.org/",'pgsql'=>"https://www.postgresql.org/docs/$Xg/",'mssql'=>"https://msdn.microsoft.com/library/",'oracle'=>"https://www.oracle.com/pls/topic/lookup?ctx=db".preg_replace('~^.* (\d+)\.(\d+)\.\d+\.\d+\.\d+.*~s','\1\2',$yf)."&id=",);if(preg_match('~MariaDB~',$yf)){$Ng['sql']="https://mariadb.com/kb/en/library/";$Ae['sql']=(isset($Ae['mariadb'])?$Ae['mariadb']:str_replace(".html","/",$Ae['sql']));}return($Ae[$y]?"$hg":"");}function +ob_gzencode($Q){return +gzencode($Q);}function +db_size($j){global$f;if(!$f->select_db($j))return"?";$K=0;foreach(table_status()as$S)$K+=$S["Data_length"]+$S["Index_length"];return +format_number($K);}function +set_utf8mb4($h){global$f;static$P=false;if(!$P&&preg_match('~\butf8mb4~i',$h)){$P=true;echo"SET NAMES ".charset($f).";\n\n";}}function +connect_error(){global$b,$f,$U,$l,$zb;if(DB!=""){header("HTTP/1.1 404 Not Found");page_header('Database'.": ".h(DB),'Invalid database.',true);}else{if($_POST["db"]&&!$l)queries_redirect(substr(ME,0,-1),'Databases have been dropped.',drop_databases($_POST["db"]));page_header('Select database',$l,false);echo"

    ".sprintf('%s version: %s through PHP extension %s',$zb[DRIVER],"".h($f->server_info)."","$f->extension")."\n","

    ".sprintf('Logged as: %s',"".h(logged_user())."")."\n";$i=$b->databases();if($i){$rf=support("scheme");$Pa=collations();echo"

    \n","\n",script("mixin(qsl('table'), {onclick: tableClick, ondblclick: partialArg(tableClick, true)});"),"".(support("database")?"\n";$i=($_GET["dbsize"]?count_tables($i):array_flip($i));foreach($i +as$j=>$T){$mf=h(ME)."db=".urlencode($j);$v=h("Db-".$j);echo"".(support("database")?"
    ":"")."".'Database'." - ".'Refresh'.""."".'Collation'."".'Tables'."".'Size'." - ".'Compute'."".script("qsl('a').onclick = partial(ajaxSetHtml, '".js_escape(ME)."script=connect');","")."
    ".checkbox("db[]",$j,in_array($j,(array)$_POST["db"]),"","","",$v):""),"".h($j)."";$Oa=h(db_collation($j,$Pa));echo"".(support("database")?"$Oa":$Oa),"".($_GET["dbsize"]?$T:"?")."","".($_GET["dbsize"]?db_size($j):"?"),"\n";}echo"
    \n",(support("database")?"\n":""),"\n","
    \n",script("tableCheck();");}}page_footer("db");}if(isset($_GET["status"]))$_GET["variables"]=$_GET["status"];if(isset($_GET["import"]))$_GET["sql"]=$_GET["import"];if(!(DB!=""?$f->select_db(DB):isset($_GET["sql"])||isset($_GET["dump"])||isset($_GET["database"])||isset($_GET["processlist"])||isset($_GET["privileges"])||isset($_GET["user"])||isset($_GET["variables"])||$_GET["script"]=="connect"||$_GET["script"]=="kill")){if(DB!=""||$_GET["refresh"]){restart_session();set_session("dbs",null);}connect_error();exit;}$Wd="RESTRICT|NO ACTION|CASCADE|SET NULL|SET DEFAULT";class TmpFile{var$handler;var$size;function __construct(){$this->handler=tmpfile();}function -write($Eb){$this->size+=strlen($Eb);fwrite($this->handler,$Eb);}function -send(){fseek($this->handler,0);fpassthru($this->handler);fclose($this->handler);}}$Bc="'(?:''|[^'\\\\]|\\\\.)*'";$Vd="IN|OUT|INOUT";if(isset($_GET["select"])&&($_POST["edit"]||$_POST["clone"])&&!$_POST["save"])$_GET["edit"]=$_GET["select"];if(isset($_GET["callf"]))$_GET["call"]=$_GET["callf"];if(isset($_GET["function"]))$_GET["procedure"]=$_GET["function"];if(isset($_GET["download"])){$a=$_GET["download"];$p=fields($a);header("Content-Type: application/octet-stream");header("Content-Disposition: attachment; filename=".friendly_url("$a-".implode("_",$_GET["where"])).".".friendly_url($_GET["field"]));$L=array(idf_escape($_GET["field"]));$H=$m->select($a,$L,array(where($_GET,$p)),$L);$J=($H?$H->fetch_row():array());echo$m->value($J[0],$p[$_GET["field"]]);exit;}elseif(isset($_GET["table"])){$a=$_GET["table"];$p=fields($a);if(!$p)$n=error();$R=table_status1($a,true);$D=$b->tableName($R);page_header(($p&&is_view($R)?$R['Engine']=='materialized view'?lang(129):lang(130):lang(131)).": ".($D!=""?$D:h($a)),$n);$b->selectLinks($R);$tb=$R["Comment"];if($tb!="")echo"

    ".lang(50).": ".h($tb)."\n";if($p)$b->tableStructurePrint($p);if(!is_view($R)){if(support("indexes")){echo"

    ".lang(132)."

    \n";$x=indexes($a);if($x)$b->tableIndexesPrint($x);echo'

    ".lang(100)."

    \n";$jd=foreign_keys($a);if($jd){echo"\n","\n";foreach($jd -as$D=>$r){echo"","
    ".lang(134)."".lang(135)."".lang(103)."".lang(102)."
    ".implode(", ",array_map('h',$r["source"]))."","".($r["db"]!=""?"".h($r["db"]).".":"").($r["ns"]!=""?"".h($r["ns"]).".":"").h($r["table"])."","(".implode(", ",array_map('h',$r["target"])).")","".h($r["on_delete"])."\n","".h($r["on_update"])."\n",''.lang(136).'';}echo"
    \n";}echo'

    ".lang(138)."

    \n";$Bi=triggers($a);if($Bi){echo"\n";foreach($Bi -as$z=>$X)echo"
    ".h($X[0])."".h($X[1])."".h($z)."".lang(136)."\n";echo"
    \n";}echo'
    +write($Za){$this->size+=strlen($Za);fwrite($this->handler,$Za);}function +send(){fseek($this->handler,0);fpassthru($this->handler);fclose($this->handler);}}$Qb="'(?:''|[^'\\\\]|\\\\.)*'";$Qc="IN|OUT|INOUT";if(isset($_GET["select"])&&($_POST["edit"]||$_POST["clone"])&&!$_POST["save"])$_GET["edit"]=$_GET["select"];if(isset($_GET["download"])){$a=$_GET["download"];$n=fields($a);header("Content-Type: application/octet-stream");header("Content-Disposition: attachment; filename=".friendly_url("$a-".implode("_",$_GET["where"])).".".friendly_url($_GET["field"]));$N=array(idf_escape($_GET["field"]));$J=$k->select($a,$N,array(where($_GET,$n)),$N);$L=($J?$J->fetch_row():array());echo$k->value($L[0],$n[$_GET["field"]]);exit;}elseif(isset($_GET["table"])){$a=$_GET["table"];$n=fields($a);if(!$n)$l=error();$S=table_status1($a,true);$F=$b->tableName($S);page_header(($n&&is_view($S)?$S['Engine']=='materialized view'?'Materialized view':'View':'Table').": ".($F!=""?$F:h($a)),$l);$b->selectLinks($S);$Ta=$S["Comment"];if($Ta!="")echo"

    ".'Comment'.": ".h($Ta)."\n";if($n)$b->tableStructurePrint($n);if(!is_view($S)){if(support("indexes")){echo"

    ".'Indexes'."

    \n";$x=indexes($a);if($x)$b->tableIndexesPrint($x);echo'

    ".'Foreign keys'."

    \n";$q=foreign_keys($a);if($q){echo"\n","\n";foreach($q +as$F=>$p){echo"","
    ".'Source'."".'Target'."".'ON DELETE'."".'ON UPDATE'."
    ".implode(", ",array_map('h',$p["source"]))."","".($p["db"]!=""?"".h($p["db"]).".":"").($p["ns"]!=""?"".h($p["ns"]).".":"").h($p["table"])."","(".implode(", ",array_map('h',$p["target"])).")","".h($p["on_delete"])."\n","".h($p["on_update"])."\n",''.'Alter'.'';}echo"
    \n";}echo'

    ".'Triggers'."

    \n";$Ag=triggers($a);if($Ag){echo"\n";foreach($Ag +as$z=>$X)echo"
    ".h($X[0])."".h($X[1])."".h($z)."".'Alter'."\n";echo"
    \n";}echo'
    qs(\'#schema\').onselectstart = function () { return false; }; -var tablePos = {',implode(",",$Uh)."\n",'}; -var em = qs(\'#schema\').offsetHeight / ',$ri,'; +var tablePos = {',implode(",",$Yf)."\n",'}; +var em = qs(\'#schema\').offsetHeight / ',$sg,'; document.onmousemove = schemaMousemove; document.onmouseup = partialArg(schemaMouseup, \'',js_escape(DB),'\'); -';foreach($ch -as$D=>$Q){echo"
    ",''.h($D)."",script("qsl('div').onmousedown = schemaMousedown;");foreach($Q["fields"]as$o){$X=''.h($o["field"]).'';echo"
    ".($o["primary"]?"$X":$X);}foreach((array)$Q["references"]as$ai=>$Ig){foreach($Ig -as$se=>$Eg){$te=$se-$Th[$D][1];$t=0;foreach($Eg[0]as$yh)echo"\n
    ";}}foreach((array)$Hg[$D]as$ai=>$Ig){foreach($Ig -as$se=>$e){$te=$se-$Th[$D][1];$t=0;foreach($e -as$Zh)echo"\n
    ";}}echo"\n
    \n";}foreach($ch -as$D=>$Q){foreach((array)$Q["references"]as$ai=>$Ig){foreach($Ig -as$se=>$Eg){$Te=$ri;$Je=-10;foreach($Eg[0]as$z=>$yh){$ig=$Q["pos"][0]+$Q["fields"][$yh]["pos"];$jg=$ch[$ai]["pos"][0]+$ch[$ai]["fields"][$Eg[1][$z]]["pos"];$Te=min($Te,$ig,$jg);$Je=max($Je,$ig,$jg);}echo"
    \n";}}}echo'
    -
    ",''.h($F)."",script("qsl('div').onmousedown = schemaMousedown;");foreach($R["fields"]as$m){$X=''.h($m["field"]).'';echo"
    ".($m["primary"]?"$X":$X);}foreach((array)$R["references"]as$eg=>$gf){foreach($gf +as$jd=>$cf){$kd=$jd-$Xf[$F][1];$u=0;foreach($cf[0]as$Ff)echo"\n
    ";}}foreach((array)$ff[$F]as$eg=>$gf){foreach($gf +as$jd=>$e){$kd=$jd-$Xf[$F][1];$u=0;foreach($e +as$dg)echo"\n
    ";}}echo"\n
    \n";}foreach($qf +as$F=>$R){foreach((array)$R["references"]as$eg=>$gf){foreach($gf +as$jd=>$cf){$Gd=$sg;$yd=-10;foreach($cf[0]as$z=>$Ff){$Je=$R["pos"][0]+$R["fields"][$Ff]["pos"];$Ke=$qf[$eg]["pos"][0]+$qf[$eg]["fields"][$cf[1][$z]]["pos"];$Gd=min($Gd,$Je,$Ke);$yd=max($yd,$Je,$Ke);}echo"
    \n";}}}echo'
    +
    -';$Vb=array('','USE','DROP+CREATE','CREATE');$Vh=array('','DROP+CREATE','CREATE');$Sb=array('','TRUNCATE+INSERT','INSERT');if($y=="sql")$Sb[]='INSERT+UPDATE';parse_str($_COOKIE["adminer_export"],$J);if(!$J)$J=array("output"=>"text","format"=>"sql","db_style"=>(DB!=""?"":"CREATE"),"table_style"=>"DROP+CREATE","data_style"=>"INSERT");if(!isset($J["events"])){$J["routines"]=$J["events"]=($_GET["dump"]=="");$J["triggers"]=$J["table_style"];}echo"
    ".lang(141)."".html_select("output",$b->dumpOutput(),$J["output"],0)."\n";echo"
    ".lang(142)."".html_select("format",$b->dumpFormat(),$J["format"],0)."\n";echo($y=="sqlite"?"":"
    ".lang(37)."".html_select('db_style',$Vb,$J["db_style"]).(support("routine")?checkbox("routines",1,$J["routines"],lang(143)):"").(support("event")?checkbox("events",1,$J["events"],lang(144)):"")),"
    ".lang(123)."".html_select('table_style',$Vh,$J["table_style"]).checkbox("auto_increment",1,$J["auto_increment"],lang(51)).(support("trigger")?checkbox("triggers",1,$J["triggers"],lang(138)):""),"
    ".lang(145)."".html_select('data_style',$Sb,$J["data_style"]),'
    -

    - +';$lb=array('','USE','DROP+CREATE','CREATE');$Zf=array('','DROP+CREATE','CREATE');$ib=array('','TRUNCATE+INSERT','INSERT');if($y=="sql")$ib[]='INSERT+UPDATE';parse_str($_COOKIE["adminer_export"],$L);if(!$L)$L=array("output"=>"text","format"=>"sql","db_style"=>(DB!=""?"":"CREATE"),"table_style"=>"DROP+CREATE","data_style"=>"INSERT");if(!isset($L["events"])){$L["routines"]=$L["events"]=($_GET["dump"]=="");$L["triggers"]=$L["table_style"];}echo"".'Output'."".html_select("output",$b->dumpOutput(),$L["output"],0)."\n";echo"".'Format'."".html_select("format",$b->dumpFormat(),$L["format"],0)."\n";echo($y=="sqlite"?"":"".'Database'."".html_select('db_style',$lb,$L["db_style"]).(support("routine")?checkbox("routines",1,$L["routines"],'Routines'):"").(support("event")?checkbox("events",1,$L["events"],'Events'):"")),"".'Tables'."".html_select('table_style',$Zf,$L["table_style"]).checkbox("auto_increment",1,$L["auto_increment"],'Auto Increment').(support("trigger")?checkbox("triggers",1,$L["triggers"],'Triggers'):""),"".'Data'."".html_select('data_style',$ib,$L["data_style"]),' +

    + -',script("qsl('table').onclick = dumpClick;");$mg=array();if(DB!=""){$db=($a!=""?"":" checked");echo"","\n";$bj="";$Wh=tables_list();foreach($Wh -as$D=>$T){$lg=preg_replace('~_.*~','',$D);$db=($a==""||$a==(substr($a,-1)=="%"?"$lg%":$D));$pg="\n";$k=$b->databases();if($k){foreach($k -as$l){if(!information_schema($l)){$lg=preg_replace('~_.*~','',$l);echo"","\n";$Zg="";$ag=tables_list();foreach($ag +as$F=>$V){$Me=preg_replace('~_.*~','',$F);$Fa=($a==""||$a==(substr($a,-1)=="%"?"$Me%":$F));$Qe="\n";$i=$b->databases();if($i){foreach($i +as$j){if(!information_schema($j)){$Me=preg_replace('~_.*~','',$j);echo"
    ".script("qs('#check-tables').onclick = partial(formCheck, /^tables\\[/);",""),"".script("qs('#check-data').onclick = partial(formCheck, /^data\\[/);",""),"
    ".checkbox("tables[]",$D,$db,$D,"","block");if($T!==null&&!preg_match('~table~i',$T))$bj.="$pg\n";else -echo"$pg\n";$mg[$lg]++;}echo$bj;if($Wh)echo -script("ajaxSetHtml('".js_escape(ME)."script=db');");}else{echo"
    ","",script("qs('#check-databases').onclick = partial(formCheck, /^databases\\[/);",""),"
    ".checkbox("databases[]",$l,$a==""||$a=="$lg%",$l,"","block")."\n";$mg[$lg]++;}}}else +',script("qsl('table').onclick = dumpClick;");$Ne=array();if(DB!=""){$Fa=($a!=""?"":" checked");echo"
    ".script("qs('#check-tables').onclick = partial(formCheck, /^tables\\[/);",""),"".script("qs('#check-data').onclick = partial(formCheck, /^data\\[/);",""),"
    ".checkbox("tables[]",$F,$Fa,$F,"","block");if($V!==null&&!preg_match('~table~i',$V))$Zg.="$Qe\n";else +echo"$Qe\n";$Ne[$Me]++;}echo$Zg;if($ag)echo +script("ajaxSetHtml('".js_escape(ME)."script=db');");}else{echo"
    ","",script("qs('#check-databases').onclick = partial(formCheck, /^databases\\[/);",""),"
    ".checkbox("databases[]",$j,$a==""||$a=="$Me%",$j,"","block")."\n";$Ne[$Me]++;}}}else echo"
    ";}echo'

    -';$bd=true;foreach($mg -as$z=>$X){if($z!=""&&$X>1){echo($bd?"

    ":" ")."".h($z)."";$bd=false;}}}elseif(isset($_GET["privileges"])){page_header(lang(71));echo'

    \n";hidden_fields_get();echo"\n",($qd?"":"\n"),"\n","\n";while($J=$H->fetch_assoc())echo'
    ".lang(35)."".lang(34)."
    '.h($J["User"])."".h($J["Host"]).''.lang(10)."\n";if(!$qd||DB!="")echo"\n";echo"
    \n","

    \n";}elseif(isset($_GET["sql"])){if(!$n&&$_POST["export"]){dump_headers("sql");$b->dumpTable("","");$b->dumpData("","table",$_POST["query"]);exit;}restart_session();$Dd=&get_session("queries");$Cd=&$Dd[DB];if(!$n&&$_POST["clear"]){$Cd=array();redirect(remove_from_uri("history"));}page_header((isset($_GET["import"])?lang(72):lang(64)),$n);if(!$n&&$_POST){$nd=false;if(!isset($_GET["import"]))$G=$_POST["query"];elseif($_POST["webfile"]){$Bh=$b->importServerPath();$nd=@fopen((file_exists($Bh)?$Bh:"compress.zlib://$Bh.gz"),"rb");$G=($nd?fread($nd,1e6):false);}else$G=get_file("sql_file",true);if(is_string($G)){if(function_exists('memory_get_usage'))@ini_set("memory_limit",max(ini_bytes("memory_limit"),2*strlen($G)+memory_get_usage()+8e6));if($G!=""&&strlen($G)<1e6){$xg=$G.(preg_match("~;[ \t\r\n]*\$~",$G)?"":";");if(!$Cd||reset(end($Cd))!=$xg){restart_session();$Cd[]=array($xg,time());set_session("queries",$Dd);stop_session();}}$zh="(?:\\s|/\\*[\s\S]*?\\*/|(?:#|-- )[^\n]*\n?|--\r?\n)";$cc=";";$kf=0;$zc=true;$h=connect();if(is_object($h)&&DB!=""){$h->select_db(DB);if($_GET["ns"]!="")set_schema($_GET["ns"],$h);}$sb=0;$Dc=array();$Sf='[\'"'.($y=="sql"?'`#':($y=="sqlite"?'`[':($y=="mssql"?'[':''))).']|/\*|-- |$'.($y=="pgsql"?'|\$[^$]*\$':'');$si=microtime(true);parse_str($_COOKIE["adminer_export"],$ya);$qc=$b->dumpFormat();unset($qc["sql"]);while($G!=""){if(!$kf&&preg_match("~^$zh*+DELIMITER\\s+(\\S+)~i",$G,$C)){$cc=$C[1];$G=substr($G,strlen($C[0]));}else{preg_match('('.preg_quote($cc)."\\s*|$Sf)",$G,$C,PREG_OFFSET_CAPTURE,$kf);list($ld,$hg)=$C[0];if(!$ld&&$nd&&!feof($nd))$G.=fread($nd,1e5);else{if(!$ld&&rtrim($G)=="")break;$kf=$hg+strlen($ld);if($ld&&rtrim($ld)!=$cc){while(preg_match('('.($ld=='/*'?'\*/':($ld=='['?']':(preg_match('~^-- |^#~',$ld)?"\n":preg_quote($ld)."|\\\\."))).'|$)s',$G,$C,PREG_OFFSET_CAPTURE,$kf)){$ah=$C[0][0];if(!$ah&&$nd&&!feof($nd))$G.=fread($nd,1e5);else{$kf=$C[0][1]+strlen($ah);if($ah[0]!="\\")break;}}}else{$zc=false;$xg=substr($G,0,$hg);$sb++;$pg="
    ".$b->sqlCommandQuery($xg)."
    \n";if($y=="sqlite"&&preg_match("~^$zh*+ATTACH\\b~i",$xg,$C)){echo$pg,"

    ".lang(147)."\n";$Dc[]=" $sb";if($_POST["error_stops"])break;}else{if(!$_POST["only_errors"]){echo$pg;ob_flush();flush();}$Fh=microtime(true);if($g->multi_query($xg)&&is_object($h)&&preg_match("~^$zh*+USE\\b~i",$xg))$h->query($xg);do{$H=$g->store_result();if($g->error){echo($_POST["only_errors"]?$pg:""),"

    ".lang(148).($g->errno?" ($g->errno)":"").": ".error()."\n";$Dc[]=" $sb";if($_POST["error_stops"])break -2;}else{$gi=" (".format_time($Fh).")".(strlen($xg)<1000?" ".lang(10)."":"");$_a=$g->affected_rows;$ej=($_POST["only_errors"]?"":$m->warnings());$fj="warnings-$sb";if($ej)$gi.=", ".lang(46)."".script("qsl('a').onclick = partial(toggle, '$fj');","");$Lc=null;$Mc="explain-$sb";if(is_object($H)){$_=$_POST["limit"];$Ef=select($H,$h,array(),$_);if(!$_POST["only_errors"]){echo"

    \n";$gf=$H->num_rows;echo"

    ".($gf?($_&&$gf>$_?lang(149,$_):"").lang(150,$gf):""),$gi;if($h&&preg_match("~^($zh|\\()*+SELECT\\b~i",$xg)&&($Lc=explain($h,$xg)))echo", Explain".script("qsl('a').onclick = partial(toggle, '$Mc');","");$u="export-$sb";echo", ".lang(73)."".script("qsl('a').onclick = partial(toggle, '$u');","")."\n"."

    \n";}}else{if(preg_match("~^$zh*+(CREATE|DROP|ALTER)$zh++(DATABASE|SCHEMA)\\b~i",$xg)){restart_session();set_session("dbs",null);stop_session();}if(!$_POST["only_errors"])echo"

    ".lang(151,$_a)."$gi\n";}echo($ej?"

    \n":"");if($Lc){echo"\n";}}$Fh=microtime(true);}while($g->next_result());}$G=substr($G,$kf);$kf=0;}}}}if($zc)echo"

    ".lang(152)."\n";elseif($_POST["only_errors"]){echo"

    ".lang(153,$sb-count($Dc))," (".format_time($si).")\n";}elseif($Dc&&$sb>1)echo"

    ".lang(148).": ".implode("",$Dc)."\n";}else -echo"

    ".upload_error($G)."\n";}echo' +';$lc=true;foreach($Ne +as$z=>$X){if($z!=""&&$X>1){echo($lc?"

    ":" ")."".h($z)."";$lc=false;}}}elseif(isset($_GET["sql"])){if(!$l&&$_POST["export"]){dump_headers("sql");$b->dumpTable("","");$b->dumpData("","table",$_POST["query"]);exit;}restart_session();$Gc=&get_session("queries");$Fc=&$Gc[DB];if(!$l&&$_POST["clear"]){$Fc=array();redirect(remove_from_uri("history"));}page_header((isset($_GET["import"])?'Import':'SQL command'),$l);if(!$l&&$_POST){$r=false;if(!isset($_GET["import"]))$I=$_POST["query"];elseif($_POST["webfile"]){$If=$b->importServerPath();$r=@fopen((file_exists($If)?$If:"compress.zlib://$If.gz"),"rb");$I=($r?fread($r,1e6):false);}else$I=get_file("sql_file",true);if(is_string($I)){if(function_exists('memory_get_usage'))@ini_set("memory_limit",max(ini_bytes("memory_limit"),2*strlen($I)+memory_get_usage()+8e6));if($I!=""&&strlen($I)<1e6){$H=$I.(preg_match("~;[ \t\r\n]*\$~",$I)?"":";");if(!$Fc||reset(end($Fc))!=$H){restart_session();$Fc[]=array($H,time());set_session("queries",$Gc);stop_session();}}$Gf="(?:\\s|/\\*[\s\S]*?\\*/|(?:#|-- )[^\n]*\n?|--\r?\n)";$rb=";";$Sd=0;$Nb=true;$g=connect();if(is_object($g)&&DB!=""){$g->select_db(DB);if($_GET["ns"]!="")set_schema($_GET["ns"],$g);}$Sa=0;$Sb=array();$ve='[\'"'.($y=="sql"?'`#':($y=="sqlite"?'`[':($y=="mssql"?'[':''))).']|/\*|-- |$'.($y=="pgsql"?'|\$[^$]*\$':'');$tg=microtime(true);parse_str($_COOKIE["adminer_export"],$ia);$Eb=$b->dumpFormat();unset($Eb["sql"]);while($I!=""){if(!$Sd&&preg_match("~^$Gf*+DELIMITER\\s+(\\S+)~i",$I,$C)){$rb=$C[1];$I=substr($I,strlen($C[0]));}else{preg_match('('.preg_quote($rb)."\\s*|$ve)",$I,$C,PREG_OFFSET_CAPTURE,$Sd);list($rc,$Ie)=$C[0];if(!$rc&&$r&&!feof($r))$I.=fread($r,1e5);else{if(!$rc&&rtrim($I)=="")break;$Sd=$Ie+strlen($rc);if($rc&&rtrim($rc)!=$rb){while(preg_match('('.($rc=='/*'?'\*/':($rc=='['?']':(preg_match('~^-- |^#~',$rc)?"\n":preg_quote($rc)."|\\\\."))).'|$)s',$I,$C,PREG_OFFSET_CAPTURE,$Sd)){$pf=$C[0][0];if(!$pf&&$r&&!feof($r))$I.=fread($r,1e5);else{$Sd=$C[0][1]+strlen($pf);if($pf[0]!="\\")break;}}}else{$Nb=false;$H=substr($I,0,$Ie);$Sa++;$Qe="

    ".$b->sqlCommandQuery($H)."
    \n";if($y=="sqlite"&&preg_match("~^$Gf*+ATTACH\\b~i",$H,$C)){echo$Qe,"

    ".'ATTACH queries are not supported.'."\n";$Sb[]=" $Sa";if($_POST["error_stops"])break;}else{if(!$_POST["only_errors"]){echo$Qe;ob_flush();flush();}$Lf=microtime(true);if($f->multi_query($H)&&is_object($g)&&preg_match("~^$Gf*+USE\\b~i",$H))$g->query($H);do{$J=$f->store_result();if($f->error){echo($_POST["only_errors"]?$Qe:""),"

    ".'Error in query'.($f->errno?" ($f->errno)":"").": ".error()."\n";$Sb[]=" $Sa";if($_POST["error_stops"])break +2;}else{$jg=" (".format_time($Lf).")".(strlen($H)<1000?" ".'Edit'."":"");$ka=$f->affected_rows;$ch=($_POST["only_errors"]?"":$k->warnings());$dh="warnings-$Sa";if($ch)$jg.=", ".'Warnings'."".script("qsl('a').onclick = partial(toggle, '$dh');","");$Zb=null;$ac="explain-$Sa";if(is_object($J)){$_=$_POST["limit"];$ie=select($J,$g,array(),$_);if(!$_POST["only_errors"]){echo"

    \n";$Pd=$J->num_rows;echo"

    ".($Pd?($_&&$Pd>$_?sprintf('%d / ',$_):"").lang(array('%d row','%d rows'),$Pd):""),$jg;if($g&&preg_match("~^($Gf|\\()*+SELECT\\b~i",$H)&&($Zb=explain($g,$H)))echo", Explain".script("qsl('a').onclick = partial(toggle, '$ac');","");$v="export-$Sa";echo", ".'Export'."".script("qsl('a').onclick = partial(toggle, '$v');","")."\n"."

    \n";}}else{if(preg_match("~^$Gf*+(CREATE|DROP|ALTER)$Gf++(DATABASE|SCHEMA)\\b~i",$H)){restart_session();set_session("dbs",null);stop_session();}if(!$_POST["only_errors"])echo"

    ".lang(array('Query executed OK, %d row affected.','Query executed OK, %d rows affected.'),$ka)."$jg\n";}echo($ch?"

    \n":"");if($Zb){echo"\n";}}$Lf=microtime(true);}while($f->next_result());}$I=substr($I,$Sd);$Sd=0;}}}}if($Nb)echo"

    ".'No commands to execute.'."\n";elseif($_POST["only_errors"]){echo"

    ".lang(array('%d query executed OK.','%d queries executed OK.'),$Sa-count($Sb))," (".format_time($tg).")\n";}elseif($Sb&&$Sa>1)echo"

    ".'Error in query'.": ".implode("",$Sb)."\n";}else +echo"

    ".upload_error($I)."\n";}echo'

    -';$Jc="";if(!isset($_GET["import"])){$xg=$_GET["sql"];if($_POST)$xg=$_POST["query"];elseif($_GET["history"]=="all")$xg=$Cd;elseif($_GET["history"]!="")$xg=$Cd[$_GET["history"]][0];echo"

    ";textarea("query",$xg,20);echo -script(($_POST?"":"qs('textarea').focus();\n")."qs('#form').onsubmit = partial(sqlSubmit, qs('#form'), '".js_escape(remove_from_uri("sql|limit|error_stops|only_errors|history"))."');"),"

    $Jc\n",lang(155).": \n";}else{echo"

    ".lang(156)."
    ";$wd=(extension_loaded("zlib")?"[.gz]":"");echo(ini_bool("file_uploads")?"SQL$wd (< ".ini_get("upload_max_filesize")."B): \n$Jc":lang(157)),"
    \n";$Kd=$b->importServerPath();if($Kd){echo"
    ".lang(158)."
    ",lang(159,"".h($Kd)."$wd"),' ',"
    \n";}echo"

    ";}echo -checkbox("error_stops",1,($_POST?$_POST["error_stops"]:isset($_GET["import"])||$_GET["error_stops"]),lang(161))."\n",checkbox("only_errors",1,($_POST?$_POST["only_errors"]:isset($_GET["import"])||$_GET["only_errors"]),lang(162))."\n","\n";if(!isset($_GET["import"])&&$Cd){print_fieldset("history",lang(163),$_GET["history"]!="");for($X=end($Cd);$X;$X=prev($Cd)){$z=key($Cd);list($xg,$gi,$uc)=$X;echo''.lang(10).""." ".@date("H:i:s",$gi).""." ".shorten_utf8(ltrim(str_replace("\n"," ",str_replace("\r","",preg_replace('~^(#|-- ).*~m','',$xg)))),80,"").($uc?" ($uc)":"")."
    \n";}echo"\n","".lang(165)."\n","\n";}echo'

    -';}elseif(isset($_GET["edit"])){$a=$_GET["edit"];$p=fields($a);$Z=(isset($_GET["select"])?($_POST["check"]&&count($_POST["check"])==1?where_check($_POST["check"][0],$p):""):where($_GET,$p));$Li=(isset($_GET["select"])?$_POST["edit"]:$Z);foreach($p -as$D=>$o){if(!isset($o["privileges"][$Li?"update":"insert"])||$b->fieldName($o)==""||$o["generated"])unset($p[$D]);}if($_POST&&!$n&&!isset($_GET["select"])){$B=$_POST["referer"];if($_POST["insert"])$B=($Li?null:$_SERVER["REQUEST_URI"]);elseif(!preg_match('~^.+&select=.+$~',$B))$B=ME."select=".urlencode($a);$x=indexes($a);$Gi=unique_array($_GET["where"],$x);$_g="\nWHERE $Z";if(isset($_POST["delete"]))queries_redirect($B,lang(166),$m->delete($a,$_g,!$Gi));else{$N=array();foreach($p -as$D=>$o){$X=process_input($o);if($X!==false&&$X!==null)$N[idf_escape($D)]=$X;}if($Li){if(!$N)redirect($B);queries_redirect($B,lang(167),$m->update($a,$N,$_g,!$Gi));if(is_ajax()){page_headers();page_messages($n);exit;}}else{$H=$m->insert($a,$N);$re=($H?last_id():0);queries_redirect($B,lang(168,($re?" $re":"")),$H);}}}$J=null;if($_POST["save"])$J=(array)$_POST["fields"];elseif($Z){$L=array();foreach($p -as$D=>$o){if(isset($o["privileges"]["select"])){$Ga=convert_field($o);if($_POST["clone"]&&$o["auto_increment"])$Ga="''";if($y=="sql"&&preg_match("~enum|set~",$o["type"]))$Ga="1*".idf_escape($D);$L[]=($Ga?"$Ga AS ":"").idf_escape($D);}}$J=array();if(!support("table"))$L=array("*");if($L){$H=$m->select($a,$L,array($Z),$L,array(),(isset($_GET["select"])?2:1));if(!$H)$n=error();else{$J=$H->fetch_assoc();if(!$J)$J=false;}if(isset($_GET["select"])&&(!$J||$H->fetch_assoc()))$J=null;}}if(!support("table")&&!$p){if(!$Z){$H=$m->select($a,array("*"),$Z,array("*"));$J=($H?$H->fetch_assoc():false);if(!$J)$J=array($m->primary=>"");}if($J){foreach($J -as$z=>$X){if(!$Z)$J[$z]=null;$p[$z]=array("field"=>$z,"null"=>($z!=$m->primary),"auto_increment"=>($z==$m->primary));}}}edit_form($a,$p,$J,$Li);}elseif(isset($_GET["create"])){$a=$_GET["create"];$Uf=array();foreach(array('HASH','LINEAR HASH','KEY','LINEAR KEY','RANGE','LIST')as$z)$Uf[$z]=$z;$Gg=referencable_primary($a);$jd=array();foreach($Gg -as$Rh=>$o)$jd[str_replace("`","``",$Rh)."`".str_replace("`","``",$o["field"])]=$Rh;$Hf=array();$R=array();if($a!=""){$Hf=fields($a);$R=table_status($a);if(!$R)$n=lang(9);}$J=$_POST;$J["fields"]=(array)$J["fields"];if($J["auto_increment_col"])$J["fields"][$J["auto_increment_col"]]["auto_increment"]=true;if($_POST)set_adminer_settings(array("comments"=>$_POST["comments"],"defaults"=>$_POST["defaults"]));if($_POST&&!process_fields($J["fields"])&&!$n){if($_POST["drop"])queries_redirect(substr(ME,0,-1),lang(169),drop_tables(array($a)));else{$p=array();$Da=array();$Pi=false;$hd=array();$Gf=reset($Hf);$Ba=" FIRST";foreach($J["fields"]as$z=>$o){$r=$jd[$o["type"]];$Ci=($r!==null?$Gg[$r]:$o);if($o["field"]!=""){if(!$o["has_default"])$o["default"]=null;if($z==$J["auto_increment_col"])$o["auto_increment"]=true;$ug=process_field($o,$Ci);$Da[]=array($o["orig"],$ug,$Ba);if(!$Gf||$ug!=process_field($Gf,$Gf)){$p[]=array($o["orig"],$ug,$Ba);if($o["orig"]!=""||$Ba)$Pi=true;}if($r!==null)$hd[idf_escape($o["field"])]=($a!=""&&$y!="sqlite"?"ADD":" ").format_foreign_key(array('table'=>$jd[$o["type"]],'source'=>array($o["field"]),'target'=>array($Ci["field"]),'on_delete'=>$o["on_delete"],));$Ba=" AFTER ".idf_escape($o["field"]);}elseif($o["orig"]!=""){$Pi=true;$p[]=array($o["orig"]);}if($o["orig"]!=""){$Gf=next($Hf);if(!$Gf)$Ba="";}}$Wf="";if($Uf[$J["partition_by"]]){$Xf=array();if($J["partition_by"]=='RANGE'||$J["partition_by"]=='LIST'){foreach(array_filter($J["partition_names"])as$z=>$X){$Y=$J["partition_values"][$z];$Xf[]="\n PARTITION ".idf_escape($X)." VALUES ".($J["partition_by"]=='RANGE'?"LESS THAN":"IN").($Y!=""?" ($Y)":" MAXVALUE");}}$Wf.="\nPARTITION BY $J[partition_by]($J[partition])".($Xf?" (".implode(",",$Xf)."\n)":($J["partitions"]?" PARTITIONS ".(+$J["partitions"]):""));}elseif(support("partitioning")&&preg_match("~partitioned~",$R["Create_options"]))$Wf.="\nREMOVE PARTITIONING";$Ne=lang(170);if($a==""){cookie("adminer_engine",$J["Engine"]);$Ne=lang(171);}$D=trim($J["name"]);queries_redirect(ME.(support("table")?"table=":"select=").urlencode($D),$Ne,alter_table($a,$D,($y=="sqlite"&&($Pi||$hd)?$Da:$p),$hd,($J["Comment"]!=$R["Comment"]?$J["Comment"]:null),($J["Engine"]&&$J["Engine"]!=$R["Engine"]?$J["Engine"]:""),($J["Collation"]&&$J["Collation"]!=$R["Collation"]?$J["Collation"]:""),($J["Auto_increment"]!=""?number($J["Auto_increment"]):""),$Wf));}}page_header(($a!=""?lang(44):lang(74)),$n,array("table"=>$a),h($a));if(!$_POST){$J=array("Engine"=>$_COOKIE["adminer_engine"],"fields"=>array(array("field"=>"","type"=>(isset($U["int"])?"int":(isset($U["integer"])?"integer":"")),"on_update"=>"")),"partition_names"=>array(""),);if($a!=""){$J=$R;$J["name"]=$a;$J["fields"]=array();if(!$_GET["auto_increment"])$J["Auto_increment"]="";foreach($Hf -as$o){$o["has_default"]=isset($o["default"]);$J["fields"][]=$o;}if(support("partitioning")){$od="FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = ".q(DB)." AND TABLE_NAME = ".q($a);$H=$g->query("SELECT PARTITION_METHOD, PARTITION_ORDINAL_POSITION, PARTITION_EXPRESSION $od ORDER BY PARTITION_ORDINAL_POSITION DESC LIMIT 1");list($J["partition_by"],$J["partitions"],$J["partition"])=$H->fetch_row();$Xf=get_key_vals("SELECT PARTITION_NAME, PARTITION_DESCRIPTION $od AND PARTITION_NAME != '' ORDER BY PARTITION_ORDINAL_POSITION");$Xf[""]="";$J["partition_names"]=array_keys($Xf);$J["partition_values"]=array_values($Xf);}}}$nb=collations();$Ac=engines();foreach($Ac -as$_c){if(!strcasecmp($_c,$J["Engine"])){$J["Engine"]=$_c;break;}}echo' +';$Xb="";if(!isset($_GET["import"])){$H=$_GET["sql"];if($_POST)$H=$_POST["query"];elseif($_GET["history"]=="all")$H=$Fc;elseif($_GET["history"]!="")$H=$Fc[$_GET["history"]][0];echo"

    ";textarea("query",$H,20);echo +script(($_POST?"":"qs('textarea').focus();\n")."qs('#form').onsubmit = partial(sqlSubmit, qs('#form'), '".js_escape(remove_from_uri("sql|limit|error_stops|only_errors|history"))."');"),"

    $Xb\n",'Limit rows'.": \n";}else{echo"

    ".'File upload'."
    ";$zc=(extension_loaded("zlib")?"[.gz]":"");echo(ini_bool("file_uploads")?"SQL$zc (< ".ini_get("upload_max_filesize")."B): \n$Xb":'File uploads are disabled.'),"
    \n";$Mc=$b->importServerPath();if($Mc){echo"
    ".'From server'."
    ",sprintf('Webserver file %s',"".h($Mc)."$zc"),' ',"
    \n";}echo"

    ";}echo +checkbox("error_stops",1,($_POST?$_POST["error_stops"]:isset($_GET["import"])||$_GET["error_stops"]),'Stop on error')."\n",checkbox("only_errors",1,($_POST?$_POST["only_errors"]:isset($_GET["import"])||$_GET["only_errors"]),'Show only errors')."\n","\n";if(!isset($_GET["import"])&&$Fc){print_fieldset("history",'History',$_GET["history"]!="");for($X=end($Fc);$X;$X=prev($Fc)){$z=key($Fc);list($H,$jg,$Ib)=$X;echo''.'Edit'.""." ".@date("H:i:s",$jg).""." ".shorten_utf8(ltrim(str_replace("\n"," ",str_replace("\r","",preg_replace('~^(#|-- ).*~m','',$H)))),80,"").($Ib?" ($Ib)":"")."
    \n";}echo"\n","".'Edit all'."\n","\n";}echo' +';}elseif(isset($_GET["edit"])){$a=$_GET["edit"];$n=fields($a);$Z=(isset($_GET["select"])?($_POST["check"]&&count($_POST["check"])==1?where_check($_POST["check"][0],$n):""):where($_GET,$n));$Kg=(isset($_GET["select"])?$_POST["edit"]:$Z);foreach($n +as$F=>$m){if(!isset($m["privileges"][$Kg?"update":"insert"])||$b->fieldName($m)==""||$m["generated"])unset($n[$F]);}if($_POST&&!$l&&!isset($_GET["select"])){$B=$_POST["referer"];if($_POST["insert"])$B=($Kg?null:$_SERVER["REQUEST_URI"]);elseif(!preg_match('~^.+&select=.+$~',$B))$B=ME."select=".urlencode($a);$x=indexes($a);$Fg=unique_array($_GET["where"],$x);$Ye="\nWHERE $Z";if(isset($_POST["delete"]))queries_redirect($B,'Item has been deleted.',$k->delete($a,$Ye,!$Fg));else{$P=array();foreach($n +as$F=>$m){$X=process_input($m);if($X!==false&&$X!==null)$P[idf_escape($F)]=$X;}if($Kg){if(!$P)redirect($B);queries_redirect($B,'Item has been updated.',$k->update($a,$P,$Ye,!$Fg));if(is_ajax()){page_headers();page_messages($l);exit;}}else{$J=$k->insert($a,$P);$id=($J?last_id():0);queries_redirect($B,sprintf('Item%s has been inserted.',($id?" $id":"")),$J);}}}$L=null;if($_POST["save"])$L=(array)$_POST["fields"];elseif($Z){$N=array();foreach($n +as$F=>$m){if(isset($m["privileges"]["select"])){$pa=convert_field($m);if($_POST["clone"]&&$m["auto_increment"])$pa="''";if($y=="sql"&&preg_match("~enum|set~",$m["type"]))$pa="1*".idf_escape($F);$N[]=($pa?"$pa AS ":"").idf_escape($F);}}$L=array();if(!support("table"))$N=array("*");if($N){$J=$k->select($a,$N,array($Z),$N,array(),(isset($_GET["select"])?2:1));if(!$J)$l=error();else{$L=$J->fetch_assoc();if(!$L)$L=false;}if(isset($_GET["select"])&&(!$L||$J->fetch_assoc()))$L=null;}}if(!support("table")&&!$n){if(!$Z){$J=$k->select($a,array("*"),$Z,array("*"));$L=($J?$J->fetch_assoc():false);if(!$L)$L=array($k->primary=>"");}if($L){foreach($L +as$z=>$X){if(!$Z)$L[$z]=null;$n[$z]=array("field"=>$z,"null"=>($z!=$k->primary),"auto_increment"=>($z==$k->primary));}}}edit_form($a,$n,$L,$Kg);}elseif(isset($_GET["create"])){$a=$_GET["create"];$we=array();foreach(array('HASH','LINEAR HASH','KEY','LINEAR KEY','RANGE','LIST')as$z)$we[$z]=$z;$ef=referencable_primary($a);$q=array();foreach($ef +as$Wf=>$m)$q[str_replace("`","``",$Wf)."`".str_replace("`","``",$m["field"])]=$Wf;$le=array();$S=array();if($a!=""){$le=fields($a);$S=table_status($a);if(!$S)$l='No tables.';}$L=$_POST;$L["fields"]=(array)$L["fields"];if($L["auto_increment_col"])$L["fields"][$L["auto_increment_col"]]["auto_increment"]=true;if($_POST)set_adminer_settings(array("comments"=>$_POST["comments"],"defaults"=>$_POST["defaults"]));if($_POST&&!process_fields($L["fields"])&&!$l){if($_POST["drop"])queries_redirect(substr(ME,0,-1),'Table has been dropped.',drop_tables(array($a)));else{$n=array();$na=array();$Og=false;$oc=array();$ke=reset($le);$ma=" FIRST";foreach($L["fields"]as$z=>$m){$p=$q[$m["type"]];$Bg=($p!==null?$ef[$p]:$m);if($m["field"]!=""){if(!$m["has_default"])$m["default"]=null;if($z==$L["auto_increment_col"])$m["auto_increment"]=true;$Ue=process_field($m,$Bg);$na[]=array($m["orig"],$Ue,$ma);if(!$ke||$Ue!=process_field($ke,$ke)){$n[]=array($m["orig"],$Ue,$ma);if($m["orig"]!=""||$ma)$Og=true;}if($p!==null)$oc[idf_escape($m["field"])]=($a!=""&&$y!="sqlite"?"ADD":" ").format_foreign_key(array('table'=>$q[$m["type"]],'source'=>array($m["field"]),'target'=>array($Bg["field"]),'on_delete'=>$m["on_delete"],));$ma=" AFTER ".idf_escape($m["field"]);}elseif($m["orig"]!=""){$Og=true;$n[]=array($m["orig"]);}if($m["orig"]!=""){$ke=next($le);if(!$ke)$ma="";}}$ye="";if($we[$L["partition_by"]]){$ze=array();if($L["partition_by"]=='RANGE'||$L["partition_by"]=='LIST'){foreach(array_filter($L["partition_names"])as$z=>$X){$Y=$L["partition_values"][$z];$ze[]="\n PARTITION ".idf_escape($X)." VALUES ".($L["partition_by"]=='RANGE'?"LESS THAN":"IN").($Y!=""?" ($Y)":" MAXVALUE");}}$ye.="\nPARTITION BY $L[partition_by]($L[partition])".($ze?" (".implode(",",$ze)."\n)":($L["partitions"]?" PARTITIONS ".(+$L["partitions"]):""));}elseif(support("partitioning")&&preg_match("~partitioned~",$S["Create_options"]))$ye.="\nREMOVE PARTITIONING";$D='Table has been altered.';if($a==""){cookie("adminer_engine",$L["Engine"]);$D='Table has been created.';}$F=trim($L["name"]);queries_redirect(ME.(support("table")?"table=":"select=").urlencode($F),$D,alter_table($a,$F,($y=="sqlite"&&($Og||$oc)?$na:$n),$oc,($L["Comment"]!=$S["Comment"]?$L["Comment"]:null),($L["Engine"]&&$L["Engine"]!=$S["Engine"]?$L["Engine"]:""),($L["Collation"]&&$L["Collation"]!=$S["Collation"]?$L["Collation"]:""),($L["Auto_increment"]!=""?number($L["Auto_increment"]):""),$ye));}}page_header(($a!=""?'Alter table':'Create table'),$l,array("table"=>$a),h($a));if(!$_POST){$L=array("Engine"=>$_COOKIE["adminer_engine"],"fields"=>array(array("field"=>"","type"=>(isset($Cg["int"])?"int":(isset($Cg["integer"])?"integer":"")),"on_update"=>"")),"partition_names"=>array(""),);if($a!=""){$L=$S;$L["name"]=$a;$L["fields"]=array();if(!$_GET["auto_increment"])$L["Auto_increment"]="";foreach($le +as$m){$m["has_default"]=isset($m["default"]);$L["fields"][]=$m;}if(support("partitioning")){$tc="FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = ".q(DB)." AND TABLE_NAME = ".q($a);$J=$f->query("SELECT PARTITION_METHOD, PARTITION_ORDINAL_POSITION, PARTITION_EXPRESSION $tc ORDER BY PARTITION_ORDINAL_POSITION DESC LIMIT 1");list($L["partition_by"],$L["partitions"],$L["partition"])=$J->fetch_row();$ze=get_key_vals("SELECT PARTITION_NAME, PARTITION_DESCRIPTION $tc AND PARTITION_NAME != '' ORDER BY PARTITION_ORDINAL_POSITION");$ze[""]="";$L["partition_names"]=array_keys($ze);$L["partition_values"]=array_values($ze);}}}$Pa=collations();$Pb=engines();foreach($Pb +as$Ob){if(!strcasecmp($Ob,$L["Engine"])){$L["Engine"]=$Ob;break;}}echo'

    -';if(support("columns")||$a==""){echo -lang(172),': +';if(support("columns")||$a==""){echo'Table name: ';if($a==""&&!$_POST)echo -script("focus(qs('#form')['name']);");echo($Ac?"".on_help("getTarget(event).value",1).script("qsl('select').onchange = helpClose;"):""),' ',($nb&&!preg_match("~sqlite|mssql~",$y)?html_select("Collation",array(""=>"(".lang(101).")")+$nb,$J["Collation"]):""),' +script("focus(qs('#form')['name']);");echo($Pb?"".on_help("getTarget(event).value",1).script("qsl('select').onchange = helpClose;"):""),' ',($Pa&&!preg_match("~sqlite|mssql~",$y)?html_select("Collation",array(""=>"(".'collation'.")")+$Pa,$L["Collation"]):""),' ';}echo' ';if(support("columns")){echo'

    -';edit_fields($J["fields"],$nb,"TABLE",$jd);echo'
    +';edit_fields($L["fields"],$Pa,"TABLE",$q);echo' ',script("editFields();"),'

    -',lang(51),': -',checkbox("defaults",1,($_POST?$_POST["defaults"]:adminer_setting("defaults")),lang(174),"columnShow(this.checked, 5)","jsonly"),(support("comment")?checkbox("comments",1,($_POST?$_POST["comments"]:adminer_setting("comments")),lang(50),"editingCommentsClick(this, true);","jsonly").' ':''),'

    - +Auto Increment: +',checkbox("defaults",1,($_POST?$_POST["defaults"]:adminer_setting("defaults")),'Default values',"columnShow(this.checked, 5)","jsonly"),(support("comment")?checkbox("comments",1,($_POST?$_POST["comments"]:adminer_setting("comments")),'Comment',"editingCommentsClick(this, true);","jsonly").' ':''),'

    + ';}echo' -';if($a!=""){echo'',confirm(lang(175,$a));}if(support("partitioning")){$Vf=preg_match('~RANGE|LIST~',$J["partition_by"]);print_fieldset("partition",lang(176),$J["partition_by"]);echo'

    -',"".on_help("getTarget(event).value.replace(/./, 'PARTITION BY \$&')",1).script("qsl('select').onchange = partitionByChange;"),'() -',lang(177),': - - -';foreach($J["partition_names"]as$z=>$X){echo'',' +';if($a!=""){echo'',confirm(sprintf('Drop %s?',$a));}if(support("partitioning")){$xe=preg_match('~RANGE|LIST~',$L["partition_by"]);print_fieldset("partition",'Partition by',$L["partition_by"]);echo'

    +',"".on_help("getTarget(event).value.replace(/./, 'PARTITION BY \$&')",1).script("qsl('select').onchange = partitionByChange;"),'() +Partitions: + + +';foreach($L["partition_names"]as$z=>$X){echo'',' -';}echo' +';}echo'

    -';}elseif(isset($_GET["indexes"])){$a=$_GET["indexes"];$Nd=array("PRIMARY","UNIQUE","INDEX");$R=table_status($a,true);if(preg_match('~MyISAM|M?aria'.(min_version(5.6,'10.0.5')?'|InnoDB':'').'~i',$R["Engine"]))$Nd[]="FULLTEXT";if(preg_match('~MyISAM|M?aria'.(min_version(5.7,'10.2.2')?'|InnoDB':'').'~i',$R["Engine"]))$Nd[]="SPATIAL";$x=indexes($a);$ng=array();if($y=="mongo"){$ng=$x["_id_"];unset($Nd[0]);unset($x["_id_"]);}$J=$_POST;if($_POST&&!$n&&!$_POST["add"]&&!$_POST["drop_col"]){$c=array();foreach($J["indexes"]as$w){$D=$w["name"];if(in_array($w["type"],$Nd)){$e=array();$xe=array();$ec=array();$N=array();ksort($w["columns"]);foreach($w["columns"]as$z=>$d){if($d!=""){$we=$w["lengths"][$z];$dc=$w["descs"][$z];$N[]=idf_escape($d).($we?"(".(+$we).")":"").($dc?" DESC":"");$e[]=$d;$xe[]=($we?$we:null);$ec[]=$dc;}}if($e){$Kc=$x[$D];if($Kc){ksort($Kc["columns"]);ksort($Kc["lengths"]);ksort($Kc["descs"]);if($w["type"]==$Kc["type"]&&array_values($Kc["columns"])===$e&&(!$Kc["lengths"]||array_values($Kc["lengths"])===$xe)&&array_values($Kc["descs"])===$ec){unset($x[$D]);continue;}}$c[]=array($w["type"],$D,$N);}}}foreach($x -as$D=>$Kc)$c[]=array($Kc["type"],$D,"DROP");if(!$c)redirect(ME."table=".urlencode($a));queries_redirect(ME."table=".urlencode($a),lang(180),alter_indexes($a,$c));}page_header(lang(132),$n,array("table"=>$a),h($a));$p=array_keys(fields($a));if($_POST["add"]){foreach($J["indexes"]as$z=>$w){if($w["columns"][count($w["columns"])]!="")$J["indexes"][$z]["columns"][]="";}$w=end($J["indexes"]);if($w["type"]||array_filter($w["columns"],'strlen'))$J["indexes"][]=array("columns"=>array(1=>""));}if(!$J){foreach($x -as$z=>$w){$x[$z]["name"]=$z;$x[$z]["columns"][]="";}$x[]=array("columns"=>array(1=>""));$J["indexes"]=$x;}echo' +';}elseif(isset($_GET["indexes"])){$a=$_GET["indexes"];$Oc=array("PRIMARY","UNIQUE","INDEX");$S=table_status($a,true);if(preg_match('~MyISAM|M?aria'.(min_version(5.6,'10.0.5')?'|InnoDB':'').'~i',$S["Engine"]))$Oc[]="FULLTEXT";if(preg_match('~MyISAM|M?aria'.(min_version(5.7,'10.2.2')?'|InnoDB':'').'~i',$S["Engine"]))$Oc[]="SPATIAL";$x=indexes($a);$Oe=array();if($y=="mongo"){$Oe=$x["_id_"];unset($Oc[0]);unset($x["_id_"]);}$L=$_POST;if($_POST&&!$l&&!$_POST["add"]&&!$_POST["drop_col"]){$oa=array();foreach($L["indexes"]as$w){$F=$w["name"];if(in_array($w["type"],$Oc)){$e=array();$od=array();$tb=array();$P=array();ksort($w["columns"]);foreach($w["columns"]as$z=>$d){if($d!=""){$nd=$w["lengths"][$z];$sb=$w["descs"][$z];$P[]=idf_escape($d).($nd?"(".(+$nd).")":"").($sb?" DESC":"");$e[]=$d;$od[]=($nd?$nd:null);$tb[]=$sb;}}if($e){$Yb=$x[$F];if($Yb){ksort($Yb["columns"]);ksort($Yb["lengths"]);ksort($Yb["descs"]);if($w["type"]==$Yb["type"]&&array_values($Yb["columns"])===$e&&(!$Yb["lengths"]||array_values($Yb["lengths"])===$od)&&array_values($Yb["descs"])===$tb){unset($x[$F]);continue;}}$oa[]=array($w["type"],$F,$P);}}}foreach($x +as$F=>$Yb)$oa[]=array($Yb["type"],$F,"DROP");if(!$oa)redirect(ME."table=".urlencode($a));queries_redirect(ME."table=".urlencode($a),'Indexes have been altered.',alter_indexes($a,$oa));}page_header('Indexes',$l,array("table"=>$a),h($a));$n=array_keys(fields($a));if($_POST["add"]){foreach($L["indexes"]as$z=>$w){if($w["columns"][count($w["columns"])]!="")$L["indexes"][$z]["columns"][]="";}$w=end($L["indexes"]);if($w["type"]||array_filter($w["columns"],'strlen'))$L["indexes"][]=array("columns"=>array(1=>""));}if(!$L){foreach($x +as$z=>$w){$x[$z]["name"]=$z;$x[$z]["columns"][]="";}$x[]=array("columns"=>array(1=>""));$L["indexes"]=$x;}echo'
    - -';if($ng){echo"
    ',lang(181),'',lang(182),'',lang(183),' +Index Type +Column (length) +Name +
    PRIMARY";foreach($ng["columns"]as$z=>$d){echo -select_input(" disabled",$p,$d)," ";}echo"\n";}$ge=1;foreach($J["indexes"]as$w){if(!$_POST["drop_col"]||$ge!=key($_POST["drop_col"])){echo"
    ".html_select("indexes[$ge][type]",array(-1=>"")+$Nd,$w["type"],($ge==count($J["indexes"])?"indexesAddRow.call(this);":1),"label-type"),"";ksort($w["columns"]);$t=1;foreach($w["columns"]as$z=>$d){echo"".select_input(" name='indexes[$ge][columns][$t]' title='".lang(48)."'",($p?array_combine($p,$p):$p),$d,"partial(".($t==count($w["columns"])?"indexesAddColumn":"indexesChangeColumn").", '".js_escape($y=="sql"?"":$_GET["indexes"]."_")."')"),($y=="sql"||$y=="mssql"?"":""),(support("descidx")?checkbox("indexes[$ge][descs][$t]",1,$w["descs"][$z],lang(59)):"")," ";$t++;}echo"\n","".script("qsl('input').onclick = partial(editingRemoveRow, 'indexes\$1[type]');");}$ge++;}echo'
    +';if($Oe){echo"PRIMARY";foreach($Oe["columns"]as$z=>$d){echo +select_input(" disabled",$n,$d)," ";}echo"\n";}$Zc=1;foreach($L["indexes"]as$w){if(!$_POST["drop_col"]||$Zc!=key($_POST["drop_col"])){echo"".html_select("indexes[$Zc][type]",array(-1=>"")+$Oc,$w["type"],($Zc==count($L["indexes"])?"indexesAddRow.call(this);":1),"label-type"),"";ksort($w["columns"]);$u=1;foreach($w["columns"]as$z=>$d){echo"".select_input(" name='indexes[$Zc][columns][$u]' title='".'Column'."'",($n?array_combine($n,$n):$n),$d,"partial(".($u==count($w["columns"])?"indexesAddColumn":"indexesChangeColumn").", '".js_escape($y=="sql"?"":$_GET["indexes"]."_")."')"),($y=="sql"||$y=="mssql"?"":""),(support("descidx")?checkbox("indexes[$Zc][descs][$u]",1,$w["descs"][$z],'descending'):"")," ";$u++;}echo"\n","".script("qsl('input').onclick = partial(editingRemoveRow, 'indexes\$1[type]');");}$Zc++;}echo'

    - - + +

    -';}elseif(isset($_GET["database"])){$J=$_POST;if($_POST&&!$n&&!isset($_POST["add_x"])){$D=trim($J["name"]);if($_POST["drop"]){$_GET["db"]="";queries_redirect(remove_from_uri("db|database"),lang(184),drop_databases(array(DB)));}elseif(DB!==$D){if(DB!=""){$_GET["db"]=$D;queries_redirect(preg_replace('~\bdb=[^&]*&~','',ME)."db=".urlencode($D),lang(185),rename_database($D,$J["collation"]));}else{$k=explode("\n",str_replace("\r","",$D));$Lh=true;$qe="";foreach($k -as$l){if(count($k)==1||$l!=""){if(!create_database($l,$J["collation"]))$Lh=false;$qe=$l;}}restart_session();set_session("dbs",null);queries_redirect(ME."db=".urlencode($qe),lang(186),$Lh);}}else{if(!$J["collation"])redirect(substr(ME,0,-1));query_redirect("ALTER DATABASE ".idf_escape($D).(preg_match('~^[a-z0-9_]+$~i',$J["collation"])?" COLLATE $J[collation]":""),substr(ME,0,-1),lang(187));}}page_header(DB!=""?lang(67):lang(115),$n,array(),h(DB));$nb=collations();$D=DB;if($_POST)$D=$J["name"];elseif(DB!="")$J["collation"]=db_collation(DB,$nb);elseif($y=="sql"){foreach(get_vals("SHOW GRANTS")as$qd){if(preg_match('~ ON (`(([^\\\\`]|``|\\\\.)*)%`\.\*)?~',$qd,$C)&&$C[1]){$D=stripcslashes(idf_unescape("`$C[2]`"));break;}}}echo' +';}elseif(isset($_GET["database"])){$L=$_POST;if($_POST&&!$l&&!isset($_POST["add_x"])){$F=trim($L["name"]);if($_POST["drop"]){$_GET["db"]="";queries_redirect(remove_from_uri("db|database"),'Database has been dropped.',drop_databases(array(DB)));}elseif(DB!==$F){if(DB!=""){$_GET["db"]=$F;queries_redirect(preg_replace('~\bdb=[^&]*&~','',ME)."db=".urlencode($F),'Database has been renamed.',rename_database($F,$L["collation"]));}else{$i=explode("\n",str_replace("\r","",$F));$Qf=true;$hd="";foreach($i +as$j){if(count($i)==1||$j!=""){if(!create_database($j,$L["collation"]))$Qf=false;$hd=$j;}}restart_session();set_session("dbs",null);queries_redirect(ME."db=".urlencode($hd),'Database has been created.',$Qf);}}else{if(!$L["collation"])redirect(substr(ME,0,-1));query_redirect("ALTER DATABASE ".idf_escape($F).(preg_match('~^[a-z0-9_]+$~i',$L["collation"])?" COLLATE $L[collation]":""),substr(ME,0,-1),'Database has been altered.');}}page_header(DB!=""?'Alter database':'Create database',$l,array(),h(DB));$Pa=collations();$F=DB;if($_POST)$F=$L["name"];elseif(DB!="")$L["collation"]=db_collation(DB,$Pa);elseif($y=="sql"){foreach(get_vals("SHOW GRANTS")as$vc){if(preg_match('~ ON (`(([^\\\\`]|``|\\\\.)*)%`\.\*)?~',$vc,$C)&&$C[1]){$F=stripcslashes(idf_unescape("`$C[2]`"));break;}}}echo'

    -',($_POST["add_x"]||strpos($D,"\n")?'
    ':'')."\n".($nb?html_select("collation",array(""=>"(".lang(101).")")+$nb,$J["collation"]).doc_link(array('sql'=>"charset-charsets.html",'mariadb'=>"supported-character-sets-and-collations/",'mssql'=>"ms187963.aspx",)):""),script("focus(qs('#name'));"),' -';if(DB!="")echo"".confirm(lang(175,DB))."\n";elseif(!$_POST["add_x"]&&$_GET["db"]=="")echo"\n";echo' +',($_POST["add_x"]||strpos($F,"\n")?'
    ':'')."\n".($Pa?html_select("collation",array(""=>"(".'collation'.")")+$Pa,$L["collation"]).'':""),script("focus(qs('#name'));"),' +';if(DB!="")echo"".confirm(sprintf('Drop %s?',DB))."\n";elseif(!$_POST["add_x"]&&$_GET["db"]=="")echo"\n";echo'

    -';}elseif(isset($_GET["scheme"])){$J=$_POST;if($_POST&&!$n){$A=preg_replace('~ns=[^&]*&~','',ME)."ns=";if($_POST["drop"])query_redirect("DROP SCHEMA ".idf_escape($_GET["ns"]),$A,lang(188));else{$D=trim($J["name"]);$A.=urlencode($D);if($_GET["ns"]=="")query_redirect("CREATE SCHEMA ".idf_escape($D),$A,lang(189));elseif($_GET["ns"]!=$D)query_redirect("ALTER SCHEMA ".idf_escape($_GET["ns"])." RENAME TO ".idf_escape($D),$A,lang(190));else -redirect($A);}}page_header($_GET["ns"]!=""?lang(68):lang(69),$n);if(!$J)$J["name"]=$_GET["ns"];echo' +';}elseif(isset($_GET["foreign"])){$a=$_GET["foreign"];$F=$_GET["name"];$L=$_POST;if($_POST&&!$l&&!$_POST["add"]&&!$_POST["change"]&&!$_POST["change-js"]){$D=($_POST["drop"]?'Foreign key has been dropped.':($F!=""?'Foreign key has been altered.':'Foreign key has been created.'));$B=ME."table=".urlencode($a);if(!$_POST["drop"]){$L["source"]=array_filter($L["source"],'strlen');ksort($L["source"]);$dg=array();foreach($L["source"]as$z=>$X)$dg[$z]=$L["target"][$z];$L["target"]=$dg;}if($y=="sqlite")queries_redirect($B,$D,recreate_table($a,$a,array(),array(),array(" $F"=>($_POST["drop"]?"":" ".format_foreign_key($L)))));else{$oa="ALTER TABLE ".table($a);$_b="\nDROP ".($y=="sql"?"FOREIGN KEY ":"CONSTRAINT ").idf_escape($F);if($_POST["drop"])query_redirect($oa.$_b,$B,$D);else{query_redirect($oa.($F!=""?"$_b,":"")."\nADD".format_foreign_key($L),$B,$D);$l='Source and target columns must have the same data type, there must be an index on the target columns and referenced data must exist.'."
    $l";}}}page_header('Foreign key',$l,array("table"=>$a),h($a));if($_POST){ksort($L["source"]);if($_POST["add"])$L["source"][]="";elseif($_POST["change"]||$_POST["change-js"])$L["target"]=array();}elseif($F!=""){$q=foreign_keys($a);$L=$q[$F];$L["source"][]="";}else{$L["table"]=$a;$L["source"]=array("");}echo'
    -

    -',script("focus(qs('#name'));"),' -';if($_GET["ns"]!="")echo"".confirm(lang(175,$_GET["ns"]))."\n";echo' -

    -';}elseif(isset($_GET["call"])){$da=($_GET["name"]?$_GET["name"]:$_GET["call"]);page_header(lang(191).": ".h($da),$n);$Wg=routine($_GET["call"],(isset($_GET["callf"])?"FUNCTION":"PROCEDURE"));$Ld=array();$Lf=array();foreach($Wg["fields"]as$t=>$o){if(substr($o["inout"],-3)=="OUT")$Lf[$t]="@".idf_escape($o["field"])." AS ".idf_escape($o["field"]);if(!$o["inout"]||substr($o["inout"],0,2)=="IN")$Ld[]=$t;}if(!$n&&$_POST){$Ya=array();foreach($Wg["fields"]as$z=>$o){if(in_array($z,$Ld)){$X=process_input($o);if($X===false)$X="''";if(isset($Lf[$z]))$g->query("SET @".idf_escape($o["field"])." = $X");}$Ya[]=(isset($Lf[$z])?"@".idf_escape($o["field"]):$X);}$G=(isset($_GET["callf"])?"SELECT":"CALL")." ".table($da)."(".implode(", ",$Ya).")";$Fh=microtime(true);$H=$g->multi_query($G);$_a=$g->affected_rows;echo$b->selectQuery($G,$Fh,!$H);if(!$H)echo"

    ".error()."\n";else{$h=connect();if(is_object($h))$h->select_db(DB);do{$H=$g->store_result();if(is_object($H))select($H,$h);else -echo"

    ".lang(192,$_a)." ".@date("H:i:s")."\n";}while($g->next_result());if($Lf)select($g->query("SELECT ".implode(", ",$Lf)));}}echo' -

    -';if($Ld){echo"\n";foreach($Ld -as$z){$o=$Wg["fields"][$z];$D=$o["field"];echo"
    ".$b->fieldName($o);$Y=$_POST["fields"][$D];if($Y!=""){if($o["type"]=="enum")$Y=+$Y;if($o["type"]=="set")$Y=array_sum($Y);}input($o,$Y,(string)$_POST["function"][$D]);echo"\n";}echo"
    \n";}echo'

    - - -

    -';}elseif(isset($_GET["foreign"])){$a=$_GET["foreign"];$D=$_GET["name"];$J=$_POST;if($_POST&&!$n&&!$_POST["add"]&&!$_POST["change"]&&!$_POST["change-js"]){$Ne=($_POST["drop"]?lang(193):($D!=""?lang(194):lang(195)));$B=ME."table=".urlencode($a);if(!$_POST["drop"]){$J["source"]=array_filter($J["source"],'strlen');ksort($J["source"]);$Zh=array();foreach($J["source"]as$z=>$X)$Zh[$z]=$J["target"][$z];$J["target"]=$Zh;}if($y=="sqlite")queries_redirect($B,$Ne,recreate_table($a,$a,array(),array(),array(" $D"=>($_POST["drop"]?"":" ".format_foreign_key($J)))));else{$c="ALTER TABLE ".table($a);$lc="\nDROP ".($y=="sql"?"FOREIGN KEY ":"CONSTRAINT ").idf_escape($D);if($_POST["drop"])query_redirect($c.$lc,$B,$Ne);else{query_redirect($c.($D!=""?"$lc,":"")."\nADD".format_foreign_key($J),$B,$Ne);$n=lang(196)."
    $n";}}}page_header(lang(197),$n,array("table"=>$a),h($a));if($_POST){ksort($J["source"]);if($_POST["add"])$J["source"][]="";elseif($_POST["change"]||$_POST["change-js"])$J["target"]=array();}elseif($D!=""){$jd=foreign_keys($a);$J=$jd[$D];$J["source"][]="";}else{$J["table"]=$a;$J["source"]=array("");}echo' -
    -';$yh=array_keys(fields($a));if($J["db"]!="")$g->select_db($J["db"]);if($J["ns"]!="")set_schema($J["ns"]);$Fg=array_keys(array_filter(table_status('',true),'fk_support'));$Zh=array_keys(fields(in_array($J["table"],$Fg)?$J["table"]:reset($Fg)));$tf="this.form['change-js'].value = '1'; this.form.submit();";echo"

    ".lang(198).": ".html_select("table",$Fg,$J["table"],$tf)."\n";if($y=="pgsql")echo -lang(77).": ".html_select("ns",$b->schemas(),$J["ns"]!=""?$J["ns"]:$_GET["ns"],$tf);elseif($y!="sqlite"){$Wb=array();foreach($b->databases()as$l){if(!information_schema($l))$Wb[]=$l;}echo -lang(76).": ".html_select("db",$Wb,$J["db"]!=""?$J["db"]:$_GET["db"],$tf);}echo' -

    +';$Ff=array_keys(fields($a));if($L["db"]!="")$f->select_db($L["db"]);if($L["ns"]!="")set_schema($L["ns"]);$df=array_keys(array_filter(table_status('',true),'fk_support'));$dg=array_keys(fields(in_array($L["table"],$df)?$L["table"]:reset($df)));$Xd="this.form['change-js'].value = '1'; this.form.submit();";echo"

    ".'Target table'.": ".html_select("table",$df,$L["table"],$Xd)."\n";if($y=="pgsql")echo'Schema'.": ".html_select("ns",$b->schemas(),$L["ns"]!=""?$L["ns"]:$_GET["ns"],$Xd);elseif($y!="sqlite"){$mb=array();foreach($b->databases()as$j){if(!information_schema($j))$mb[]=$j;}echo'DB'.": ".html_select("db",$mb,$L["db"]!=""?$L["db"]:$_GET["db"],$Xd);}echo' +

    - -';$ge=0;foreach($J["source"]as$z=>$X){echo"","
    ',lang(134),'',lang(135),'
    ".html_select("source[".(+$z)."]",array(-1=>"")+$yh,$X,($ge==count($J["source"])-1?"foreignAddRow.call(this);":1),"label-source"),"".html_select("target[".(+$z)."]",$Zh,$J["target"][$z],1,"label-target");$ge++;}echo'
    +SourceTarget +';$Zc=0;foreach($L["source"]as$z=>$X){echo"","".html_select("source[".(+$z)."]",array(-1=>"")+$Ff,$X,($Zc==count($L["source"])-1?"foreignAddRow.call(this);":1),"label-source"),"".html_select("target[".(+$z)."]",$dg,$L["target"][$z],1,"label-target");$Zc++;}echo'

    -',lang(103),': ',html_select("on_delete",array(-1=>"")+explode("|",$sf),$J["on_delete"]),' ',lang(102),': ',html_select("on_update",array(-1=>"")+explode("|",$sf),$J["on_update"]),doc_link(array('sql'=>"innodb-foreign-key-constraints.html",'mariadb'=>"foreign-keys/",'pgsql'=>"sql-createtable.html#SQL-CREATETABLE-REFERENCES",'mssql'=>"ms174979.aspx",'oracle'=>"https://docs.oracle.com/cd/B19306_01/server.102/b14200/clauses002.htm#sthref2903",)),'

    - -

    -';if($D!=""){echo'',confirm(lang(175,$D));}echo' +ON DELETE: ',html_select("on_delete",array(-1=>"")+explode("|",$Wd),$L["on_delete"]),' ON UPDATE: ',html_select("on_update",array(-1=>"")+explode("|",$Wd),$L["on_update"]),'','

    + +

    +';if($F!=""){echo'',confirm(sprintf('Drop %s?',$F));}echo'

    -';}elseif(isset($_GET["view"])){$a=$_GET["view"];$J=$_POST;$If="VIEW";if($y=="pgsql"&&$a!=""){$O=table_status($a);$If=strtoupper($O["Engine"]);}if($_POST&&!$n){$D=trim($J["name"]);$Ga=" AS\n$J[select]";$B=ME."table=".urlencode($D);$Ne=lang(201);$T=($_POST["materialized"]?"MATERIALIZED VIEW":"VIEW");if(!$_POST["drop"]&&$a==$D&&$y!="sqlite"&&$T=="VIEW"&&$If=="VIEW")query_redirect(($y=="mssql"?"ALTER":"CREATE OR REPLACE")." VIEW ".table($D).$Ga,$B,$Ne);else{$bi=$D."_adminer_".uniqid();drop_create("DROP $If ".table($a),"CREATE $T ".table($D).$Ga,"DROP $T ".table($D),"CREATE $T ".table($bi).$Ga,"DROP $T ".table($bi),($_POST["drop"]?substr(ME,0,-1):$B),lang(202),$Ne,lang(203),$a,$D);}}if(!$_POST&&$a!=""){$J=view($a);$J["name"]=$a;$J["materialized"]=($If!="VIEW");if(!$n)$n=error();}page_header(($a!=""?lang(43):lang(204)),$n,array("table"=>$a),h($a));echo' +';}elseif(isset($_GET["view"])){$a=$_GET["view"];$L=$_POST;$me="VIEW";if($y=="pgsql"&&$a!=""){$Mf=table_status($a);$me=strtoupper($Mf["Engine"]);}if($_POST&&!$l){$F=trim($L["name"]);$pa=" AS\n$L[select]";$B=ME."table=".urlencode($F);$D='View has been altered.';$V=($_POST["materialized"]?"MATERIALIZED VIEW":"VIEW");if(!$_POST["drop"]&&$a==$F&&$y!="sqlite"&&$V=="VIEW"&&$me=="VIEW")query_redirect(($y=="mssql"?"ALTER":"CREATE OR REPLACE")." VIEW ".table($F).$pa,$B,$D);else{$fg=$F."_adminer_".uniqid();drop_create("DROP $me ".table($a),"CREATE $V ".table($F).$pa,"DROP $V ".table($F),"CREATE $V ".table($fg).$pa,"DROP $V ".table($fg),($_POST["drop"]?substr(ME,0,-1):$B),'View has been dropped.',$D,'View has been created.',$a,$F);}}if(!$_POST&&$a!=""){$L=view($a);$L["name"]=$a;$L["materialized"]=($me!="VIEW");if(!$l)$l=error();}page_header(($a!=""?'Alter view':'Create view'),$l,array("table"=>$a),h($a));echo'
    -

    ',lang(183),': -',(support("materializedview")?" ".checkbox("materialized",1,$J["materialized"],lang(129)):""),'

    ';textarea("select",$J["select"]);echo'

    - -';if($a!=""){echo'',confirm(lang(175,$a));}echo' +

    Name: +',(support("materializedview")?" ".checkbox("materialized",1,$L["materialized"],'Materialized view'):""),'

    ';textarea("select",$L["select"]);echo'

    + +';if($a!=""){echo'',confirm(sprintf('Drop %s?',$a));}echo'

    -';}elseif(isset($_GET["event"])){$aa=$_GET["event"];$Yd=array("YEAR","QUARTER","MONTH","DAY","HOUR","MINUTE","WEEK","SECOND","YEAR_MONTH","DAY_HOUR","DAY_MINUTE","DAY_SECOND","HOUR_MINUTE","HOUR_SECOND","MINUTE_SECOND");$Hh=array("ENABLED"=>"ENABLE","DISABLED"=>"DISABLE","SLAVESIDE_DISABLED"=>"DISABLE ON SLAVE");$J=$_POST;if($_POST&&!$n){if($_POST["drop"])query_redirect("DROP EVENT ".idf_escape($aa),substr(ME,0,-1),lang(205));elseif(in_array($J["INTERVAL_FIELD"],$Yd)&&isset($Hh[$J["STATUS"]])){$bh="\nON SCHEDULE ".($J["INTERVAL_VALUE"]?"EVERY ".q($J["INTERVAL_VALUE"])." $J[INTERVAL_FIELD]".($J["STARTS"]?" STARTS ".q($J["STARTS"]):"").($J["ENDS"]?" ENDS ".q($J["ENDS"]):""):"AT ".q($J["STARTS"]))." ON COMPLETION".($J["ON_COMPLETION"]?"":" NOT")." PRESERVE";queries_redirect(substr(ME,0,-1),($aa!=""?lang(206):lang(207)),queries(($aa!=""?"ALTER EVENT ".idf_escape($aa).$bh.($aa!=$J["EVENT_NAME"]?"\nRENAME TO ".idf_escape($J["EVENT_NAME"]):""):"CREATE EVENT ".idf_escape($J["EVENT_NAME"]).$bh)."\n".$Hh[$J["STATUS"]]." COMMENT ".q($J["EVENT_COMMENT"]).rtrim(" DO\n$J[EVENT_DEFINITION]",";").";"));}}page_header(($aa!=""?lang(208).": ".h($aa):lang(209)),$n);if(!$J&&$aa!=""){$K=get_rows("SELECT * FROM information_schema.EVENTS WHERE EVENT_SCHEMA = ".q(DB)." AND EVENT_NAME = ".q($aa));$J=reset($K);}echo' -
    - -
    ',lang(183),' -
    ',lang(210),' -
    ',lang(211),' -
    ',lang(212),' ',html_select("INTERVAL_FIELD",$Yd,$J["INTERVAL_FIELD"]),'
    ',lang(118),'',html_select("STATUS",$Hh,$J["STATUS"]),'
    ',lang(50),' -
    ',checkbox("ON_COMPLETION","PRESERVE",$J["ON_COMPLETION"]=="PRESERVE",lang(213)),'
    -

    ';textarea("EVENT_DEFINITION",$J["EVENT_DEFINITION"]);echo'

    - -';if($aa!=""){echo'',confirm(lang(175,$aa));}echo' -

    -';}elseif(isset($_GET["procedure"])){$da=($_GET["name"]?$_GET["name"]:$_GET["procedure"]);$Wg=(isset($_GET["function"])?"FUNCTION":"PROCEDURE");$J=$_POST;$J["fields"]=(array)$J["fields"];if($_POST&&!process_fields($J["fields"])&&!$n){$Ff=routine($_GET["procedure"],$Wg);$bi="$J[name]_adminer_".uniqid();drop_create("DROP $Wg ".routine_id($da,$Ff),create_routine($Wg,$J),"DROP $Wg ".routine_id($J["name"],$J),create_routine($Wg,array("name"=>$bi)+$J),"DROP $Wg ".routine_id($bi,$J),substr(ME,0,-1),lang(214),lang(215),lang(216),$da,$J["name"]);}page_header(($da!=""?(isset($_GET["function"])?lang(217):lang(218)).": ".h($da):(isset($_GET["function"])?lang(219):lang(220))),$n);if(!$_POST&&$da!=""){$J=routine($_GET["procedure"],$Wg);$J["name"]=$da;}$nb=get_vals("SHOW CHARACTER SET");sort($nb);$Xg=routine_languages();echo' -
    -

    ',lang(183),': -',($Xg?lang(19).": ".html_select("language",$Xg,$J["language"])."\n":""),' -

    - -';edit_fields($J["fields"],$nb,$Wg);if(isset($_GET["function"])){echo"
    ".lang(221);edit_type("returns",$J["returns"],$nb,array(),($y=="pgsql"?array("void","trigger"):array()));}echo'
    -',script("editFields();"),'
    -

    ';textarea("definition",$J["definition"]);echo'

    - -';if($da!=""){echo'',confirm(lang(175,$da));}echo' -

    -';}elseif(isset($_GET["sequence"])){$fa=$_GET["sequence"];$J=$_POST;if($_POST&&!$n){$A=substr(ME,0,-1);$D=trim($J["name"]);if($_POST["drop"])query_redirect("DROP SEQUENCE ".idf_escape($fa),$A,lang(222));elseif($fa=="")query_redirect("CREATE SEQUENCE ".idf_escape($D),$A,lang(223));elseif($fa!=$D)query_redirect("ALTER SEQUENCE ".idf_escape($fa)." RENAME TO ".idf_escape($D),$A,lang(224));else -redirect($A);}page_header($fa!=""?lang(225).": ".h($fa):lang(226),$n);if(!$J)$J["name"]=$fa;echo' -
    -

    - -';if($fa!="")echo"".confirm(lang(175,$fa))."\n";echo' -

    -';}elseif(isset($_GET["type"])){$ga=$_GET["type"];$J=$_POST;if($_POST&&!$n){$A=substr(ME,0,-1);if($_POST["drop"])query_redirect("DROP TYPE ".idf_escape($ga),$A,lang(227));else -query_redirect("CREATE TYPE ".idf_escape(trim($J["name"]))." $J[as]",$A,lang(228));}page_header($ga!=""?lang(229).": ".h($ga):lang(230),$n);if(!$J)$J["as"]="AS ";echo' -
    -

    -';if($ga!="")echo"".confirm(lang(175,$ga))."\n";else{echo"\n";textarea("as",$J["as"]);echo"

    \n";}echo' -

    -';}elseif(isset($_GET["trigger"])){$a=$_GET["trigger"];$D=$_GET["name"];$Ai=trigger_options();$J=(array)trigger($D,$a)+array("Trigger"=>$a."_bi");if($_POST){if(!$n&&in_array($_POST["Timing"],$Ai["Timing"])&&in_array($_POST["Event"],$Ai["Event"])&&in_array($_POST["Type"],$Ai["Type"])){$rf=" ON ".table($a);$lc="DROP TRIGGER ".idf_escape($D).($y=="pgsql"?$rf:"");$B=ME."table=".urlencode($a);if($_POST["drop"])query_redirect($lc,$B,lang(231));else{if($D!="")queries($lc);queries_redirect($B,($D!=""?lang(232):lang(233)),queries(create_trigger($rf,$_POST)));if($D!="")queries(create_trigger($rf,$J+array("Type"=>reset($Ai["Type"]))));}}$J=$_POST;}page_header(($D!=""?lang(234).": ".h($D):lang(235)),$n,array("table"=>$a));echo' +';}elseif(isset($_GET["trigger"])){$a=$_GET["trigger"];$F=$_GET["name"];$_g=trigger_options();$L=(array)trigger($F,$a)+array("Trigger"=>$a."_bi");if($_POST){if(!$l&&in_array($_POST["Timing"],$_g["Timing"])&&in_array($_POST["Event"],$_g["Event"])&&in_array($_POST["Type"],$_g["Type"])){$Vd=" ON ".table($a);$_b="DROP TRIGGER ".idf_escape($F).($y=="pgsql"?$Vd:"");$B=ME."table=".urlencode($a);if($_POST["drop"])query_redirect($_b,$B,'Trigger has been dropped.');else{if($F!="")queries($_b);queries_redirect($B,($F!=""?'Trigger has been altered.':'Trigger has been created.'),queries(create_trigger($Vd,$_POST)));if($F!="")queries(create_trigger($Vd,$L+array("Type"=>reset($_g["Type"]))));}}$L=$_POST;}page_header(($F!=""?'Alter trigger'.": ".h($F):'Create trigger'),$l,array("table"=>$a));echo'
    -
    ',lang(236),'',html_select("Timing",$Ai["Timing"],$J["Timing"],"triggerChange(/^".preg_quote($a,"/")."_[ba][iud]$/, '".js_escape($a)."', this.form);"),'
    ',lang(237),'',html_select("Event",$Ai["Event"],$J["Event"],"this.form['Timing'].onchange();"),(in_array("UPDATE OF",$Ai["Event"])?" ":""),'
    ',lang(49),'',html_select("Type",$Ai["Type"],$J["Type"]),'
    -

    ',lang(183),': -',script("qs('#form')['Timing'].onchange();"),'

    ';textarea("Statement",$J["Statement"]);echo'

    - -';if($D!=""){echo'',confirm(lang(175,$D));}echo' +Time',html_select("Timing",$_g["Timing"],$L["Timing"],"triggerChange(/^".preg_quote($a,"/")."_[ba][iud]$/, '".js_escape($a)."', this.form);"),'Event',html_select("Event",$_g["Event"],$L["Event"],"this.form['Timing'].onchange();"),(in_array("UPDATE OF",$_g["Event"])?" ":""),'Type',html_select("Type",$_g["Type"],$L["Type"]),' +

    Name: +',script("qs('#form')['Timing'].onchange();"),'

    ';textarea("Statement",$L["Statement"]);echo'

    + +';if($F!=""){echo'',confirm(sprintf('Drop %s?',$F));}echo'

    -';}elseif(isset($_GET["user"])){$ha=$_GET["user"];$sg=array(""=>array("All privileges"=>""));foreach(get_rows("SHOW PRIVILEGES")as$J){foreach(explode(",",($J["Privilege"]=="Grant option"?"":$J["Context"]))as$Fb)$sg[$Fb][$J["Privilege"]]=$J["Comment"];}$sg["Server Admin"]+=$sg["File access on server"];$sg["Databases"]["Create routine"]=$sg["Procedures"]["Create routine"];unset($sg["Procedures"]["Create routine"]);$sg["Columns"]=array();foreach(array("Select","Insert","Update","References")as$X)$sg["Columns"][$X]=$sg["Tables"][$X];unset($sg["Server Admin"]["Usage"]);foreach($sg["Tables"]as$z=>$X)unset($sg["Databases"][$z]);$af=array();if($_POST){foreach($_POST["objects"]as$z=>$X)$af[$X]=(array)$af[$X]+(array)$_POST["grants"][$z];}$rd=array();$pf="";if(isset($_GET["host"])&&($H=$g->query("SHOW GRANTS FOR ".q($ha)."@".q($_GET["host"])))){while($J=$H->fetch_row()){if(preg_match('~GRANT (.*) ON (.*) TO ~',$J[0],$C)&&preg_match_all('~ *([^(,]*[^ ,(])( *\([^)]+\))?~',$C[1],$Fe,PREG_SET_ORDER)){foreach($Fe -as$X){if($X[1]!="USAGE")$rd["$C[2]$X[2]"][$X[1]]=true;if(preg_match('~ WITH GRANT OPTION~',$J[0]))$rd["$C[2]$X[2]"]["GRANT OPTION"]=true;}}if(preg_match("~ IDENTIFIED BY PASSWORD '([^']+)~",$J[0],$C))$pf=$C[1];}}if($_POST&&!$n){$qf=(isset($_GET["host"])?q($ha)."@".q($_GET["host"]):"''");if($_POST["drop"])query_redirect("DROP USER $qf",ME."privileges=",lang(238));else{$cf=q($_POST["user"])."@".q($_POST["host"]);$Zf=$_POST["pass"];if($Zf!=''&&!$_POST["hashed"]&&!min_version(8)){$Zf=$g->result("SELECT PASSWORD(".q($Zf).")");$n=!$Zf;}$Lb=false;if(!$n){if($qf!=$cf){$Lb=queries((min_version(5)?"CREATE USER":"GRANT USAGE ON *.* TO")." $cf IDENTIFIED BY ".(min_version(8)?"":"PASSWORD ").q($Zf));$n=!$Lb;}elseif($Zf!=$pf)queries("SET PASSWORD FOR $cf = ".q($Zf));}if(!$n){$Tg=array();foreach($af -as$if=>$qd){if(isset($_GET["grant"]))$qd=array_filter($qd);$qd=array_keys($qd);if(isset($_GET["grant"]))$Tg=array_diff(array_keys(array_filter($af[$if],'strlen')),$qd);elseif($qf==$cf){$nf=array_keys((array)$rd[$if]);$Tg=array_diff($nf,$qd);$qd=array_diff($qd,$nf);unset($rd[$if]);}if(preg_match('~^(.+)\s*(\(.*\))?$~U',$if,$C)&&(!grant("REVOKE",$Tg,$C[2]," ON $C[1] FROM $cf")||!grant("GRANT",$qd,$C[2]," ON $C[1] TO $cf"))){$n=true;break;}}}if(!$n&&isset($_GET["host"])){if($qf!=$cf)queries("DROP USER $qf");elseif(!isset($_GET["grant"])){foreach($rd -as$if=>$Tg){if(preg_match('~^(.+)(\(.*\))?$~U',$if,$C))grant("REVOKE",array_keys($Tg),$C[2]," ON $C[1] FROM $cf");}}}queries_redirect(ME."privileges=",(isset($_GET["host"])?lang(239):lang(240)),!$n);if($Lb)$g->query("DROP USER $cf");}}page_header((isset($_GET["host"])?lang(35).": ".h("$ha@$_GET[host]"):lang(146)),$n,array("privileges"=>array('',lang(71))));if($_POST){$J=$_POST;$rd=$af;}else{$J=$_GET+array("host"=>$g->result("SELECT SUBSTRING_INDEX(CURRENT_USER, '@', -1)"));$J["pass"]=$pf;if($pf!="")$J["hashed"]=true;$rd[(DB==""||$rd?"":idf_escape(addcslashes(DB,"%_\\"))).".*"]=array();}echo'
    - -
    ',lang(34),' -
    ',lang(35),' -
    ',lang(36),' -';if(!$J["hashed"])echo -script("typePassword(qs('#pass'));");echo(min_version(8)?"":checkbox("hashed",1,$J["hashed"],lang(241),"typePassword(this.form['pass'], this.checked);")),'
    - -';echo"\n","\n";foreach(array(""=>"","Server Admin"=>lang(34),"Databases"=>lang(37),"Tables"=>lang(131),"Columns"=>lang(48),"Procedures"=>lang(242),)as$Fb=>$dc){foreach((array)$sg[$Fb]as$rg=>$tb){echo"$dc'.h($rg);$t=0;foreach($rd -as$if=>$qd){$D="'grants[$t][".h(strtoupper($rg))."]'";$Y=$qd[strtoupper($rg)];if($Fb=="Server Admin"&&$if!=(isset($rd["*.*"])?"*.*":".*"))echo"
    ".lang(71).doc_link(array('sql'=>"grant.html#priv_level"));$t=0;foreach($rd -as$if=>$qd){echo''.($if!="*.*"?"":"*.*");$t++;}echo"
    ";elseif(isset($_GET["grant"]))echo"";else{echo"";}$t++;}}}echo"
    \n",'

    - -';if(isset($_GET["host"])){echo'',confirm(lang(175,"$ha@$_GET[host]"));}echo' -

    -';}elseif(isset($_GET["processlist"])){if(support("kill")){if($_POST&&!$n){$le=0;foreach((array)$_POST["kill"]as$X){if(kill_process($X))$le++;}queries_redirect(ME."processlist=",lang(245,$le),$le||!$_POST["kill"]);}}page_header(lang(116),$n);echo' -
    -
    - -',script("mixin(qsl('table'), {onclick: tableClick, ondblclick: partialArg(tableClick, true)});");$t=-1;foreach(process_list()as$t=>$J){if(!$t){echo"".(support("kill")?"\n";}echo"".(support("kill")?"
    ":"");foreach($J -as$z=>$X)echo"$z".doc_link(array('sql'=>"show-processlist.html#processlist_".strtolower($z),'pgsql'=>"monitoring-stats.html#PG-STAT-ACTIVITY-VIEW",'oracle'=>"REFRN30223",));echo"
    ".checkbox("kill[]",$J[$y=="sql"?"Id":"pid"],0):"");foreach($J -as$z=>$X)echo"".(($y=="sql"&&$z=="Info"&&preg_match("~Query|Killed~",$J["Command"])&&$X!="")||($y=="pgsql"&&$z=="current_query"&&$X!="")||($y=="oracle"&&$z=="sql_text"&&$X!="")?"".shorten_utf8($X,100,"").' '.lang(246).'':h($X));echo"\n";}echo'
    -
    -

    -';if(support("kill")){echo($t+1)."/".lang(247,max_connections()),"

    \n";}echo' -

    -',script("tableCheck();");}elseif(isset($_GET["select"])){$a=$_GET["select"];$R=table_status1($a);$x=indexes($a);$p=fields($a);$jd=column_foreign_keys($a);$lf=$R["Oid"];parse_str($_COOKIE["adminer_import"],$za);$Ug=array();$e=array();$fi=null;foreach($p -as$z=>$o){$D=$b->fieldName($o);if(isset($o["privileges"]["select"])&&$D!=""){$e[$z]=html_entity_decode(strip_tags($D),ENT_QUOTES);if(is_shortable($o))$fi=$b->selectLengthProcess();}$Ug+=$o["privileges"];}list($L,$sd)=$b->selectColumnsProcess($e,$x);$ce=count($sd)selectSearchProcess($p,$x);$Bf=$b->selectOrderProcess($p,$x);$_=$b->selectLimitProcess();if($_GET["val"]&&is_ajax()){header("Content-Type: text/plain; charset=utf-8");foreach($_GET["val"]as$Hi=>$J){$Ga=convert_field($p[key($J)]);$L=array($Ga?$Ga:idf_escape(key($J)));$Z[]=where_check($Hi,$p);$I=$m->select($a,$L,$Z,$L);if($I)echo -reset($I->fetch_row());}exit;}$ng=$Ji=null;foreach($x -as$w){if($w["type"]=="PRIMARY"){$ng=array_flip($w["columns"]);$Ji=($L?$ng:array());foreach($Ji -as$z=>$X){if(in_array(idf_escape($z),$L))unset($Ji[$z]);}break;}}if($lf&&!$ng){$ng=$Ji=array($lf=>0);$x[]=array("type"=>"PRIMARY","columns"=>array($lf));}if($_POST&&!$n){$kj=$Z;if(!$_POST["all"]&&is_array($_POST["check"])){$eb=array();foreach($_POST["check"]as$bb)$eb[]=where_check($bb,$p);$kj[]="((".implode(") OR (",$eb)."))";}$kj=($kj?"\nWHERE ".implode(" AND ",$kj):"");if($_POST["export"]){cookie("adminer_import","output=".urlencode($_POST["output"])."&format=".urlencode($_POST["format"]));dump_headers($a);$b->dumpTable($a,"");$od=($L?implode(", ",$L):"*").convert_fields($e,$p,$L)."\nFROM ".table($a);$ud=($sd&&$ce?"\nGROUP BY ".implode(", ",$sd):"").($Bf?"\nORDER BY ".implode(", ",$Bf):"");if(!is_array($_POST["check"])||$ng)$G="SELECT $od$kj$ud";else{$Fi=array();foreach($_POST["check"]as$X)$Fi[]="(SELECT".limit($od,"\nWHERE ".($Z?implode(" AND ",$Z)." AND ":"").where_check($X,$p).$ud,1).")";$G=implode(" UNION ALL ",$Fi);}$b->dumpData($a,"table",$G);exit;}if(!$b->selectEmailProcess($Z,$jd)){if($_POST["save"]||$_POST["delete"]){$H=true;$_a=0;$N=array();if(!$_POST["delete"]){foreach($e -as$D=>$X){$X=process_input($p[$D]);if($X!==null&&($_POST["clone"]||$X!==false))$N[idf_escape($D)]=($X!==false?$X:idf_escape($D));}}if($_POST["delete"]||$N){if($_POST["clone"])$G="INTO ".table($a)." (".implode(", ",array_keys($N)).")\nSELECT ".implode(", ",$N)."\nFROM ".table($a);if($_POST["all"]||($ng&&is_array($_POST["check"]))||$ce){$H=($_POST["delete"]?$m->delete($a,$kj):($_POST["clone"]?queries("INSERT $G$kj"):$m->update($a,$N,$kj)));$_a=$g->affected_rows;}else{foreach((array)$_POST["check"]as$X){$gj="\nWHERE ".($Z?implode(" AND ",$Z)." AND ":"").where_check($X,$p);$H=($_POST["delete"]?$m->delete($a,$gj,1):($_POST["clone"]?queries("INSERT".limit1($a,$G,$gj)):$m->update($a,$N,$gj,1)));if(!$H)break;$_a+=$g->affected_rows;}}}$Ne=lang(249,$_a);if($_POST["clone"]&&$H&&$_a==1){$re=last_id();if($re)$Ne=lang(168," $re");}queries_redirect(remove_from_uri($_POST["all"]&&$_POST["delete"]?"page":""),$Ne,$H);if(!$_POST["delete"]){edit_form($a,$p,(array)$_POST["fields"],!$_POST["clone"]);page_footer();exit;}}elseif(!$_POST["import"]){if(!$_POST["val"])$n=lang(250);else{$H=true;$_a=0;foreach($_POST["val"]as$Hi=>$J){$N=array();foreach($J -as$z=>$X){$z=bracket_escape($z,1);$N[idf_escape($z)]=(preg_match('~char|text~',$p[$z]["type"])||$X!=""?$b->processInput($p[$z],$X):"NULL");}$H=$m->update($a,$N," WHERE ".($Z?implode(" AND ",$Z)." AND ":"").where_check($Hi,$p),!$ce&&!$ng," ");if(!$H)break;$_a+=$g->affected_rows;}queries_redirect(remove_from_uri(),lang(249,$_a),$H);}}elseif(!is_string($Zc=get_file("csv_file",true)))$n=upload_error($Zc);elseif(!preg_match('~~u',$Zc))$n=lang(251);else{cookie("adminer_import","output=".urlencode($za["output"])."&format=".urlencode($_POST["separator"]));$H=true;$pb=array_keys($p);preg_match_all('~(?>"[^"]*"|[^"\r\n]+)+~',$Zc,$Fe);$_a=count($Fe[0]);$m->begin();$kh=($_POST["separator"]=="csv"?",":($_POST["separator"]=="tsv"?"\t":";"));$K=array();foreach($Fe[0]as$z=>$X){preg_match_all("~((?>\"[^\"]*\")+|[^$kh]*)$kh~",$X.$kh,$Ge);if(!$z&&!array_diff($Ge[1],$pb)){$pb=$Ge[1];$_a--;}else{$N=array();foreach($Ge[1]as$t=>$kb)$N[idf_escape($pb[$t])]=($kb==""&&$p[$pb[$t]]["null"]?"NULL":q(str_replace('""','"',preg_replace('~^"|"$~','',$kb))));$K[]=$N;}}$H=(!$K||$m->insertUpdate($a,$K,$ng));if($H)$H=$m->commit();queries_redirect(remove_from_uri("page"),lang(252,$_a),$H);$m->rollback();}}}$Rh=$b->tableName($R);if(is_ajax()){page_headers();ob_start();}else -page_header(lang(53).": $Rh",$n);$N=null;if(isset($Ug["insert"])||!support("table")){$N="";foreach((array)$_GET["where"]as$X){if($jd[$X["col"]]&&count($jd[$X["col"]])==1&&($X["op"]=="="||(!$X["op"]&&!preg_match('~[_%]~',$X["val"]))))$N.="&set".urlencode("[".bracket_escape($X["col"])."]")."=".urlencode($X["val"]);}}$b->selectLinks($R,$N);if(!$e&&support("table"))echo"

    ".lang(253).($p?".":": ".error())."\n";else{echo"

    \n","
    ";hidden_fields_get();echo(DB!=""?''.(isset($_GET["ns"])?'':""):"");echo'',"
    \n";$b->selectColumnsPrint($L,$e);$b->selectSearchPrint($Z,$e,$x);$b->selectOrderPrint($Bf,$e,$x);$b->selectLimitPrint($_);$b->selectLengthPrint($fi);$b->selectActionPrint($x);echo"
    \n";$E=$_GET["page"];if($E=="last"){$md=$g->result(count_rows($a,$Z,$ce,$sd));$E=floor(max(0,$md-1)/$_);}$fh=$L;$td=$sd;if(!$fh){$fh[]="*";$Gb=convert_fields($e,$p,$L);if($Gb)$fh[]=substr($Gb,2);}foreach($L -as$z=>$X){$o=$p[idf_unescape($X)];if($o&&($Ga=convert_field($o)))$fh[$z]="$Ga AS $X";}if(!$ce&&$Ji){foreach($Ji -as$z=>$X){$fh[]=idf_escape($z);if($td)$td[]=idf_escape($z);}}$H=$m->select($a,$fh,$Z,$td,$Bf,$_,$E,true);if(!$H)echo"

    ".error()."\n";else{if($y=="mssql"&&$E)$H->seek($_*$E);$yc=array();echo"

    \n";$K=array();while($J=$H->fetch_assoc()){if($E&&$y=="oracle")unset($J["RNUM"]);$K[]=$J;}if($_GET["page"]!="last"&&$_!=""&&$sd&&$ce&&$y=="sql")$md=$g->result(" SELECT FOUND_ROWS()");if(!$K)echo"

    ".lang(12)."\n";else{$Pa=$b->backwardKeys($a,$Rh);echo"

    ","",script("mixin(qs('#table'), {onclick: tableClick, ondblclick: partialArg(tableClick, true), onkeydown: editingKeydown});"),"".(!$sd&&$L?"":"\n";if(is_ajax()){if($_%2==1&&$E%2==1)odd();ob_end_clean();}foreach($b->rowDescriptions($K,$jd)as$Xe=>$J){$Gi=unique_array($K[$Xe],$x);if(!$Gi){$Gi=array();foreach($K[$Xe]as$z=>$X){if(!preg_match('~^(COUNT\((\*|(DISTINCT )?`(?:[^`]|``)+`)\)|(AVG|GROUP_CONCAT|MAX|MIN|SUM)\(`(?:[^`]|``)+`\))$~',$z))$Gi[$z]=$X;}}$Hi="";foreach($Gi -as$z=>$X){if(($y=="sql"||$y=="pgsql")&&preg_match('~char|text|enum|set~',$p[$z]["type"])&&strlen($X)>64){$z=(strpos($z,'(')?$z:idf_escape($z));$z="MD5(".($y!='sql'||preg_match("~^utf8~",$p[$z]["collation"])?$z:"CONVERT($z USING ".charset($g).")").")";$X=md5($X);}$Hi.="&".($X!==null?urlencode("where[".bracket_escape($z)."]")."=".urlencode($X):"null%5B%5D=".urlencode($z));}echo"".(!$sd&&$L?"":"";}}}if($Pa)echo"\n";}if(is_ajax())exit;echo"
    ".script("qs('#all-page').onclick = partial(formCheck, /check/);","")." ".lang(254)."");$Ye=array();$pd=array();reset($L);$Bg=1;foreach($K[0]as$z=>$X){if(!isset($Ji[$z])){$X=$_GET["columns"][key($L)];$o=$p[$L?($X?$X["col"]:current($L)):$z];$D=($o?$b->fieldName($o,$Bg):($X["fun"]?"*":$z));if($D!=""){$Bg++;$Ye[$z]=$D;$d=idf_escape($z);$Gd=remove_from_uri('(order|desc)[^=]*|page').'&order%5B0%5D='.urlencode($z);$dc="&desc%5B0%5D=1";echo"".script("mixin(qsl('th'), {onmouseover: partial(columnMouse), onmouseout: partial(columnMouse, ' hidden')});",""),'';echo -apply_sql_function($X["fun"],$D)."";echo"";}$pd[$z]=$X["fun"];next($L);}}$xe=array();if($_GET["modify"]){foreach($K -as$J){foreach($J -as$z=>$X)$xe[$z]=max($xe[$z],min(40,strlen(utf8_decode($X))));}}echo($Pa?"".lang(255):"")."
    ".checkbox("check[]",substr($Hi,1),in_array(substr($Hi,1),(array)$_POST["check"])).($ce||information_schema(DB)?"":" ".lang(256).""));foreach($J -as$z=>$X){if(isset($Ye[$z])){$o=$p[$z];$X=$m->value($X,$o);if($X!=""&&(!isset($yc[$z])||$yc[$z]!=""))$yc[$z]=(is_mail($X)?$Ye[$z]:"");$A="";if(preg_match('~blob|bytea|raw|file~',$o["type"])&&$X!="")$A=ME.'download='.urlencode($a).'&field='.urlencode($z).$Hi;if(!$A&&$X!==null){foreach((array)$jd[$z]as$r){if(count($jd[$z])==1||end($r["source"])==$z){$A="";foreach($r["source"]as$t=>$yh)$A.=where_link($t,$r["target"][$t],$K[$Xe][$yh]);$A=($r["db"]!=""?preg_replace('~([?&]db=)[^&]+~','\1'.urlencode($r["db"]),ME):ME).'select='.urlencode($r["table"]).$A;if($r["ns"])$A=preg_replace('~([?&]ns=)[^&]+~','\1'.urlencode($r["ns"]),$A);if(count($r["source"])==1)break;}}}if($z=="COUNT(*)"){$A=ME."select=".urlencode($a);$t=0;foreach((array)$_GET["where"]as$W){if(!array_key_exists($W["col"],$Gi))$A.=where_link($t++,$W["col"],$W["val"],$W["op"]);}foreach($Gi -as$he=>$W)$A.=where_link($t++,$he,$W);}$X=select_value($X,$A,$o,$fi);$u=h("val[$Hi][".bracket_escape($z)."]");$Y=$_POST["val"][$Hi][bracket_escape($z)];$tc=!is_array($J[$z])&&is_utf8($X)&&$K[$Xe][$z]==$J[$z]&&!$pd[$z];$ei=preg_match('~text|lob~',$o["type"]);echo"".($ei?"":"");}else{$Ae=strpos($X,"");echo" data-text='".($Ae?2:($ei?1:0))."'".($tc?"":" data-warning='".h(lang(257))."'").">$X";$b->backwardKeysPrint($Pa,$K[$Xe]);echo"
    \n","
    \n";}if(!is_ajax()){if($K||$E){$Ic=true;if($_GET["page"]!="last"){if($_==""||(count($K)<$_&&($K||!$E)))$md=($E?$E*$_:0)+count($K);elseif($y!="sql"||!$ce){$md=($ce?false:found_rows($R,$Z));if($md$_||$E));if($Pf){echo(($md===false?count($K)+1:$md-$E*$_)>$_?'

    '.lang(258).''.script("qsl('a').onclick = partial(selectLoadMore, ".(+$_).", '".lang(259)."…');",""):''),"\n";}}echo"

    \n";if($b->selectImportPrint()){echo"
    ","".'Import'."",script("qsl('a').onclick = partial(toggle, 'import');",""),"","
    ";}echo"\n","\n",(!$t&&$N?"":script("tableCheck();"));}}}if(is_ajax()){ob_end_clean();exit;}}elseif(isset($_GET["variables"])){$Mf=isset($_GET["status"]);page_header($Mf?'Status':'Variables');$Vg=($Mf?show_status():show_variables());if(!$Vg)echo"

    ".'No rows.'."\n";else{echo"\n";foreach($Vg +as$z=>$X){echo"","
    ".h($z)."","".h($X);}echo"
    \n";}}elseif(isset($_GET["script"])){header("Content-Type: text/javascript; charset=utf-8");if($_GET["script"]=="db"){$Tf=array("Data_length"=>0,"Index_length"=>0,"Data_free"=>0);foreach(table_status()as$F=>$S){json_row("Comment-$F",h($S["Comment"]));if(!is_view($S)){foreach(array("Engine","Collation")as$z)json_row("$z-$F",h($S[$z]));foreach($Tf+array("Auto_increment"=>0,"Rows"=>0)as$z=>$X){if($S[$z]!=""){$X=format_number($S[$z]);json_row("$z-$F",($z=="Rows"&&$X&&$S["Engine"]==($Hf=="pgsql"?"table":"InnoDB")?"~ $X":$X));if(isset($Tf[$z]))$Tf[$z]+=($S["Engine"]!="InnoDB"||$z!="Data_free"?$S[$z]:0);}elseif(array_key_exists($z,$S))json_row("$z-$F");}}}foreach($Tf +as$z=>$X)json_row("sum-$z",format_number($X));json_row("");}elseif($_GET["script"]=="kill")$f->query("KILL ".number($_POST["kill"]));else{foreach(count_tables($b->databases())as$j=>$X){json_row("tables-$j",$X);json_row("size-$j",db_size($j));}json_row("");}exit;}else{$bg=array_merge((array)$_POST["tables"],(array)$_POST["views"]);if($bg&&!$l&&!$_POST["search"]){$J=true;$D="";if($y=="sql"&&$_POST["tables"]&&count($_POST["tables"])>1&&($_POST["drop"]||$_POST["truncate"]||$_POST["copy"]))queries("SET foreign_key_checks = 0");if($_POST["truncate"]){if($_POST["tables"])$J=truncate_tables($_POST["tables"]);$D='Tables have been truncated.';}elseif($_POST["move"]){$J=move_tables((array)$_POST["tables"],(array)$_POST["views"],$_POST["target"]);$D='Tables have been moved.';}elseif($_POST["copy"]){$J=copy_tables((array)$_POST["tables"],(array)$_POST["views"],$_POST["target"]);$D='Tables have been copied.';}elseif($_POST["drop"]){if($_POST["views"])$J=drop_views($_POST["views"]);if($J&&$_POST["tables"])$J=drop_tables($_POST["tables"]);$D='Tables have been dropped.';}elseif($y!="sql"){$J=($y=="sqlite"?queries("VACUUM"):apply_queries("VACUUM".($_POST["optimize"]?"":" ANALYZE"),$_POST["tables"]));$D='Tables have been optimized.';}elseif(!$_POST["tables"])$D='No tables.';elseif($J=queries(($_POST["optimize"]?"OPTIMIZE":($_POST["check"]?"CHECK":($_POST["repair"]?"REPAIR":"ANALYZE")))." TABLE ".implode(", ",array_map('idf_escape',$_POST["tables"])))){while($L=$J->fetch_assoc())$D.="".h($L["Table"]).": ".h($L["Msg_text"])."
    ";}queries_redirect(substr(ME,0,-1),$D,$J);}page_header(($_GET["ns"]==""?'Database'.": ".h(DB):'Schema'.": ".h($_GET["ns"])),$l,true);if($b->homepage()){if($_GET["ns"]!==""){echo"

    ".'Tables and views'."

    \n";$ag=tables_list();if(!$ag)echo"

    ".'No tables.'."\n";else{echo"

    \n";if(support("table")){echo"
    ".'Search data in tables'."
    ","",script("qsl('input').onkeydown = partialArg(bodyKeydown, 'search');","")," \n","
    \n";if($_POST["search"]&&$_POST["query"]!=""){$_GET["where"][0]["op"]="LIKE %%";search_tables();}}echo"
    \n","\n",script("mixin(qsl('table'), {onclick: tableClick, ondblclick: partialArg(tableClick, true)});"),'','\n";$T=0;foreach($ag +as$F=>$V){$Yg=($V!==null&&!preg_match('~table|sequence~i',$V));$v=h("Table-".$F);echo'
    '.script("qs('#check-all').onclick = partial(formCheck, /^(tables|views)\[/);",""),''.'Table',''.'Engine'.'',''.'Collation'.'',''.'Data Length'.'',''.'Index Length'.'',''.'Data Free'.'',''.'Auto Increment'.'',''.'Rows'.'',(support("comment")?''.'Comment'.'':''),"
    '.checkbox(($Yg?"views[]":"tables[]"),$F,in_array($F,$bg,true),"","","",$v),''.(support("table")||support("indexes")?"".h($F).'':h($F));if($Yg){echo''.(preg_match('~materialized~i',$V)?'Materialized view':'View').'','?';}else{foreach(array("Engine"=>array(),"Collation"=>array(),"Data_length"=>array("create",'Alter table'),"Index_length"=>array("indexes",'Alter indexes'),"Data_free"=>array("edit",'New item'),"Auto_increment"=>array("auto_increment=1&create",'Alter table'),"Rows"=>array("select",'Select data'),)as$z=>$A){$v=" id='$z-".h($F)."'";echo($A?"".(support("table")||$z=="Rows"||(support("indexes")&&$z!="Data_length")?"?":"?"):"");}$T++;}echo(support("comment")?"":"");}echo"
    ".sprintf('%d in total',count($ag)),"".h($y=="sql"?$f->result("SELECT @@default_storage_engine"):""),"".h(db_collation(DB,collations()));foreach(array("Data_length","Index_length","Data_free")as$z)echo"";echo"
    \n","
    \n";if(!information_schema(DB)){echo"\n";}echo"
    \n",script("tableCheck();");}echo'
    -
    +
    diff --git a/scripts/install_services.sh b/scripts/install_services.sh index 2b40b0b..b1812c2 100755 --- a/scripts/install_services.sh +++ b/scripts/install_services.sh @@ -18,42 +18,30 @@ update_system() { set_hostname() { if [ "$(hostname)" == "raspberrypi" ];then - echo "Setting hostname to 'birdnetpi'" hostnamectl set-hostname birdnetpi sed -i 's/raspberrypi/birdnetpi/g' /etc/hosts fi } install_lynx() { - if ! which lynx &> /dev/null;then apt -y install lynx - fi } install_ftpd() { - if ! [ -f /etc/ftpuseres ];then apt -y install ftpd - fi } install_scripts() { - echo "Installing BirdNET-Pi scripts to /usr/local/bin" ln -sf ${my_dir}/* /usr/local/bin/ rm /usr/local/bin/index.html } install_mariadb() { - if ! which sqlite3 &> /dev/null;then - echo "Installing SQLite3" - apt -qqy install sqlite3 php-sqlite3 - echo "SQLite Installed" - fi - echo "Initializing the database" + apt -qqy install sqlite3 php-sqlite3 ${my_dir}/createdb.sh } install_birdnet_analysis() { - echo "Installing the birdnet_analysis.service" cat << EOF > /etc/systemd/system/birdnet_analysis.service [Unit] Description=BirdNET Analysis @@ -72,7 +60,6 @@ EOF } install_birdnet_server() { - echo "Installing the birdnet_server.service" cat << EOF > /etc/systemd/system/birdnet_server.service [Unit] Description=BirdNET Analysis Server @@ -90,7 +77,6 @@ EOF } install_extraction_service() { - echo "Installing the extraction.service and extraction.timer" cat << EOF > /etc/systemd/system/extraction.service [Unit] Description=BirdNET BirdSound Extraction @@ -99,26 +85,14 @@ Restart=on-failure RestartSec=3 Type=simple User=${USER} -ExecStart=/usr/local/bin/extract_new_birdsounds.sh +ExecStart=/usr/bin/env bash -c 'while true;do extract_new_birdsounds.sh;sleep ${RECORDING_LENGTH};done' [Install] WantedBy=multi-user.target EOF - cat << EOF > /etc/systemd/system/extraction.timer -[Unit] -Description=BirdNET BirdSound Extraction Timer -Requires=extraction.service -[Timer] -Unit=extraction.service -OnCalendar=*:*:0/10 -[Install] -WantedBy=multi-user.target -EOF - systemctl enable extraction.timer systemctl enable extraction.service } install_pushed_notifications() { - echo "Installing Pushed.co mobile notifications" cat << EOF > /etc/systemd/system/pushed_notifications.service [Unit] Description=BirdNET-Pi Pushed.co Notifications @@ -138,8 +112,6 @@ create_necessary_dirs() { echo "Creating necessary directories" [ -d ${EXTRACTED} ] || sudo -u ${USER} mkdir -p ${EXTRACTED} [ -d ${EXTRACTED}/By_Date ] || sudo -u ${USER} mkdir -p ${EXTRACTED}/By_Date - [ -d ${EXTRACTED}/By_Common_Name ] || sudo -u ${USER} mkdir -p ${EXTRACTED}/By_Common_Name - [ -d ${EXTRACTED}/By_Scientific_Name ] || sudo -u ${USER} mkdir -p ${EXTRACTED}/By_Scientific_Name [ -d ${EXTRACTED}/Charts ] || sudo -u ${USER} mkdir -p ${EXTRACTED}/Charts [ -d ${PROCESSED} ] || sudo -u ${USER} mkdir -p ${PROCESSED} @@ -148,7 +120,6 @@ create_necessary_dirs() { BIRDNETLOG_URL="$(echo ${BIRDNETLOG_URL} | sed 's/\/\//\\\/\\\//g')" sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8080/${BIRDNETLOG_URL}/g" $(dirname ${my_dir})/homepage/*.html sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8080/${BIRDNETLOG_URL}/g" $(dirname ${my_dir})/scripts/*.html - sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8080/${BIRDNETLOG_URL}/g" $(dirname ${my_dir})/scripts/*.html sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8080/${BIRDNETLOG_URL}/g" $(dirname ${my_dir})/scripts/*.php sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8080/${BIRDNETLOG_URL}/g" $(dirname ${my_dir})/scripts/*/*.php fi @@ -156,10 +127,8 @@ create_necessary_dirs() { WEBTERMINAL_URL="$(echo ${WEBTERMINAL_URL} | sed 's/\/\//\\\/\\\//g')" sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8888/${WEBTERMINAL_URL}/g" $(dirname ${my_dir})/homepage/*.html sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8888/${WEBTERMINAL_URL}/g" $(dirname ${my_dir})/scripts/*.html - sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8888/${WEBTERMINAL_URL}/g" $(dirname ${my_dir})/scripts/*.html sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8888/${WEBTERMINAL_URL}/g" $(dirname ${my_dir})/scripts/*.php sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8888/${WEBTERMINAL_URL}/g" $(dirname ${my_dir})/scripts/*/*.php - fi sudo -u ${USER} ln -fs $(dirname ${my_dir})/model/labels.txt ${my_dir}/ @@ -167,14 +136,12 @@ create_necessary_dirs() { if [ -z ${BIRDNETPI_URL} ];then sudo -u${USER} sed -i "s/birdnetpi.local/$(hostname).local/g" $(dirname ${my_dir})/homepage/*.html sudo -u${USER} sed -i "s/birdnetpi.local/$(hostname).local/g" $(dirname ${my_dir})/scripts/*.html - sudo -u${USER} sed -i "s/birdnetpi.local/$(hostname).local/g" $(dirname ${my_dir})/scripts/*.html sudo -u${USER} sed -i "s/birdnetpi.local/$(hostname).local/g" $(dirname ${my_dir})/scripts/*.php sudo -u${USER} sed -i "s/birdnetpi.local/$(hostname).local/g" $(dirname ${my_dir})/scripts/*/*.php else BIRDNETPI_URL="$(echo ${BIRDNETPI_URL} | sed 's/\/\//\\\/\\\//g')" sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local/${BIRDNETPI_URL}/g" $(dirname ${my_dir})/homepage/*.html sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local/${BIRDNETPI_URL}/g" $(dirname ${my_dir})/scripts/*.html - sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local/${BIRDNETPI_URL}/g" $(dirname ${my_dir})/scripts/*.html sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local/${BIRDNETPI_URL}/g" $(dirname ${my_dir})/scripts/*.php sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local/${BIRDNETPI_URL}/g" $(dirname ${my_dir})/scripts/*/*.php fi diff --git a/scripts/overview.php b/scripts/overview.php index 8db3bf5..377029a 100644 --- a/scripts/overview.php +++ b/scripts/overview.php @@ -5,40 +5,7 @@ error_reporting(E_ALL); header("refresh: 300;"); $myDate = date('Y-m-d'); $chart = "Combo-$myDate.png"; -$mysqli = mysqli_connect(); -$mysqli->select_db('birds'); -if ($mysqli->connect_error) { - die('Connect Error (' . - $mysqli->connect_errno . ') '. - $mysqli->connect_error); -} - -// SQL query to select data from database -$sql0 = "SELECT COUNT(*) AS 'Total' FROM detections"; -$totalcount = $mysqli->query($sql0); - -$sql1 = "SELECT Com_Name, Sci_Name, Date, Time FROM detections - ORDER BY Date DESC, Time DESC LIMIT 1"; -$mostrecent = $mysqli->query($sql1); - -$sql2 = "SELECT COUNT(*) AS 'Total' FROM detections - WHERE Date = CURDATE()"; -$todayscount = $mysqli->query($sql2); - -$sql3 = "SELECT COUNT(*) AS 'Total' FROM detections - WHERE Date = CURDATE() - AND Time >= DATE_SUB(NOW(),INTERVAL 1 HOUR)"; -$lasthourcount = $mysqli->query($sql3); - -$sql4 = "SELECT Com_Name - FROM detections - WHERE Date = CURDATE() - GROUP BY Com_Name"; -$specieslist = $mysqli->query($sql4); -$speciescount = mysqli_num_rows($specieslist); - -$mysqli->close(); ?> @@ -77,27 +44,17 @@ a {

    Overview

    -fetch_assoc()) -{ - $dbname = preg_replace('/ /', '_', $rows['Com_Name']); - $dbname = preg_replace('/\'/', '', $dbname); - $dbsciname = preg_replace('/ /', '_', $rows['Sci_Name']); -?> - - - - + + + +
    Most Recent DetectionMore InfoMore Info
    -
    @@ -110,9 +67,9 @@ while($rows=$mostrecent ->fetch_assoc()) Number of Detections - fetch_assoc()) { echo $row['Total']; };?> - fetch_assoc()) { echo $row['Total']; };?> - fetch_assoc()) { echo $row['Total']; };?> + + +
    @@ -120,7 +77,7 @@ while($rows=$mostrecent ->fetch_assoc()) - +
    Species Detected Today
    diff --git a/scripts/server.py b/scripts/server.py index e1787d5..1a0da1e 100755 --- a/scripts/server.py +++ b/scripts/server.py @@ -46,7 +46,7 @@ except: # Open most recent Configuration and grab DB_PWD as a python variable with open('/home/pi/BirdNET-Pi/thisrun.txt', 'r') as f: this_run = f.readlines() - db_pwd = str(str(str([i for i in this_run if i.startswith('DB_PWD')]).split('=')[1]).split('\\')[0]) + audiofmt = "." + str(str(str([i for i in this_run if i.startswith('AUDIOFMT')]).split('=')[1]).split('\\')[0]) def loadModel(): @@ -350,16 +350,16 @@ def handle_client(conn, addr): Sens = str(args.sensitivity) Overlap = str(args.overlap) File_Name = Com_Name.replace(" ", "_") + '-' + Confidence + '-' + \ - Date.replace("/", "-") + '-birdnet-' + Time + '.mp3' + Date.replace("/", "-") + '-birdnet-' + Time + audiofmt #Connect to SQLite Database - con = sqlite3.connect('/home/pi/BirdNET-Pi/scripts/birds2.db') + con = sqlite3.connect('/home/pi/BirdNET-Pi/scripts/birds.db') cur = con.cursor() cur.execute("INSERT INTO detections VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", (Date, Time, Sci_Name, Com_Name, str(score), Lat, Lon, Cutoff, Week, Sens, Overlap, File_Name)) con.commit() con.close() - print(str(current_date) + ';' + str(current_time) + ';' + entry[0].replace('_', ';') + ';' + str(entry[1]) + ';' + str(args.lat) + ';' + str(args.lon) + ';' + str(min_conf) + ';' + str(week) + ';' + str(args.sensitivity) +';' + str(args.overlap) + Com_Name.replace(" ", "_") + '-' + str(score) + '-' + str(current_date) + '-birdnet-' + str(current_time) + '.mp3' + '\n') + print(str(current_date) + ';' + str(current_time) + ';' + entry[0].replace('_', ';') + ';' + str(entry[1]) + ';' + str(args.lat) + ';' + str(args.lon) + ';' + str(min_conf) + ';' + str(week) + ';' + str(args.sensitivity) +';' + str(args.overlap) + Com_Name.replace(" ", "_") + '-' + str(score) + '-' + str(current_date) + '-birdnet-' + str(current_time) + audiofmt + '\n') if birdweather_id != "99999": diff --git a/scripts/stats.php b/scripts/stats.php index 98cd4a5..75c25b4 100644 --- a/scripts/stats.php +++ b/scripts/stats.php @@ -3,60 +3,6 @@ ini_set('display_errors', 1); ini_set('display_startup_errors', 1); error_reporting(E_ALL); -$mysqli = mysqli_connect(); -$mysqli->select_db('birds'); - -if ($mysqli->connect_error) { - die('Connect Error (' . - $mysqli->connect_errno . ') '. - $mysqli->connect_error); -} - -// SQL query to select data from database -$sql = "SELECT COUNT(*) AS 'Total' FROM detections - ORDER BY Date DESC, Time DESC"; -$totalcount = $mysqli->query($sql); - -$sql1 = "SELECT Com_Name, COUNT(*), MAX(Confidence) - FROM detections - GROUP BY Com_Name - ORDER BY COUNT(*) DESC"; -$stats = $mysqli->query($sql1); - -$sql2 = "SELECT COUNT(*) AS 'Total' FROM detections - WHERE Date = CURDATE()"; -$todayscount = $mysqli->query($sql2); - -$sql3 = "SELECT COUNT(*) AS 'Total' FROM detections - WHERE Date = CURDATE() - AND Time >= DATE_SUB(NOW(),INTERVAL 1 HOUR)"; -$lasthourcount = $mysqli->query($sql3); - -$sql4 = "SELECT Com_Name, Date, Time, MAX(Confidence) - FROM detections - GROUP BY Com_Name - ORDER BY MAX(Confidence) DESC"; -$specieslist = $mysqli->query($sql4); -$speciescount = mysqli_num_rows($specieslist); - -$sql5 = "SELECT Com_Name,COUNT(*) - AS 'Total' - FROM detections - GROUP BY Com_Name - ORDER BY Total DESC"; -$speciestally = $mysqli->query($sql5); - -$getspecies = "SELECT Com_Name from detections - GROUP BY Com_Name"; -$result = $mysqli->query($getspecies); - -if(isset($_POST['species'])){ - $selection = $_POST['species']; - $specificspecies = "SELECT Com_Name, Sci_Name, COUNT(*), MAX(Confidence) from detections - WHERE Com_Name = \"$selection\""; - $specificstats = $mysqli->query($specificspecies);} - -$mysqli->close(); ?> @@ -179,10 +125,10 @@ form { Number of Unique Species - fetch_assoc()) { echo $row['Total']; };?> - fetch_assoc()) { echo $row['Total']; };?> - fetch_assoc()) { echo $row['Total']; };?> - + + + +

    Summary

    @@ -192,36 +138,20 @@ form { Occurrences Max Confidence Score -fetch_assoc()) -{ - $MAX = sprintf("%.1f%%", $rows['MAX(Confidence)'] * 100); - $links = preg_replace('/ /', '_', $rows['Com_Name']); - $links = preg_replace('/\'/', '', $links); -?> - - - + + + -

    Species Stats

    diff --git a/scripts/viewdb.php b/scripts/viewdb.php index 45abb55..9175164 100644 --- a/scripts/viewdb.php +++ b/scripts/viewdb.php @@ -4,51 +4,6 @@ ini_set('display_startup_errors', 1); error_reporting(E_ALL); header("refresh: 30;"); -$mysqli = mysqli_connect(); -$mysqli->select_db('birds'); - -if ($mysqli->connect_error) { - die('Connect Error (' . - $mysqli->connect_errno . ') '. - $mysqli->connect_error); -} - -// SQL query to select data from database -$sql = "SELECT COUNT(*) AS 'Total' FROM detections - ORDER BY Date DESC, Time DESC"; -$totalcount = $mysqli->query($sql); - -$sql1 = "SELECT Date, Time, Sci_Name, Com_Name, MAX(Confidence) - FROM detections - WHERE Date = CURDATE() - GROUP BY Date, Time, Sci_Name, Com_Name - ORDER BY Time DESC"; -$mosttable = $mysqli->query($sql1); - -$sql2 = "SELECT COUNT(*) AS 'Total' FROM detections - WHERE Date = CURDATE()"; -$todayscount = $mysqli->query($sql2); - -$sql3 = "SELECT COUNT(*) AS 'Total' FROM detections - WHERE Date = CURDATE() - AND Time >= DATE_SUB(NOW(),INTERVAL 1 HOUR)"; -$lasthourcount = $mysqli->query($sql3); - -$sql4 = "SELECT Com_Name, Date, Time, MAX(Confidence) - FROM detections - GROUP BY Com_Name - ORDER BY MAX(Confidence) DESC"; -$specieslist = $mysqli->query($sql4); -$speciescount = mysqli_num_rows($specieslist); - -$sql5 = "SELECT Com_Name,COUNT(*) - AS 'Total' - FROM detections - GROUP BY Com_Name - ORDER BY Total DESC"; -$speciestally = $mysqli->query($sql5); - -$mysqli->close(); ?> @@ -81,16 +36,15 @@ a { Number of Unique Species - fetch_assoc()) { echo $row['Total']; };?> - fetch_assoc()) { echo $row['Total']; };?> - fetch_assoc()) { echo $row['Total']; };?> - + + + +

    Today's Detections

    - @@ -99,25 +53,11 @@ a { - -fetch_assoc()) -{ - $Confidence = sprintf("%.1f%%", $rows['MAX(Confidence)'] * 100); - $dbname = preg_replace('/ /', '_', $rows['Com_Name']); - $dbname = preg_replace('/\'/', '', $dbname); - $dbsciname = preg_replace('/ /', '_', $rows['Sci_Name']); -?> - - - - - - + + + + + -
    TimeConfidence Links
    All About Birds, WikipediaAll About Birds, Wikipedia
    From 48791b9bc434e238bfaf862a1abfe6ec55af95e4 Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Fri, 18 Feb 2022 13:25:07 -0500 Subject: [PATCH 012/160] removed old variable --- birdnet.conf-defaults | 51 ++------------------------------------- scripts/install_config.sh | 38 +++-------------------------- 2 files changed, 6 insertions(+), 83 deletions(-) diff --git a/birdnet.conf-defaults b/birdnet.conf-defaults index afe90b3..01a857a 100644 --- a/birdnet.conf-defaults +++ b/birdnet.conf-defaults @@ -4,13 +4,10 @@ #--------------------- Required: Latitude, and Longitude ----------------------# -## The shell substitution below guesses these based on your network. THESE NEED -## TO BE CHANGED TO STATIC VALUES ## Please only go to 4 decimal places. Example:43.3984 -LATITUDE="$(curl -s4 ifconfig.co/json | awk '/lat/ {print $2}' | tr -d ',')" -LONGITUDE="$(curl -s4 ifconfig.co/json | awk '/lon/ {print $2}' | tr -d ',')" - +LATITUDE= +LONGITUDE= #--------------------- BirdWeather Station Information -----------------------# #_____________The variable below can be set to have your BirdNET-Pi____________# @@ -76,24 +73,6 @@ PUSHED_APP_SECRET= RECS_DIR=/home/pi/BirdSongs - -#------------------------------ Extraction Service ---------------------------# - -## DO_EXTRACTIONS is simply a setting for enabling the extraction.service. -## Set this to Y or y to enable extractions. - -DO_EXTRACTIONS=y - -#----------------------------- Recording Service ----------------------------# -#____________________The variable below can be set to enable __________________# -#________________________the birdnet_recording.service ________________________# - -## DO_RECORDING is simply a setting for enabling the 24/7 -## birdnet_recording.service. -## Set this to Y or y to enable recording. - -DO_RECORDING=y - ## REC_CARD is the sound card you would want the birdnet_recording.service to ## use. Leave this as "default" to use PulseAudio (recommended), or use ## the output from "aplay -L" to specify an ALSA device. @@ -110,12 +89,6 @@ PROCESSED=${RECS_DIR}/Processed EXTRACTED=${RECS_DIR}/Extracted -## IDFILE is the file that keeps a complete list of every spececies that -## BirdNET has identified from your data-set. It is a relic and not really -## used anymore. - -IDFILE=${HOME}/BirdNET-Pi/IdentifiedSoFar.txt - ## OVERLAP is the value in seconds which BirdNET should use when analyzing ## the data. The values must be between 0.0-2.9. @@ -142,11 +115,6 @@ CHANNELS=2 FULL_DISK=purge -## VENV is the python virtual environment wherein all modules and site-packages -## have been installed. - -VENV=/home/pi/BirdNET-Pi/birdnet - ## RECORDING_LENGTH sets the length of the recording that BirdNET-Lite will ## analyze. @@ -177,18 +145,3 @@ BIRDNET_USER=pi ## These are just for debugging LAST_RUN= THIS_RUN= - -## DEPRECATED -#------------------------------- NoMachine ----------------------------------# -#_____________The variable below can be set include NoMachine__________________# -#_________________remote desktop software to be installed._____________________# - -# Keep this EMPTY if you do not want to install NoMachine. # - -## INSTALL_NOMACHINE is simply a setting that can be enabled to install -## NoMachine alongside the BirdNET-Pi for remote desktop access. This in- -## staller assumes personal use. Please reference the LICENSE file included -## in this repository for more information. -## Set this to Y or y to install NoMachine alongside the BirdNET-Lite - -INSTALL_NOMACHINE=y diff --git a/scripts/install_config.sh b/scripts/install_config.sh index 5c9fd16..efdbb13 100755 --- a/scripts/install_config.sh +++ b/scripts/install_config.sh @@ -20,9 +20,8 @@ install_config() { ## TO BE CHANGED TO STATIC VALUES ## Please only go to 4 decimal places. Example:43.3984 -LATITUDE="$(curl -s4 ifconfig.co/json | awk '/lat/ {print $2}' | tr -d ',')" -LONGITUDE="$(curl -s4 ifconfig.co/json | awk '/lon/ {print $2}' | tr -d ',')" - +LATITUDE=$(curl -s4 ifconfig.co/json | awk '/lat/ {print $2}' | tr -d ',') +LONGITUDE=$(curl -s4 ifconfig.co/json | awk '/lon/ {print $2}' | tr -d ',') #--------------------- BirdWeather Station Information -----------------------# #_____________The variable below can be set to have your BirdNET-Pi____________# @@ -88,24 +87,6 @@ PUSHED_APP_SECRET= RECS_DIR=/home/pi/BirdSongs - -#------------------------------ Extraction Service ---------------------------# - -## DO_EXTRACTIONS is simply a setting for enabling the extraction.service. -## Set this to Y or y to enable extractions. - -DO_EXTRACTIONS=y - -#----------------------------- Recording Service ----------------------------# -#____________________The variable below can be set to enable __________________# -#________________________the birdnet_recording.service ________________________# - -## DO_RECORDING is simply a setting for enabling the 24/7 -## birdnet_recording.service. -## Set this to Y or y to enable recording. - -DO_RECORDING=y - ## REC_CARD is the sound card you would want the birdnet_recording.service to ## use. Leave this as "default" to use PulseAudio (recommended), or use ## the output from "aplay -L" to specify an ALSA device. @@ -116,17 +97,11 @@ REC_CARD=default ## after extractions have been made from them. This includes both WAVE and ## BirdNET.selection.txt files. -PROCESSED=${RECS_DIR}/Processed +PROCESSED=/home/pi/BirdSongs/Processed ## EXTRACTED is the directory where the extracted audio selections are moved. -EXTRACTED=${RECS_DIR}/Extracted - -## IDFILE is the file that keeps a complete list of every spececies that -## BirdNET has identified from your data-set. It is a relic and not really -## used anymore. - -IDFILE=${HOME}/BirdNET-Pi/IdentifiedSoFar.txt +EXTRACTED=/home/pi/BirdSongs/Extracted ## OVERLAP is the value in seconds which BirdNET should use when analyzing ## the data. The values must be between 0.0-2.9. @@ -154,11 +129,6 @@ CHANNELS=2 FULL_DISK=purge -## VENV is the python virtual environment wherein all modules and site-packages -## have been installed. - -VENV=/home/pi/BirdNET-Pi/birdnet - ## RECORDING_LENGTH sets the length of the recording that BirdNET-Lite will ## analyze. From e2fff7ce4386c9558e43cb2b8e2e9b43bd92cc36 Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Fri, 18 Feb 2022 13:57:31 -0500 Subject: [PATCH 013/160] new install services for testing --- scripts/install_services.sh | 176 +++++++++--------------------------- 1 file changed, 45 insertions(+), 131 deletions(-) diff --git a/scripts/install_services.sh b/scripts/install_services.sh index b1812c2..02fd85a 100755 --- a/scripts/install_services.sh +++ b/scripts/install_services.sh @@ -7,15 +7,22 @@ USER=pi HOME=/home/pi my_dir=${HOME}/BirdNET-Pi/scripts tmpfile=$(mktemp) -nomachine_url="https://download.nomachine.com/download/7.7/Arm/nomachine_7.7.4_1_arm64.deb" gotty_url="https://github.com/yudai/gotty/releases/download/v1.0.1/gotty_linux_arm.tar.gz" config_file="$(dirname ${my_dir})/birdnet.conf" - -update_system() { - apt update && apt -y upgrade +install_depends() { + curl -1sLf \ + 'https://dl.cloudsmith.io/public/caddy/stable/setup.deb.sh' \ + | sudo -E bash + apt -qqq update && apt -qqy upgrade + echo "icecast2 icecast2/icecast-setup boolean false" | debconf-set-selections + apt install -qqy caddy lynx ftpd sqlite3 php-sqlite3 alsa-utils \ + pulseaudio avahi-utils sox libsox-fmt-mp3 php php-fpm php-mysql php-xml \ + php-zip icecast2 + wget -c ${gotty_url} -O - | tar -xz -C /usr/local/bin/ } + set_hostname() { if [ "$(hostname)" == "raspberrypi" ];then hostnamectl set-hostname birdnetpi @@ -23,12 +30,8 @@ set_hostname() { fi } -install_lynx() { - apt -y install lynx -} - -install_ftpd() { - apt -y install ftpd +update_etc_hosts() { + sed -ie s/'$(hostname).local'/"$(hostname).local ${BIRDNETPI_URL//https:\/\/} ${WEBTERMINAL_URL//https:\/\/} ${BIRDNETLOG_URL//https:\/\/}"/g /etc/hosts } install_scripts() { @@ -36,11 +39,6 @@ install_scripts() { rm /usr/local/bin/index.html } -install_mariadb() { - apt -qqy install sqlite3 php-sqlite3 - ${my_dir}/createdb.sh -} - install_birdnet_analysis() { cat << EOF > /etc/systemd/system/birdnet_analysis.service [Unit] @@ -175,22 +173,7 @@ generate_BirdDB() { chown pi:pi ${my_dir}/BirdDB.txt && chmod g+rw ${my_dir}/BirdDB.txt } -install_alsa() { - echo "Checking for alsa-utils and pulseaudio" - if which arecord &> /dev/null ;then - echo "alsa-utils installed" - else - echo "Installing alsa-utils" - apt install -qqy alsa-utils - echo "alsa-utils installed" - fi - if which pulseaudio &> /dev/null;then - echo "PulseAudio installed" - else - echo "Installing pulseaudio" - apt install -qqy pulseaudio - echo "PulseAudio installed" - fi +set_login() { if ! [ -d /etc/lightdm ];then systemctl set-default multi-user.target ln -fs /lib/systemd/system/getty@.service /etc/systemd/system/getty.target.wants/getty@tty1.service @@ -220,25 +203,7 @@ EOF systemctl enable birdnet_recording.service } -install_caddy() { - if ! which caddy &> /dev/null ;then - echo "Installing Caddy" - curl -1sLf \ - 'https://dl.cloudsmith.io/public/caddy/stable/setup.deb.sh' \ - | sudo -E bash - apt -qq update - apt install -qqy caddy=2.4.5 && apt-mark hold caddy - systemctl enable --now caddy - usermod -aG pi caddy - else - echo "Caddy is installed" - systemctl enable --now caddy - usermod -aG pi caddy - fi -} - install_Caddyfile() { - echo "Installing the Caddyfile" [ -d /etc/caddy ] || mkdir /etc/caddy if [ -f /etc/caddy/Caddyfile ];then cp /etc/caddy/Caddyfile{,.original} @@ -300,20 +265,11 @@ ${BIRDNETLOG_URL} { } EOF fi - systemctl reload caddy -} - -update_etc_hosts() { - sed -ie s/'$(hostname).local'/"$(hostname).local ${BIRDNETPI_URL//https:\/\/} ${WEBTERMINAL_URL//https:\/\/} ${BIRDNETLOG_URL//https:\/\/}"/g /etc/hosts + systemctl enable caddy + usermod -aG pi caddy } install_avahi_aliases() { - echo "Installing Avahi Services" - if ! which avahi-publish &> /dev/null; then - echo "Installing avahi-utils" - apt install -y avahi-utils &> /dev/null - fi - echo "Installing avahi-alias service" cat << 'EOF' > /etc/systemd/system/avahi-alias@.service [Unit] Description=Publish %I as alias for %H.local via mdns @@ -343,7 +299,7 @@ ExecStart=/usr/local/bin/spectrogram.sh [Install] WantedBy=multi-user.target EOF - systemctl enable spectrogram_viewer.service + systemctl enable spectrogram_viewer.service } install_chart_viewer_service() { @@ -364,16 +320,10 @@ EOF } install_gotty_logs() { - echo "Installing GoTTY logging" - if ! which gotty &> /dev/null;then - echo "Installing GoTTY binary" - wget -c ${gotty_url} -O - | tar -xz -C /usr/local/bin/ - fi sudo -u ${USER} ln -sf $(dirname ${my_dir})/templates/gotty \ ${HOME}/.gotty sudo -u ${USER} ln -sf $(dirname ${my_dir})/templates/bashrc \ ${HOME}/.bashrc - echo "Installing the birdnet_log.service" cat << EOF > /etc/systemd/system/birdnet_log.service [Unit] Description=BirdNET Analysis Log @@ -388,7 +338,6 @@ ExecStart=/usr/local/bin/gotty -p 8080 --title-format "BirdNET-Pi Log" birdnet_l WantedBy=multi-user.target EOF systemctl enable birdnet_log.service - echo "Installing the web_terminal.service" cat << EOF > /etc/systemd/system/web_terminal.service [Unit] Description=BirdNET-Pi Web Terminal @@ -405,52 +354,20 @@ EOF systemctl enable web_terminal.service } -install_sox() { - if which sox | grep mp3 &> /dev/null;then - echo "Sox is installed" - else - echo "Installing sox" - apt install -y sox libsox-fmt-mp3 - echo "Sox installed" - fi -} - -install_php() { - if ! which php &> /dev/null || ! which php-fpm || ! apt list --installed | grep php-xml;then - echo "Installing PHP modules" - apt install -qqy php php-fpm php-mysql php-xml php-zip - else - echo "PHP and PHP-FPM installed" - fi - echo "Configuring PHP for Caddy" - sed -i 's/www-data/caddy/g' /etc/php/*/fpm/pool.d/www.conf - systemctl restart php7\*-fpm.service - echo "Adding Caddy sudoers rule" - cat << EOF > /etc/sudoers.d/010_caddy-nopasswd +configure_caddy_php() { + echo "Configuring PHP for Caddy" + sed -i 's/www-data/caddy/g' /etc/php/*/fpm/pool.d/www.conf + systemctl restart php7\*-fpm.service + echo "Adding Caddy sudoers rule" + cat << EOF > /etc/sudoers.d/010_caddy-nopasswd caddy ALL=(ALL) NOPASSWD: ALL EOF - chmod 0440 /etc/sudoers.d/010_caddy-nopasswd - if [ ! -d ${HOME}/phpsysinfo ];then - echo "Fetching phpSysInfo" - sudo -u ${USER} git clone https://github.com/phpsysinfo/phpsysinfo.git \ - ${HOME}/phpsysinfo - fi + chmod 0440 /etc/sudoers.d/010_caddy-nopasswd } -install_icecast() { - if ! which icecast2;then - echo "Installing IceCast2" - echo "icecast2 icecast2/icecast-setup boolean false" | debconf-set-selections - apt install -qqy icecast2 - config_icecast - systemctl enable icecast2.service - /etc/init.d/icecast2 start - else - echo "Icecast2 is installed" - config_icecast - systemctl enable icecast2.service - /etc/init.d/icecast2 start - fi +install_phpsysinfo() { + sudo -u ${USER} git clone https://github.com/phpsysinfo/phpsysinfo.git \ + ${HOME}/phpsysinfo } config_icecast() { @@ -462,10 +379,10 @@ config_icecast() { for i in "${passwords[@]}";do sed -i "s/<${i}password>.*<\/${i}password>/<${i}password>${ICE_PWD}<\/${i}password>/g" /etc/icecast2/icecast.xml done + systemctl enable icecast2.service } install_livestream_service() { - echo "Installing Live Stream service" cat << EOF > /etc/systemd/system/livestream.service [Unit] Description=BirdNET-Pi Live Stream @@ -485,42 +402,39 @@ EOF } install_cleanup_cron() { - echo "Installing the cleanup.cron" cat $(dirname ${my_dir})/templates/cleanup.cron >> /etc/crontab } -install_selected_services() { +install_services() { set_hostname - update_system + update_etc_hosts + set_login + create_necessary_dirs + + install_depends install_scripts + install_Caddyfile + install_avahi_aliases install_birdnet_analysis install_birdnet_server - install_extraction_service - install_alsa install_recording_service - install_php - install_caddy - install_Caddyfile - update_etc_hosts - install_avahi_aliases - install_gotty_logs - install_sox - install_mariadb + install_extraction_service + install_pushed_notifications install_spectrogram_service install_chart_viewer_service - install_pushed_notifications - install_icecast + install_gotty_logs + install_phpsysinfo install_livestream_service - create_necessary_dirs - generate_BirdDB install_cleanup_cron - install_ftpd - install_lynx + + generate_BirdDB + configure_caddy_php + config_icecast } if [ -f ${config_file} ];then source ${config_file} - install_selected_services + install_services else echo "Unable to find a configuration file. Please make sure that $config_file exists." fi From e2acc020f12adbd10b9ebc2e7386c406091cd345 Mon Sep 17 00:00:00 2001 From: Patrick McGuire <60325264+mcguirepr89@users.noreply.github.com> Date: Fri, 18 Feb 2022 14:13:10 -0500 Subject: [PATCH 014/160] Update newinstaller.sh --- newinstaller.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/newinstaller.sh b/newinstaller.sh index c84c6a5..140af08 100644 --- a/newinstaller.sh +++ b/newinstaller.sh @@ -8,5 +8,4 @@ if ! which git &> /dev/null;then sudo apt -y install git fi git clone -b ${branch} https://github.com/mcguirepr89/BirdNET-Pi.git ${HOME}/BirdNET-Pi && -cp ${HOME}/BirdNET-Pi/birdnet.conf-defaults ${HOME}/BirdNET-Pi/birdnet.conf && ${HOME}/BirdNET-Pi/scripts/install_birdnet.sh From f62d39d877afaf10667746d5f0894ed33dbe8e1c Mon Sep 17 00:00:00 2001 From: Patrick McGuire <60325264+mcguirepr89@users.noreply.github.com> Date: Fri, 18 Feb 2022 14:20:35 -0500 Subject: [PATCH 015/160] Update newinstaller.sh --- newinstaller.sh | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/newinstaller.sh b/newinstaller.sh index 140af08..4c507dd 100644 --- a/newinstaller.sh +++ b/newinstaller.sh @@ -8,4 +8,11 @@ if ! which git &> /dev/null;then sudo apt -y install git fi git clone -b ${branch} https://github.com/mcguirepr89/BirdNET-Pi.git ${HOME}/BirdNET-Pi && -${HOME}/BirdNET-Pi/scripts/install_birdnet.sh +${HOME}/BirdNET-Pi/scripts/install_birdnet.sh | tee -a installation.log 2>&1 +if [ ${PIPESTATUS[0]} -eq 0 ];then + echo "Installation completed successfully" >> installation.log + sudo reboot +else + echo "The installation exited unsuccessfully." >> installation.log + exit 1 +fi From 99c63ee0691fa8aabad764349db415769dbd8954 Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Fri, 18 Feb 2022 14:28:25 -0500 Subject: [PATCH 016/160] removed VENV variable as it is unneeded --- scripts/install_birdnet.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/scripts/install_birdnet.sh b/scripts/install_birdnet.sh index 13df62c..1f7e98a 100755 --- a/scripts/install_birdnet.sh +++ b/scripts/install_birdnet.sh @@ -61,7 +61,5 @@ install_birdnet() { [ -d ${RECS_DIR} ] || mkdir -p ${RECS_DIR} &> /dev/null install_deps -if [ ! -d ${VENV} ];then - install_birdnet -fi +install_birdnet exit 0 From ebe39de283f57d36a990a541987ece057e599c1f Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Fri, 18 Feb 2022 14:33:53 -0500 Subject: [PATCH 017/160] new logging --- newinstaller.sh | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/newinstaller.sh b/newinstaller.sh index 4c507dd..fd98dca 100644 --- a/newinstaller.sh +++ b/newinstaller.sh @@ -1,5 +1,7 @@ #!/usr/bin/env bash # Simple new installer +exec > >(tee -i installation.log) +exec 2>&1 HOME=/home/pi USER=pi branch=sqlite @@ -8,11 +10,11 @@ if ! which git &> /dev/null;then sudo apt -y install git fi git clone -b ${branch} https://github.com/mcguirepr89/BirdNET-Pi.git ${HOME}/BirdNET-Pi && -${HOME}/BirdNET-Pi/scripts/install_birdnet.sh | tee -a installation.log 2>&1 +${HOME}/BirdNET-Pi/scripts/install_birdnet.sh if [ ${PIPESTATUS[0]} -eq 0 ];then - echo "Installation completed successfully" >> installation.log + echo "Installation completed successfully" sudo reboot else - echo "The installation exited unsuccessfully." >> installation.log + echo "The installation exited unsuccessfully." exit 1 fi From cfef74be7af532cf76216020b6c905fb7d1a08b5 Mon Sep 17 00:00:00 2001 From: Patrick McGuire <60325264+mcguirepr89@users.noreply.github.com> Date: Fri, 18 Feb 2022 14:51:10 -0500 Subject: [PATCH 018/160] Update newinstaller.sh --- newinstaller.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/newinstaller.sh b/newinstaller.sh index fd98dca..a9e33ce 100644 --- a/newinstaller.sh +++ b/newinstaller.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # Simple new installer -exec > >(tee -i installation.log) -exec 2>&1 +exec > >(tee -ia installation.log) +exec 2> >(tee -ia installation.log >&2) HOME=/home/pi USER=pi branch=sqlite @@ -9,7 +9,7 @@ if ! which git &> /dev/null;then sudo apt update sudo apt -y install git fi -git clone -b ${branch} https://github.com/mcguirepr89/BirdNET-Pi.git ${HOME}/BirdNET-Pi && +git clone -b ${branch} https://github.com/mcguirepr89/BirdNET-Pi.git ${HOME}/BirdNET-Pi 2&>1 && ${HOME}/BirdNET-Pi/scripts/install_birdnet.sh if [ ${PIPESTATUS[0]} -eq 0 ];then echo "Installation completed successfully" From 93c658cb6e80094d4787362e764965bde9d70dbd Mon Sep 17 00:00:00 2001 From: Patrick McGuire <60325264+mcguirepr89@users.noreply.github.com> Date: Fri, 18 Feb 2022 14:52:36 -0500 Subject: [PATCH 019/160] Update newinstaller.sh --- newinstaller.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/newinstaller.sh b/newinstaller.sh index a9e33ce..fe6dbc9 100644 --- a/newinstaller.sh +++ b/newinstaller.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # Simple new installer -exec > >(tee -ia installation.log) +exec > >(tee -ia installation.log) exec 2> >(tee -ia installation.log >&2) HOME=/home/pi USER=pi From e7db0e1789cf211d2bdc16e27b591eefc8c4e9ca Mon Sep 17 00:00:00 2001 From: Patrick McGuire <60325264+mcguirepr89@users.noreply.github.com> Date: Fri, 18 Feb 2022 14:53:52 -0500 Subject: [PATCH 020/160] Update newinstaller.sh --- newinstaller.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/newinstaller.sh b/newinstaller.sh index fe6dbc9..a488859 100644 --- a/newinstaller.sh +++ b/newinstaller.sh @@ -1,7 +1,8 @@ #!/usr/bin/env bash # Simple new installer -exec > >(tee -ia installation.log) -exec 2> >(tee -ia installation.log >&2) +exec > >(tee -i logfile.txt) +exec 2>&1 + HOME=/home/pi USER=pi branch=sqlite From ce02b13af48971f82eb7594b30221a3c19f82009 Mon Sep 17 00:00:00 2001 From: Patrick McGuire <60325264+mcguirepr89@users.noreply.github.com> Date: Fri, 18 Feb 2022 14:55:27 -0500 Subject: [PATCH 021/160] Update newinstaller.sh --- newinstaller.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/newinstaller.sh b/newinstaller.sh index a488859..6cd553c 100644 --- a/newinstaller.sh +++ b/newinstaller.sh @@ -10,7 +10,7 @@ if ! which git &> /dev/null;then sudo apt update sudo apt -y install git fi -git clone -b ${branch} https://github.com/mcguirepr89/BirdNET-Pi.git ${HOME}/BirdNET-Pi 2&>1 && +git clone -b ${branch} https://github.com/mcguirepr89/BirdNET-Pi.git ${HOME}/BirdNET-Pi && ${HOME}/BirdNET-Pi/scripts/install_birdnet.sh if [ ${PIPESTATUS[0]} -eq 0 ];then echo "Installation completed successfully" From 58ce0ac2627cdab31aa41a6a8750109ccfb12f94 Mon Sep 17 00:00:00 2001 From: Patrick McGuire <60325264+mcguirepr89@users.noreply.github.com> Date: Fri, 18 Feb 2022 14:56:02 -0500 Subject: [PATCH 022/160] Update newinstaller.sh --- newinstaller.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/newinstaller.sh b/newinstaller.sh index 6cd553c..7713bb2 100644 --- a/newinstaller.sh +++ b/newinstaller.sh @@ -1,5 +1,6 @@ #!/usr/bin/env bash # Simple new installer +set -x exec > >(tee -i logfile.txt) exec 2>&1 From 84fb3ebc62e79a5a9c9be76062f607eb0ebc4578 Mon Sep 17 00:00:00 2001 From: Patrick McGuire <60325264+mcguirepr89@users.noreply.github.com> Date: Fri, 18 Feb 2022 15:00:22 -0500 Subject: [PATCH 023/160] Update newinstaller.sh --- newinstaller.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/newinstaller.sh b/newinstaller.sh index 7713bb2..9c33852 100644 --- a/newinstaller.sh +++ b/newinstaller.sh @@ -1,8 +1,7 @@ #!/usr/bin/env bash # Simple new installer set -x -exec > >(tee -i logfile.txt) -exec 2>&1 +exec > >(tee -i logfile.txt) 2>&1 HOME=/home/pi USER=pi From 7c1e22eced1281fea0e2360d9baeb4f2819adc06 Mon Sep 17 00:00:00 2001 From: Patrick McGuire <60325264+mcguirepr89@users.noreply.github.com> Date: Fri, 18 Feb 2022 15:01:23 -0500 Subject: [PATCH 024/160] Update newinstaller.sh --- newinstaller.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/newinstaller.sh b/newinstaller.sh index 9c33852..c41a1bd 100644 --- a/newinstaller.sh +++ b/newinstaller.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # Simple new installer set -x -exec > >(tee -i logfile.txt) 2>&1 +exec > >(tee -i installation$(date +%F).txt) 2>&1 HOME=/home/pi USER=pi From 0913dc3e21b50696e48d1a6e65690fc6c27829b8 Mon Sep 17 00:00:00 2001 From: Patrick McGuire <60325264+mcguirepr89@users.noreply.github.com> Date: Fri, 18 Feb 2022 15:04:04 -0500 Subject: [PATCH 025/160] Update newinstaller.sh --- newinstaller.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/newinstaller.sh b/newinstaller.sh index c41a1bd..a727aa7 100644 --- a/newinstaller.sh +++ b/newinstaller.sh @@ -1,7 +1,5 @@ #!/usr/bin/env bash # Simple new installer -set -x -exec > >(tee -i installation$(date +%F).txt) 2>&1 HOME=/home/pi USER=pi @@ -11,6 +9,8 @@ if ! which git &> /dev/null;then sudo apt -y install git fi git clone -b ${branch} https://github.com/mcguirepr89/BirdNET-Pi.git ${HOME}/BirdNET-Pi && +set -x +exec > >(tee -i installation$(date +%F).txt) 2>&1 ${HOME}/BirdNET-Pi/scripts/install_birdnet.sh if [ ${PIPESTATUS[0]} -eq 0 ];then echo "Installation completed successfully" From 0cd56a13f0ce797e6a8d64ae8c0c5d26a9c767c5 Mon Sep 17 00:00:00 2001 From: Patrick McGuire <60325264+mcguirepr89@users.noreply.github.com> Date: Fri, 18 Feb 2022 15:09:45 -0500 Subject: [PATCH 026/160] Update install_services.sh --- scripts/install_services.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/install_services.sh b/scripts/install_services.sh index 02fd85a..af3e82a 100755 --- a/scripts/install_services.sh +++ b/scripts/install_services.sh @@ -409,7 +409,6 @@ install_services() { set_hostname update_etc_hosts set_login - create_necessary_dirs install_depends install_scripts @@ -427,6 +426,7 @@ install_services() { install_livestream_service install_cleanup_cron + create_necessary_dirs generate_BirdDB configure_caddy_php config_icecast From cab8440ce15e4e96f7a9f8d3cf04e27a5d79eef7 Mon Sep 17 00:00:00 2001 From: Patrick McGuire <60325264+mcguirepr89@users.noreply.github.com> Date: Fri, 18 Feb 2022 15:23:14 -0500 Subject: [PATCH 027/160] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bcf25b4..da438af 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ If your installation isn't in one of the countries listed above, please let me k * FTP server included * Automatic extraction of detected data (creating audio clips of detected bird sounds) * Spectrograms available for all extractions -* MariaDB integration +* SQLite3 Database * NoMachine remote desktop (for personal use only) * Live audio stream * Adminer database maintenance From 6584d7669073570b0e69fe05d6de1bd272b546ce Mon Sep 17 00:00:00 2001 From: Patrick McGuire <60325264+mcguirepr89@users.noreply.github.com> Date: Fri, 18 Feb 2022 15:25:37 -0500 Subject: [PATCH 028/160] Update README.md --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index da438af..02bfd59 100644 --- a/README.md +++ b/README.md @@ -45,11 +45,10 @@ If your installation isn't in one of the countries listed above, please let me k * Automatic extraction of detected data (creating audio clips of detected bird sounds) * Spectrograms available for all extractions * SQLite3 Database -* NoMachine remote desktop (for personal use only) * Live audio stream * Adminer database maintenance -* Integrated phpSysInfo -* New species mobile notifications from Pushed.co (for iOS users only) +* [phpSysInfo](https://github.com/phpsysinfo/phpsysinfo) +* New species mobile notifications from [Pushed.co](https://pushed.co/quick-start-guide) (for iOS users only) * Localization supported ## Requirements From 806f1b5f4579a7ab109f444474636a2fd4eac16e Mon Sep 17 00:00:00 2001 From: Patrick McGuire <60325264+mcguirepr89@users.noreply.github.com> Date: Fri, 18 Feb 2022 15:32:44 -0500 Subject: [PATCH 029/160] Update newinstaller.sh --- newinstaller.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/newinstaller.sh b/newinstaller.sh index a727aa7..135a5e3 100644 --- a/newinstaller.sh +++ b/newinstaller.sh @@ -9,8 +9,7 @@ if ! which git &> /dev/null;then sudo apt -y install git fi git clone -b ${branch} https://github.com/mcguirepr89/BirdNET-Pi.git ${HOME}/BirdNET-Pi && -set -x -exec > >(tee -i installation$(date +%F).txt) 2>&1 + ${HOME}/BirdNET-Pi/scripts/install_birdnet.sh if [ ${PIPESTATUS[0]} -eq 0 ];then echo "Installation completed successfully" From 044bfef54405b9d4bb8d42805bd99dd92815850e Mon Sep 17 00:00:00 2001 From: Patrick McGuire <60325264+mcguirepr89@users.noreply.github.com> Date: Fri, 18 Feb 2022 15:33:25 -0500 Subject: [PATCH 030/160] Update install_birdnet.sh --- scripts/install_birdnet.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/install_birdnet.sh b/scripts/install_birdnet.sh index 1f7e98a..1d5414a 100755 --- a/scripts/install_birdnet.sh +++ b/scripts/install_birdnet.sh @@ -1,6 +1,7 @@ #!/usr/bin/env bash # Install BirdNET script -set -x # debugging +set -x +exec > >(tee -i installation-$(date +%F).txt) 2>&1 set -e # exit installation if anything fails my_dir=$(realpath $(dirname $0)) trap '${my_dir}/dump_logs.sh && echo -e "\n\nExiting the installation. Goodbye!" && exit 1' SIGINT From 84e42cf9233eb3e2ed96929a908a54b35c8afb32 Mon Sep 17 00:00:00 2001 From: Patrick McGuire <60325264+mcguirepr89@users.noreply.github.com> Date: Fri, 18 Feb 2022 15:46:51 -0500 Subject: [PATCH 031/160] Update install_services.sh --- scripts/install_services.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/install_services.sh b/scripts/install_services.sh index af3e82a..f383ebb 100755 --- a/scripts/install_services.sh +++ b/scripts/install_services.sh @@ -430,6 +430,7 @@ install_services() { generate_BirdDB configure_caddy_php config_icecast + ${my_dir}/createdb.sh } if [ -f ${config_file} ];then From 4b38aa90b8540aad0fb72f1df8bb6c990fb80b4b Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Fri, 18 Feb 2022 16:06:20 -0500 Subject: [PATCH 032/160] removed database password --- scripts/advanced.php | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/scripts/advanced.php b/scripts/advanced.php index e67c5bc..8252746 100644 --- a/scripts/advanced.php +++ b/scripts/advanced.php @@ -25,15 +25,6 @@ if(isset($_POST['submit'])) { } } - if(isset($_POST["db_pwd"])) { - $db_pwd = $_POST["db_pwd"]; - if(strcmp($db_pwd,$config['DB_PWD']) !== 0) { - shell_exec('sudo /usr/local/bin/update_db_pwd_bullseye.sh'); - $contents = preg_replace("/DB_PWD=.*/", "DB_PWD=$db_pwd", $contents); - $contents2 = preg_replace("/DB_PWD=.*/", "DB_PWD=$db_pwd", $contents2); - } - } - if(isset($_POST["ice_pwd"])) { $ice_pwd = $_POST["ice_pwd"]; if(strcmp($ice_pwd,$config['ICE_PWD']) !== 0) { @@ -306,9 +297,6 @@ foreach($formats as $format){

    This password protects the Live Audio Stream, the Processed extractions, phpSysInfo, your Tools, and WebTerminal. When you update this value, the web server will reload, so wait about 30 seconds and then reload the page.

    - -
    -

    This password protects the database. When you update this value, it will be updated automatically.


    From 1656851ef20c2f2aced5877fcea158fae6a786fb Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Fri, 18 Feb 2022 16:12:57 -0500 Subject: [PATCH 033/160] consolidating --- requirements.txt | 4 ++++ scripts/install_birdnet.sh | 30 ------------------------------ scripts/install_services.sh | 3 ++- 3 files changed, 6 insertions(+), 31 deletions(-) diff --git a/requirements.txt b/requirements.txt index ff000e5..c211da6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,7 @@ +pip +wheel +setuptools +tflite_runtime-2.6.0-cp39-none-linux_aarch64.whl colorama==0.4.4 librosa mysql-connector-python diff --git a/scripts/install_birdnet.sh b/scripts/install_birdnet.sh index 1d5414a..b7f8f38 100755 --- a/scripts/install_birdnet.sh +++ b/scripts/install_birdnet.sh @@ -21,41 +21,11 @@ fi sudo ./install_services.sh || exit 1 source /etc/birdnet/birdnet.conf -apt_deps=(swig ffmpeg wget unzip curl cmake make bc) -libs_modules=(libjpeg-dev zlib1g-dev python3-dev python3-pip python3-venv) - -install_deps() { - echo "Checking dependencies" - for i in "${libs_modules[@]}";do - if [ $(apt list --installed 2>/dev/null | grep "$i" | wc -l) -le 0 ];then - echo " Installing $i" - sudo apt -y install ${i} &> /dev/null - else - echo "$i is installed!" - fi - done - - for i in "${apt_deps[@]}";do - if ! which $i &>/dev/null ;then - echo "Installing $i" - sudo apt -y install ${i} &> /dev/null - else - echo "$i is installed!" - fi - done -} - install_birdnet() { cd ~/BirdNET-Pi || exit 1 echo "Establishing a python virtual environment" python3 -m venv birdnet source ./birdnet/bin/activate - echo "Upgrading pip, wheel, and setuptools" - pip3 install --upgrade pip wheel setuptools - # TFLite Pre-built binaires from https://github.com/PINTO0309/TensorflowLite-bin - echo "Installing the TFLite bin wheel" - pip3 install --upgrade tflite_runtime-2.6.0-cp39-none-linux_aarch64.whl - echo "Making sure everything else is installed" pip3 install -U -r /home/pi/BirdNET-Pi/requirements.txt } diff --git a/scripts/install_services.sh b/scripts/install_services.sh index f383ebb..62c6bcb 100755 --- a/scripts/install_services.sh +++ b/scripts/install_services.sh @@ -18,7 +18,8 @@ install_depends() { echo "icecast2 icecast2/icecast-setup boolean false" | debconf-set-selections apt install -qqy caddy lynx ftpd sqlite3 php-sqlite3 alsa-utils \ pulseaudio avahi-utils sox libsox-fmt-mp3 php php-fpm php-mysql php-xml \ - php-zip icecast2 + php-zip icecast2 swig ffmpeg wget unzip curl cmake make bc libjpeg-dev \ + zlib1g-dev python3-dev python3-pip python3-venv wget -c ${gotty_url} -O - | tar -xz -C /usr/local/bin/ } From b64d0b52ebcc2496526b5c756e7d6f36922724b9 Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Fri, 18 Feb 2022 16:15:12 -0500 Subject: [PATCH 034/160] removed missing function --- scripts/install_birdnet.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/install_birdnet.sh b/scripts/install_birdnet.sh index b7f8f38..f5d1f15 100755 --- a/scripts/install_birdnet.sh +++ b/scripts/install_birdnet.sh @@ -31,6 +31,5 @@ install_birdnet() { [ -d ${RECS_DIR} ] || mkdir -p ${RECS_DIR} &> /dev/null -install_deps install_birdnet exit 0 From 079e439a87560bf800786afeba3ca38e27ac913f Mon Sep 17 00:00:00 2001 From: Patrick McGuire <60325264+mcguirepr89@users.noreply.github.com> Date: Fri, 18 Feb 2022 17:00:06 -0500 Subject: [PATCH 035/160] Update requirements.txt --- requirements.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index c211da6..ec67542 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,7 +4,6 @@ setuptools tflite_runtime-2.6.0-cp39-none-linux_aarch64.whl colorama==0.4.4 librosa -mysql-connector-python pytz tzlocal pandas From f30ac0b8d22ef953c227e6184a71a8a3d4a7b59a Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Fri, 18 Feb 2022 18:04:22 -0500 Subject: [PATCH 036/160] rewritten for sqlite --- scripts/overview.php | 39 +++++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/scripts/overview.php b/scripts/overview.php index 377029a..c7fd2e2 100644 --- a/scripts/overview.php +++ b/scripts/overview.php @@ -6,6 +6,29 @@ header("refresh: 300;"); $myDate = date('Y-m-d'); $chart = "Combo-$myDate.png"; +$db = new SQLite3('/home/pi/BirdNET-Pi/scripts/birds.db', SQLITE3_OPEN_CREATE | SQLITE3_OPEN_READWRITE); + +$statement = $db->prepare('SELECT COUNT(*) FROM detections'); +$result = $statement->execute(); +$totalcount = $result->fetchArray(SQLITE3_ASSOC); + +$statement2 = $db->prepare('SELECT COUNT(*) FROM detections WHERE Date == DATE(\'now\')'); +$result2 = $statement2->execute(); +$todaycount = $result2->fetchArray(SQLITE3_ASSOC); + +$statement3 = $db->prepare('SELECT COUNT(*) FROM detections WHERE TIME >= TIME(\'now\', \'localtime\', \'-1 hour\')'); +$result3 = $statement3->execute(); +$hourcount = $result3->fetchArray(SQLITE3_ASSOC); + +$statement4 = $db->prepare('SELECT Com_Name, Sci_Name, Time, Confidence FROM detections LIMIT 1'); +$result4 = $statement4->execute(); +$mostrecent = $result4->fetchArray(SQLITE3_ASSOC); +$comlink = preg_replace('/ /', '_', $mostrecent['Com_Name']); +$scilink = preg_replace('/ /', '_', $mostrecent['Sci_Name']); + +$statement5 = $db->prepare('SELECT COUNT(DISTINCT(Com_Name)) FROM detections WHERE Date == Date(\'now\')'); +$result5 = $statement5->execute(); +$speciestally = $result5->fetchArray(SQLITE3_ASSOC); ?> @@ -47,10 +70,10 @@ a { - - - - + + + +
    Most Recent DetectionMore Info">More Info
    @@ -67,9 +90,9 @@ a { Number of Detections - - - + + + @@ -77,7 +100,7 @@ a { - +
    Species Detected Today
    From 857fd981a938a3e485e4b053605909f23efd325b Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Sat, 19 Feb 2022 13:09:32 -0500 Subject: [PATCH 037/160] rewritten php and some python for SQLITE --- model/labels_l18n.zip | Bin 2282557 -> 2282018 bytes scripts/daily_plot.py | 26 +++------- scripts/extract_new_birdsounds.sh | 68 +++---------------------- scripts/history.php | 10 +++- scripts/overview.php | 12 ++--- scripts/server.py | 4 +- scripts/stats.php | 81 ++++++++++++++++++------------ scripts/stop_core_services.sh | 2 +- scripts/update_birdnet2.sh | 1 - scripts/viewdb.php | 51 +++++++++++++++---- 10 files changed, 122 insertions(+), 133 deletions(-) diff --git a/model/labels_l18n.zip b/model/labels_l18n.zip index 68a822bca6412fc974d7111065c93dcfed4f858d..9503754fe3a36d21846cbcdfdbe069492d8b4e53 100644 GIT binary patch delta 74327 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

    $vK$kd| zUvP{aH9!-{NPkxI-9jU1;WC~4XA4EC-EW;N*IyL&bQ>1TL#2WB9OAW5Kv4+6noV?Y z+Y9=XYb9~aH5D27HC|MbQ_s%#u&P2AspDeTzk`oTUs`fN2K#l zA`ngcJ*pE$%}h|fvb>N6@SToDoikB5jCCT~u1h+~6gb+w9^xs+K07A9#i! z@*AsB(E@d-ZY;mp^97Y5mBdY;*IR-h(cMSWSpSEdJR%nSvzp8{7J=~declt zP=7@;c3~=QAp?Ezja>Q^P7vDi21iqR#8Y;q9%%_fScHDzEnK^@BrGyin0S}7NN1D25JSH`In6;doWs!sZq4?ZR|VOoMxqUoc>swOA5 z-@~H(V|3aYhwpL+D1oa}ER=#cc7=Quihp9}c1CIU*uFGER*mKgfIHDyNZ-d>QhL%Q zeJ9E!1B&P-$FzF0Y3ZagdmHc>VGQm(kZ5BqAf!ZDdbi`6%xB51n?a+AMd^z zChL5N#sDN?t1eujt+G--OMF^5qECX1QqPeJ;o9{%J;u_~Z{Hnb%)n*3eI}?_ECfRx2{(dw6cI>ZOFOGboe( zi~G@vq(ajFoy)T_t4~!@e|`1m4&{lni&AE@@PF~3=1>A}W}` znFqNAqm|TX3iULTL4TO?#Vodjfyp;( zJ|nh7%2J>#wgeCiWG{iZ8ESXE)&L1N*yGsFsFS%D5?<@kta>bAwDmZS7c>BME^6$o z5xtRKVrq&M!w4-^(zVE~p=<3q2;#iJQYgxpxKSJJ#Nb!xReGEyhot`{OX?4<$(hi` zOHjj=B^GklIX$)6DStJlfSpko?u&bFV?9?Z-3R+3-MZr?g^&~}&kROPTA4Xgb^sm^ zR19W1TU=aE1jOrqYcySmE!r4VqzL$b+C-j8ce)Imc36D?dhdli*I%HMW}WOie}R6u z*>UVza;R-IW_ThMk`b)x$5Vb-EO8;XdI?hQCwylzHOQmWOn*s&Y1OXmJ=J;C#*_z3*A___fp1SDmF3At+x z8zH+&EX?``2^-5L!^CS7{4U&(~bdEATHKi)!Ac87V*y@X{_!fsvwO~^edMMmkM;~!SPY-*l`!D?0 z&&!di4C#*5Z(aWUk2dE~#KWP`$8)cUXyzsanYIXv)_(ih|97x1sPF&On?H>X*0-!_S3@;r}=DRSL?$cZmxk>-$7#}+3oQZsX#>| zJnRBj&bzjN6T(UIy>c2hQKHx=y(V@4T3_;J`>)Pe)}}RlfOD*0mG)WDqC!m&h2XxF zHG&TD3vK4iv%1f;!*f?FNSAWtBqtPW>=ceBmVW}rNNVc?h`UJ?Sbp(9)S`uj z6e-r^2{Q*<(B(}V3cDm{$*q~_Ae#UDHxF^e3gfO4JC1byY(GsS)*`W^M7w*69#e;R711 z?tgu4!SB>#t97}muy8A$x%~jNjLAskAo9a(K++aPWcagk=Xed!zR|+i3MfTiCUxxF zN8ZRzjlTK{bwP0t3c4ShqH|zm;NQuX*9xv9{JJal?UF4}5zqvVeFm8o%J$CFYs%Qd-cS^=9!d+O0aYkFwtQ~ zFW44rK<*@!Qcp`0q#9GFj@epgGT9Dm3`GBfh~bKVPn5+5&IrgVU@rG1U0d9ju=esA2kypA$G7=M}7 z1XHnxHjpn7r3wx=U70u;S>Ym4S~Ee?{HTU>v>CBTOW6rwjfwVWVx5YFbd6dma7bB} zC~(z4sa6mgVXBd-?!GsLAT%4Zzm4d#@+4g3>O2RkXVpG#I?)2EdXV~%a@y`+RwUZ1 z<+=i2Xa^jZ&K{)dHabtK#IZnh;S!GGkg-*8W2%;GVw319w;JAFQda+f-617b$W@*? zlS6614gSn;F(6gz+^U?Oo_{FoTo*_>Anz_GvRaU5GNf>n&hk#y!y|3AuVy^Y<(9O% z4!1*;{-3cO80*g!g4iMi_4(v*JL6MiP40bOOm7y0dLp;N-u_n~rsD^E+&BGRtWNX4 z`(*6fO|I_Gpd(5TFuD^QPl?z$2=BGwIpMQCUUV>_SVJVUc z?OqlJO((AUE+o<_0Y?da#VMrV$$8Z*y18)=RK#oxMUy7>gy@87i;*Wzzh<=dbbb2m zwJT9q@B+-5Gu*x+{ghk5C~1Q{V!Upp_uT+q9ICj#e1>8nomgZs?c5@o!J}^7*g`a+ zb;YY+>O?^k1y!9s1%GXtkQ>BXP7tfjDp>n3<>u``))9A<18Hp^c}JKZF=cM@`FQUx z(eap-RMFDVAAZMqy7PRX-8XXQt|VpEyyWPQWGHH|6z0kfO1pJ@@BMtGnYQz-wEdI8 zYjKQ^PIa`%m2F;gvgdHBlm+&m5oY+6b#!tK*Dm;#jv>xw7k|RQD;#(9DB34w#nmCG z@Fs9?DvfH!9z1uev4hmW?icGWokXc{9?ZEKSUahe0OT9BN}7AmCJ4=8&Dz^Dt-F$N zsZBdd%(I)Mh({>c4aDR+Eixg~U_#=ncLnUuYTEf+gyAr=+r*CdI9Sn!D?85%;k^Ky z%xTu9beVIy1%GKtuYelkpr=Vv0hIW${Z%X$hgRZ!w9k;JZsYVsimm_@8a6nVY$?n= zRbE)*)*Ul*#n=YQmUQg4lEWuk9Mr{6+|EyO0@v+Bx%%g4t}cp25$&ha*;kkP)NMv< ztu?xHEB_nm&^0tQX)k3hHmK!t=VEl|z#*LJwpSX>Ie*3-|87AGyqN|_lq6JkQ0X(x zUpV0mpqKR(cScs&zk>a$4D$g>l4AvC7n)bGn^0(k9v9n7R-{d`tHaUs?Qahn%uyHm zM%P{goiINP#Mz?6Ns2s{fT9JnOw22*1~#B&^~yIEf?cKsLlyRDSIQv`T*^Ul`0?mF zC?7O%J%76^yf?Lmp`l6EYp#W?LD)?i-ksEZb6O$eM4v*fl+{?NKrJ1wZ#P-%0umM@ z5{#X&IC49K>V}YESZL86juYiL;6IYGsc|O*^N`!Hj=lv@!PZpb*}^Qe?tNbg z^_H+RIA$8JW<{4$gj#jk6ge&?r-P%$WU+xqh=0_Jnxep}0--C2D@)BeUz_+w6$n)0 zUZ`4i*Qz%7jpIPrGgNI%%c7d_5`2ouU09cUR?BBFPnJAozDyaxz-W zDNox$7B0mL6)d_QQC&ebRl)PheVGL~=SCS?JjOEB)i=*BdmyZMLKi|?*o3i=8R4WZ zD1Ukn&tw67O*xu`dh=F#D^L!S*Ua3@=pbK$Jd-s} zBU&v>wU`f;ju}we(l@6OvqniB5JH3ItGN`-yMBOP>T~EyK4pe=Oc9L@bw$#Ab1izP zcoe+#Y#_An*ny>XwJIymbgqqVV+;T4XMfAB_gXOW0yBrOAh$KaDy}lQ#D|7*d<$7< zs`l@|x=?hp+lM`9k36Tl%)cHY5*bggBG99xsc(DHD!faaS;^fQqSYSd8Cif*6OULz z{K1N(TFfEXE+^*?0nI%5NBj@>^)y_Dz!;=<%{w+o-tHonTTjPUzAyAM=!k({S$_$Y zrF^k|yl^cHO7y1AY!Gy;&}#2lKITn5>I?U|xGMS`z3B z=Y0h`Viku>a4NQ(3`)`!ALS1whIx9fPoHV)9Q|tnO~s>S>G=9vMb=U)TvlV?Ix3G7 zOi(^n*Ef{f$LLQ(Dm`JO$g7j5qknnxWudcAYnl|n&D5`60xn#fQ-jc}34#(hlkBJ| zdm%dMApP^m5)DFcDn>PYl4a$jsNim|Xu(ZSX!-L$vh@pea6(BX2eXY(S!?mQxE5*e zT7=}5e!p8k?|&oC4sugyTCtj3q{r=`=_Hd@Sh30SKG4M_sZDcsfwHX>A%DO<=)lS^ zAxdZM!ishQu{YE%7H!w06qOxZha#~yG#TO?N{` z@br^~5l72*P#ol4;U*;5XqP;0T7uyzIs7|NP6-r+`mNUAa-KJr!~bGul+Dw^m>2MS z=c_ba(m)TwK6!0K=qvU1oWJs*qjyWik1eV~e z=M(`bBIpESDm6NdgvGqIgM`N%M#%EqI=g5Yn^eEB6_pSd{5D;pQ8~B)qq7M1azW2; zqtIL0v!K1^09&wBobxM6(8!W)fy#~q9Mx!nYEo8Ap4LEAd0OtK)PGxU-^=b{*S=kE^LsJ)&r-^tYoyKtCCQhjFkO4C6u;MP_EFzp`f7u&im|?Q|7?Y;$(K^ z(PWYr%9o^Ciy>ml9Dm5NoR}A++6`bnru*jtFt!%yTNfq}YZ@t&W%C7@{6QD<_hT3@ z2#V7$xuRBBH-uQ8%5c!%P#E#A;NH?E!)2ru^~jxahuUN@ut3CwG-+5NV%v^oDC4ZOrI?FH z+n2lH|C5yHV`q*E(qDX>Y~?t-1AAEp)>Vs&+xX7&;U_oSh`A$1(NEgjG));DOM+|H zYBV+pH(BUDIfguVkx%}CGmVSESHooYb(x@64{`(Wq#&vLO%0*va)v_JnfJ;2Kvvi4 z8}8AE<=zX-y?>@{2bCTb3=E+low3P_80eW!TZrV@<>*OC_Z2Aiuk}-EU|S=&O;qnh zF$$t)^)PnX6IxJX>-bv}ab z#`QXU8}0M6n7V~tX9W0OJaBsKG~aux=^HK#y@FD$<$v87>EZv29;56uO-yX#q&gNm zxRPgFaSTY0UKGT7`hgd{MzIn~<9u>%bIDi@7?{f>*$3M9 zz)Sr13c~g6rzBC(`ks@xfTGnTIgAzH$|SZrU{yn^2)+^fQQ9)KzA^5KZ2m+Ewg#@K z!-9j^_-GnzI7AJf&Y;g`UnA%xqYSV&cRG?qcw)p^5>eo^NFfKS zbSt+al~N>aBp{0uL@S|f9W0}Q?4b~+$Q^|0muT4kLJuJr@lZJ#&s?snHRm|Q z&hf+qS9XqR$AF(6hq+cL&emV7zXp2RzVqC}ijJ<{7PfvtAkGk2PjsMP?`30}JbnaW z-G4BH%5hFnnzL8eyW$6Z=Xc zb|xj_D;OHGX`wRy`0wfPi=SyI0dkY~?0&DV!T(z;8{i48$ER@2GNzv(>`~kXHzZ7j zq?Kjwnf{b(0wR{yvIHR{p^KwxgNgO=F@JKXtiufsX>c>1CpIm~z`H{$xPnbw!xvL5 zeduvq$-h@+(*@J50^QM>!&@!NSY3hZASBPp5!*C4TW!epY}|N6YX@vFGkZdq%l2%j1XZCI?lih=&2^;oQf^zG`o9e_Nf|Wq!>B;e@or{g+&ws>+ zg~MzQH<>rBvW=}(wh(%2gN@;%^$ks4q|72?w){99w`BXFiWBr~iS~cczaRnB``2gg z0<}W-?!haL3?5mBNBcF{TPOnQe71xWLS4J+f!HTinMVtpZ7iiujO3mtM1|M z2Fb{2h)P+?ir+!cA0$Wkd28dv<6mg0y#k_`X|CW(I9T&=*K^8cAtMU&5cs zv|8raDlOJ^0m}`m4iC#M*nfX48*WrE+S6ojf;EGzJMzatR2G{!=}equQOtEVs4321 zFBw17YI2r}d|Gr1Pdy^djek7)#}^u`YTilA;7V5L>{h6_E77;2sbBQyKhg!srC-ch z5}cd?u6m?%#1AJ^!q7#bp*>$SH)IXD&H||o^P6x^a{67JPS!C$;!Wl z8Oz|sY*5hg1@Q&@fO}aQ<0%qO*Lm2O>R;pF#@>8V<>m>vvT~QmS5SX_l!C03>jh^& zlrV1GP}M`OA@csX-d`v422s$Y{y?~*a~lY0GW;(M3iWXhs7GeUUlpgDyG>6!dr33B8YoW zWeMQ#CWXdGQb{m>)HW!5*n|`ve!v9`tmTnm+yF(CSvg?a1gT0Eos`Rktzh}z(HJey zyZDg@O3bGayMLB#F6$%nPTUm}mqGX<)AuPFkyL0v$Z*JseY4B1UIiCk99ZGon69Kek!0-Nq_1|nlRT%sz@pj(!Hyo`Abx)Nw#3JuuJFw-O6&$8TkWE>^eh`_2g=}hy@;*!YP(c z4-+3TqG|_7NEZpJ+Ig#qQfeKiBBdlL3S!kL=707}dN{UEW&!o)H6`s{a}cDWxe2EO zBJ+;(Gur{H5V$BRaFntM#8Tjh0s29q(?lCZW(-oE-;uq>?JL^f3U^vvJBd>?QEdIv zv!e|)uc&u!v8eO>3Gv&&ZARNr7HCrHPv zAAfywnoRD}OZjHMI=rHM)9NgQy-;o+Uui|~(Uc{s)xIpwk_bY)#hjB|;dnI-P<3=^ zhH#6Dh4swcEUE?<*8U2Knj9m95c-c%!i2f{ae8*PJB!FP@>fk9S(0gsQn8jMj?EGF zQR%3^BdWZ@sWxu!x+H;}sZ`5&wyrF`<1jobbmm34IQKA z_5CX{y+@IRDbaV^gKo-AXG^oJeQi;fh<)t1IHQdV-Rxs9y;6SPdkX{Ytk0rLE%BOn zu-Yz7;-clo*+6Q=PSF;22Y=bq{zJElhS&!5sx}I*DMpqgWb@8_rr7O|mPy)e(CAb0 zq6qz$U=%q$(^j$+jee_k&A+fnlFE!Dn$L7##DH#|nJ*VC-ml1uqTZ|LGU2$1onk&H z)vqjH#W_F0RqkVr1OE+SqBZO##B}iY)}6mfL%9t~qU*6)>1LSj+JE*(J6@dfkLkJ2 za|1^wm}b+-)K~6#^9v`)J~%{y``M@fP6_2#Wxebc!RxX%_$J2CrBJ8&_wG&7Js2_pQ^xOGo@eciA(#T z!fsT-9cvTM&z0R?3V-0u;XP`6RLCnelCI-&lb@fs>?5*`$lYcE@xyG<`kUv6I)E_l zCE^DVO~i#o0hQ4E<$M0`e@{jD@aYd2Xx9~9T`(aE{uNsE)Opg}qh+ZUF>rL-TAZkH z*eobO!*{1O2ynQWKvZnUFLVfez9duFapMRf6NLy&|C?(fL3%uOos5iKW<=vJxASXmqj#x$i_E(F#8^c`z=C3Xl zO56+1K-MQp=y@3=wY&$5JuL1_yoYQ?k@DmOeFWOxAo{v!xhhSl*@fGb%13}8Y2i9VzES8tCDF)ID^01 zSG-Typu?3FvrUfq4$?ClM_$57H`8R}7YKL#` zW8+=##?`1)P5$9%*F1cX3+f1Jy|q{$Oo_W;p^VlyIG=*Dt>G7Q`WLK&xuor_A=)Y> zvUgh7S@TCFGcEtH^O0x?{Ya~Z&cgZ!?#qg|E`NnK28i~2`KH@EDzfn=n1LUyJ%;9| z={B?_06ojb@JuF<3THJx9_~jIjR>B0_=nX)Bs0gOKtv15*Vmb(tpF^rzUXcFf~LjX zRUko54rR%zWU?9UO`lcl8pDo`vq-Hn*SY)xGRy22{=f7$nS5?Me~EwKUwZL5r601` z{C`5SjAJ;dg%A=mR3Mtwn3VqiozIK)VD1Xb(F|UG5i?&k3CsblBnVJ;YL9hR1z1D| zq6j%&A@YJPr00B?Ix{<%LcFwSQ`ti1w76c;?A+ii+TFq;ssPHHXKFMQT5S{yo8f!a zn3sSEoE}=*+I9ny;CI}JB{f^Ypne|U#edCY7yUo7VT1wCgTn|Dvf?*ra=pBSqBxe# zQq@ailvef3`$RGko1hUXLr~te&ZYpN6cyrNv~`WLFyVf(b+SUyW-nR~-&*-=eHqTo z!dp<~@-*r^Gy>jHNKG~2ANpxseuwjKCh2ZxzUOjeSdPTP-Lb#(u6e&mhM0=9dH}^`q83`V( za5?!Sl%5@!@yh^C5=QEZT59-X5yI96u^rcB{GI=cz6s3>6@U4RxCZ9xp`e)kDZ(2MLE%*t~c@-0!1M^zIuP= z`YyB~iu-^@o_{+n(roKkw6^3tH@DkL!xywC>|*&xtY%$d^nl5ouj4o!#Y2(h%#Ft+ zmhl_y{&Q@L1!hpJhks%XlV~Bq6seF$tb~U%easJW0&^Em24uh@O#3(IV0Ph|11~1- zF7OgwBC#Q=N4$fbMJAJ8hJ}xS^|XsFGvKHOywfpkrv0n)-0h6Lhsw;~#S1x7TEgVm z+F!tn$PrjryJ$p@M2m)9qWAA)Bi{ZF64WNg!P3nBT!UkxHh=f_j^ZmEjVnbp>JKEb zhpepE_z1e%q-rRgrg1K_($>`;Xx5J`5%ZI!zdS;BLWM|(vz=J^DT*$wh6@!9t}9kO zz#7ALJNJcOja)^KOiOdt*XEiGrg-!IzZ%W9LzKK|079yWTn*|Ov}#1V26;QpQ7>#Y z=JgM${aX#jlz&FYBiy1t9d-VNTnEtBnT53YAalheta{t+U@D^ zyI)LK^5uUU=;wh}d1ph{e04pdvSjNx+8PG0{V2@ENsSS=osNlx-)N(;6aOa2;yG4f z(%J!ys(=4BT93pb&Wa#sd!(Yo%up%H`5PBex}5b80mP-dIZRlW0b_Wz{Z~K63@vZT zPZ`8Lp3rJ-#HK3xM&pCF3M>mAXBVWXbjh14_mI0gviBG|&dXb*zo&xLyhjsaVkdE8 zx|k6TlEDccHAf;w4^4d#WmK9|^3ogz;7C|3(0_W!77ste3c0k@9%Tj8G?f`g)G~SL zX+a6js zVSlj?4^poBD|KmD-?R78-rYlWXzwKt zoyDW~aM?Qg!y@tFcCV;{Taie=2h$FToNNApULopK_po06i}Rul;K`2i^(_6ehh*iG zD+fr*9L*knqK!_C+QcH?L4Gydj!s)s?SH{&eIvwPs6Fl>Mf+Lo*BIn`4+-5d4Iejv zv-F{=WE4{$g|y~r6TafmNhwKPsGW2C_#@8=E0B&h)eb=qVhNy=!h{e1EW* zaYS+=RJMGvyO6bL;j~IX`u_HkV5J{a@cFk$IypyayOrW?4N#Ec z3F(^G0I=bUl8DiiT-OHj&KfBNHLigf(0L+j&%}-#Ti}|%%E##z#{5;`;v<(m?feKW zL@%YVH<(v*>4a9NORVub$x`$EqJR57Tf%8a?Z{jk24<+J$-;3|&8A*>ud;ESU(MKA zXhdN%1D`F!$wleT($7hqg*9TfsETF}4sq+&g;YP8d)O-{H|}xi-ew8+(s5n)Efm|C zBcd~6+$EZ}=o|jJ;VIpZ{`}SSJIG?%7dpRfa5k?r5YLakjm^<7-d;Fa*ndXyVZk@> zi*-GDHOBAUY--RM*`iIb2|2?Nd1hU@LviS%bXR-%npZz8&>*vv)(MXJ@_o|l< z1CEC4w`ptA2+#&FhLaWQ(0^1n#NlBM03d=)|E2%=nH%Y#w-1lT9s<9UKXP+n^XU$4 zM_=f;2Jb^Y{FFY-`VQvH$JmE(HGHQdSvnfVqWAUH@43t->xnc#NOtuNF2fDlf@}O> zU<27N-;4$`e0^700V-v-s*fXwscqXcduk0Ttc@apzCq!eRRM7`7Jt=fp-&B72qwnr zRwvur6z+`1_U1wZx8F;pw(xQ`n1CMR+HI_LHv!E@vB6v))ra4fj@-jWuCw&{C$6}4 zK$A7X9WSLqjBT+|R3b1M#!8AM`Y7n1sy!hURA&9imdxXy;84(ASTV3A)O(MTR}y#4 zKB=JP|YbkfM}ys9l7`LRma~D%MbS9QP;h(U+#XW6i$=s8j17neqf^IWG`0y zqtv-;AFfqH(bm|-h3=Vr2BiV#Ghz1wkHntPqJa%^1iKRl?WHqd)=5+IBYDx|*{vXG zFrwKb*+`o(m4Au|b=_kd8gr5%wE}43XdSb&8{*?{qVDE}TivJ$zk^A-;9@nkQLzAr zCQ}n2EV|U}tBHXQFruHcGIQOn{o{mKug|K9;BF`}a@t04Qv=SdN(EaRrDe?G9yB4^ zsEK>YX{j)h{uOpwx`#7SUtiOJnqXyHm~5RNMoXKsoqwxOoXIyFXW^1V1h$PTHsWu| z0$HBOdmr{Lc~{Xe_M^k|b85!gM8m2`97B;uh9g&@dyu3LS41zZcqyzKGP%S5;r>DR zU-U%&FQ7A8rlG9ZT|^xUmGM>0&?iasb6=EuY&(GpI4wV+@kM)~ql2WoIuwd5cbAp6 zQDPDoEPvT-s7F^m!g%!|hC4aXsyc%ihuSEOvXKdkOk)9I!M+E($^F^R9;bg*E+Mu$ zpl47#V`17S6z5I!2EiLNGn9TsO{73_0g)mn*TVTy%Qh!0k|w6TNgvr7Ey01p?NE+S z6MO}y4uN}m!=KPtW`;x>FlQvputoz+57`Y+J%0?vUZ#=JJ1%kByib!ou_<*Eni}$H z0ZR>v+HILLBk`s#TtS@aO@$JF(ezQRq>U;|uyT!ag+vQ8o1H=J4*T_0m6~606|nK5ogHE z8_TonqzZFQ6w1H9&v5A=td+7U!s{8U;|NQUuMYKIV9geRq3Zh1Nm)uZLut=~S5Tj;Rh2=gb9F{MJbJIQZ z<&Ud7-J*Eq_x^45)r?OX4&)YrGWf){&OV-Y20E%wSKXaHdp|D?ENut}4Ibs1-*Tgf zAXOpJx}7$}>2@=tAQ<)CZI~z_;(w*Oi*G_YdqS5NZo8z%jcE9^z;trbtd4fO28bKD z!a_`Ed<{gQ6*#exU|N#PKcUx!lX5psNMJ8i;(Rg_GGx_2%B8qp1&aEL|DXqEzXq(U z1}xPdCIUJ)(QF}0OM-1Nso>orFW#S-KTsqhwx~)|v(RQ~KoiZsVy!iRe1D?nI^*~v zwm_69ex;MQq&PKD-2O>w6lhEG4Tv(lQa+`D5XB7+aE)%~VUSPwpt*9=>YVDE=;%IN z(8Gv4qCfvlHdMBLAHIlop)14<+bSv>cOq(*bSd5z-u*HZe`Vg_5K8smK<{>z;U$+%JKdc zVnBc`oaa&cP&&bZI7D_{7HP8}MwW}5C_mn-m3eBoN6d4t5!rw(X}fbCtC7ZU%fzkdsAl#ZZ5$SLiQqUR?L$Snvj(8ovFmiLNdRjAOF*>01;9_d^qGfQ4;R`J z|v?PG09{k;`}HoSij3%t0}wi>S6lt;0@0)nt$Dw6$0Q)q`D=^ct^r>H*m z+fHpa(nX*MK`))p;UsFPJ-)aQw**b@qT+a(IH-Z+sRwP46})JZgxtqQw55WvxD|&> zG-g}D&a9w#klyE~ve;TxW-~V{qpO`P>KE;N;7!Wj-gtYWNxdxicW!@dC%s4tUqHJY zIMfe=Nm&8UuxHgDR;7_P(9T!do-Ub6y@R8p`yRg*&ChpWN%&QFh8-A6JIfAHh+yqO z6aV@135o0Z@QVOz*laH>!pGC4zLd7QzZ*$(exjH9N=_vEX?a*=8^}b<9$FfVNyhK^ zzw_#&V>r5Vquc|2;yu18JfQuM_5N4%(3L4f2lYaYYYr&+oSkH&LyOI z*O(-O_{sX~i$_0a!(nzvC< zRm^6@HdYsb9~6HzEH(gWT@3n1hA$nIa#Pwm=Vl* z`U|wg?B#!i58I!_n%LmA#^MBh_jgu4EFnzgMwy42TroaqlI9I#Mez;K^we22ABY99 zVi1Vg6?wF@nrLt5<*1Hw^kIPz#UkZviq2eQeiq|1obj&+jr@VXK#(~6q0I+iQCv}I zj*}+Uo6A?tu`{ZsM6i<%B!{@er(WVz8| zW~*l(hT4>qQ=(!wn0=%Tgs39B2h&Q~dkf&bj?Joyzcv9&Yp zeh*5A{ShVT^)T8)GvAIIvKS`Z|7iV4le2%+2w?2UWjN1hCMhlTSh$3Cp=<+YSm$GN zk{v)Yz|)UhUur;SxRJLhl`2zqzv)vzlR2R9NKUD}?4;gl1&J=uA2#+UU4ur}H)3C^ zM{{p}rny9!9+@~J6*7$Rj1nuO1)>Lb;VCclzBcI24QW{-U@>jTU>;t2I)B5FY+rxE z>4Dpe?jvsIqV}R(HWqaes2h--O$4== z{#0Fc0)&&+wT038+-47ReUnVh=&BDvA@lkk8mp-gg=hi0a3<&B84szGf)};|UFiPKuE{r-qW^!Ql(@oUy)LP47N*25lq?enRMPVoW&V9&P&I>G zKCz3{gh+aKvBS@M_xwzo&zsENT};v7O}EfpXl0~+0=M$Mf8D~#sEWbg`+~?aE;JbS zpoRD_LSKIY9t`4Nxs^$cbRB94561wh1f?LNB?)b`(2_;OCt{>8X5Cy_yr+K+63aHS zJ!pgPHV9h75Qyfu$-3v-8v7gxPhD4W$Je;3#^YD}dia6=K73EM_^5t|LXkvrc>A2N zmV!OEx!~f*8y!9xYF%Ha=j!QU8Lzt0M+buTsT?KG$cOEuMrQI24Eiqjks8ObvtRu< zUk`tqpjUJFY|iJ-qOrZeXXAgkD2z5~NxGx)c*m+S@x4l|YwqZiSb~pr*(=Zst-!kZ zO%bm}!hohn2BvQ7<0;pT@1d9uc>nSd^~H3iKfSvC!g*{m6E61Y0#60p+4wPj-^eJ~ zNbKR%;^y+AkO=({Ge4l@uo{;b5~egy{`N)iyzj!Ji$uQ0jj=jEqIiF?qMPQUPij9^?2{4xBfY4JVAVdfHJ{$*ICUQHafO2Cc2_hxr;R`{O2A}xdz|cy>a$fQcik(8D^v$J(uQ3 z1vA)6w2aAQ6stG`CGlias<{DEi;-j0SVrbH`Lb79iOVHlsXKq{E|gBn3q4*qKAff8 z1JdNWL`g?~-MwDHN|0Xz-q#NH?gIj-ql*HNJ2*r@ppc(R3EHqykP2$hB?t4}`0UWo;h+6R)$R3d;$Gjbv zi>%anj5Vy})INXE!d3%>335Rpb8N5%<934>gulQx`6sLY!}MER=o9;F41ImEg=6o_ z=pr$^Y=fdgjx`FKbyQ!Y^Es+|V2^8lKz47XlG8cBj%3Dx;4oTc-yczI5NQTF&yS%y za(s0Kw&R17S^Zq(%O1=QZ-0X8iW0^34{R7_2a4u>5=(#JKZIjVz%`ElVD0f#az^WT z=c4EZoqE%A)Of0pcDxu4AJcZPT16=_QIs)O*sFzpj4CoIE&K{Cxbxu;1Jgmx9Qud` z`i|sqp&K?<7A*uOq{L`oMwJDpk|ho|vn5i+%3bN6p3RA#%KIOaBW8|URO({9y&>E*$YaGX*a3Qb65;$W z|3DrW3;Qo_W29ebXUHC-7TZj;ZyUFH`4PQgrcAoO@4!)S;&aDguDxtSdGj@8HG>FS zx50mDPNyjH8pzSRNRdftxDfi34JdK6YFQ~6UC*HI-G&`~uiPkjOS_=as!4&NT1+8c-QxH7|njC@Me; z2%5U$7T4GrJqc*%nkHDOyVsoN*k(6rI=p{#vn=H!Byc)u-I3PJ?xj1jsbETcwpY`? z?c>PkSdNa{c<%g|B*H~57!qDPSF&^h%H#PCf9}HG@IXwj5!U-mM&f+ieUHzc&vzUG z$9)i+)LI3}htw`mJycnRJE+74#+vFcm~^{8hr1%k8&nR`{`-@oS3;nUsrNe|dA-RVfa=ADZizJ}dPrED}hVP4EG44Du|Gy7W5FiaL__=j zKx2-a3haGQ1`Ye072s1Wlg4vL7omOh1x1MV!X=?N0nkHb54+kq_8*qV4lH;40WQ)z zhlN_BWKK+MMThYP6uDhERDXnJ`~kW#VgDuu+K`TmDB_A_*xoe}JGcbteh`1#8SPQ4nJXTK1^RRPR0T>H2EMuS}m9c7xYp?!O#j|onZhwzJsM}+xkqU*#u2ywq4WBkBaWPlYoVow zNp*j3!=DjJ9xo+Bb??feNEm3yA8Xi-GUK0i zkPjo>Fp^QY|ASvu>Y+Tm_R&&XejXQt1>*bZy1VHMRI0vwSr)v1^#v-jeJuWn^QF4} z>^b*unlb}s1*6G+Hm7-!saYd}%3ua9NiO=P*O(Ku?vg@+NYSkj(tD3h z;dr5kR?wF?F8;cRxLkjdEvO--@U{?;w3ST+-H~(RHkG2`CYBq$YZh@!jo&gfH4x0% ziV^J!wovp{ijv~U`)?6v#F;Mr5{V7$3U)hS`=+S{)Q)e5!9Pyzgfeiiijv% zxT`k{F|_TaKzq0+#SFPC<)5#ioq49CvPaA{l`iZ&j@}+oFBgBX1&`rEu57;rMJ?vs z_i_UnmdoAP;?}m1Qo9A|#w{WRo^m*)0m76BQMj%>9|{>f=IOKOO9i7j^NQUocRS-? zYo3DaOopin)K#Or5V*Hws;SsqA|~CIiwlK7{|Yrg93oYFazd~i=3qX#C4UoNL&CR* zf0C~>*wYPGsK9^HQjw>U=Y|3v&IlyFF14uFZMu+^d{Qa#glp1JIPzH_Rqrqfp%+zK z1uB%}sF1tF))08H$%n0n?&giNm7umtA8bS_Dg>?Z85DnZ?FCZ}qN$za2Q?es7#15v zqMoY6B3c>=h1O>0IFFc9_f%hJ4(L=Jc)kD3TIoEm69^CKa0)Ns=t@N`so9F7_u_Ex z-5TMefLXi`ejx)7MZ|{V{j){0U|*xMGRMy_sOU?(2Fjm|6ENg)HQd`MOK-(+@3t7EqDei1XvW=Og#?{}sfUDCu*Wt98EB=9 z?Zmyjr0Gsd6{lhRI%WNob?Iwd&W_6BkTUEw>Lr|DB8vtdiW{2O>cWxEpOKrw6zr@G zjvmAFGt;+KI(Q9u#SHG2G{b5Luk6^LRG37vBbI+pok2zRMY;@bA$9iyo{0r$#8W>U zrKC7Zp5&JyfW#_UDbvm}vnni%pF+E5J$$u;R22Rwe;odxUE;!9xByZ&Fx{xu7sxa{ z!9qI#pK1-N1qxbwl1Ogv6ikFkh8+*8m&fV%d58%}ZKgTXv7kz+_#74j8B7(X?7ati8#I*3)o6bp z<69TvWDB6l#!{iQ!ijAOWh9O^=jLfr6dzN~fBt&}FCL$u4O!ZEm>&JIU0?F+`184w zNBx16YT$<)v(j5&a_(~SZ67SpotxGxHj24#vBFJN!q5JV4*Wl&ScF{ky&pyvuWX-VSlLg?R*ZkBXCwy^ z8!RmGHHO@j%d3f2L?1`7Td1&;LH%{f0J?>lqeKO$E{74htf|ByqX|XMXM4KNIg7i7 z=zge5bF0xLg(3v1^=Kx@$Q)RW)A~Omnv%LjRHI3wk<)~nbzrfq6|Bw(u_=f|_zDHv zLDOU$*INzKX1AD8=gE3(za)R41~M;ebh+o+c6`m26dlJJ=1;l_>1HjItraLq%m$IX znbuDaWfN?%RU+CqyM2JuU~e{_XJWLk5#eZr*r-(w^)U0S^OJ!cvPQrx?wocKQr)u( zp)R(BPg<{80kVmKmV=qE2=dsajm0o(zvXxsvK?O_qO@PxX*kxkB#?hp)~7T?12J(s z;!(Y@{ydr$h$DCQ0@+P|Y9m^dJ4A^eW}MkZ@4ZDtAqnwtzb2#}nP(P9pRqYkY7@Ix zn5)AEm{HwJCTWK3ms#)ihU>^5pGhRa3)i(AnRMK%(1QyW)S|}=6k$XG52Sx_; zB0hd4M9}&K8`r7&tz3U5Pr)%2GGemk(`PRCb*pjOU1%Mhee~AWpJylQV!7B>^dB^c z9|0nlhzYs+WxK3QA}>o6QBT z%P8STq;m$h1$5y8C#y)ut`SKliC$dmM-JGiwQk9AY`7lJ{Ra|5W(`U4+Uygr5U-Zz zbSI6Cb1tYxNg|3*GT2~o@!kA5j3^R|c8h?SfXW&p1lkdr@9;RiDBkMnIu7&vQ9yU&E`rY^eZ5SHyiVv%S<~EF;b0SG7 z-4aCF9WdFOB1A~mF%zWQxRN(2zem_{O>iOLB}Vt{w)4yB@l3HA1y*(&B|^}pd6sZs zeg`F%dv5YH6`g)2rn{FgRCn~Y&;;JWX$H&pDG|mhDI0$rdjjl`yhW>P3zCzfWHoOw z6Rg5P+!_g}5182vU^r^D!=`)VHUcFyHfqu4uO=%cOZJTWaeneHN%wGhPO=VvAs3sr zB^LG*fsO*oex1z2@9gaSz~w$06qmfomM*=rdSoDS9J;`2zlYR%Z*#HHA4PizXNTEE z6-lGd77~9H%{$W$B)rSWpZQm!s}%a$8gjYmDHnu4Hsdtt0GQ~1V>giSW3(+*X*?#o zGqhGCeGjJ@;VW1?HuW)Sd?rex6x}nV>?qNR3s6md z&UE&1{ejuCsn6a(EdIvMC>fNrG89(`4{Ii-K%i3S5(t2ImMRC?`G}GZ5yoOFlhn~j zC&_;b1!WHOv%kBu)8q#28r+B_SDkvuO^jE^`8E~zVdtEt4P@4xYDI`7WQo4|ae8*P z1D{0Gj}!MPZGj8%=u}M5wbV(7Z*m&7Zyik zBcp}$?v;yfvSKFfLuJ{;%X06Ny+>EiD{X)8x_eR9J2$u+mklu=Zr@YbKw7mcblF!hn<>Yg_H} zZdUr!8mg4hXQQdWHcE9NzOmzlyEON)b^02Je3^5p-E56vWkBa^$>mIf>70ED(tCd( zK{q|JVl46VD|(OcG;E~WjjAn_|T}`n5RS5`} z-#iqB$Cy}j60dJB_QzvRz6eIy+0+kDF?y7X$Me~mXH=q>N)>*Dpj7k?OO{x0oIO{- zApb>#^a>@9YLHa{CBOHrPc`QsN1A^l|Mh9Kclt4%eba8KaxbjvFq%|Q&8XCZ0|b0K zCWY3jn0$11x>cn|>82s&r|biz;gd%_Pn6_RLO?MNxmwm4&j*eIU{vjOiA;5(0y{zv zla;?{#{1Ra3I9RePn5N*ho8+o?@i3+TmvxsS;JA70FBXTL@Ft*M$j%G6=Hu-zbpr0 zDX{bbUf)*|chTd9+cB$t5*c$~r?$ild3*_Mn&i1aTSeGaK^wQ8L<6-nbbpPmLcTMp555e7v=SZoULO8qo#FOpjz<+@ex=iAxkC z$0T5}sn*y*9NVJj;nj>UD5Za<6Cg@UMC54auTe6S&$|tbETkYM@-8t)3z@r-owx!? z=a|?PkW@XE2!HhCK3&iZWR4+l;Zohq&71=uw7Z-G+hp{rVn@Yz9@0H#bxXqbD2GIL zApTJC789EyK_1-PFsfO%L1;FodqnImvV-J68aGgkB)m25(p$F27dU?gNfNU!M5_c7 zbEM@N*uqVaZ1BdG{iPeIa7?p&HN+tSqieVryJIUttmat+4(Q#d)EB*SGC^2jbeyCo zj=qR15`StTO|RhaM(3%Q$g^Qa->t zGQdU?Qlu5@EQrz>NQD7i&%%Y>FLt`$yib%`O-IW>W zPkKW3EU+jMkW^GUo1{uoV&}x)PqJS-P=pm@J$cI6w16rg3#xxR0#v&=G;X`A7qW-J zi?d$|R(6En!A81gN-pl;Vgqbi>$E|xuSX^wi*sL%g+(vcU=%z{Eyr}lB=keX@qP*2 z#iR(*L?*kzlImG{7CtfeO*J=7++z#&E8H~(OEkHrVk{eU7&*A3+gv;xM1eX(sxA|m ziTr4z*{GFY%yEBo&;~LF4SsPFa!7F+n1do6x)2pWqe3&=0N`yH zR@^y4klCYsUVv|)ELmpbC-blV#EZYOi=X6}{|L{sJ#&}7jAh$&c{|X7JjYVMILURp zs&2Xbj0kZl@4xfAxHG5rnZl-Fg1@?QWx)N+e2TyPOv-;v6w-vPk8~^_0b`o>+bjCK zs9r~)cRJEsXXC$u=Gt#%wQQjrLIZV->_d97N&18}^gPUHXk$k01> ze$^*wA?bgdy>L!^gmoxBe-wgCIU0thT!rnv+OAhVzXZG?2nU7A6?B!Ukc$>rcwn%} z4k+2bYnf_)hLOpQ-9DJ{hzgAYINn_s&pFQfz=?{n`2r^mBZO@vO{^NAB>OJARhc@- zC>3tR-(?+51L&a~6RKakMV-ULgcG;H{m=#bWVwG2`u3MbQd%WKzPZ}7fgn`D@n}ID z2O~~%&V96hK#_XL{c9R9bm-|=WIggL+Be6CP>M4ABqG-hnCi3~^= zclTTCg?0utJZDvRVoH4TS}92tsRLUG%rl0Yrh|re@285% zzkz?IJ{5^NvBh{#>om=Y=8w}dTJdW5DQIV$Epka^Ge5Dw>a@j-=J^>>c2^Nww>UM! zeqvg{rFErT&%${|lvZs)U+vNvNyzi|BBD|yY(i7RzNj-xOt4rxQNb33OyZ{hR6@q9 z_V<N8bNRR; z0@?gN6z5*!3!{aqZ6Im@ck}7&o8bnW|9@d$lI2Ejbv^ega^{g1QC7KJpQ~|MDZ77c zPjo;MNg^2x(9uweT#wh_(Lbw={qMd8O$0(dZZeg)3`PgwwfC0vwqgh*(2-M9N%Wj2 z;1;yFT$Nn3(QJUoe}kb*Y=15T-C*>NhpN$RgDO0_LYa4sx(@E9_n`S*Os6g#Ex-6M zU4Q#eGL=gt`qlzHxnt4(=DUApvT)N-1TpfkIA|6XR3^+q8+c?Vj|>~ed8 zBNt8%$N}ka)eM3D;A;b96TDRCTcIp*-i2wze+POjpZ+w&xj&7^0il7Xk6@0zC>%|- z9K&yhH7zTVpq0PC0vHWU>Y)7Ib3`~nV56R-vKP(?EFuYlZnT;w*3+2+SE_#_C{cBK zRSI?m^u-V52CxGwvaM2-L=SieDy|H@{zW_SSB~6s5x&K-*u>mHt{WKlU^!X&16CK@#pvsi9x^D|hJX#(crO121^&^v$h7OWajz`M6h z^}(ga$BH1nb{4q)RHnZug~|n0YvuZFk6%5{t<15Eq0L-1Phuw?Z~XK zIOoWv#;Vv+f@<;gHOw|@^na-QCTsYG{vz}WQj1U^rBz(0z+8Vy3GJb8tWznsrfP57 ze4tN?bx)uVl&u@S2=K^=X~qfIyOY)=2$4x+wFa(P){zlI93+pROuF_qk|~n%4U-g| zmG7F6@;-vxD|%Nl3dX@Hs7ACI3QgpL+bo5Vj?6=vzFXLEiJJ^K(kRJDDL}mNaszWw z2-C!hrGU~Urv!f)8{otyFv#IxkzQPNH+b-hq!lMrDhqiF)Ksh_kUJQ_Tg;tVxlKq^ zQ)YBxCGd;yoyPe2!8^<3@iB`)-?SiysM)UAn@EfF;II>tQ%xn7N%Q7{80u?avQ-ny z?g};^VezV7A3SQ8W1XqOYz7k(m#fMzS~WzLlI{F+H!^=u)YBE5(qvtACyvb)agju< zp0K)}C&Qfc0UMOc(CQ7>j735XlJd!2yhTlQdLqIWUKD!LKf}D1cW2LIIrb8WXE$Aw zwK=Ys*oiYvWPVfQRSUs|7#0_hCZh)In9XdiJ#Ip(Ca@L)tg!T&KO;qWwGbWSN*Fyx z@&r{hT}gjkU7p!bX@NN zr#dpzf>}#iQ7GPkWf9Lp0kDBXWdL7<)pg@#Yv4?rs^kN2!qP^|c25gp6y4AKOY@OV zjtmcB8`2nD<3LFV>RUHljR0hOEHQhOT&eWW8i#*O^%N|;J~)`8yD+TjHW6UqHh@JO zE%y;uIMvX4p)L8So8__$i-sY3+Rp~Z8|!j*^o6u-ONm2r#eYW9o1R@tD3DpNRmNNv zKX4>->2qN>U0o7o<;abAOB@ELZRH))QJ?}1+Pe%Nk5WBL1`)Q+KXYX>QWg*KFAE6L z*vfz4^%FuEOB06ZN!995qG+k=bjyJS<1SoCgtiwE+DHJNF}&#V&25jDnlG!PKp22l zM)VS;=oL1V*V%$)3Zi9kKy%H>g5%~~m7t>wylE@r|7uh-!HI^Gr}w)Rh-1csb?>*n zH^w4>cK&B?plm4z-$b^4HNVh*9Cd=Q%1Id8fGPWVdJ*_m6x-HedKxDazn(s++`?|d;;wFC{RqKx5U6(BO$XH7``g|b{2RaN%uyDhg!+HrPOt9r zH1H4QR~SdoMA8tG_e0q=&{UBW#xwW&M6z+nq{G|spM=xGBxmb$3zJL^I*vQXYJ9GD zze2L5L)|l1VH*xHEDfHl$111O9HPw;a-!gU2g7H0`rtxmqgF;}1qbU-gXQ*^`4Kkb zUC{EORMNeLltQ$aY5(Gvckg-0Yo9{f&6}gv1R}0u-@Q+IJuYs}J9kv?Z2Q)FgL)4TF){l`4roM!q z?e54d?_6j>prC)1FQBR{agkoP zy8B0DP*t={`_L+=v|a)F{=#Cwbed0pqAl(7;Cq8|#f5I ziwYNIWaqa9)W~;K8d`q_UuHa>3Je>aw#0{e_!lFrlMXV$&|Kw?Jp9lg-7T+`e0DkQx|q4P_-B`qgGvyv4WVRAJZZx%DzfeP0*j$8EIRM^oisu+u8pq79Lp_c_Z zK5)tK)151s-Xhm6asy_;OLAdL%U)8l2?lNXfu-anS&t3|@OOXF{``ncRJ2C+C$a2! z@!12(p8?B&vk?W;N3lPd32m`_)EpQJN)9im0{k4ZQ`-WDbDxOPv(MN8`-mxG8*xqI2YQ-MPN*$pQ$Oq4OTQ=M|_KoTm`gp2UIhV&_;`B360jgo($MgI-a zoiQE;UY$}w|2TgpatK3NHd1*$(PfQ>5WeRGeD^U-ioNUKWImOLy12tBPVm?zQ6Et` zX#MfrJ_eFIeLYuT|Aki@agpfn71Wn+8eIjQ0RDQmRzmU}A@6kO8j`}j5LdiLrYglu zFQLK97Mhvh?nw*$E67WHd4baJ7)sxwh15)q1gNpjJv4u|tXR5iZlSMOvQmgORqQbE z9&gyZq$(of$f=LAP&j1hK;Db2zp*UO{kdVv6hk^mn zZ^n}tBh!BvI3xmBh*u=qMTXmwsvC?}84XJnA8f-A!g61vL2NQ{^9{5TR5s!HJ+M^y zB1gMUC~ctTsHq1pA-N3-TZ#B#iB+PBS?dJ0?#<+vQ53JUs>Bv_p%v9`jdIZMUF`#k ze{TMw^(n&Ho>1`=5<><2Nekb~fqWlyy!(Xr>jz+i72}#v24M`3Z$W`6HI+JR0B5AC;@)YEti#Bx!;!m{8O-(roe=u# zB{zQ;E=In{$$VRPk@iuY}R zs4@i`_wh)36lPrlFD1s9LL2NiVud}7B+?mfEPkV^kLIh3qJl(6kI|1)#_$-uB+Nhb0 zJnf=~6xa%da2xNoosr{ez|kVAB?>CcV3@Y*sp~G%5-+?Ktzf8#L*)5l(}i2elbe6~ z6Zfho7zCo(f_1{y@!x@7qm(^0)F3~3TVDaj(bY5M7m*C<(5{KyNij)(BQaO$C_QX3 zNYP(Ccf4A^I#dOGU^AOj(g)w4FBVKqmFHV z(28x=F!hm2L9k~JmBI^VwOz3;5-FgjcKk>)O5e|C@{vYVRL-IvcruRUh(bzPF)K{s z$P=f$Ac-zv-F#H)e4&0dM0dw37GNXh@C`)iLv{OraDY=xC7^(G<~5j-_WTDVev zTW9wcgh=@~*QCfT9GJ5^(Jj#uupQ7XZCouxW;&voi(AtILCP*F&-Pys?cfg02GI2C zRoHy*8AwLhY)tFCTmyyjS>Atv1{>-Q9P$ntvo-E~-s7IhKUg9i&eJ8|cp<*K*NE5m zPOtaVNUPx42ywhPEJ@Q|f+^2#I7+j0_t01T70mr;(sTa08g zalX+0`N;-;KR*3w?m7Z~k(H0UvqAdDVPG>)TN*=KpU;K%tI?uE&ou8=h?~=g=9%-k z8bjmtB-QiWA-x%`x@M*Mu7c2=dF}m~JDcoRR+A?)9;MY8IdPLB-A)8@W4}4gT*+#S z-n}{}4UpwJ4mqh8%#D9M4Bh*Kw|li39Nl8>sE&|H9|z@*D4c0FDVK#qmFmM+Q0-U8 zjoF~!>3e1lLdkzxN9pyQuHlt7oB2Aw(zJrLcF^}wU1T^y7zi&fYR&tey?-IN9_cy4 zD=86@tt#u@TBxMwkfexPD0-Gw)tGuSd5vm;>80Z^;RlY*j4gi%NF_X(^C7pvHbALW z7R84**Oee{rY)lr?~yWp`qrK4HG_6VMxA|pAs=c9ssmQVg$0FDUw2y)DUguG49Njq zp|V2bT(QO$aMZ)`%UfB2-?{!Bq9$Yqk^MQ2tVv&@nWJ9I5xCMadvXdRmx-*!FHeYE zoN=zED<~PqfJ}dhb=T`hq@$)PM^h3`EnBT{S`co^^j%Oob3wQm?+>gLb|U;3{IHdw3`Y za3y?c3vIwGU4XUCZlzgZ48P1|H-=YNU^!E9oUKy3fjHAT?QiCiAYcL}_?^S$d^rNB z;p!V0DbHc?VtQ*Ame3_vcJxC5!hE!A5I3rEq!C*~9I9JVz?g0I3(CA>;Td!ubS?0y z3d{hy58i+Me)RRYX>@Y_gT4siI!Q{XW(Z+u86m$P_RGI#wB;mHO-;@`9~W>fvamat z6m0E4NzrR8_LB@##Z={CYC^iHa79se+eSUy;NR#U{w;j^=un68^pSwaHBh1(Mm~($ zfOuo`nA1>pNVOmbY(nA!mU^=-sJt#e(%Lv)eH(v(mLFf{znd`Z7RJ$SQOg$a6hzHZ zqXyr4`*-`eFaDN^IMG_x)kGgJP?0_O;T+2RP!kJX-_d_~)tU(MR^}eF{72g3UY9n8_DhM`7HxYi zAZ?haljG{DNK5k0cUF9LrEAv!&%OH5$uZkvpv2Z=U;CLEd*f>p^%id0l^uAGs4y2M zAYrU z37*@0vr@*Y45&cgS(4-tneYt`z!s8I_DBb?=YR_XdP5gTWm&g za6&N?2&+ZEAk5xtNR;*^*V|v-LZ6>b{=mq;2UM<jxJIcEHP zB)6Jtrizc`YFnc@FDsi1ps^!;G|9F0@pA0g9og~Si9ECt;hfFf({!0J)-6_fXZc)tOdb3^2L_?Lb=zA6jg{?Zjn zqx{3aU|`59M={#&WC^Efgw|!wDJ;oB7@;9ZIq8WCvFOr9meqS&r$QjTQnJ1Y8Prtf>lfDHq712oXL+fBOx!h>-`bK{F{n$9pwq>(%q~t$m z>Z}$@l?)PD#}*-!RGKdHS6=*EI9dmUY?8vrSCN&@k)uNyF0RAqk$Hd5FI#FVPa z_USE58can$Qo`q33{wCLQRJgFehu1&Doru50m14M(XIl!i+^i?@DA$()BgJgsG<}p z1tS_*DBQS#H8eR9!Y*11M_&m(UcO)aDsb?liJbiLlG<)s2$h!PynJ(f3T~k_+t&4I z=Pf7T!e*~aI-vRZ@*eucfa}9h%Lua8aTFLIe z{deHV?C+jI?o4xP9)|fSRsYHghSdPsPyuM5rf4fz0mfh=T$g_-=CPxQ#?kI+rz#Ep zkTUOGF2*sW&HhApEm61zFnPMLmabuo;09KButpuSg>)Vv(NMM@G(hMfwT`zxc#Tx- zUxM_Ua+}Z|ghTE!i<6zP#*mv%UeJjvVi2v_|H4`5NyN`3=j}3CdA3?n-$Bll;K-hG zvDVXPe~^2p(zkz!Tj@EV$O;vXT<7z7oJ9UAb5>Wo99iX6(I)C3?kQ->qv#5-D#;H% zPS;qD>Ygl|QmOT}MBL$w$Z~Iwd?=4HEGZF?qS1dB+P;G0(yBlzJewbh!s2V_F&t3i z#IeH`3?)ZJtw1SDB@L$uQ%J*Q$%q;wU3fNM-e1Tr=;wba&F-J+8KUG(;h^ogOC9KM z|GBWLR(-s+iaRTRRS2aAvyMDtPN_k(GkADLMY~}Q=sYXYp<(gNqK@@2wl|?NtN-59 zl4$p193iK%8iyXwA_UuTOY2cnT&%=|E5LHTIiHHf>cNR-^&m~L|L0GL{WQMfp@h0x zT~`ls`!9cFD40%a7`KmenduMu#Q*8}AFE3gw&~IqE)x5JybIWznHNnBvi%nXHQoh2 z(j(6~pP9 z8+$$@bkhmyF4uCf_STonZMi6f?i7fr>2#j>+HI$Vr6A-+)=^GSF3dW13o8b)#G{iY zyEKL(Z)>%N*XNLK)H?13ic zygDtDJQv9auE4|1^HOet$vJh7kN_u@0Wz19JJ3U)svkz{93vRwz#>*fiv#LkBQJYN zbrnq7h+K}#Z~x_O65=#y%S77$Ce(YWjv;^b@)xKoW?mR4D{%Box5(@v#R6zqB!-a7 zS_VqWREI_&GAz?<(d`}|v4GG{CrvGh@byP5sI*kv+@+K1mI{X|2<0@{K}=B3q34z8 zwRUhu^zO@H*1=(IybjrzLi5-z9y~(wZbDH(t0!qeu#Zb%h&)8)+WN)Rp8XS|0knU( zzWXCcL4od1Y-qh9L5%zq*b&mbk+6*BxUA;?$}b%cC7PJxK{5+zQsYn{2zkarg^5!o zjI55=IfR*xK2)w<1*zU2)#Gq#Y*avOeNwpyXS*88mD{=%Riomi^$N;`k5`UasLK~LzAB2XL|N~pJ1<6Bu82M7u>pJ*NC zic7Iy(@UhIRp>S~_&kJ{riL=h)Lc*wzq)P%60=g8UJ;e3F~WLOs3u7@r0_Faop}Pn zh8KxlXs);|fX(ZZz1B^DG-Gz^E05P=DMGe@4?1t!-I=<=VhWycmDotxTF>^9OoOCmpZL>mkM8fKicZUvtM?u z8PtUdCT2_I#*;%Z!7K~@e@lsxS&nk zr+9}=tnLa@+|<3b!jEVs)DD?nJf8Cw&z<1N_#cC$ro!vY;PSS_<@_a z@QDGuV}r<=Wrm(~qrzpbQOTp1{w>fKg)NHa$`L&i$7`@-p^6SxcjK6MrYSRKJl{It zT?(+c7SKO@79-do$Lp*b3O3XyDm%>{pr^^%&?(L!PY-{=dXUROa_YRF z`7!YRZ``g8FtP(zA3}+FoupFlq5hnus7l73YFwqu69P6%g?KO*Tsph*@N>ncYCc;% zEafgsFw0uJIaip$~ggwW&)w4AOxTA~Dytzlh0l)QzDB&b;K^_E343 zFDcr$u)!Y#EE#R7Xrms;v55+CYVAo71jKpy)s|3g?zeE&%}-nxW6Py zB!8PNL_9^-;vS@N)RMv#!7>8bO7TkwT%UWde=y2TV;#|Fe6% zImkrkBs`RNBkvj@!^Vr35UoPX6d3ZG`)H7(^-thFnR!7h1Yi=m zb&W+0L076`?%-&tGwLgr(J5i!3oWtaylC5iv02N=@#3r^UCg3-xX^A*ag>L|AWGN; zg|6-v$Ydb9WqSI{=gvl!PKzb-#nzwga2bDz58pz{C8GBS(W92#X*Ec;9_QsheQ$z8 z#n*$&t1INL>(9a_Bip>9O{fvHnnhYcnPLMa9Q7#LXe{}V-J3|H)H_;yQQvF+WqJmvDemsDc(E2|@#1d9Dems> zTC7+puFu}{e||4MbIqLO%6wmBl1Xyq92v9ac>LV6*8wbU)G&S5y0Zgs*H%#FZi~fy z&VKv-zrQ439z&#kpQ^2+mg1~oh$K(!p8K(0@m&F+F7@nI(Sn6kyos(PHFjntyd>Y? zlo}dZuqel86%M+}6NUq@3w>%MLCoe)4@{>%V*wU#*6aMVSD-XMm(`; zLW14ck~zGx^}GbqzK0&u?8?>K_v7R`7bNvIE`L7OdmaZpy86q0t}F|aJXE;f=M_iI z17GOKsMyni_$wg6xomWL$LGY6=d^`6=#kTs=`Chyx@*LkrT>2C0Yv$M{{7dHcZ<;M<$|2?Rj*oG#bB(LTJ3czpRYe&Dr*L9(0! z`Re$${S+z{o+g{$YA0HRQB?OI3Tn`vb#^rN(B&zeR{lMcvMSf;l?CInXyq6c$m26) zqF>DNh3a9Y!2M~@9Mff1FQZ5I1#C%pxt5)l8F0#XDU=eO`jSSySlNKB;oZZV!Qwkf zSiAO-mzx8#8l)OR73_0NrmVs&;+pMpBdv(P4}NU$+X}D4Khh1($m+o{XH<+MZhU6r zTo!VTwj2GpCBF3Lry9zeXSt0oIQ)UPMV%Wp5tYeli-ff2-^*#zxlK~cC5d=r(e{Qp zZ+K!{7D0@=5;myvyOHG4lkfX4STJRxil=2#3oQC)!fQ1vQC=!tg~#5c_P&J`Uu=Q2 z)duv>ig4=X>j85Kf6u>gd}m7{HSwQoksq(%9?TCkw91{y4evyudb2y7-0TiJggg3m zM{rEhb?mtgbKWXL)eUn zf2ml#3ouNim?1zal3wdcm&(yZE#=K?lLQ`$d?Y4qC5Bb5H>r{VH>u0kM2+<_rsXTF z=5$Zh(=$1=HB|5%;fTJ%_P&J^VQDv2Sh;~K>kkLCU>uR~49koSU;609q#D)7`U(Um zmQPR6fAa3}P&X@EsL4yN3@AnSXZ`(~thvMj>Y3KKx zze&1fo*YguOA=gbL+HzJboC>^!$QqXj+%b0MrE3>_Az2+`O<_uVB??F<&I3fZ4 z+09E&C?$3O4Kw#C2L^CEx8IYj=w&mf2|zIAOx zy1PhdkJFKih9lGMpE<6Z8kR`y<^Gu$F~DMD{)8(lwf~ui-~}hPM$B(KtZFtX%9iX? z1Dqn-w2y>v1Etq@X7WX_Y;)b`jgda#mNw;IRqRLMBs@+!>TH7LD$TH1F_TAm0Pw`M z);G0l+$LMbF8erzn|z;3dn`%UsL57I-#IL0r*IvDjsixdz@D?_J!h|=B9V%4bA3o& zYXf5()lQpxG^;+Y=m^FzseJAZIW$2JF{#`@d75X5{(F@v*^-Iwb2LLgpIYsSfe2$#ONgZ0nAHEsDTP*_hJ8S@9h5J{sg@4Y3 zTKO1*thPsQl|$=E0%4;C3;IiD8j!Lf)JvNr_Tlm>2PDWP`kCV~>)~hG4Vn{ew=PE* z@b02fNdS#N8x`<+AH~(XN`B(_xxKVq;JBt8V3#!)Wz+5MW5KWrXl2QCO=QE>vC?Z`?MI|h#i($s)l#`tt=tksEMx!YByNM>*&a-a5q5?Oq0IAy&-4oks1$Fx z1oz5)mrFqd{(}eFU-%d2*H;^jCW{HFGBTeN?s41naT_2=dar>VX{$wH`$Ei8O!>aK zagb;Ff6vtkr(&T!FZ<3UUffU`KCAKBbytK{$iDd7n&lYp(!k=3BobS6Tm!E| zjBHvImoAu#)_A}8sD`@UGzmry9vQx59@WjBv~oJ?Vt~s$Il_*NIJ5jJ7^#K}mYsE8 zm{Kn_rBv^8*W9xOhb17Nbm_-qRTyH39fHy(D0}FsRF^1f>KB<5PIV+c9fpnC6)=hv z=6lE5sH#DjT%(fsu=MH0($}I{ZfJXL;g~>NOE++%-|2XGSxP=nY34t2l?6I6Pw#I2 zU_DOt_6&it2=uY~<&;yPXN0E#94#FideW6wWx29L^2oEP39&0hs@8Ir*h znrkBLv3zBgbY`@o)=l>#Jm!OPL-fGd4Puk1Y`T#VPa|36$tg!!<&ba8``^tLCGiJU zt1rW8!{QJrG{(NAmEs2c>e6e|7L9hcCX6#RaW!sG?--bV8xKdzz*iEOvN)P*a z_3-|;m&Qkz$t&PhlOLr{i*?ZCJ$xx7qVLImPkD;=L=KGacW)OzZyAI_^`9iBz}P3iO0m=lQXXE;;MW0t-v8WE6{@GCDam#bijl#VSwv4jeY z%tM#|TuMDv*plxXWlb=ej6!&OX}w5XR9;Qz`A~g%Xn|JC65POqrE*Gp<^Y(~lVu4yOk#wpWuS({~pKuhuG^qe*Un6W9 zG}BmxJ?8E|dVx`Ee|dMclT(WPdXfPKzXb(64FyMr@u0EcE0cRLxA#Z(u#+sm;_DrT zvQ+5s!|cP#(F2}vbo*szau?s1q7u_cL40h)4MKnvEH}Hx*p{%F9?oZl%l;I-X;dml zPPuuP(3O6Q3+2cOAaVFC@2}8Jzhd?aTXOzBwxHO{hA}iwRK!J@c14-I-a0VagOeaF z`vWOjIUWrMC_Bp3%h#}%oV<5HS~~TbfK#XjeHPWgMSRYlkKd&)F2LB2TR|~ zSl*v%*$TWrY!}rtnZ>Ykc_Ydv3p@E0mH{jkwtQOUa~K3T5ho*k;suXPFgLG@=F#bB z>}a~hn}l4eCK-3=B1 zqMZg&r|H2B^aWEF(5Qz0-rC;xtFT2%xLf0_QTMCT)_)_&c-(H{5|ogwd#MzKAdIvn zM}!%*too^l)?fW-We3AotH0tXV`VON%AlnhANi!hSVYb{qR4To>9|G>ef;&C9q`PA zz)&t+q?weH1|;s+-yl!1o!UMPaE2EwP`*xy@bPl3WQQq!b(vC>U3|zCo_{p*#k5n*DnNdVK4PPWn8opKii5kpD@YI9?iJCw7>pYbI zv9}4>rM_ZkA%fxht6!A$%1{VQqp)lVnZ}AEMLdd zycjV1rX9hKLg%VdRZPOdnoM`~D=Bjx#Ob$K=u(K4pCDI`mX#>f;}%>y%Njtj|L(c1e+9{`y-Ynf#{ z7^8n^cji;twtXi%3ym-zD5LUK4AnbmceMe+ zFA0IL-oT6SuHhZ^P3+Z3!z)}z2$v~Q2GwFJ^X#sm^$#Cds{W0w?OpMcn&*UJpVMl0 zYeh(aM`H^W7!>6cpBbZkI^1Mab8(4O=p|8qj72uyF;z24l1;6)!+GAe_{-CmP`;dy z%j4OwJmy-7{9|I|Oid(kjL-eua@}isP#p9o5C+DuxlAwZIUD1&w=lBu-a^QTF_aFm z2-*IWu@ISW^3IvAqeAK~m0xQhDFZAD={-aqfGI6yy5oOx8|HH>D(4S)8YG9;?@$w) zseHzfO&MCI(p)uU-)%mlu(Oibch6bfhHXF$ZHS#ollDBHf~bK!;+8x63!d@Mtc%jx z%D}PNF!H006c}jUTPb5{1io%&RFo#+5&j^T;bPfX7I)m`8rYc!X6hI~VaR%`+Jslj zpeyAH8_?#0yvBw>Zdf%RC$%?QNUU&H7`LbQexc116?IIAo#$4)Dc3n699jqHgH zNsegxRM(Zo+4tdsz!`189Vku1v$f%m2iD9Ml45pL{KK>Hbx5HeQ88KJkPMYlRc(8A z^ms$%;o2#KtK0hwSdV#{Y>KiaHCNeYTJX^T^uR$Xk1}#SezcG)KGdE9h zdwH7Za2ohC_w0w0zrqkAdD1b4lIrKYGNdWMD$eIvjd_|Q#qc==zu13O6hp2ECSP#S zpf-LAYcun}RKY|lZ%jal@Cqr%08bxT^?k16yTDf(qj0+_6~|R)7X>Dt7aS4(ERa^J zfdg1FrP9KCi2mFN;XVmP&3^`G=8n0}iR(DyS1aJoZ}SI7tfeWMG0bEzsQv)mD9q5Ip-|FyIFmr~j0+^IRaUMrm zs;H%?;G$gOhR4a375C{Itv;}Lip5sbVdq$5q<@I}XSe|xf?cm~`nUWMA`<4Au!c~( z2G?Ro63nkF940*#+=v`a9!t>vH}6796qcsAKMptMx%#vZ$ve!ybZ|ZvDqG3^5MGML zXNjHfDlMy(?)VArgnP=E5C{Lz<{`y0iyH`vytRX?jwp;M3en=vA>Oi45gM3Q6RS5D zHe{AXO^ulaTaW|q9M3*a^e7Px`HmH>0_4r+%r8;fhbz_#^8~y~d8_)E;u$uPmeh4f zg0w7(h=|}nqD9!qS6A$)Vq=GTRTZ<5!I{k+ItmFLC2qr_*P_q7Re{}Nyg9!AA%;$2 zcAW62nt#*&R`2U_Z$;wbZHXu_pWy@aM3Z`A$%xont&7kKq|$uX-W)^>B`sOK_c{E_BT!dB+ZWt(>iT>Gc*y=y^+;)nv~T$eJF&!AS;f!cbF^~H3}$&f%u$=U zma5gADH_0F+@SItdS0hwkJ^8Y=T?2|CJGUjOXdHPEzKe5(KyjrNEns&P)nJ^YIqeB zh1~9Lk>>xTGEdAiktc>x&eI| zd19u!*{^^-&Za_wb(o^Agy%A&yVR5-=cL7(LV40p7Z-ZA!q+Rw5NE-xt1}m7EOUf9 zLN9(^UqrnrHOH@9QZBdc7wa#+7@zj3!0bNja?g9ZDRP5?1gLeQnU5)c3egt2pC(w+ z=Pwo6!-!d;@&gZ-=6MH8z4)&%z2|Bp0;Dltci{eU;L(qXV4=gbg*BAWfS)mq6lEkD z`;13+=U{~8a0l-63iUiHaK&VA@RvT+2XK^_FtOl?H1dwM(j>ODMNS@{ixzX+QUS=?FKFG>3|(aVZw=$OP=G z+OdWHY(f0JN4UmzM8T2GnKpigZ}M9ByulG|`>pyJ!-@jUVmkX(virW&`Qhktcwh#C zJ&#pC1LktW)s21twNV zadb^jHBg?zz=*G2bT*5pkOf&J2-7}_v(F{?5dL!vJ)wJZcUIg2RpOt^ea?TmJ<)9xx{C7{xsb+)|?I)$5=NRR;@p`Gw%1 zqL1rHi=^4V0cE1?j%ut3e{5u@*z9d2K zBw%IRa!~fNiQRxdIQQB8$UrUwb1sm%R13~0jYS)!*3rAj89Ngjg`wZ$>jX?@Ef^lB zxwWmN!Z_cF^$sQXEy&=yt}hL!4dAH8LR@YoKu}$ z&Zo`SJo>P#b(fMyyU`=RgS|tJAH4XIHLs@~z004H2Y<{XLH{ELwo&X@hmT+d>4RZ~ zm^4#HFc%JV_Sfpf2*a(vRkl94o=H^bo&q)F#R)sh&txvfu{!-FU-_PI7`jQ4A*FoYHg6Kh`dbcg!YHR|09j zNs{eKZrhrcl=|{`Kl;P2+~_1UP04&AaxYUiti~?Lqtf});aiq>7%k{CJ^*1Ep!e{B zr`@hTci|-Pb2>;bSwtz>)LuKGhii=N3Hr@#!N&x`(+y^ByPf4g3pbkC0D||CijEc} z>{Wal=j8sv-sJOK=q}zkac#2=;1S;d?9bhoUh+PjGRE7nCbC!bv^JK zFJnCf{Hvr5K?ZSPKpSJPj{4gUM{_yW*oWkO9UNc8(p54qiO$0}MWsd6(uta`Nk0AZ zH74GV^CScRBoy{zV`y>clr=a$a@UV%(ESGWbXJbY{TmHm2+vwrp{v!~9|c8mU~4;T zn+uRD0UO`WddeHQQMtyYQB_wq+0}PS0)jS<&3H5Tq~3VcOu;a`TR?Kk89KvO=T5bv zET;oa^gi%!BZZ7(=@%*#IRG=bIV%eae0;3f%l6|IB&pfM!ezMF?ZI-K$*KyPcRk1W zuvv)%ELJyd28uFuGv6dC;E?Rkwk)D`)MatR53iN z2E-@TScf(bM&8xRJQaG4q=$~v!l-S_VsXpBCjz3Au5d|htJt!YvzUn$r1Arbr6t;1 z75f<_GUL8kjk#lTBQUK%ikrpkqPCtByv)0n4O6p20<9Ascg>uekW*x`A=XzW{(ek` z9nI!atPJ)1%_XF(UCuCfUu7p}rXFu=yGW1j14!xRmkznwLJHn_W{sij!6)x>1$|ec zb?99_PjXhS;&%jMVK`ZU^JM=J0HSW%=CQd-$n$P?mK~SidA;+-4HT`z_Ol)08og=F z);a9aYHVIc05{TnUO1*FKLo@C(zIvEfQ?9vMw}IS4+-Sl69c0)<-263FNxX6rC6yz z&Gx)(8}G?n0)IkSs4kW6BO@YI$#LM97BLC2VC&R)SR*A ze#64mqv47u3)_*|4eWd~mp=TOquJZ9M&3Ig&#47)+z8`?p#^QGAsnT}4 zLO4>dEi0c6kZM`~N!&r!5v7|4TP~FheQK0V_k z?&KeWNaEN?_2unD7RCVsy*N&|1>6At+F<))p7kg}O-bb&`)?Z7EzPS#YZ#A63{`_G zu%A^7D3F8N32UNo@i89JL8gd_uavJaJi=VUBAodId|AMD@toL z+{V+h1jfvk3N%*#YUvrm3h)hkfD{zKJn>sL5X-b%u`mBJi`1*h2)KTH^3wQ5+S}pe z_?t*Y&xt^R1HUw1Ng9IKpBwVY1G9Y!@M9?+s%6@&*vB2PA6;sE6~CybMik!DZ-izjZcP0gq?@9s9#DOe2OBV2 z{VP)A+MKQp+!6IQtTfTLN5!SL`($Xcnb=0g_0yTEU?fnY`w7K7aM0^=_KorP$8wT( z28w6=#FW_w0}(4_lN5lWyh5hF65|M#;fXZk0K!L9FEj!61DQwfAc@RmV%U@A?bpJc z?abkr?<|Y-QC;d9NeS^AaAnX=8DMENWT`k6*ANM63BGz5{W>jPS)eiIze*EIN7V8x z>Ct-iK26)l7kJ+ALScm5KY5^Ini#t`iS=_A$e09(W%5#c5B^UpEnfX_K-lk51*Q;3 zwL7|C`0+l%YZcLC6KWnNeNM#vdzT|Ndb>_F8kLmeNO6xre<2CN!YdalZE*NxDzNZ_ z*woUBkI4uM;V2xrnpXQ*LIZ5xy5FMYPgqwm()wUY9d)9u!|(7P9mFj@kAClQa_Vh? z9~qe&LS__W-PNqdPqyw6L&c#|$BArNDOJ*X)Z%dbK+mJ=i|4sdth-jZW4ZIa0~vq_ z8ls9D|GeZ~Gk~+M*n$dd8v;+l=mIK=(tW%>vY^Hwv@Y=qv~)BLUmj?gQG_orB2_({ z{zewMv&TZl|L$aVU%w?1N!RTCB!&>c;4M55`a;m~EI{>3s7lndN#qnp*Cbm4H2f=D zYIbvGs6H?cM6=R18h(7}i_8*WBItRx*17=F^K5r=4t#>~dNXVL*$H+?ZP__<3>~kU z&{bdaQosG%obUaC%tO|in&-j+wrO|5(lO2f2gYvSDh1be7k{qO5gIKUjEM}55~$84 zdedujlUciwZ6<(oM~S2l-_q0rke{<;xw;wbZz>VS6XBDN^siSd+1AEA9tFS-C*Npg z@k4)&)1}~!vSG2`ZvZd0y)=Z&XO$T=1;q}9iJB+b5`cFOl5qqD) z7Vc$S9*Lz>{+gBkHPZ`Rc}1KkCxz`Z)Q=OX%2$pDAM}DQjv-+3pnDGQ_yVS4r?Lb1 z5uDv336iN0eu!HRtOY4?h(kwl$#R%?6#41TmM`O;d=itS#GN6z$grdBlj(HS&e2h~ zKnCyhZ`j_sdw96PcVa6IzxY*eo_wP>iWsFX1t>n;deAcqp15QAil2|YLDb7XG2tO= z8?tMWC&#~VtWkjbMnAg})>kZfR@nob4U)uBxM^7ndRdKdX*SD|;&L1(Jw=lEc2M

    pyHCO9+xdulOosp7_rW;%N7|hCcOQ zBSeGHihhH$l|XOD`Zo;JG@yUJk*;?*6tRa@^XYbN^}#|D??^>i{uzTZShXm4q{4r~9BLJDVus{<^y(h4GY3_n`mAch=Xb)W*l?GO`WLE*v zx9-)uRo>7-ijG?}+(D~=+yMQHZi?r z85&kd#sm!s;F=5Le|1}n|Er%t>u@M0kPnkke^wO4;6HsGgw*_}A6_7^Q_$nh@! z=iv2!zSt?KZ@>mp3f&Hu9s_y$PpNVtD$`J%T!iF76@W`Y@;{&3|6d354AcjRg~-l8 z_q!c{Wc;VH*O0US)Dj&cHcJCUH&LMapU)GbK10I>8J&eLf4qwNe`P-#2=zD(1q5S` O1_P;Qj0Oe<=Kle)t%Fhk diff --git a/scripts/daily_plot.py b/scripts/daily_plot.py index 90b517c..7632aed 100755 --- a/scripts/daily_plot.py +++ b/scripts/daily_plot.py @@ -1,9 +1,8 @@ #!/home/pi/BirdNET-Pi/birdnet/bin/python3 -import mysql.connector as sql +import sqlite3 import os import configparser - import pandas as pd import seaborn as sns import matplotlib.pyplot as plt @@ -11,25 +10,14 @@ from matplotlib.colors import LogNorm from datetime import datetime import textwrap -#Extract DB_PWD from thisrun.txt -with open('/home/pi/BirdNET-Pi/thisrun.txt', 'r') as f: - this_run = f.readlines() - db_pwd = str(str(str([i for i in this_run if i.startswith('DB_PWD')]).split('=')[1]).split('\\')[0]) +conn = sqlite3.connect('/home/pi/BirdNET-Pi/scripts/birds.db') +df = pd.read_sql_query("SELECT * from detections", conn) +cursor = conn.cursor() +cursor.execute('SELECT * FROM detections') +table_rows = cursor.fetchall() -db_connection = sql.connect(host='localhost', - database='birds', - user='birder', - password=db_pwd) - - -db_cursor=db_connection.cursor(dictionary=True) - -db_cursor.execute('SELECT * FROM detections') - -table_rows = db_cursor.fetchall() - -df=pd.DataFrame(table_rows) +#df=pd.DataFrame(table_rows) #Convert Date and Time Fields to Panda's format df['Date']=pd.to_datetime(df['Date']) diff --git a/scripts/extract_new_birdsounds.sh b/scripts/extract_new_birdsounds.sh index 029edc6..651b723 100755 --- a/scripts/extract_new_birdsounds.sh +++ b/scripts/extract_new_birdsounds.sh @@ -61,14 +61,13 @@ for h in "${SCAN_DIRS[@]}";do SCIENTIFIC_NAME=""$(echo ${line} \ | awk -F\; '!/birdnet/{print $3}')"" CONFIDENCE=""$(echo ${line} \ - | awk -F\; '{print $5}' \ - | cut -d'.' -f2)"" - CONFIDENCE_SCORE="${CONFIDENCE:0:2}%" + | awk -F\; '{print $5}')"" + + #CONFIDENCE_SCORE="${CONFIDENCE:0:2}%" + CONFIDENCE_SCORE="$(printf %.0f $(echo "scale=2; ${CONFIDENCE} * 100" | bc))" NEWFILE="${COMMON_NAME// /_}-${CONFIDENCE_SCORE}-${OLDFILE//.wav/.${AUDIOFMT}}" echo "NEWFILE=$NEWFILE" NEWSPECIES_BYDATE="${EXTRACTED}/By_Date/${DATE}/${COMMON_NAME// /_}" - NEWSPECIES_BY_COMMON="${EXTRACTED}/By_Common_Name/${COMMON_NAME// /_}" - NEWSPECIES_BY_SCIENCE="${EXTRACTED}/By_Scientific_Name/${SCIENTIFIC_NAME// /_}" # If the extracted file already exists, move on if [[ -f "${NEWSPECIES_BYDATE}/${NEWFILE}" ]];then @@ -85,16 +84,6 @@ for h in "${SCAN_DIRS[@]}";do # it is created [[ -d "${NEWSPECIES_BYDATE}" ]] || mkdir -p "${NEWSPECIES_BYDATE}" - - # If a directory does not already exist for the species (by-species), - # it is created. - [[ -d "${NEWSPECIES_BY_COMMON}" ]] || mkdir -p "${NEWSPECIES_BY_COMMON}" - - # If a directory does not already exist for the species (by-species), - # it is created. - [[ -d "${NEWSPECIES_BY_SCIENCE}" ]] || mkdir -p "${NEWSPECIES_BY_SCIENCE}" - - # If there are already 20 extracted entries for a given species # for today, remove the oldest file and create the new one. # if [[ "$(find ${NEWSPECIES_BYDATE} | wc -l)" -ge 20 ]];then @@ -131,9 +120,6 @@ for h in "${SCAN_DIRS[@]}";do sox "${h}/${OLDFILE}" "${NEWSPECIES_BYDATE}/${NEWFILE}" \ trim "${START}" "${END}" - #ffmpeg -hide_banner -loglevel error -nostdin -i "${h}/${OLDFILE}" \ - # -acodec copy -ss "${START}" -to "${END}"\ - # "${NEWSPECIES_BYDATE}/${NEWFILE}" # Create spectrogram for extraction sox "${NEWSPECIES_BYDATE}/${NEWFILE}" -n remix 1 rate 24k spectrogram \ @@ -141,48 +127,6 @@ for h in "${SCAN_DIRS[@]}";do -c "${NEWSPECIES_BYDATE}/${NEWFILE}" \ -o "${NEWSPECIES_BYDATE}/${NEWFILE}.png" - # Remove the oldest symbolic links that would make the directory have more - # than 20 entries. - if [[ "$(find ${NEWSPECIES_BY_COMMON} | wc -l)" -ge 40 ]];then - echo "20 ${SPECIES}s, already! Removing the oldest by-species and making a new one" - cd ${NEWSPECIES_BY_COMMON} || exit 1 - ls -1t . | tail -n +40 | xargs -r rm -vv - ln -fs "${NEWSPECIES_BYDATE}/${NEWFILE}"\ - "${NEWSPECIES_BY_COMMON}/${NEWFILE}" - ln -fs "${NEWSPECIES_BYDATE}/${NEWFILE}.png"\ - "${NEWSPECIES_BY_COMMON}/${NEWFILE}.png" - echo "Success! New extraction for ${COMMON_NAME}" - else - # Make symbolic link of the extraction to add to By_Common_Name - ln -fs "${NEWSPECIES_BYDATE}/${NEWFILE}"\ - "${NEWSPECIES_BY_COMMON}/${NEWFILE}" - ln -fs "${NEWSPECIES_BYDATE}/${NEWFILE}.png"\ - "${NEWSPECIES_BY_COMMON}/${NEWFILE}.png" - fi - - # Remove the oldest symbolic links that would made the directory have more - # than 20 entries. - if [[ "$(find ${NEWSPECIES_BY_SCIENCE} | wc -l)" -ge 40 ]];then - echo "20 ${SPECIES}s, already! Removing the oldest by-species and making a new one" - cd ${NEWSPECIES_BY_SCIENCE} || exit 1 - ls -1t . | tail -n +40 | xargs -r rm -vv - ln -fs "${NEWSPECIES_BYDATE}/${NEWFILE}"\ - "${NEWSPECIES_BY_SCIENCE}/${NEWFILE}" - ln -fs "${NEWSPECIES_BYDATE}/${NEWFILE}.png"\ - "${NEWSPECIES_BY_SCIENCE}/${NEWFILE}.png" - echo "Success! New extraction for ${COMMON_NAME}" - else - ln -fs "${NEWSPECIES_BYDATE}/${NEWFILE}"\ - "${NEWSPECIES_BY_SCIENCE}/${NEWFILE}" - ln -fs "${NEWSPECIES_BYDATE}/${NEWFILE}.png"\ - "${NEWSPECIES_BY_SCIENCE}/${NEWFILE}.png" - fi - - - # Finally, 'a' is incremented by one to allow multiple extractions per - # species per minute. - #a=$((a + 1)) - done < "${TMPFILE}" # Once each line of the TMPFILE has been processed, the TMPFILE is emptied @@ -192,11 +136,11 @@ for h in "${SCAN_DIRS[@]}";do # Rename files that have been processed so that they are not processed on the # next extraction. [[ -d "${PROCESSED}" ]] || mkdir "${PROCESSED}" - echo "Moving processed files to ${PROCESSED}" + #echo "Moving processed files to ${PROCESSED}" mv ${h}/* ${PROCESSED} &> /dev/null || continue done -echo "Linking Processed files to "${EXTRACTED}/Processed" web directory" +#echo "Linking Processed files to "${EXTRACTED}/Processed" web directory" # After all audio extractions have taken place, a directory is created to house # the original WAVE and .txt files used for this extraction processs. if [[ ! -L ${EXTRACTED}/Processed ]] || [[ ! -e ${EXTRACTED}/Processed ]];then diff --git a/scripts/history.php b/scripts/history.php index 9da8ee7..c8e0237 100644 --- a/scripts/history.php +++ b/scripts/history.php @@ -10,6 +10,14 @@ $theDate = date('Y-m-d'); } $chart = "Combo-$theDate.png"; $chart2 = "Combo2-$theDate.png"; + +$db = new SQLite3('/home/pi/BirdNET-Pi/scripts/birds.db', SQLITE3_OPEN_CREATE | SQLITE3_OPEN_READWRITE); + +$statement1 = $db->prepare("SELECT COUNT(*) FROM detections + WHERE Date == \"$theDate\""); +$result1 = $statement1->execute(); +$totalcount = $result1->fetchArray(SQLITE3_ASSOC); + ?> @@ -52,7 +60,7 @@ hr { - +
    Total Detections For The Day
    diff --git a/scripts/overview.php b/scripts/overview.php index c7fd2e2..d355d39 100644 --- a/scripts/overview.php +++ b/scripts/overview.php @@ -20,10 +20,10 @@ $statement3 = $db->prepare('SELECT COUNT(*) FROM detections WHERE TIME >= TIME(\ $result3 = $statement3->execute(); $hourcount = $result3->fetchArray(SQLITE3_ASSOC); -$statement4 = $db->prepare('SELECT Com_Name, Sci_Name, Time, Confidence FROM detections LIMIT 1'); +$statement4 = $db->prepare('SELECT Com_Name, Sci_Name, Date, Time, Confidence, File_Name FROM detections ORDER BY Time ASC LIMIT 1'); $result4 = $statement4->execute(); $mostrecent = $result4->fetchArray(SQLITE3_ASSOC); -$comlink = preg_replace('/ /', '_', $mostrecent['Com_Name']); +$comname = preg_replace('/ /', '_', $mostrecent['Com_Name']); $scilink = preg_replace('/ /', '_', $mostrecent['Sci_Name']); $statement5 = $db->prepare('SELECT COUNT(DISTINCT(Com_Name)) FROM detections WHERE Date == Date(\'now\')'); @@ -70,8 +70,8 @@ a { - - + + @@ -91,7 +91,7 @@ a { - +
    Most Recent Detection">">" target="footer"/> More Info
    Number of Detections
    @@ -100,7 +100,7 @@ a { - +
    Species Detected Today
    diff --git a/scripts/server.py b/scripts/server.py index 1a0da1e..7aa6f1d 100755 --- a/scripts/server.py +++ b/scripts/server.py @@ -302,7 +302,7 @@ def handle_client(conn, addr): #print('Time:', date_time_obj.time()) print('Date-time:', date_time_obj) now = date_time_obj - current_date = now.strftime("%Y/%m/%d") + current_date = now.strftime("%Y-%m-%d") current_time = now.strftime("%H:%M:%S") current_iso8601 = now.astimezone(get_localzone()).isoformat() @@ -342,7 +342,7 @@ def handle_client(conn, addr): species = entry[0] Sci_Name,Com_Name = species.split('_') score = entry[1] - Confidence = "{:.0%}".format(score) + Confidence = str(round(score*100)) Lat = str(args.lat) Lon = str(args.lon) Cutoff = str(args.min_conf) diff --git a/scripts/stats.php b/scripts/stats.php index 75c25b4..90e893f 100644 --- a/scripts/stats.php +++ b/scripts/stats.php @@ -3,6 +3,20 @@ ini_set('display_errors', 1); ini_set('display_startup_errors', 1); error_reporting(E_ALL); +$db = new SQLite3('/home/pi/BirdNET-Pi/scripts/birds.db', SQLITE3_OPEN_CREATE | SQLITE3_OPEN_READWRITE); + +$statement = $db->prepare('SELECT Com_Name, COUNT(*), MAX(Confidence), Sci_Name FROM detections GROUP BY Com_Name ORDER BY COUNT(*) DESC'); +$result = $statement->execute(); + +$statement2 = $db->prepare('SELECT Com_Name FROM detections GROUP BY Com_Name ORDER BY Com_Name ASC'); +$result2 = $statement2->execute(); + +if(isset($_POST['species'])){ + $selection = $_POST['species']; + $statement3 = $db->prepare("SELECT Com_Name, Sci_Name, COUNT(*), MAX(Confidence) from detections + WHERE Com_Name = '$selection'"); + $result3 = $statement3->execute(); +} ?> @@ -116,21 +130,6 @@ form {

    -

    Number of Detections

    - - - - - - - - - - - - - -
    TotalTodayLast HourNumber of Unique Species

    Summary

    @@ -138,22 +137,40 @@ form { +fetchArray(SQLITE3_ASSOC)) +{ +$comname = preg_replace('/ /', '_', $results['Com_Name']); +$comlink = "/By_Date/".date('Y-m-d')."/".$comname; +$sciname = preg_replace('/ /', '_', $results['Sci_Name']); +?> - - - - + + + +
    Occurrences Max Confidence Score

    Species Stats

    -

    fetch_assoc()) { - $count = $rows['COUNT(*)']; - $maxconf = $rows['MAX(Confidence)']; - $name = $rows['Com_Name']; - $sciname = $rows['Sci_Name']; - $dbname = preg_replace('/ /', '_', $rows['Com_Name']); +while($results=$result3->fetchArray(SQLITE3_ASSOC)){ + $count = $results['COUNT(*)']; + $maxconf = $results['MAX(Confidence)']; + $name = $results['Com_Name']; + $sciname = $results['Sci_Name']; + $dbname = preg_replace('/ /', '_', $results['Com_Name']); $dbname = preg_replace('/\'/', '', $dbname); - $dbsciname = preg_replace('/ /', '_', $rows['Sci_Name']); + $dbsciname = preg_replace('/ /', '_', $results['Sci_Name']); $imagelink = shell_exec("/home/pi/BirdNET-Pi/scripts/get_image.sh $dbsciname"); $imagecitation = shell_exec("/home/pi/BirdNET-Pi/scripts/get_citation.sh $dbsciname"); $str= " -
    $name - $sciname + $name + $sciname $count $maxconf - Wikipedia, All About Birds + All About Birds "; echo str_pad($str, 4096); diff --git a/scripts/stop_core_services.sh b/scripts/stop_core_services.sh index 0d5eb98..309986c 100755 --- a/scripts/stop_core_services.sh +++ b/scripts/stop_core_services.sh @@ -6,7 +6,7 @@ services=(birdnet_recording.service birdnet_analysis.service birdnet_server.service chart_viewer.service -extraction.timer +extraction.service spectrogram_viewer.service) for i in "${services[@]}";do diff --git a/scripts/update_birdnet2.sh b/scripts/update_birdnet2.sh index e27a8ba..a3bf9ca 100755 --- a/scripts/update_birdnet2.sh +++ b/scripts/update_birdnet2.sh @@ -48,7 +48,6 @@ spectrogram_viewer.service pushed_notifications.service livestream.service icecast2.service -extraction.timer extraction.service chart_viewer.service birdnet_recording.service diff --git a/scripts/viewdb.php b/scripts/viewdb.php index 9175164..7b51e51 100644 --- a/scripts/viewdb.php +++ b/scripts/viewdb.php @@ -4,6 +4,31 @@ ini_set('display_startup_errors', 1); error_reporting(E_ALL); header("refresh: 30;"); + +$db = new SQLite3('/home/pi/BirdNET-Pi/scripts/birds.db', SQLITE3_OPEN_CREATE | SQLITE3_OPEN_READWRITE); + +$statement0 = $db->prepare('SELECT Time, Com_Name, Sci_Name, Confidence, File_Name FROM detections WHERE Date == Date(\'now\') ORDER BY Time DESC'); +$result0 = $statement0->execute(); + +$statement1 = $db->prepare('SELECT COUNT(*) FROM detections'); +$result1 = $statement1->execute(); +$totalcount = $result1->fetchArray(SQLITE3_ASSOC); + +$statement2 = $db->prepare('SELECT COUNT(*) FROM detections WHERE Date == DATE(\'now\')'); +$result2 = $statement2->execute(); +$todaycount = $result2->fetchArray(SQLITE3_ASSOC); + +$statement3 = $db->prepare('SELECT COUNT(*) FROM detections WHERE TIME >= TIME(\'now\', \'localtime\', \'-1 hour\')'); +$result3 = $statement3->execute(); +$hourcount = $result3->fetchArray(SQLITE3_ASSOC); + +$statement4 = $db->prepare('SELECT Com_Name, Sci_Name, Time, Confidence FROM detections LIMIT 1'); +$result4 = $statement4->execute(); +$mostrecent = $result4->fetchArray(SQLITE3_ASSOC); + +$statement5 = $db->prepare('SELECT COUNT(DISTINCT(Com_Name)) FROM detections'); +$result5 = $statement5->execute(); +$speciestally = $result5->fetchArray(SQLITE3_ASSOC); ?> @@ -36,10 +61,10 @@ a { Number of Unique Species - - - - + + + +
    @@ -53,11 +78,19 @@ a { Confidence Links +fetchArray(SQLITE3_ASSOC)) +{ +$comname = preg_replace('/ /', '_', $todaytable['Com_Name']); +$comlink = "/By_Date/".date('Y-m-d')."/".$comname."/".$todaytable['File_Name']; +$sciname = preg_replace('/ /', '_', $todaytable['Sci_Name']); +?> - - - - - All About Birds, Wikipedia + + + + + All About Birds, Wikipedia + From 5c07c471bf60d6f177048c9f8a7ecd4cbfb50e85 Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Sun, 20 Feb 2022 09:25:42 -0500 Subject: [PATCH 038/160] better overview --- scripts/clear_all_data.sh | 10 +++---- scripts/createdb.sh | 1 + scripts/daily_plot.py | 2 +- scripts/overview.php | 56 ++++++++++++++++++++------------------- scripts/viewdb.php | 6 ++--- 5 files changed, 37 insertions(+), 38 deletions(-) diff --git a/scripts/clear_all_data.sh b/scripts/clear_all_data.sh index d4f72c6..7c8498c 100755 --- a/scripts/clear_all_data.sh +++ b/scripts/clear_all_data.sh @@ -16,8 +16,6 @@ sudo rm -f $(dirname ${my_dir})/BirdDB.txt echo "Creating necessary directories" [ -d ${EXTRACTED} ] || sudo -u ${USER} mkdir -p ${EXTRACTED} [ -d ${EXTRACTED}/By_Date ] || sudo -u ${USER} mkdir -p ${EXTRACTED}/By_Date -[ -d ${EXTRACTED}/By_Common_Name ] || sudo -u ${USER} mkdir -p ${EXTRACTED}/By_Common_Name -[ -d ${EXTRACTED}/By_Scientific_Name ] || sudo -u ${USER} mkdir -p ${EXTRACTED}/By_Scientific_Name [ -d ${EXTRACTED}/Charts ] || sudo -u ${USER} mkdir -p ${EXTRACTED}/Charts [ -d ${PROCESSED} ] || sudo -u ${USER} mkdir -p ${PROCESSED} @@ -70,8 +68,8 @@ sudo -u ${USER} cp -f $(dirname ${my_dir})/templates/index_bootstrap.html ${HOME echo "Setting Wttr.in URL to "${LATITUDE}", "${LONGITUDE}"" sudo -u${USER} sed -i "s/https:\/\/v2.wttr.in\//https:\/\/v2.wttr.in\/"${LATITUDE},${LONGITUDE}"/g" $(dirname ${my_dir})/homepage/menu.html -chmod -R g+rw $(dirname ${my_dir}) -chmod -R g+rw ${RECS_DIR} +sudo chmod -R g+rw $(dirname ${my_dir}) +sudo chmod -R g+rw ${RECS_DIR} echo "Generating BirdDB.txt" if ! [ -f $(dirname ${my_dir})/BirdDB.txt ];then @@ -81,10 +79,10 @@ elif ! grep Date $(dirname ${my_dir})/BirdDB.txt;then sudo -u ${USER} sed -i '1 i\Date;Time;Sci_Name;Com_Name;Confidence;Lat;Lon;Cutoff;Week;Sens;Overlap' $(dirname ${my_dir})/BirdDB.txt fi ln -sf $(dirname ${my_dir})/BirdDB.txt ${my_dir}/BirdDB.txt && - chown pi:pi ${my_dir}/BirdDB.txt && chmod g+rw ${my_dir}/BirdDB.txt +sudo chown pi:pi ${my_dir}/BirdDB.txt && sudo chmod g+rw ${my_dir}/BirdDB.txt echo "Dropping and re-creating database" -sudo /home/pi/BirdNET-Pi/scripts/createdb_bullseye.sh +sudo /home/pi/BirdNET-Pi/scripts/createdb.sh echo "Restarting services" sudo systemctl start birdnet_recording.service diff --git a/scripts/createdb.sh b/scripts/createdb.sh index 70145f3..bfeece3 100755 --- a/scripts/createdb.sh +++ b/scripts/createdb.sh @@ -8,6 +8,7 @@ # the DB, be sure to run this as root or with sudo source /etc/birdnet/birdnet.conf sqlite3 /home/pi/BirdNET-Pi/scripts/birds.db << EOF +DROP TABLE IF EXISTS detections; CREATE TABLE IF NOT EXISTS detections ( Date DATE, Time TIME, diff --git a/scripts/daily_plot.py b/scripts/daily_plot.py index 7632aed..096279b 100755 --- a/scripts/daily_plot.py +++ b/scripts/daily_plot.py @@ -153,7 +153,7 @@ heat_frame = pd.DataFrame(data=0, index=heat.index, columns = hours_in_day) heat=(heat+heat_frame).fillna(0) #Generatie heatmap plot -plot = sns.heatmap(heat, norm=LogNorm(), annot=True, annot_kws={"fontsize":7}, cmap = pal , square = False, cbar=False, linewidths = 0.5, linecolor = "Grey", ax=axs[1], yticklabels = False) +plot = sns.heatmap(heat, norm=LogNorm(), annot=True, fmt="g", annot_kws={"fontsize":7}, cmap = pal , square = False, cbar=False, linewidths = 0.5, linecolor = "Grey", ax=axs[1], yticklabels = False) plot.set_xticklabels(plot.get_xticklabels(), rotation = 0, size = 7) # Set heatmap border diff --git a/scripts/overview.php b/scripts/overview.php index d355d39..c8c62c9 100644 --- a/scripts/overview.php +++ b/scripts/overview.php @@ -47,6 +47,13 @@ a { text-decoration: none; color:black; } +table, th { + background-color: rgb(119, 196, 135); + border:none; +} +th { + padding: 0 5px; +} .center { display: block; margin-left: 5px; @@ -64,47 +71,42 @@ a { -

    Overview

    -
    -
    - - - - - - - - -
    Most Recent Detection">" target="footer"/>More Info
    +
    -
    - -
    -
    - +
    - + - - -
    Total Today Last HourSpecies Detected Today
    Number of Detections
    -
    -
    - - -
    Species Detected Today
    -
    +
    + + + + + + + + + + + + + + + + +
    Scientific NameCommon NameListenConfidence
    Most Recent Detection">" target="footer"/>
    +
    "; diff --git a/scripts/viewdb.php b/scripts/viewdb.php index 7b51e51..6d8dd68 100644 --- a/scripts/viewdb.php +++ b/scripts/viewdb.php @@ -76,7 +76,6 @@ a { Scientific Name Common Name Confidence - Links fetchArray(SQLITE3_ASSOC)) @@ -87,10 +86,9 @@ $sciname = preg_replace('/ /', '_', $todaytable['Sci_Name']); ?> - - + + - All About Birds, Wikipedia From 286aa095f9dcc581fa978eafcff634b2e9dc8c05 Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Mon, 21 Feb 2022 16:33:01 -0500 Subject: [PATCH 039/160] time to test installation --- scripts/daily_plot.py.newer | 141 ++++++++++++++++++++++++++++++++++++ scripts/extra_info.sh | 32 ++++++-- scripts/install_services.sh | 8 +- scripts/overview.php | 35 ++++++++- scripts/server.py | 14 ++-- scripts/stats.php | 27 ++++++- scripts/viewdb.php | 29 ++++++++ templates/phpsysinfo.ini | 4 +- 8 files changed, 267 insertions(+), 23 deletions(-) create mode 100755 scripts/daily_plot.py.newer diff --git a/scripts/daily_plot.py.newer b/scripts/daily_plot.py.newer new file mode 100755 index 0000000..8e1729a --- /dev/null +++ b/scripts/daily_plot.py.newer @@ -0,0 +1,141 @@ +#!/home/pi/BirdNET-Pi/birdnet/bin/python3 + +import os +import configparser +import pandas as pd +import seaborn as sns +import numpy as np +import matplotlib.pyplot as plt +from matplotlib.colors import LogNorm +from datetime import datetime +import textwrap +import sqlite3 + +conn = sqlite3.connect('/home/pi/BirdNET-Pi/scripts/birds.db') +df = pd.read_sql_query("SELECT * from detections", conn) +cursor = conn.cursor() + +table_rows = cursor.fetchall() + +#df=pd.DataFrame(table_rows) + +#Convert Date and Time Fields to Panda's format +df['Date']=pd.to_datetime(df['Date']) +df['Time']=pd.to_datetime(df['Time'], unit='ns') + + +#Add round hours to dataframe +df['Hour of Day'] = [r.hour for r in df.Time] + +#Create separate dataframes for separate locations +df_plt=df #Default to use the whole Dbase + +#Get todays readings +now = datetime.now() +df_plt_today = df_plt[df_plt['Date']==now.strftime("%Y-%m-%d")] + +#Set number of species to report +#For ALL +readings = len(df_plt_today['Com_Name'].value_counts()) +# Uncomment for user selection +readings = 10 + + +plt_top10_today = (df_plt_today['Com_Name'].value_counts()[:readings]) + +df_plt_top10_today = df_plt_today[df_plt_today.Com_Name.isin(plt_top10_today.index)] + +#Set Palette for graphics +pal = "Greens" + +#Set up plot axes and titles + +# f, axs = plt.subplots(1, 3, figsize = (10, 5 * vert_scale), gridspec_kw=dict(width_ratios=[3, 2, 5])) + +vert_scale = readings / 10 +f, axs = plt.subplots(1, 2, figsize = (10, 5 * vert_scale), gridspec_kw=dict(width_ratios=[3, 6]), facecolor='#77C487') +plt.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=0, hspace=0) + +#generate y-axis order for all figures based on frequency +freq_order = pd.value_counts(df_plt_top10_today['Com_Name']).iloc[:readings].index + +# this groups by name and calculates mean/max conf +confmax = df_plt_top10_today.groupby('Com_Name')['Confidence'].max() +confavg = df_plt_top10_today.groupby('Com_Name')['Confidence'].mean() +#reorder confmax/avg to detection frequency order +confmax = confmax.reindex(freq_order) +confavg = confavg.reindex(freq_order) +# norm avg values for color palette +norm = plt.Normalize(confavg.values.min(), confavg.values.max()) +# bars of frequency plot based on avg color palette +colors = plt.cm.Greens(norm(confavg)) + +#Generate frequency plot +plot=sns.countplot(y='Com_Name', data = df_plt_top10_today, palette = colors, order=freq_order, ax=axs[0]) + +# for container in axs[0].containers: +# axs[0].bar_label(containers) + +# Function to show value on bars - from https://stackoverflow.com/questions/43214978/seaborn-barplot-displaying-values +def show_values_on_bars(ax,label): + i = 0 + for p in ax.patches: + _x = p.get_x() + p.get_width()* 0.9 + _y = p.get_y() + p.get_height() / 2 + value = '{:.0%}'.format(label[i]) + # Uncomment for Species Count Total + # value = '{:,}'.format(p.get_width()) + ax.text(_x, _y, value, ha='center', va='center', size=8, fontweight='bold', color='darkgreen', bbox=dict(facecolor='lightgrey',pad = 4.0)) + i=i+1 + +# Prints Max Confidence on bars +show_values_on_bars(axs[0],confmax) + +#Try plot grid lines between bars - problem at the moment plots grid lines on bars - want between bars +# plot.grid(True, axis='y') +z=plot.get_ymajorticklabels() +plot.set_yticklabels(['\n'.join(textwrap.wrap(ticklabel.get_text(),15)) for ticklabel in plot.get_yticklabels()], fontsize = 10) +plot.set(ylabel=None) +plot.set(xlabel="Detections") +# Comma formatting for when your Detections are >1,000 +# current_values=plot.gca().get_xticks() +# plt.gca().set_xticklabels(['{:,0f}'.format(x) for x in current_values]) + +#If you want violin/box plots uncomment here and ** above +# plot = sns.boxenplot(x=df_plt_top10_today['Confidence']*100,color='Green', y=df_plt_top10_today['Com_Name'], ax=axs[1],order=freq_order) +# plot.set(xlabel="Confidence", ylabel=None,yticklabels=[]) + + +#Generate crosstab matrix for heatmap plot + +heat = pd.crosstab(df_plt_top10_today['Com_Name'],df_plt_top10_today['Hour of Day']) +#Order heatmap Birds by frequency of occurrance +heat.index = pd.CategoricalIndex(heat.index, categories = freq_order) +heat.sort_index(level=0, inplace=True) + + +hours_in_day = pd.Series(data = range(0,24)) +heat_frame = pd.DataFrame(data=0, index=heat.index, columns = hours_in_day) +heat=(heat+heat_frame).fillna(0) + +#Generatie heatmap plot +plot = sns.heatmap(heat, norm=LogNorm(), annot=True, fmt="g", annot_kws={"fontsize":7}, cmap = pal , square = False, cbar=False, linewidths = 0.5, linecolor = "Grey", ax=axs[1], yticklabels = False) +plot.set_xticklabels(plot.get_xticklabels(), rotation = 0, size = 8) + +# Set heatmap border +for _, spine in plot.spines.items(): + spine.set_visible(True) + +plot.set(ylabel=None) +plot.set(xlabel="Hour of Day") +#Set combined plot layout and titles +#f.tight_layout() +#f.subplots_adjust(top=0.95) +#f.suptitle("DAILY OVERVIEW FOR "+ str(now.strftime("%d-%m-%Y %H:%M")),x=0.5,y=1.5,va='top') + +#Save combined plot +savename='/home/pi/BirdSongs/Extracted/Charts/Combo-'+str(now.strftime("%Y-%m-%d"))+'.png' +plt.savefig(savename) +plt.show() +plt.close() + diff --git a/scripts/extra_info.sh b/scripts/extra_info.sh index 5438b8f..129a226 100755 --- a/scripts/extra_info.sh +++ b/scripts/extra_info.sh @@ -13,28 +13,44 @@ revbinary=$(echo $binary|rev) if echo $binary | grep 1 ;then echo "ISSUES DETECTED" if [ ${revbinary:0:1} -eq 1 &> /dev/null ];then - echo "Under-voltage detected" + message="Under-voltage detected" + echo "$message" + dmesg -H | grep -i voltage fi if [ ${revbinary:1:1} -eq 1 &> /dev/null ];then - echo "Arm frequency capped" + message="Arm frequency capped" + echo "$message" + dmesg -H | grep -i frequen fi if [ ${revbinary:2:1} -eq 1 &> /dev/null ];then - echo "Currently Throttled" + message="Currently Throttled" + echo "$message" + dmesg -H | grep -i throttl fi if [ ${revbinary:3:1} -eq 1 &> /dev/null ];then - echo "Soft temperatue limit active" + message="Soft temperatue limit active" + echo "$message" + dmesg -H | grep -i temperature fi if [ ${revbinary:16:1} -eq 1 &> /dev/null ];then - echo "Under-voltage has occurred" + message="Under-voltage has occurred" + echo "$message" + dmesg -H | grep -i voltage fi if [ ${revbinary:17:1} -eq 1 &> /dev/null ];then - echo "Arm frequency capping has occurred" + message="Arm frequency capping has occurred" + echo "$message" + dmesg -H | grep -i frequen fi if [ ${revbinary:18:1} -eq 1 &> /dev/null ];then - echo "Throttling has occurred" + message="Throttling has occurred" + echo "$message" + dmesg -H | grep -i throttl fi if [ ${revbinary:19:1} -eq 1 &> /dev/null ];then - echo "Soft temperature limit has occurred" + message="Soft temperature limit has occurred" + echo "$message" + dmesg -H | grep -i temperature fi fi echo "....................................Clock Speeds................................" diff --git a/scripts/install_services.sh b/scripts/install_services.sh index 62c6bcb..6116da7 100755 --- a/scripts/install_services.sh +++ b/scripts/install_services.sh @@ -84,7 +84,7 @@ Restart=on-failure RestartSec=3 Type=simple User=${USER} -ExecStart=/usr/bin/env bash -c 'while true;do extract_new_birdsounds.sh;sleep ${RECORDING_LENGTH};done' +ExecStart=/usr/bin/env bash -c 'while true;do extract_new_birdsounds.sh;sleep 3;done' [Install] WantedBy=multi-user.target EOF @@ -152,9 +152,9 @@ create_necessary_dirs() { sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/history.php ${EXTRACTED} sudo -u ${USER} ln -fs $(dirname ${my_dir})/homepage/images/favicon.ico ${EXTRACTED} sudo -u ${USER} ln -fs ${HOME}/phpsysinfo ${EXTRACTED} - sudo -u ${USER} cp -f $(dirname ${my_dir})/templates/phpsysinfo.ini ${HOME}/phpsysinfo/ - sudo -u ${USER} cp -f $(dirname ${my_dir})/templates/green_bootstrap.css ${HOME}/phpsysinfo/templates/ - sudo -u ${USER} cp -f $(dirname ${my_dir})/templates/index_bootstrap.html ${HOME}/phpsysinfo/templates/html + sudo -u ${USER} ln -fs $(dirname ${my_dir})/templates/phpsysinfo.ini ${HOME}/phpsysinfo/ + sudo -u ${USER} ln -fs $(dirname ${my_dir})/templates/green_bootstrap.css ${HOME}/phpsysinfo/templates/ + sudo -u ${USER} ln -fs $(dirname ${my_dir})/templates/index_bootstrap.html ${HOME}/phpsysinfo/templates/html echo "Setting Wttr.in URL to "${LATITUDE}", "${LONGITUDE}"" sudo -u${USER} sed -i "s/https:\/\/v2.wttr.in\//https:\/\/v2.wttr.in\/"${LATITUDE},${LONGITUDE}"/g" $(dirname ${my_dir})/homepage/menu.html diff --git a/scripts/overview.php b/scripts/overview.php index c8c62c9..edbc53f 100644 --- a/scripts/overview.php +++ b/scripts/overview.php @@ -7,26 +7,50 @@ $myDate = date('Y-m-d'); $chart = "Combo-$myDate.png"; $db = new SQLite3('/home/pi/BirdNET-Pi/scripts/birds.db', SQLITE3_OPEN_CREATE | SQLITE3_OPEN_READWRITE); +if($db == False) { + echo "Database is busy"; + header("refresh: 0;"); +} $statement = $db->prepare('SELECT COUNT(*) FROM detections'); +if($statement == False) { + echo "Database is busy"; + header("refresh: 0;"); +} $result = $statement->execute(); $totalcount = $result->fetchArray(SQLITE3_ASSOC); $statement2 = $db->prepare('SELECT COUNT(*) FROM detections WHERE Date == DATE(\'now\')'); +if($statement2 == False) { + echo "Database is busy"; + header("refresh: 0;"); +} $result2 = $statement2->execute(); $todaycount = $result2->fetchArray(SQLITE3_ASSOC); $statement3 = $db->prepare('SELECT COUNT(*) FROM detections WHERE TIME >= TIME(\'now\', \'localtime\', \'-1 hour\')'); +if($statement3 == False) { + echo "Database is busy"; + header("refresh: 0;"); +} $result3 = $statement3->execute(); $hourcount = $result3->fetchArray(SQLITE3_ASSOC); -$statement4 = $db->prepare('SELECT Com_Name, Sci_Name, Date, Time, Confidence, File_Name FROM detections ORDER BY Time ASC LIMIT 1'); +$statement4 = $db->prepare('SELECT Com_Name, Sci_Name, Date, Time, Confidence, File_Name FROM detections ORDER BY Date DESC, Time DESC LIMIT 1'); +if($statement4 == False) { + echo "Database is busy"; + header("refresh: 0;"); +} $result4 = $statement4->execute(); $mostrecent = $result4->fetchArray(SQLITE3_ASSOC); $comname = preg_replace('/ /', '_', $mostrecent['Com_Name']); $scilink = preg_replace('/ /', '_', $mostrecent['Sci_Name']); $statement5 = $db->prepare('SELECT COUNT(DISTINCT(Com_Name)) FROM detections WHERE Date == Date(\'now\')'); +if($statement5 == False) { + echo "Database is busy"; + header("refresh: 0;"); +} $result5 = $statement5->execute(); $speciestally = $result5->fetchArray(SQLITE3_ASSOC); ?> @@ -54,6 +78,12 @@ table, th { th { padding: 0 5px; } +button { + background-color: rgb(219, 295, 235); + border:none; + font-size:large; + cursor:pointer; +} .center { display: block; margin-left: 5px; @@ -101,7 +131,8 @@ th { Most Recent Detection - "> +
    +
    " target="footer"/> diff --git a/scripts/server.py b/scripts/server.py index 7aa6f1d..3916582 100755 --- a/scripts/server.py +++ b/scripts/server.py @@ -353,12 +353,16 @@ def handle_client(conn, addr): Date.replace("/", "-") + '-birdnet-' + Time + audiofmt #Connect to SQLite Database - con = sqlite3.connect('/home/pi/BirdNET-Pi/scripts/birds.db') - cur = con.cursor() - cur.execute("INSERT INTO detections VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", (Date, Time, Sci_Name, Com_Name, str(score), Lat, Lon, Cutoff, Week, Sens, Overlap, File_Name)) + try: + con = sqlite3.connect('/home/pi/BirdNET-Pi/scripts/birds.db') + cur = con.cursor() + cur.execute("INSERT INTO detections VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", (Date, Time, Sci_Name, Com_Name, str(score), Lat, Lon, Cutoff, Week, Sens, Overlap, File_Name)) - con.commit() - con.close() + con.commit() + con.close() + except: + print("Database busy") + time.sleep(2) print(str(current_date) + ';' + str(current_time) + ';' + entry[0].replace('_', ';') + ';' + str(entry[1]) + ';' + str(args.lat) + ';' + str(args.lon) + ';' + str(min_conf) + ';' + str(week) + ';' + str(args.sensitivity) +';' + str(args.overlap) + Com_Name.replace(" ", "_") + '-' + str(score) + '-' + str(current_date) + '-birdnet-' + str(current_time) + audiofmt + '\n') if birdweather_id != "99999": diff --git a/scripts/stats.php b/scripts/stats.php index 597d35f..1c684c8 100644 --- a/scripts/stats.php +++ b/scripts/stats.php @@ -4,17 +4,33 @@ ini_set('display_startup_errors', 1); error_reporting(E_ALL); $db = new SQLite3('/home/pi/BirdNET-Pi/scripts/birds.db', SQLITE3_OPEN_CREATE | SQLITE3_OPEN_READWRITE); - +if($db == False) { + echo "Database busy"; + header("refresh: 0;"); +} $statement = $db->prepare('SELECT Com_Name, COUNT(*), MAX(Confidence), Sci_Name FROM detections GROUP BY Com_Name ORDER BY COUNT(*) DESC'); +if($statement == False) { + echo "Database busy"; + header("refresh: 0;"); +} $result = $statement->execute(); + $statement2 = $db->prepare('SELECT Com_Name FROM detections GROUP BY Com_Name ORDER BY Com_Name ASC'); +if($statement2 == False) { + echo "Database busy"; + header("refresh: 0;"); +} $result2 = $statement2->execute(); if(isset($_POST['species'])){ $selection = $_POST['species']; $statement3 = $db->prepare("SELECT Com_Name, Sci_Name, COUNT(*), MAX(Confidence) from detections WHERE Com_Name = '$selection'"); + if($statement3 == False) { + echo "Database busy"; + header("refresh: 0;"); + } $result3 = $statement3->execute(); } ?> @@ -80,6 +96,12 @@ a { text-align: center; } +button { + background-color: rgb(219, 295, 235); + border:none; + font-size:large; + cursor:pointer; +} img { width:75%; @@ -143,7 +165,8 @@ $comlink = "/By_Date/".date('Y-m-d')."/".$comname; $sciname = preg_replace('/ /', '_', $results['Sci_Name']); ?> - +
    +
    diff --git a/scripts/viewdb.php b/scripts/viewdb.php index 6d8dd68..3bd7238 100644 --- a/scripts/viewdb.php +++ b/scripts/viewdb.php @@ -6,29 +6,58 @@ error_reporting(E_ALL); header("refresh: 30;"); $db = new SQLite3('/home/pi/BirdNET-Pi/scripts/birds.db', SQLITE3_OPEN_CREATE | SQLITE3_OPEN_READWRITE); +if($db == False){ + echo "Database is busy"; + header("refresh: 0;"); +} $statement0 = $db->prepare('SELECT Time, Com_Name, Sci_Name, Confidence, File_Name FROM detections WHERE Date == Date(\'now\') ORDER BY Time DESC'); +if($statement0 == False){ + echo "Database is busy"; + header("refresh: 0;"); +} $result0 = $statement0->execute(); $statement1 = $db->prepare('SELECT COUNT(*) FROM detections'); +if($statement1 == False){ + echo "Database is busy"; + header("refresh: 0;"); +} $result1 = $statement1->execute(); $totalcount = $result1->fetchArray(SQLITE3_ASSOC); $statement2 = $db->prepare('SELECT COUNT(*) FROM detections WHERE Date == DATE(\'now\')'); +if($statement2 == False){ + echo "Database is busy"; + header("refresh: 0;"); +} $result2 = $statement2->execute(); $todaycount = $result2->fetchArray(SQLITE3_ASSOC); $statement3 = $db->prepare('SELECT COUNT(*) FROM detections WHERE TIME >= TIME(\'now\', \'localtime\', \'-1 hour\')'); +if($statement3 == False){ + echo "Database is busy"; + header("refresh: 0;"); +} $result3 = $statement3->execute(); $hourcount = $result3->fetchArray(SQLITE3_ASSOC); $statement4 = $db->prepare('SELECT Com_Name, Sci_Name, Time, Confidence FROM detections LIMIT 1'); +if($statement4 == False){ + echo "Database is busy"; + header("refresh: 0;"); +} $result4 = $statement4->execute(); $mostrecent = $result4->fetchArray(SQLITE3_ASSOC); $statement5 = $db->prepare('SELECT COUNT(DISTINCT(Com_Name)) FROM detections'); +if($statement4 == False){ + echo "Database is busy"; + header("refresh: 0;"); +} $result5 = $statement5->execute(); $speciestally = $result5->fetchArray(SQLITE3_ASSOC); + ?> diff --git a/templates/phpsysinfo.ini b/templates/phpsysinfo.ini index 90bab10..ccf35df 100644 --- a/templates/phpsysinfo.ini +++ b/templates/phpsysinfo.ini @@ -397,7 +397,7 @@ HIDE_TOTALS=false ; Example : HIDE_NETWORK_INTERFACE="eth0,sit0" ; HIDE_NETWORK_INTERFACE=true //hide all network interfaces ; -HIDE_NETWORK_INTERFACE="lo" +HIDE_NETWORK_INTERFACE="" ; Use a regular expression in the name of a hidden network interface (e.g. HIDE_NETWORK_INTERFACE="docker.*") @@ -785,7 +785,7 @@ USE_REGEX=false ; ; string contains a list of process names that are checked, names are seperated by a comma (on WinNT names must end with '.exe') ; -PROCESSES="avahi-daemon,gotty,sshd,mariadbd,ffmpeg,vncserver-x11-serviced,nxd,bash" +PROCESSES="avahi-daemon,gotty,sshd,ffmpeg,icecast2,arecord,server.py" [quotas] From bc125dcdb4b573e2be47024a290953e2fe388f40 Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Tue, 22 Feb 2022 09:45:21 -0500 Subject: [PATCH 040/160] adding very preliminary by_species dig --- scripts/play.css | 91 +++++++++++++++++++++++++++++++++++++++++++++++ scripts/play.php | 87 ++++++++++++++++++++++++++++++++++++++++++++ scripts/stats.php | 29 ++++----------- 3 files changed, 184 insertions(+), 23 deletions(-) create mode 100644 scripts/play.css create mode 100644 scripts/play.php diff --git a/scripts/play.css b/scripts/play.css new file mode 100644 index 0000000..7e8560e --- /dev/null +++ b/scripts/play.css @@ -0,0 +1,91 @@ +/* style sheet */ +* { + font-family: 'Arial', 'Gill Sans', 'Gill Sans MT', + ' Calibri', 'Trebuchet MS', 'sans-serif'; + box-sizing: border-box; +} + +a { + text-decoration:none; +} + +body { + background-color: rgb(119, 196, 135); +} + +.column { + display:block; + float:top; + width:33%; + margin-left:0; + margin-right:auto; +} + +table { + background-color: rgb(219, 255, 235); + margin: 0 auto; + font-size: large; + border-collapse: collapse; + border-spacing: 0; + width: 100%; + border: 1px solid black; +} + +h1 { + text-align: center; + color: black; + font-size: xx-large; +} + +h2 { + margin-left: -150px; + text-align: center; + color: black; + font-size: large; +} + +h3 { + text-align: center; + color: black; + font-size: large; +} + +td { + background-color: rgb(219, 255, 235); + font-weight: lighter; + border: 1px solid black; + padding: 10px; + text-align: center; +} + +th { + background-color: rgb(219, 255, 235); + font-weight: bold; + border: 1px solid black; + padding: 10px; + text-align: center; +} + +button { + background-color: transparent; + font-size: large; + border:none; + cursor:pointer; +} + +@media screen and (max-width: 1000px) { + h2 { + margin-left: 0; + text-align: center; + color: black; + font-size: large; + } + + .column { + width: 80%; + } + +} +body::-webkit-scrollbar { + display:none +} diff --git a/scripts/play.php b/scripts/play.php new file mode 100644 index 0000000..33b5552 --- /dev/null +++ b/scripts/play.php @@ -0,0 +1,87 @@ +prepare('SELECT DISTINCT(Com_Name) from detections ORDER BY Com_Name'); +if($statement == False){ + echo "Database is busy"; + header("refresh: 0;"); +} +$result = $statement->execute(); + +?> + + + + + + + + + +fetchArray(SQLITE3_ASSOC)) +{ + $comname = preg_replace('/ /', '_', $results['Com_Name']); + $comlink = "/By_Date/".date('Y-m-d')."/".$comname; +?> +
    + + + + + + +
    + +
    +
    + +prepare("SELECT * FROM detections where Com_Name == \"$name\" ORDER BY Date DESC, Time DESC"); + if($statement2 == False){ + echo "Database is busy"; + header("refresh: 0;"); + } + $result2 = $statement2->execute(); + echo " + + + + + + + "; + while($results=$result2->fetchArray(SQLITE3_ASSOC)) + { + $comname = preg_replace('/ /', '_', $results['Com_Name']); + $date = $results['Date']; + $comlink = "/By_Date/".$date."/".$comname."/".$results['File_Name']; + $sciname = preg_replace('/ /', '_', $results['Sci_Name']); + $sci_name = $results['Sci_Name']; + $time = $results['Time']; + $confidence = $results['Confidence']; + echo " + + + + + + + "; + + }echo "
    DateTimeScientific NameCommon NameConfidence
    $date$time$sci_name
    + $confidence
    ";}?> + + diff --git a/scripts/stats.php b/scripts/stats.php index 1c684c8..19aa494 100644 --- a/scripts/stats.php +++ b/scripts/stats.php @@ -150,7 +150,9 @@ select {
    -

    Summary

    +Choose a species below to show statistics.

    "; +};?> @@ -175,31 +177,13 @@ $sciname = preg_replace('/ /', '_', $results['Sci_Name']); ?>
    Common Name
    -
    -
    -

    Species Stats

    - - -
    $species + $str = "
    +

    $species

    +

    Species Stats

    - @@ -220,7 +204,6 @@ while($results=$result3->fetchArray(SQLITE3_ASSOC)){ $imagelink = shell_exec("/home/pi/BirdNET-Pi/scripts/get_image.sh $dbsciname"); $imagecitation = shell_exec("/home/pi/BirdNET-Pi/scripts/get_citation.sh $dbsciname"); $str= " - From 3caa9c3c9575fd7f280247a9166e6ed4d71c7f65 Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Tue, 22 Feb 2022 10:50:59 -0500 Subject: [PATCH 041/160] a little less ugly --- scripts/play.css | 12 ++++++++++-- scripts/play.php | 7 +++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/scripts/play.css b/scripts/play.css index 7e8560e..4d7828d 100644 --- a/scripts/play.css +++ b/scripts/play.css @@ -15,12 +15,20 @@ body { .column { display:block; - float:top; width:33%; - margin-left:0; + margin-left:auto; margin-right:auto; } +.left { + float:left; +} + +.right { + float:right; + width:66%; +} + table { background-color: rgb(219, 255, 235); margin: 0 auto; diff --git a/scripts/play.php b/scripts/play.php index 33b5552..311e435 100644 --- a/scripts/play.php +++ b/scripts/play.php @@ -27,13 +27,13 @@ $result = $statement->execute(); +
    fetchArray(SQLITE3_ASSOC)) { $comname = preg_replace('/ /', '_', $results['Com_Name']); $comlink = "/By_Date/".date('Y-m-d')."/".$comname; ?> -
    Common Name Scientific Name Occurrences Highest Confidence Score
    $name $sciname $count $maxconf
    @@ -43,9 +43,10 @@ while($results=$result->fetchArray(SQLITE3_ASSOC))
    -
    +
    +
    fetchArray(SQLITE3_ASSOC)) "; }echo "";}?> +
    +
    From e01542612091e1e5360cedcdc988fb8225bc4bfc Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Tue, 22 Feb 2022 14:56:53 -0500 Subject: [PATCH 042/160] updating play.php --- scripts/play.php | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/scripts/play.php b/scripts/play.php index 311e435..24e6b53 100644 --- a/scripts/play.php +++ b/scripts/play.php @@ -9,12 +9,23 @@ if($db == False){ header("refresh: 0;"); } +if(isset($_POST['bydate'])){ +$statement = $db->prepare('SELECT DISTINCT(Date), Com_Name from detections GROUP BY Date'); +if($statement == False){ + echo "Database is busy"; + header("refresh: 0;"); +} +$result = $statement->execute(); +$view = "bydate"; +} else { $statement = $db->prepare('SELECT DISTINCT(Com_Name) from detections ORDER BY Com_Name'); if($statement == False){ echo "Database is busy"; header("refresh: 0;"); } $result = $statement->execute(); +$view = "byspecies"; +} ?> @@ -38,7 +49,13 @@ while($results=$result->fetchArray(SQLITE3_ASSOC))
    - +$date";} +else { + $name = $results['Com_Name']; + echo "";}?>
    From 1b50ee88f189618b10f25ccab95dec9c0a0ffa82 Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Tue, 22 Feb 2022 15:10:15 -0500 Subject: [PATCH 043/160] updated menu.html -- sorry gang! --- homepage/menu.html | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/homepage/menu.html b/homepage/menu.html index 3e2b3af..e94b825 100644 --- a/homepage/menu.html +++ b/homepage/menu.html @@ -16,6 +16,11 @@ body { text-align: left; padding-bottom: 30px; } +form { + padding:0; + margin:0; +} + h3 { margin: 0px 0px -15px 0px; text-align: center; @@ -32,6 +37,11 @@ footer { bottom: 0; width:100%; } +button { + background-color: transparent; + text-size:large; + border:none; +} hr { border-bottom: 1px solid black; } @@ -43,9 +53,12 @@ body::-webkit-scrollbar {
    Extractions
    - - By Date
    - - By Common Name
    - - By Scientific Name
    +
    + - +
    +
    + - +
    - Processed

    From 3d6466783b58963ab71cfbe1530ee0ff31398034 Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Tue, 22 Feb 2022 15:22:33 -0500 Subject: [PATCH 044/160] adding play.php where it belongs --- scripts/install_services.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/install_services.sh b/scripts/install_services.sh index 6116da7..80da0ef 100755 --- a/scripts/install_services.sh +++ b/scripts/install_services.sh @@ -145,6 +145,7 @@ create_necessary_dirs() { sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local/${BIRDNETPI_URL}/g" $(dirname ${my_dir})/scripts/*/*.php fi + sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/play.* ${EXTRACTED} sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/spectrogram.php ${EXTRACTED} sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/overview.php ${EXTRACTED} sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/stats.php ${EXTRACTED} From 78c66580a6042846342ce2fe709cdd0ed4b91d7a Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Tue, 22 Feb 2022 15:28:05 -0500 Subject: [PATCH 045/160] adding pointer cursor to menu.html buttons --- homepage/menu.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/homepage/menu.html b/homepage/menu.html index e94b825..3690a9c 100644 --- a/homepage/menu.html +++ b/homepage/menu.html @@ -41,6 +41,7 @@ button { background-color: transparent; text-size:large; border:none; + cursor:pointer; } hr { border-bottom: 1px solid black; @@ -74,7 +75,7 @@ body::-webkit-scrollbar { - BirdWeather
    - Repository
    - Wiki Help Page
    - - Wttr.in Report
    + - Wttr.in Report
    - BirdNET

    From 4e36dcd6a872fe39e701618acec5affc64d999d5 Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Wed, 23 Feb 2022 09:26:12 -0500 Subject: [PATCH 046/160] better navigation / fixes --- homepage/menu.html | 2 +- scripts/play.php | 158 ++++++++++++++++++++++++++++----------------- scripts/stats.php | 2 +- 3 files changed, 99 insertions(+), 63 deletions(-) diff --git a/homepage/menu.html b/homepage/menu.html index 3690a9c..f116a01 100644 --- a/homepage/menu.html +++ b/homepage/menu.html @@ -39,7 +39,7 @@ footer { } button { background-color: transparent; - text-size:large; + font-size:small; border:none; cursor:pointer; } diff --git a/scripts/play.php b/scripts/play.php index 24e6b53..0cddd5b 100644 --- a/scripts/play.php +++ b/scripts/play.php @@ -10,21 +10,41 @@ if($db == False){ } if(isset($_POST['bydate'])){ -$statement = $db->prepare('SELECT DISTINCT(Date), Com_Name from detections GROUP BY Date'); -if($statement == False){ - echo "Database is busy"; - header("refresh: 0;"); -} -$result = $statement->execute(); -$view = "bydate"; -} else { -$statement = $db->prepare('SELECT DISTINCT(Com_Name) from detections ORDER BY Com_Name'); -if($statement == False){ - echo "Database is busy"; - header("refresh: 0;"); -} -$result = $statement->execute(); -$view = "byspecies"; + $statement = $db->prepare('SELECT DISTINCT(Date), Com_Name from detections GROUP BY Date'); + if($statement == False){ + echo "Database is busy"; + header("refresh: 0;"); + } + $result = $statement->execute(); + $view = "bydate"; +} elseif(isset($_POST['byspecies'])) { + $statement = $db->prepare('SELECT DISTINCT(Com_Name) from detections ORDER BY Com_Name'); + if($statement == False){ + echo "Database is busy"; + header("refresh: 0;"); + } + $result = $statement->execute(); + $view = "byspecies"; +} elseif(isset($_POST['date'])) { + $date = $_POST['date']; + $statement = $db->prepare("SELECT DISTINCT(Com_Name) from detections WHERE Date == \"$date\" ORDER BY Com_Name"); + if($statement == False){ + echo "Database is busy"; + header("refresh: 0;"); + } + $result = $statement->execute(); + $view = "date"; +} elseif(isset($_POST['species'])) { + $species = $_POST['species']; + $statement = $db->prepare("SELECT * from detections WHERE Com_Name == \"$species\" ORDER BY Com_Name"); + $statement3 = $db->prepare("SELECT Date, Time, Com_Name, MAX(Confidence), File_Name from detections WHERE Com_Name == \"$species\" ORDER BY Com_Name"); + if($statement == False || $statement3 == False){ + echo "Database is busy"; + header("refresh: 0;"); + } + $result = $statement->execute(); + $result3 = $statement3->execute(); + $view = "species"; } ?> @@ -39,68 +59,84 @@ $view = "byspecies";
    +fetchArray(SQLITE3_ASSOC)) { - $comname = preg_replace('/ /', '_', $results['Com_Name']); - $comlink = "/By_Date/".date('Y-m-d')."/".$comname; ?> -
    $date";} -else { - $name = $results['Com_Name']; - echo "";}?> + if($view == "bydate"){ + $date = $results['Date']; + echo ""; + } elseif($view == "byspecies") { + $name = $results['Com_Name']; + echo ""; + } elseif($view == "date") { + $name = $results['Com_Name']; + echo ""; + }; };} else { + while($results=$result3->fetchArray(SQLITE3_ASSOC)){ + $maxconf = $results['MAX(Confidence)']; + $date = $results['Date']; + $time = $results['Time']; + $comname = preg_replace('/ /', '_', $results['Com_Name']); + $file = $results['File_Name']; + $filename = "/By_Date/".$date."/".$comname."/".$results['File_Name']; + echo " + + + + + +
    Max Confidence: $maxconf
    Most confident recording: $file
    "; + };};?>
    -
    prepare("SELECT * FROM detections where Com_Name == \"$name\" ORDER BY Date DESC, Time DESC"); - if($statement2 == False){ - echo "Database is busy"; - header("refresh: 0;"); - } - $result2 = $statement2->execute(); - echo " - - - - - - - "; - while($results=$result2->fetchArray(SQLITE3_ASSOC)) - { - $comname = preg_replace('/ /', '_', $results['Com_Name']); - $date = $results['Date']; - $comlink = "/By_Date/".$date."/".$comname."/".$results['File_Name']; - $sciname = preg_replace('/ /', '_', $results['Sci_Name']); - $sci_name = $results['Sci_Name']; - $time = $results['Time']; - $confidence = $results['Confidence']; - echo " - - - - - - - "; + if(isset($_POST['species'])){ + $name = $_POST['species']; + $statement2 = $db->prepare("SELECT * FROM detections where Com_Name == \"$name\" ORDER BY Date DESC, Time DESC"); + if($statement2 == False){ + echo "Database is busy"; + header("refresh: 0;"); + } + $result2 = $statement2->execute(); + echo "
    DateTimeScientific NameCommon NameConfidence
    $date$time$sci_name
    - $confidence
    + + + + + + + "; + while($results=$result2->fetchArray(SQLITE3_ASSOC)) + { + $comname = preg_replace('/ /', '_', $results['Com_Name']); + $date = $results['Date']; + $comlink = "/By_Date/".$date."/".$comname."/".$results['File_Name']; + $sciname = preg_replace('/ /', '_', $results['Sci_Name']); + $sci_name = $results['Sci_Name']; + $time = $results['Time']; + $confidence = $results['Confidence']; + echo " + + + + + + + "; - }echo "
    DateTimeScientific NameCommon NameConfidence
    $date$time$sci_name
    + $confidence
    ";}?> + }echo "";}?>
    diff --git a/scripts/stats.php b/scripts/stats.php index 19aa494..2d53770 100644 --- a/scripts/stats.php +++ b/scripts/stats.php @@ -26,7 +26,7 @@ $result2 = $statement2->execute(); if(isset($_POST['species'])){ $selection = $_POST['species']; $statement3 = $db->prepare("SELECT Com_Name, Sci_Name, COUNT(*), MAX(Confidence) from detections - WHERE Com_Name = '$selection'"); + WHERE Com_Name = \"$selection\""); if($statement3 == False) { echo "Database busy"; header("refresh: 0;"); From ab416e30a590b71881883fedcdd9a8607ed5cbb1 Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Wed, 23 Feb 2022 09:47:48 -0500 Subject: [PATCH 047/160] stats automatically pulls "Best" recording --- scripts/stats.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/scripts/stats.php b/scripts/stats.php index 2d53770..3b102ee 100644 --- a/scripts/stats.php +++ b/scripts/stats.php @@ -25,7 +25,7 @@ $result2 = $statement2->execute(); if(isset($_POST['species'])){ $selection = $_POST['species']; - $statement3 = $db->prepare("SELECT Com_Name, Sci_Name, COUNT(*), MAX(Confidence) from detections + $statement3 = $db->prepare("SELECT Com_Name, Sci_Name, COUNT(*), MAX(Confidence), File_Name, Date from detections WHERE Com_Name = \"$selection\""); if($statement3 == False) { echo "Database busy"; @@ -187,6 +187,7 @@ $sciname = preg_replace('/ /', '_', $results['Sci_Name']); Scientific Name Occurrences Highest Confidence Score + Best Recording Links "; echo str_pad($str, 4096); @@ -196,18 +197,21 @@ $sciname = preg_replace('/ /', '_', $results['Sci_Name']); while($results=$result3->fetchArray(SQLITE3_ASSOC)){ $count = $results['COUNT(*)']; $maxconf = $results['MAX(Confidence)']; + $date = $results['Date']; $name = $results['Com_Name']; $sciname = $results['Sci_Name']; $dbname = preg_replace('/ /', '_', $results['Com_Name']); $dbname = preg_replace('/\'/', '', $dbname); $dbsciname = preg_replace('/ /', '_', $results['Sci_Name']); + $filename = "/By_Date/".$date."/".$dbname."/".$results['File_Name']; $imagelink = shell_exec("/home/pi/BirdNET-Pi/scripts/get_image.sh $dbsciname"); $imagecitation = shell_exec("/home/pi/BirdNET-Pi/scripts/get_citation.sh $dbsciname"); $str= " $sciname $count $maxconf - All About Birds + Listen + All About Birds "; echo str_pad($str, 4096); From 01253296970b7232685743051f21e614518d5e05 Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Wed, 23 Feb 2022 09:53:59 -0500 Subject: [PATCH 048/160] new version number/color --- README.md | 2 +- homepage/images/version.svg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a630b4b..559b08f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

    - BirdNET-Pi + BirdNET-Pi

    A realtime acoustic bird classification system for the Raspberry Pi 4B diff --git a/homepage/images/version.svg b/homepage/images/version.svg index fd1be85..1d17fee 100644 --- a/homepage/images/version.svg +++ b/homepage/images/version.svg @@ -1 +1 @@ -version: 0.11.1version0.11.1 \ No newline at end of file +SQLite: 0.12SQLite0.12 \ No newline at end of file From c691045c067d71551e7b3b1fad89b32b4713f156 Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Wed, 23 Feb 2022 10:05:45 -0500 Subject: [PATCH 049/160] removed redundant link --- homepage/menu.html | 1 - 1 file changed, 1 deletion(-) diff --git a/homepage/menu.html b/homepage/menu.html index f116a01..2bfe9fe 100644 --- a/homepage/menu.html +++ b/homepage/menu.html @@ -73,7 +73,6 @@ body::-webkit-scrollbar {

    External
    - BirdWeather
    - - Repository
    - Wiki Help Page
    - Wttr.in Report
    - BirdNET
    From ad3919eae58efef630930eead7aca1d9c1b51145 Mon Sep 17 00:00:00 2001 From: Patrick McGuire <60325264+mcguirepr89@users.noreply.github.com> Date: Wed, 23 Feb 2022 10:10:01 -0500 Subject: [PATCH 050/160] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 559b08f..458aa7c 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ If your installation isn't in one of the countries listed above, please let me k The system can be installed with: ``` -curl -s https://raw.githubusercontent.com/mcguirepr89/BirdNET-Pi/main/newinstaller.sh | bash | tee -a installation.log 2>&1 && sudo reboot +curl -s https://raw.githubusercontent.com/mcguirepr89/BirdNET-Pi/main/newinstaller.sh | bash ``` The installer takes care of any and all necessary updates, so you can run that as the very first command upon the first boot, if you'd like. From 66c5a2b9613b9d45ccab645ba474de77780032ff Mon Sep 17 00:00:00 2001 From: Patrick McGuire <60325264+mcguirepr89@users.noreply.github.com> Date: Wed, 23 Feb 2022 10:41:49 -0500 Subject: [PATCH 051/160] Delete update_services.sh --- scripts/update_services.sh | 591 ------------------------------------- 1 file changed, 591 deletions(-) delete mode 100755 scripts/update_services.sh diff --git a/scripts/update_services.sh b/scripts/update_services.sh deleted file mode 100755 index d6ef6fa..0000000 --- a/scripts/update_services.sh +++ /dev/null @@ -1,591 +0,0 @@ -#!/usr/bin/env bash -# This reinstalls the services -set -x # Uncomment to enable debugging -trap 'rm -f ${tmpfile}' EXIT -trap 'exit 1' SIGINT SIGHUP -USER=pi -HOME=/home/pi -my_dir=${HOME}/BirdNET-Pi/scripts -tmpfile=$(mktemp) -nomachine_url="https://download.nomachine.com/download/7.7/Arm/nomachine_7.7.4_1_arm64.deb" -gotty_url="https://github.com/yudai/gotty/releases/download/v1.0.1/gotty_linux_arm.tar.gz" -config_file="$(dirname ${my_dir})/birdnet.conf" - -install_ftpd() { - if ! [ -f /etc/ftpuseres ];then - apt -y install ftpd - fi -} - -install_lynx() { - if ! which lynx &> /dev/null;then - apt -y install lynx - fi -} - -install_scripts() { - echo "Installing BirdNET-Pi scripts to /usr/local/bin" - ln -sf ${my_dir}/* /usr/local/bin/ - rm /usr/local/bin/index.html -} - -install_mariadb() { - if ! which mysql &> /dev/null;then - echo "Installing MariaDB Server" - apt -qqy install mariadb-server - echo "MariaDB Installed" - fi - source /etc/os-release - if [[ "${VERSION_CODENAME}" == "buster" ]];then - USER=${USER} ${my_dir}/update_db_pwd_buster.sh - elif [[ "${VERSION_CODENAME}" == "bullseye" ]];then - mysql -e " - SET PASSWORD FOR 'birder'@'localhost' = PASSWORD('${DB_PWD}'); - FLUSH PRIVILEGES"; - sed -i "s/mysqli.default_host =.*/mysqli.default_host = localhost/g" /etc/php/7.4/fpm/php.ini - sed -i "s/mysqli.default_user =.*/mysqli.default_user = birder/g" /etc/php/7.4/fpm/php.ini - sed -i "s/mysqli.default_pw =.*/mysqli.default_pw = ${DB_PWD}/g" /etc/php/7.4/fpm/php.ini - fi -} - -install_birdnet_analysis() { - echo "Installing the birdnet_analysis.service" - cat << EOF > /etc/systemd/system/birdnet_analysis.service -[Unit] -Description=BirdNET Analysis -After=birdnet_server.service -Requires=birdnet_server.service -[Service] -Restart=always -Type=simple -RestartSec=2 -User=${USER} -ExecStart=/usr/local/bin/birdnet_analysis.sh -[Install] -WantedBy=multi-user.target -EOF - systemctl enable birdnet_analysis.service -} - -install_birdnet_server() { - echo "Installing the birdnet_server.service" - cat << EOF > /etc/systemd/system/birdnet_server.service -[Unit] -Description=BirdNET Analysis Server -Before=birdnet_analysis.service -[Service] -Restart=always -Type=simple -RestartSec=2 -User=${USER} -ExecStart=/usr/local/bin/server.py -[Install] -WantedBy=multi-user.target -EOF - systemctl enable birdnet_server.service -} - - -install_extraction_service() { - echo "Installing the extraction.service and extraction.timer" - cat << EOF > /etc/systemd/system/extraction.service -[Unit] -Description=BirdNET BirdSound Extraction -[Service] -Restart=on-failure -RestartSec=3 -Type=simple -User=${USER} -ExecStart=/usr/local/bin/extract_new_birdsounds.sh -[Install] -WantedBy=multi-user.target -EOF - cat << EOF > /etc/systemd/system/extraction.timer -[Unit] -Description=BirdNET BirdSound Extraction Timer -Requires=extraction.service - -[Timer] -Unit=extraction.service -OnCalendar=*:*:0/10 - -[Install] -WantedBy=multi-user.target -EOF - systemctl enable extraction.timer - systemctl enable extraction.service -} - -install_pushed_notifications() { - echo "Installing Pushed.co mobile notifications" - cat << EOF > /etc/systemd/system/pushed_notifications.service -[Unit] -Description=BirdNET-Pi Pushed.co Notifications -[Service] -Restart=on-success -RestartSec=3 -Type=simple -User=pi -ExecStart=/usr/local/bin/species_notifier.sh -[Install] -WantedBy=multi-user.target -EOF - systemctl enable pushed_notifications.service -} - -create_necessary_dirs() { - echo "Creating necessary directories" - [ -d ${EXTRACTED} ] || sudo -u ${USER} mkdir -p ${EXTRACTED} - [ -d ${EXTRACTED}/By_Date ] || sudo -u ${USER} mkdir -p ${EXTRACTED}/By_Date - [ -d ${EXTRACTED}/By_Common_Name ] || sudo -u ${USER} mkdir -p ${EXTRACTED}/By_Common_Name - [ -d ${EXTRACTED}/By_Scientific_Name ] || sudo -u ${USER} mkdir -p ${EXTRACTED}/By_Scientific_Name - [ -d ${EXTRACTED}/Charts ] || sudo -u ${USER} mkdir -p ${EXTRACTED}/Charts - [ -d ${PROCESSED} ] || sudo -u ${USER} mkdir -p ${PROCESSED} - - sudo -u ${USER} ln -fs $(dirname ${my_dir})/homepage/* ${EXTRACTED} - if [ ! -z ${BIRDNETLOG_URL} ];then - BIRDNETLOG_URL="$(echo ${BIRDNETLOG_URL} | sed 's/\/\//\\\/\\\//g')" - sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8080/${BIRDNETLOG_URL}/g" $(dirname ${my_dir})/homepage/*.html - sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8080/${BIRDNETLOG_URL}/g" $(dirname ${my_dir})/scripts/*.html - sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8080/${BIRDNETLOG_URL}/g" $(dirname ${my_dir})/scripts/*.html - sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8080/${BIRDNETLOG_URL}/g" $(dirname ${my_dir})/scripts/*.php - sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8080/${BIRDNETLOG_URL}/g" $(dirname ${my_dir})/scripts/*/*.php - fi - if [ ! -z ${WEBTERMINAL_URL} ];then - WEBTERMINAL_URL="$(echo ${WEBTERMINAL_URL} | sed 's/\/\//\\\/\\\//g')" - sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8888/${WEBTERMINAL_URL}/g" $(dirname ${my_dir})/homepage/*.html - sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8888/${WEBTERMINAL_URL}/g" $(dirname ${my_dir})/scripts/*.html - sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8888/${WEBTERMINAL_URL}/g" $(dirname ${my_dir})/scripts/*.html - sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8888/${WEBTERMINAL_URL}/g" $(dirname ${my_dir})/scripts/*.php - sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8888/${WEBTERMINAL_URL}/g" $(dirname ${my_dir})/scripts/*/*.php - fi - - sudo -u ${USER} ln -fs $(dirname ${my_dir})/model/labels.txt ${my_dir}/ - sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts ${EXTRACTED} - if [ -z ${BIRDNETPI_URL} ];then - sudo -u${USER} sed -i "s/birdnetpi.local/$(hostname).local/g" $(dirname ${my_dir})/homepage/*.html - sudo -u${USER} sed -i "s/birdnetpi.local/$(hostname).local/g" $(dirname ${my_dir})/scripts/*.html - sudo -u${USER} sed -i "s/birdnetpi.local/$(hostname).local/g" $(dirname ${my_dir})/scripts/*.html - sudo -u${USER} sed -i "s/birdnetpi.local/$(hostname).local/g" $(dirname ${my_dir})/scripts/*.php - sudo -u${USER} sed -i "s/birdnetpi.local/$(hostname).local/g" $(dirname ${my_dir})/scripts/*/*.php - else - BIRDNETPI_URL="$(echo ${BIRDNETPI_URL} | sed 's/\/\//\\\/\\\//g')" - sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local/${BIRDNETPI_URL}/g" $(dirname ${my_dir})/homepage/*.html - sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local/${BIRDNETPI_URL}/g" $(dirname ${my_dir})/scripts/*.html - sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local/${BIRDNETPI_URL}/g" $(dirname ${my_dir})/scripts/*.html - sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local/${BIRDNETPI_URL}/g" $(dirname ${my_dir})/scripts/*.php - sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local/${BIRDNETPI_URL}/g" $(dirname ${my_dir})/scripts/*/*.php - fi - - sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/spectrogram.php ${EXTRACTED} - sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/viewday.php ${EXTRACTED} - sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/overview.php ${EXTRACTED} - sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/stats.php ${EXTRACTED} - sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/viewdb.php ${EXTRACTED} - sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/history.php ${EXTRACTED} - sudo -u ${USER} ln -fs $(dirname ${my_dir})/homepage/images/favicon.ico ${EXTRACTED} - sudo -u ${USER} ln -fs ${HOME}/phpsysinfo ${EXTRACTED} - sudo -u ${USER} cp -f $(dirname ${my_dir})/templates/phpsysinfo.ini ${HOME}/phpsysinfo/ - sudo -u ${USER} cp -f $(dirname ${my_dir})/templates/green_bootstrap.css ${HOME}/phpsysinfo/templates/ - sudo -u ${USER} cp -f $(dirname ${my_dir})/templates/index_bootstrap.html ${HOME}/phpsysinfo/templates/html - - echo "Setting Wttr.in URL to "${LATITUDE}", "${LONGITUDE}"" - sudo -u${USER} sed -i "s/https:\/\/v2.wttr.in\//https:\/\/v2.wttr.in\/"${LATITUDE},${LONGITUDE}"/g" $(dirname ${my_dir})/homepage/menu.html - chmod -R g+rw $(dirname ${my_dir}) - chmod -R g+rw ${RECS_DIR} -} - -generate_BirdDB() { - echo "Generating BirdDB.txt" - if ! [ -f $(dirname ${my_dir})/BirdDB.txt ];then - sudo -u ${USER} touch $(dirname ${my_dir})/BirdDB.txt - echo "Date;Time;Sci_Name;Com_Name;Confidence;Lat;Lon;Cutoff;Week;Sens;Overlap" | sudo -u ${USER} tee -a $(dirname ${my_dir})/BirdDB.txt - elif ! grep Date $(dirname ${my_dir})/BirdDB.txt;then - sudo -u ${USER} sed -i '1 i\Date;Time;Sci_Name;Com_Name;Confidence;Lat;Lon;Cutoff;Week;Sens;Overlap' $(dirname ${my_dir})/BirdDB.txt - fi - ln -sf $(dirname ${my_dir})/BirdDB.txt ${my_dir}/BirdDB.txt && - chown pi:pi ${my_dir}/BirdDB.txt && chmod g+rw ${my_dir}/BirdDB.txt -} - -install_alsa() { - echo "Checking for alsa-utils and pulseaudio" - if which arecord &> /dev/null ;then - echo "alsa-utils installed" - else - echo "Installing alsa-utils" - apt install -qqy alsa-utils - echo "alsa-utils installed" - fi - if which pulseaudio &> /dev/null;then - echo "PulseAudio installed" - else - echo "Installing pulseaudio" - apt install -qqy pulseaudio - echo "PulseAudio installed" - fi - if ! [ -d /etc/lightdm ];then - systemctl set-default multi-user.target - ln -fs /lib/systemd/system/getty@.service /etc/systemd/system/getty.target.wants/getty@tty1.service - cat > /etc/systemd/system/getty@tty1.service.d/autologin.conf << EOF -[Service] -ExecStart= -ExecStart=-/sbin/agetty --autologin $USER --noclear %I \$TERM -EOF - fi - -} - -install_recording_service() { - echo "Installing birdnet_recording.service" - cat << EOF > /etc/systemd/system/birdnet_recording.service -[Unit] -Description=BirdNET Recording - -[Service] -Environment=XDG_RUNTIME_DIR=/run/user/1000 -Restart=always -Type=simple -RestartSec=3 -User=${USER} -ExecStart=/usr/local/bin/birdnet_recording.sh - -[Install] -WantedBy=multi-user.target -EOF - systemctl enable birdnet_recording.service -} - -install_caddy() { - if ! which caddy &> /dev/null ;then - echo "Installing Caddy" - curl -1sLf \ - 'https://dl.cloudsmith.io/public/caddy/stable/setup.deb.sh' \ - | sudo -E bash - apt install -qqy caddy=2.4.5 - systemctl enable --now caddy - else - echo "Caddy is installed" - systemctl enable --now caddy - fi -} - -install_Caddyfile() { - echo "Installing the Caddyfile" - [ -d /etc/caddy ] || mkdir /etc/caddy - if [ -f /etc/caddy/Caddyfile ];then - cp /etc/caddy/Caddyfile{,.original} - fi - php_version="$(awk -F'php' '{print $3}' <(ls -l $(which /etc/alternatives/php)))" - if ! [ -z ${CADDY_PWD} ];then - HASHWORD=$(caddy hash-password -plaintext ${CADDY_PWD}) - cat << EOF > /etc/caddy/Caddyfile -http://localhost http://$(hostname).local ${BIRDNETPI_URL} { - root * ${EXTRACTED} - file_server browse - basicauth /Processed* { - birdnet ${HASHWORD} - } - basicauth /scripts* { - birdnet ${HASHWORD} - } - basicauth /stream { - birdnet ${HASHWORD} - } - basicauth /phpsysinfo* { - birdnet ${HASHWORD} - } - reverse_proxy /stream localhost:8000 - php_fastcgi unix//run/php/php${php_version}-fpm.sock -} -EOF - else - cat << EOF > /etc/caddy/Caddyfile -http://localhost http://$(hostname).local ${BIRDNETPI_URL} { - root * ${EXTRACTED} - file_server browse - reverse_proxy /stream localhost:8000 - php_fastcgi unix//run/php/php${php_version}-fpm.sock -} -EOF - fi - - if [ ! -z ${WEBTERMINAL_URL} ] && [ ! -z ${HASHWORD} ];then - cat << EOF >> /etc/caddy/Caddyfile -${WEBTERMINAL_URL} { - basicauth { - birdnet ${HASHWORD} - } - reverse_proxy localhost:8888 -} -EOF - elif [ ! -z ${WEBTERMINAL_URL} ] && [ -z ${HASHWORD} ];then - cat << EOF >> /etc/caddy/Caddyfile -${WEBTERMINAL_URL} { - reverse_proxy localhost:8888 -} -EOF - fi - if [ ! -z ${BIRDNETLOG_URL} ];then - cat << EOF >> /etc/caddy/Caddyfile - -${BIRDNETLOG_URL} { - reverse_proxy localhost:8080 -} -EOF - fi -} - -update_etc_hosts() { - sed -ie s/'$(hostname).local'/"$(hostname).local ${BIRDNETPI_URL//https:\/\/} ${WEBTERMINAL_URL//https:\/\/} ${BIRDNETLOG_URL//https:\/\/}"/g /etc/hosts -} - -install_avahi_aliases() { - echo "Installing Avahi Services" - if ! which avahi-publish &> /dev/null; then - echo "Installing avahi-utils" - apt install -y avahi-utils &> /dev/null - fi - echo "Installing avahi-alias service" - cat << 'EOF' > /etc/systemd/system/avahi-alias@.service -[Unit] -Description=Publish %I as alias for %H.local via mdns -After=network.target network-online.target -Requires=network-online.target - -[Service] -Restart=always -RestartSec=3 -Type=simple -ExecStart=/bin/bash -c "/usr/bin/avahi-publish -a -R %I $(hostname -I |cut -d' ' -f1)" - -[Install] -WantedBy=multi-user.target -EOF -systemctl enable avahi-alias@"$(hostname)".local.service -} - -install_spectrogram_service() { - cat << EOF > /etc/systemd/system/spectrogram_viewer.service -[Unit] -Description=BirdNET-Pi Spectrogram Viewer -[Service] -Restart=always -RestartSec=10 -Type=simple -User=${USER} -ExecStart=/usr/local/bin/spectrogram.sh -[Install] -WantedBy=multi-user.target -EOF - systemctl enable spectrogram_viewer.service -} - -install_chart_viewer_service() { - echo "Installing the chart_viewer.service" - cat << EOF > /etc/systemd/system/chart_viewer.service -[Unit] -Description=BirdNET-Pi Chart Viewer Service - -[Service] -Restart=always -RestartSec=300 -Type=simple -User=pi -ExecStart=/usr/local/bin/daily_plot.py -[Install] -WantedBy=multi-user.target -EOF - systemctl enable chart_viewer.service -} - -install_gotty_logs() { - echo "Installing GoTTY logging" - if ! which gotty &> /dev/null;then - echo "Installing GoTTY binary" - wget -c ${gotty_url} -O - | tar -xz -C /usr/local/bin/ - fi - sudo -u ${USER} ln -sf $(dirname ${my_dir})/templates/gotty \ - ${HOME}/.gotty - sudo -u ${USER} ln -sf $(dirname ${my_dir})/templates/bashrc \ - ${HOME}/.bashrc - echo "Installing the birdnet_log.service" - cat << EOF > /etc/systemd/system/birdnet_log.service -[Unit] -Description=BirdNET Analysis Log - -[Service] -Restart=on-failure -RestartSec=3 -Type=simple -User=${USER} -Environment=TERM=xterm-256color -ExecStart=/usr/local/bin/gotty -p 8080 --title-format "BirdNET-Pi Log" birdnet_log.sh - -[Install] -WantedBy=multi-user.target -EOF - systemctl enable birdnet_log.service - echo "Installing the Web Terminal" - cat << EOF > /etc/systemd/system/web_terminal.service -[Unit] -Description=BirdNET-Pi Web Terminal - -[Service] -Restart=on-failure -RestartSec=3 -Type=simple -User=${USER} -Environment=TERM=xterm-256color -ExecStart=/usr/local/bin/gotty -w -p 8888 --title-format "BirdNET-Pi Terminal" bash - -[Install] -WantedBy=multi-user.target -EOF - systemctl enable web_terminal.service -} - -install_sox() { - if which sox | grep mp3 &> /dev/null;then - echo "Sox is installed" - else - echo "Installing sox" - apt install -y sox libsox-fmt-mp3 - echo "Sox installed" - fi -} - -install_php() { - if ! which php &> /dev/null || ! which php-fpm || ! apt list --installed | grep php-xml;then - echo "Installing PHP modules" - apt install -qqy php php-fpm php-mysql php-xml php-zip - else - echo "PHP and PHP-FPM installed" - fi - echo "Configuring PHP for Caddy" - sed -i 's/www-data/caddy/g' /etc/php/*/fpm/pool.d/www.conf - echo "Adding Caddy sudoers rule" - cat << EOF > /etc/sudoers.d/010_caddy-nopasswd -caddy ALL=(ALL) NOPASSWD: ALL -EOF - chmod 0440 /etc/sudoers.d/010_caddy-nopasswd - if [ ! -d ${HOME}/phpsysinfo ];then - echo "Fetching phpSysInfo" - sudo -u ${USER} git clone https://github.com/phpsysinfo/phpsysinfo.git \ - ${HOME}/phpsysinfo - fi -} - -install_icecast() { - if ! which icecast2;then - echo "Installing IceCast2" - echo "icecast2 icecast2/icecast-setup boolean false" | debconf-set-selections - apt install -qqy icecast2 - config_icecast - systemctl enable icecast2.service - /etc/init.d/icecast2 start - else - echo "Icecast2 is installed" - config_icecast - systemctl enable icecast2.service - /etc/init.d/icecast2 start - fi -} - -config_icecast() { - if [ -f /etc/icecast2/icecast.xml ];then - cp /etc/icecast2/icecast.xml{,.prebirdnetpi} - fi - sed -i 's/>adminbirdnet.*<\/${i}password>/<${i}password>${ICE_PWD}<\/${i}password>/g" /etc/icecast2/icecast.xml - done -} - -install_livestream_service() { - echo "Installing Live Stream service" - cat << EOF > /etc/systemd/system/livestream.service -[Unit] -Description=BirdNET-Pi Live Stream -After=network-online.target -Requires=network-online.target - -[Service] -Environment=XDG_RUNTIME_DIR=/run/user/1000 -Restart=always -Type=simple -RestartSec=3 -User=${USER} -ExecStart=/usr/local/bin/livestream.sh - -[Install] -WantedBy=multi-user.target -EOF - systemctl enable livestream.service -} - -install_nomachine() { - if [ ! -d /usr/share/NX ] && [ -d /etc/lightdm ];then - echo "Installing NoMachine" - curl -s -o ${HOME}/nomachine.deb -O "${nomachine_url}" - apt install -y ${HOME}/nomachine.deb - rm -f ${HOME}/nomachine.deb - echo "Enabling VNC" - systemctl enable --now vncserver-x11-serviced.service - fi -} - -install_cleanup_cron() { - echo "Installing the cleanup.cron" - cat $(dirname ${my_dir})/templates/cleanup.cron >> /etc/crontab -} - -install_selected_services() { - sudo apt -qqqq update - install_scripts - install_birdnet_analysis - install_birdnet_server - - if [[ "${DO_EXTRACTIONS}" =~ [Yy] ]];then - install_extraction_service - fi - - if [[ "${DO_RECORDING}" =~ [Yy] ]];then - install_alsa - install_recording_service - fi - - install_php - install_caddy - install_Caddyfile - update_etc_hosts - install_avahi_aliases - install_gotty_logs - install_sox - install_mariadb - install_spectrogram_service - install_chart_viewer_service - install_pushed_notifications - - if [ ! -z "${ICE_PWD}" ];then - install_icecast - install_livestream_service - fi - - if [[ "${INSTALL_NOMACHINE}" =~ [Yy] ]];then - install_nomachine - fi - - create_necessary_dirs - generate_BirdDB - install_cleanup_cron - install_ftpd - install_lynx -} - -if [ -f ${config_file} ];then - source ${config_file} - install_selected_services -else - echo "Unable to find a configuration file. Please make sure that $config_file exists." -fi From 793629e1c0e869e6781184c728b18fb18a05c9f4 Mon Sep 17 00:00:00 2001 From: Patrick McGuire <60325264+mcguirepr89@users.noreply.github.com> Date: Wed, 23 Feb 2022 10:42:03 -0500 Subject: [PATCH 052/160] Delete update_birdnet2.sh --- scripts/update_birdnet2.sh | 58 -------------------------------------- 1 file changed, 58 deletions(-) delete mode 100755 scripts/update_birdnet2.sh diff --git a/scripts/update_birdnet2.sh b/scripts/update_birdnet2.sh deleted file mode 100755 index a3bf9ca..0000000 --- a/scripts/update_birdnet2.sh +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env bash -# Second stage of update -USER=pi -birdnet_conf=/home/pi/BirdNET-Pi/birdnet.conf -my_dir=${HOME}/BirdNET-Pi/scripts - -# Stage 1 updates the services -sudo ${my_dir}/update_services.sh - -# Stage 1.5: adding new birdnet.conf entries -if ! grep FULL_DISK ${birdnet_conf} &> /dev/null;then - cat << EOF >> ${birdnet_conf} - -## FULL_DISK can be set to configure how the system reacts to a full disk -## purge = Remove the oldest day's worth of recordings -## keep = Keep all data and `stop_core_services.sh` - -FULL_DISK=purge -EOF -fi - -if ! grep AUDIOFMT ${birdnet_conf} &> /dev/null;then - cat<< EOF >> ${birdnet_conf} -## AUDIOFMT set the audio format that sox should use for the extractions. -## The default is mp3. Available formats are: 8svx aif aifc aiff aiffc al amb -## amr-nb amr-wb anb au avr awb caf cdda cdr cvs cvsd cvu dat dvms f32 f4 f64 f8 -## fap flac fssd gsm gsrt hcom htk ima ircam la lpc lpc10 lu mat mat4 mat5 maud -## mp2 mp3 nist ogg paf prc pvf raw s1 s16 s2 s24 s3 s32 s4 s8 sb sd2 sds sf sl -## sln smp snd sndfile sndr sndt sou sox sph sw txw u1 u16 u2 u24 u3 u32 u4 u8 -## ub ul uw vms voc vorbis vox w64 wav wavpcm wv wve xa xi -## Note: Most have not been tested. - -AUDIOFMT=mp3 -EOF -fi - -sudo -u${USER} sed -i 's/EXTRACTIONLOG_URL/WEBTERMINAL_URL/g' ${birdnetconf} - -# Replace Backup labels.txt -sudo -u${USER} cp -f ~/BirdNET-Pi/model/labels.txt.bak ~/BirdNET-Pi/model/labels.txt - -# Stage 2 restarts the services -sudo systemctl daemon-reload -sudo systemctl stop birdnet_recording.service -sudo rm -rf ${RECS_DIR}/$(date +%B-%Y/%d-%A)/* -services=(web_terminal.service -spectrogram_viewer.service -pushed_notifications.service -livestream.service -icecast2.service -extraction.service -chart_viewer.service -birdnet_recording.service -birdnet_log.service) - -for i in "${services[@]}";do -sudo systemctl restart "${i}" -done From 5d5630993b278408dbd9bfdc1f9a0dc7e5c58136 Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Wed, 23 Feb 2022 18:02:08 -0500 Subject: [PATCH 053/160] removed extraction.timer from service restart --- scripts/restart_services.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/restart_services.sh b/scripts/restart_services.sh index fe618b9..4752661 100755 --- a/scripts/restart_services.sh +++ b/scripts/restart_services.sh @@ -13,7 +13,6 @@ spectrogram_viewer.service pushed_notifications.service livestream.service icecast2.service -extraction.timer extraction.service chart_viewer.service birdnet_recording.service From 066b9c1c34ebe916d031c89ea4c35e844cfdeb22 Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Wed, 23 Feb 2022 18:05:11 -0500 Subject: [PATCH 054/160] making sure play.php and play.css make their way into ${EXTRACTED} --- scripts/install_services.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/install_services.sh b/scripts/install_services.sh index 80da0ef..0727717 100755 --- a/scripts/install_services.sh +++ b/scripts/install_services.sh @@ -145,7 +145,8 @@ create_necessary_dirs() { sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local/${BIRDNETPI_URL}/g" $(dirname ${my_dir})/scripts/*/*.php fi - sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/play.* ${EXTRACTED} + sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/play.css ${EXTRACTED} + sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/play.php ${EXTRACTED} sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/spectrogram.php ${EXTRACTED} sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/overview.php ${EXTRACTED} sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/stats.php ${EXTRACTED} From cf0a3436f770cc71664dafcb7e3945f23acc679c Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Wed, 23 Feb 2022 22:18:35 -0500 Subject: [PATCH 055/160] new ui --- scripts/advanced.php | 101 ++----------------------- scripts/config.php | 103 +------------------------- scripts/history.php | 40 ++-------- scripts/install_services.sh | 2 +- scripts/overview.php | 70 +++++------------- scripts/play.php | 3 +- scripts/spectrogram.php | 4 +- scripts/stats.php | 143 +++++------------------------------- scripts/viewdb.php | 16 +--- 9 files changed, 59 insertions(+), 423 deletions(-) diff --git a/scripts/advanced.php b/scripts/advanced.php index 8252746..892fead 100644 --- a/scripts/advanced.php +++ b/scripts/advanced.php @@ -155,93 +155,6 @@ if(isset($_POST['submit'])) {

    Advanced Settings

    - +

    Defaults

    - -
    diff --git a/scripts/config.php b/scripts/config.php index 421b5c9..8bc9a39 100644 --- a/scripts/config.php +++ b/scripts/config.php @@ -6,111 +6,10 @@ ini_set('display_errors',1); ?>

    Basic Settings

    - +
    diff --git a/scripts/history.php b/scripts/history.php index c8e0237..71f9b44 100644 --- a/scripts/history.php +++ b/scripts/history.php @@ -21,42 +21,16 @@ $totalcount = $result1->fetchArray(SQLITE3_ASSOC); ?> - - + - +
    -
    +
    @@ -67,14 +41,14 @@ hr { "; + echo ""; } else { - echo "

    No Charts for $theDate

    "; + echo "

    No Charts for $theDate

    "; } echo "
    "; if (file_exists('/home/pi/BirdSongs/Extracted/Charts/'.$chart2)) { - echo ""; + echo ""; } else { - echo "

    No Charts For $theDate

    "; + echo "

    No Charts For $theDate

    "; }?> diff --git a/scripts/install_services.sh b/scripts/install_services.sh index 0727717..211a6a1 100755 --- a/scripts/install_services.sh +++ b/scripts/install_services.sh @@ -17,7 +17,7 @@ install_depends() { apt -qqq update && apt -qqy upgrade echo "icecast2 icecast2/icecast-setup boolean false" | debconf-set-selections apt install -qqy caddy lynx ftpd sqlite3 php-sqlite3 alsa-utils \ - pulseaudio avahi-utils sox libsox-fmt-mp3 php php-fpm php-mysql php-xml \ + pulseaudio avahi-utils sox libsox-fmt-mp3 php php-fpm php-curl php-xml \ php-zip icecast2 swig ffmpeg wget unzip curl cmake make bc libjpeg-dev \ zlib1g-dev python3-dev python3-pip python3-venv wget -c ${gotty_url} -O - | tar -xz -C /usr/local/bin/ diff --git a/scripts/overview.php b/scripts/overview.php index edbc53f..d95a8a8 100644 --- a/scripts/overview.php +++ b/scripts/overview.php @@ -20,7 +20,7 @@ if($statement == False) { $result = $statement->execute(); $totalcount = $result->fetchArray(SQLITE3_ASSOC); -$statement2 = $db->prepare('SELECT COUNT(*) FROM detections WHERE Date == DATE(\'now\')'); +$statement2 = $db->prepare('SELECT COUNT(*) FROM detections WHERE Date == DATE(\'now\', \'localtime\')'); if($statement2 == False) { echo "Database is busy"; header("refresh: 0;"); @@ -44,9 +44,10 @@ if($statement4 == False) { $result4 = $statement4->execute(); $mostrecent = $result4->fetchArray(SQLITE3_ASSOC); $comname = preg_replace('/ /', '_', $mostrecent['Com_Name']); -$scilink = preg_replace('/ /', '_', $mostrecent['Sci_Name']); +$comname = preg_replace('/\'/', '', $comname); +$filename = "/By_Date/".$mostrecent['Date']."/".$comname."/".$mostrecent['File_Name']; -$statement5 = $db->prepare('SELECT COUNT(DISTINCT(Com_Name)) FROM detections WHERE Date == Date(\'now\')'); +$statement5 = $db->prepare('SELECT COUNT(DISTINCT(Com_Name)) FROM detections WHERE Date == Date(\'now\',\'localtime\')'); if($statement5 == False) { echo "Database is busy"; header("refresh: 0;"); @@ -62,48 +63,13 @@ $speciestally = $result5->fetchArray(SQLITE3_ASSOC); Overview - - - - - +
    -
    Total Detections For The Day
    +
    @@ -120,31 +86,31 @@ button {
    -
    Total Today
    +
    - - - - - + + + + + - - - + + +
    Scientific NameCommon NameListenConfidenceScientific NameCommon NameListenConfidence
    Most Recent Detection
    " target="footer"/>

    "; + echo ""; } else { - echo "

    No Detections For Today

    "; + echo "

    No Detections For Today

    "; } ?>

    Currently Analyzing

    - + diff --git a/scripts/play.php b/scripts/play.php index 0cddd5b..4f50b30 100644 --- a/scripts/play.php +++ b/scripts/play.php @@ -53,13 +53,12 @@ if(isset($_POST['bydate'])){ -
    - +
    fetchArray(SQLITE3_ASSOC)) diff --git a/scripts/spectrogram.php b/scripts/spectrogram.php index 9f2ca18..248b9f9 100644 --- a/scripts/spectrogram.php +++ b/scripts/spectrogram.php @@ -7,5 +7,5 @@ if (file_exists('/home/pi/BirdNET-Pi/thisrun.txt')) { $refreshtime = $config['RECORDING_LENGTH']; header("refresh:$refreshtime"); ?> - - + + diff --git a/scripts/stats.php b/scripts/stats.php index 3b102ee..c534daf 100644 --- a/scripts/stats.php +++ b/scripts/stats.php @@ -8,25 +8,16 @@ if($db == False) { echo "Database busy"; header("refresh: 0;"); } -$statement = $db->prepare('SELECT Com_Name, COUNT(*), MAX(Confidence), Sci_Name FROM detections GROUP BY Com_Name ORDER BY COUNT(*) DESC'); +$statement = $db->prepare('SELECT Date, Time, File_Name, Com_Name, COUNT(*), MAX(Confidence) FROM detections GROUP BY Com_Name ORDER BY COUNT(*) DESC'); if($statement == False) { echo "Database busy"; header("refresh: 0;"); } $result = $statement->execute(); - -$statement2 = $db->prepare('SELECT Com_Name FROM detections GROUP BY Com_Name ORDER BY Com_Name ASC'); -if($statement2 == False) { - echo "Database busy"; - header("refresh: 0;"); -} -$result2 = $statement2->execute(); - if(isset($_POST['species'])){ $selection = $_POST['species']; - $statement3 = $db->prepare("SELECT Com_Name, Sci_Name, COUNT(*), MAX(Confidence), File_Name, Date from detections - WHERE Com_Name = \"$selection\""); + $statement3 = $db->prepare("SELECT Com_Name, Sci_Name, COUNT(*), MAX(Confidence), File_Name, Date, Time from detections WHERE Com_Name = \"$selection\""); if($statement3 == False) { echo "Database busy"; header("refresh: 0;"); @@ -35,142 +26,46 @@ if(isset($_POST['species'])){ } ?> -BirdNET-Pi DB - - +
    Choose a species below to show statistics.

    "; + echo "

    Choose a species below to show statistics.

    "; };?>
    + fetchArray(SQLITE3_ASSOC)) { $comname = preg_replace('/ /', '_', $results['Com_Name']); -$comlink = "/By_Date/".date('Y-m-d')."/".$comname; -$sciname = preg_replace('/ /', '_', $results['Sci_Name']); +$comname = preg_replace('/\'/', '', $comname); +$filename = "/By_Date/".$results['Date']."/".$comname."/".$results['File_Name']; ?> - - + + + + fetchArray(SQLITE3_ASSOC)){ $count = $results['COUNT(*)']; $maxconf = $results['MAX(Confidence)']; $date = $results['Date']; + $time = $results['Time']; $name = $results['Com_Name']; $sciname = $results['Sci_Name']; - $dbname = preg_replace('/ /', '_', $results['Com_Name']); - $dbname = preg_replace('/\'/', '', $dbname); - $dbsciname = preg_replace('/ /', '_', $results['Sci_Name']); - $filename = "/By_Date/".$date."/".$dbname."/".$results['File_Name']; + $comname = preg_replace('/ /', '_', $results['Com_Name']); + $comname = preg_replace('/\'/', '', $comname); + $filename = "/By_Date/".$date."/".$comname."/".$results['File_Name']; $imagelink = shell_exec("/home/pi/BirdNET-Pi/scripts/get_image.sh $dbsciname"); $imagecitation = shell_exec("/home/pi/BirdNET-Pi/scripts/get_citation.sh $dbsciname"); $str= " - - + +
    Common Name Occurrences Max Confidence ScoreBest Recording
    + +
    $sciname $count $maxconfListenAll About Birds$date $time All About Birds
    "; echo str_pad($str, 4096); diff --git a/scripts/viewdb.php b/scripts/viewdb.php index 3bd7238..567acc9 100644 --- a/scripts/viewdb.php +++ b/scripts/viewdb.php @@ -11,7 +11,7 @@ if($db == False){ header("refresh: 0;"); } -$statement0 = $db->prepare('SELECT Time, Com_Name, Sci_Name, Confidence, File_Name FROM detections WHERE Date == Date(\'now\') ORDER BY Time DESC'); +$statement0 = $db->prepare('SELECT Time, Com_Name, Sci_Name, Confidence, File_Name FROM detections WHERE Date == Date(\'now\', \'localtime\') ORDER BY Time DESC'); if($statement0 == False){ echo "Database is busy"; header("refresh: 0;"); @@ -26,7 +26,7 @@ if($statement1 == False){ $result1 = $statement1->execute(); $totalcount = $result1->fetchArray(SQLITE3_ASSOC); -$statement2 = $db->prepare('SELECT COUNT(*) FROM detections WHERE Date == DATE(\'now\')'); +$statement2 = $db->prepare('SELECT COUNT(*) FROM detections WHERE Date == DATE(\'now\', \'localtime\')'); if($statement2 == False){ echo "Database is busy"; header("refresh: 0;"); @@ -67,21 +67,13 @@ $speciestally = $result5->fetchArray(SQLITE3_ASSOC); BirdNET-Pi DB - - +

    Number of Detections

    -
    -
    @@ -96,8 +88,6 @@ a {
    Total
    -
    -

    Today's Detections

    From 10090f9411e18913e4cb17655e8f7d5521fd419c Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Thu, 24 Feb 2022 13:27:08 -0500 Subject: [PATCH 056/160] saving changes --- scripts/birdnet_analysis.sh | 18 ++++++------- scripts/clear_all_data.sh | 1 + scripts/config.php | 14 ++++------ scripts/overview.php | 36 +++++++++++++++---------- scripts/play.php | 54 ++++++++++++++++++------------------- scripts/restart_services.sh | 2 +- scripts/server.py | 1 + scripts/spectrogram.php | 11 ++------ scripts/stats.php | 13 ++++----- scripts/viewdb.php | 19 ++++++++----- scripts/write_config.php | 14 ---------- 11 files changed, 87 insertions(+), 96 deletions(-) diff --git a/scripts/birdnet_analysis.sh b/scripts/birdnet_analysis.sh index dbf0e81..acc0a47 100755 --- a/scripts/birdnet_analysis.sh +++ b/scripts/birdnet_analysis.sh @@ -166,9 +166,9 @@ run_analysis() { --lon "${LONGITUDE}" \ --week "${WEEK}" \ --overlap "${OVERLAP}" \ - --sensitivity "${SENSITIVITY}" \ + --sensitivity "${SENSITIVITY}" \ --min_conf "${CONFIDENCE}" \ - --include_list "${INCLUDE_LIST}" + --include_list "${INCLUDE_LIST}" elif [ -f ${1}/${i} ] && [ ! -f ${INCLUDE_LIST} ] && [ -f ${EXCLUDE_LIST} ] && [ -z $BIRDWEATHER_ID ];then echo "analyze.py \ --i "${1}/${i}" \ @@ -187,9 +187,9 @@ run_analysis() { --lon "${LONGITUDE}" \ --week "${WEEK}" \ --overlap "${OVERLAP}" \ - --sensitivity "${SENSITIVITY}" \ + --sensitivity "${SENSITIVITY}" \ --min_conf "${CONFIDENCE}" \ - --exclude_list "${EXCLUDE_LIST}" + --exclude_list "${EXCLUDE_LIST}" elif [ -f ${1}/${i} ] && [ -f ${INCLUDE_LIST} ] && [ -f ${EXCLUDE_LIST} ] && [ -z $BIRDWEATHER_ID ];then echo "analyze.py \ --i "${1}/${i}" \ @@ -209,7 +209,7 @@ run_analysis() { --lon "${LONGITUDE}" \ --week "${WEEK}" \ --overlap "${OVERLAP}" \ - --sensitivity "${SENSITIVITY}" \ + --sensitivity "${SENSITIVITY}" \ --min_conf "${CONFIDENCE}" \ --include_list "${INCLUDE_LIST}" \ --exclude_list "${EXCLUDE_LIST}" @@ -231,7 +231,7 @@ run_analysis() { --lon "${LONGITUDE}" \ --week "${WEEK}" \ --overlap "${OVERLAP}" \ - --sensitivity "${SENSITIVITY}" \ + --sensitivity "${SENSITIVITY}" \ --min_conf "${CONFIDENCE}" \ --birdweather_id "${BIRDWEATHER_ID}" elif [ -f ${1}/${i} ] && [ -f ${INCLUDE_LIST} ] && [ ! -f ${EXCLUDE_LIST} ] && [ ! -z $BIRDWEATHER_ID ];then @@ -253,7 +253,7 @@ run_analysis() { --lon "${LONGITUDE}" \ --week "${WEEK}" \ --overlap "${OVERLAP}" \ - --sensitivity "${SENSITIVITY}" \ + --sensitivity "${SENSITIVITY}" \ --min_conf "${CONFIDENCE}" \ --include_list "${INCLUDE_LIST}" \ --birdweather_id "${BIRDWEATHER_ID}" @@ -276,7 +276,7 @@ run_analysis() { --lon "${LONGITUDE}" \ --week "${WEEK}" \ --overlap "${OVERLAP}" \ - --sensitivity "${SENSITIVITY}" \ + --sensitivity "${SENSITIVITY}" \ --min_conf "${CONFIDENCE}" \ --exclude_list "${EXCLUDE_LIST}" \ --birdweather_id "${BIRDWEATHER_ID}" @@ -300,7 +300,7 @@ run_analysis() { --lon "${LONGITUDE}" \ --week "${WEEK}" \ --overlap "${OVERLAP}" \ - --sensitivity "${SENSITIVITY}" \ + --sensitivity "${SENSITIVITY}" \ --min_conf "${CONFIDENCE}" \ --include_list "${INCLUDE_LIST}" \ --exclude_list "${EXCLUDE_LIST}" \ diff --git a/scripts/clear_all_data.sh b/scripts/clear_all_data.sh index 7c8498c..1eba83b 100755 --- a/scripts/clear_all_data.sh +++ b/scripts/clear_all_data.sh @@ -60,6 +60,7 @@ sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/overview.php ${EXTRACTED} sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/stats.php ${EXTRACTED} sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/viewdb.php ${EXTRACTED} sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/history.php ${EXTRACTED} +sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/play.php ${EXTRACTED} sudo -u ${USER} ln -fs $(dirname ${my_dir})/homepage/images/favicon.ico ${EXTRACTED} sudo -u ${USER} ln -fs ${HOME}/phpsysinfo ${EXTRACTED} sudo -u ${USER} cp -f $(dirname ${my_dir})/templates/phpsysinfo.ini ${HOME}/phpsysinfo/ diff --git a/scripts/config.php b/scripts/config.php index 8bc9a39..4b950fe 100644 --- a/scripts/config.php +++ b/scripts/config.php @@ -12,7 +12,7 @@ ini_set('display_errors',1);
    -
    + Ukrainian

    - -
    - - -
    - + +
    diff --git a/scripts/overview.php b/scripts/overview.php index d95a8a8..e67161b 100644 --- a/scripts/overview.php +++ b/scripts/overview.php @@ -28,7 +28,7 @@ if($statement2 == False) { $result2 = $statement2->execute(); $todaycount = $result2->fetchArray(SQLITE3_ASSOC); -$statement3 = $db->prepare('SELECT COUNT(*) FROM detections WHERE TIME >= TIME(\'now\', \'localtime\', \'-1 hour\')'); +$statement3 = $db->prepare('SELECT COUNT(*) FROM detections WHERE Date == Date(\'now\', \'localtime\') AND TIME >= TIME(\'now\', \'localtime\', \'-1 hour\')'); if($statement3 == False) { echo "Database is busy"; header("refresh: 0;"); @@ -78,9 +78,13 @@ $speciestally = $result5->fetchArray(SQLITE3_ASSOC);
    - + + + - + + +
    @@ -88,19 +92,23 @@ $speciestally = $result5->fetchArray(SQLITE3_ASSOC); - - - - - + + + + + - - + + - - - + + + +
    Scientific NameCommon NameListenConfidenceMost Recent DetectionScientific NameCommon NameListenConfidence
    Most Recent Detection".$mostrecent['Time'];?>

    + + +
    @@ -108,7 +116,7 @@ $speciestally = $result5->fetchArray(SQLITE3_ASSOC); if (file_exists('/home/pi/BirdSongs/Extracted/Charts/'.$chart)) { echo ""; } else { - echo "

    No Detections For Today

    "; + echo "

    No Detections For Today

    "; } ?>

    Currently Analyzing

    diff --git a/scripts/play.php b/scripts/play.php index 4f50b30..10239b9 100644 --- a/scripts/play.php +++ b/scripts/play.php @@ -10,24 +10,16 @@ if($db == False){ } if(isset($_POST['bydate'])){ - $statement = $db->prepare('SELECT DISTINCT(Date), Com_Name from detections GROUP BY Date'); + $statement = $db->prepare('SELECT DISTINCT(Date), Com_Name FROM detections GROUP BY Date'); if($statement == False){ echo "Database is busy"; header("refresh: 0;"); } $result = $statement->execute(); $view = "bydate"; -} elseif(isset($_POST['byspecies'])) { - $statement = $db->prepare('SELECT DISTINCT(Com_Name) from detections ORDER BY Com_Name'); - if($statement == False){ - echo "Database is busy"; - header("refresh: 0;"); - } - $result = $statement->execute(); - $view = "byspecies"; } elseif(isset($_POST['date'])) { $date = $_POST['date']; - $statement = $db->prepare("SELECT DISTINCT(Com_Name) from detections WHERE Date == \"$date\" ORDER BY Com_Name"); + $statement = $db->prepare("SELECT DISTINCT(Com_Name) FROM detections WHERE Date == \"$date\" ORDER BY Com_Name"); if($statement == False){ echo "Database is busy"; header("refresh: 0;"); @@ -36,8 +28,8 @@ if(isset($_POST['bydate'])){ $view = "date"; } elseif(isset($_POST['species'])) { $species = $_POST['species']; - $statement = $db->prepare("SELECT * from detections WHERE Com_Name == \"$species\" ORDER BY Com_Name"); - $statement3 = $db->prepare("SELECT Date, Time, Com_Name, MAX(Confidence), File_Name from detections WHERE Com_Name == \"$species\" ORDER BY Com_Name"); + $statement = $db->prepare("SELECT * FROM detections WHERE Com_Name == \"$species\" ORDER BY Com_Name"); + $statement3 = $db->prepare("SELECT Date, Time, Com_Name, MAX(Confidence), File_Name FROM detections WHERE Com_Name == \"$species\" ORDER BY Com_Name"); if($statement == False || $statement3 == False){ echo "Database is busy"; header("refresh: 0;"); @@ -45,8 +37,15 @@ if(isset($_POST['bydate'])){ $result = $statement->execute(); $result3 = $statement3->execute(); $view = "species"; +} else { + $statement = $db->prepare('SELECT DISTINCT(Com_Name) FROM detections ORDER BY Com_Name'); + if($statement == False){ + echo "Database is busy"; + header("refresh: 0;"); + } + $result = $statement->execute(); + $view = "byspecies"; } - ?> @@ -57,7 +56,6 @@ if(isset($_POST['bydate'])){ -
    fetchArray(SQLITE3_ASSOC))
    + fetchArray(SQLITE3_ASSOC)) $maxconf = $results['MAX(Confidence)']; $date = $results['Date']; $time = $results['Time']; - $comname = preg_replace('/ /', '_', $results['Com_Name']); + $name = $results['Com_Name']; + $comname = preg_replace('/ /', '_', $name); + $comname = preg_replace('/\'/', '', $comname); $file = $results['File_Name']; $filename = "/By_Date/".$date."/".$comname."/".$results['File_Name']; echo " + - + +
    $name Max Confidence: $maxconf
    Most confident recording: $fileMost confident recording:
    "; };};?>
    -
    -
    fetchArray(SQLITE3_ASSOC)) $result2 = $statement2->execute(); echo " - - + + @@ -119,24 +120,23 @@ while($results=$result->fetchArray(SQLITE3_ASSOC)) while($results=$result2->fetchArray(SQLITE3_ASSOC)) { $comname = preg_replace('/ /', '_', $results['Com_Name']); + $comname = preg_replace('/\'/', '', $comname); $date = $results['Date']; - $comlink = "/By_Date/".$date."/".$comname."/".$results['File_Name']; + $filename = "/By_Date/".$date."/".$comname."/".$results['File_Name']; $sciname = preg_replace('/ /', '_', $results['Sci_Name']); $sci_name = $results['Sci_Name']; $time = $results['Time']; $confidence = $results['Confidence']; echo " - - + + - - "; }echo "
    DateTimeWhenListen Scientific Name Common Name Confidence
    $date$time$date $time $sci_name
    + + $confidence
    ";}?> -
    -
    diff --git a/scripts/restart_services.sh b/scripts/restart_services.sh index 4752661..cb5384b 100755 --- a/scripts/restart_services.sh +++ b/scripts/restart_services.sh @@ -23,6 +23,6 @@ sudo systemctl restart "${i}" done until grep 5050 <(netstat -tulpn 2>&1);do sudo systemctl restart birdnet_server.service -sleep 30 +sleep 45 done sudo systemctl restart birdnet_analysis.service diff --git a/scripts/server.py b/scripts/server.py index 3916582..5ca5064 100755 --- a/scripts/server.py +++ b/scripts/server.py @@ -349,6 +349,7 @@ def handle_client(conn, addr): Week = str(args.week) Sens = str(args.sensitivity) Overlap = str(args.overlap) + Com_Name = Com_Name.replate("'", "") File_Name = Com_Name.replace(" ", "_") + '-' + Confidence + '-' + \ Date.replace("/", "-") + '-birdnet-' + Time + audiofmt diff --git a/scripts/spectrogram.php b/scripts/spectrogram.php index 248b9f9..cc324bf 100644 --- a/scripts/spectrogram.php +++ b/scripts/spectrogram.php @@ -1,11 +1,4 @@ "; ?> - - diff --git a/scripts/stats.php b/scripts/stats.php index c534daf..98989b6 100644 --- a/scripts/stats.php +++ b/scripts/stats.php @@ -76,7 +76,6 @@ $filename = "/By_Date/".$results['Date']."/".$comname."/".$results['File_Name']; $species = $_POST['species']; $str = "

    $species

    -

    Species Stats

    @@ -96,27 +95,29 @@ while($results=$result3->fetchArray(SQLITE3_ASSOC)){ $time = $results['Time']; $name = $results['Com_Name']; $sciname = $results['Sci_Name']; + $dbsciname = preg_replace('/ /', '_', $sciname); $comname = preg_replace('/ /', '_', $results['Com_Name']); $comname = preg_replace('/\'/', '', $comname); $filename = "/By_Date/".$date."/".$comname."/".$results['File_Name']; $imagelink = shell_exec("/home/pi/BirdNET-Pi/scripts/get_image.sh $dbsciname"); $imagecitation = shell_exec("/home/pi/BirdNET-Pi/scripts/get_citation.sh $dbsciname"); - $str= " + echo str_pad(" -
    Scientific Name
    $sciname $count $maxconf $date $time All About Birds
    "; - echo str_pad($str, 4096); + ", '4096'); ob_flush(); flush(); - echo " + echo str_pad("
    $imagecitation
    -
    "; +
    ", '4096'); + ob_flush(); + flush(); }} ?> diff --git a/scripts/viewdb.php b/scripts/viewdb.php index 567acc9..05e5126 100644 --- a/scripts/viewdb.php +++ b/scripts/viewdb.php @@ -3,8 +3,6 @@ ini_set('display_errors', 1); ini_set('display_startup_errors', 1); error_reporting(E_ALL); -header("refresh: 30;"); - $db = new SQLite3('/home/pi/BirdNET-Pi/scripts/birds.db', SQLITE3_OPEN_CREATE | SQLITE3_OPEN_READWRITE); if($db == False){ echo "Database is busy"; @@ -34,7 +32,7 @@ if($statement2 == False){ $result2 = $statement2->execute(); $todaycount = $result2->fetchArray(SQLITE3_ASSOC); -$statement3 = $db->prepare('SELECT COUNT(*) FROM detections WHERE TIME >= TIME(\'now\', \'localtime\', \'-1 hour\')'); +$statement3 = $db->prepare('SELECT COUNT(*) FROM detections WHERE Date == Date(\'now\', \'localtime\') AND TIME >= TIME(\'now\', \'localtime\', \'-1 hour\')'); if($statement3 == False){ echo "Database is busy"; header("refresh: 0;"); @@ -83,15 +81,20 @@ $speciestally = $result5->fetchArray(SQLITE3_ASSOC); - +
    + +
    - +
    + +

    Today's Detections

    + @@ -100,11 +103,13 @@ $speciestally = $result5->fetchArray(SQLITE3_ASSOC); while($todaytable=$result0->fetchArray(SQLITE3_ASSOC)) { $comname = preg_replace('/ /', '_', $todaytable['Com_Name']); -$comlink = "/By_Date/".date('Y-m-d')."/".$comname."/".$todaytable['File_Name']; +$comname = preg_replace('/\'/', '_', $comname); +$filename = "/By_Date/".date('Y-m-d')."/".$comname."/".$todaytable['File_Name']; $sciname = preg_replace('/ /', '_', $todaytable['Sci_Name']); ?> - + + diff --git a/scripts/write_config.php b/scripts/write_config.php index f423cd5..ed5aa19 100644 --- a/scripts/write_config.php +++ b/scripts/write_config.php @@ -26,25 +26,11 @@ $fh = fopen("/home/pi/BirdNET-Pi/birdnet.conf", "w"); $fh2 = fopen("/home/pi/BirdNET-Pi/thisrun.txt", "w"); fwrite($fh, $contents); fwrite($fh2, $contents2); -session_start(); -$_SESSION['success'] = 1; -if(isset($_POST["normal"])){ - header('Location:config.php'); -}else{ - header('Location:../../'); -} $language = $_POST["language"]; if ($language != "none"){ $command = "sudo -upi mv /home/pi/BirdNET-Pi/model/labels.txt /home/pi/BirdNET-Pi/model/labels.txt.old && sudo -upi unzip /home/pi/BirdNET-Pi/model/labels_l18n.zip $language -d /home/pi/BirdNET-Pi/model && sudo -upi mv /home/pi/BirdNET-Pi/model/$language /home/pi/BirdNET-Pi/model/labels.txt"; $command_output = `$command`; -session_start(); -$_SESSION['success'] = 1; -if(isset($_POST["normal"])){ - header('Location:config.php'); -}else{ - header('Location:../../'); -} } ?> From 9d16d0245cb9cebb91106e7b91ee88d5d8bd7b58 Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Thu, 24 Feb 2022 14:11:54 -0500 Subject: [PATCH 057/160] configs are updating --- scripts/advanced.php | 28 +++++++++------------------- scripts/config.php | 18 ++++++++++-------- scripts/write_config.php | 2 ++ 3 files changed, 21 insertions(+), 27 deletions(-) diff --git a/scripts/advanced.php b/scripts/advanced.php index 892fead..852d211 100644 --- a/scripts/advanced.php +++ b/scripts/advanced.php @@ -166,9 +166,7 @@ if (file_exists('/home/pi/BirdNET-Pi/thisrun.txt')) { ?>

    Advanced Settings

    -
    -
    -
    +

    Defaults

    -

    Custom URLs

    When you update any of the URL settings below, the web server will reload, so be sure to wait at least 30 seconds and then reload the page.

    @@ -236,24 +232,18 @@ foreach($formats as $format){

    Min=0.5, Max=1.5



    - +?>
    - -
    - - -
    -
    - - -
    -
    + +
    + + diff --git a/scripts/config.php b/scripts/config.php index 4b950fe..52501e5 100644 --- a/scripts/config.php +++ b/scripts/config.php @@ -66,18 +66,20 @@ if (file_exists('/home/pi/BirdNET-Pi/thisrun.txt')) {

    - - -
    - - +?> + + +
    + + - diff --git a/scripts/write_config.php b/scripts/write_config.php index ed5aa19..c509183 100644 --- a/scripts/write_config.php +++ b/scripts/write_config.php @@ -2,6 +2,7 @@ error_reporting(E_ALL); ini_set('display_errors',1); +if(isset($_POST["latitude"])){ $latitude = $_POST["latitude"]; $longitude = $_POST["longitude"]; $birdweather_id = $_POST["birdweather_id"]; @@ -32,5 +33,6 @@ if ($language != "none"){ $command = "sudo -upi mv /home/pi/BirdNET-Pi/model/labels.txt /home/pi/BirdNET-Pi/model/labels.txt.old && sudo -upi unzip /home/pi/BirdNET-Pi/model/labels_l18n.zip $language -d /home/pi/BirdNET-Pi/model && sudo -upi mv /home/pi/BirdNET-Pi/model/$language /home/pi/BirdNET-Pi/model/labels.txt"; $command_output = `$command`; } +} ?> From a9d386c6218f6d4fd28b66db12b1de4398821fc4 Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Thu, 24 Feb 2022 19:09:10 -0500 Subject: [PATCH 058/160] this is the new one --- homepage/index.php | 108 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 homepage/index.php diff --git a/homepage/index.php b/homepage/index.php new file mode 100644 index 0000000..31eb1c6 --- /dev/null +++ b/homepage/index.php @@ -0,0 +1,108 @@ + + + $_POST['species'] ]; + httpPost('/stats.php', $data);} + } + if($_POST['view'] == "History"){ + include('history.php'); + $data = [ 'date' => $_POST['date'] ]; + httpPost('/history.php', $data); + } + if($_POST['view'] == "Tools"){ + echo "
    + + + "; + } + if($_POST['view'] == "Live Stream"){ + echo "
    ";} + if($_POST['view'] == "Extractions"){ + include('play.php'); + $data = []; + httpPost('/play.php', $data);} + while($_POST['view'] == "Spectrogram"){ + ob_start(); + $time = time(); + echo str_pad("", '4096'); + ob_flush(); + flush(); + sleep($config['RECORDING_LENGTH']); + ob_clean(); + ob_end_clean(); + ob_end_flush();} + if($_POST['view'] == "Settings"){ + if(isset($_POST['submit'])){ + $data = [ + 'latitude' => $_POST["latitude"], + 'longitude' => $_POST["longitude"], + 'birdweather_id' => $_POST["birdweather_id"], + 'pushed_app_key' => $_POST["pushed_app_key"], + 'pushed_app_secret' => $_POST["pushed_app_secret"], + 'language' => $_POST["language"], + 'submit' => $_POST["submit"], + ]; + $url = $_SERVER['HTTP_REFERER']; + httpPost("$url/scripts/update_config.php", $data); + } + include('scripts/config.php'); + } + if($_POST['view'] == "Advanced"){ + if(isset($_POST['submit'])){ + $data = [ + 'caddy_pwd' => $_POST["caddy_pwd"], + 'ice_pwd' => $_POST["ice_pwd"], + 'webterminal_url' => $_POST["webterminal_url"], + 'birdnetlog_url' => $_POST["birdnetlog_url"], + 'birdnetpi_url' => $_POST["birdnetpi_url"], + 'overlap' => $_POST["overlap"], + 'confidence' => $_POST["confidence"], + 'sensitivity' => $_POST["sensitivity"], + 'full_disk' => $_POST["full_disk"], + 'rec_card' => $_POST["rec_card"], + 'channels' => $_POST["channels"], + 'recording_length' => $_POST["recording_length"], + 'extraction_length' => $_POST["extraction_length"], + 'audiofmt' => $_POST["audiofmt"], + 'status' => "Success" + ]; + $url = $_SERVER['HTTP_REFERER']; + httpPost("$url/scripts/update_config.php", $data); + } + include('scripts/advanced.php'); + } + if($_POST['view'] == "System"){header('location:phpsysinfo/index.php');} + if($_POST['view'] == "Log"){ + $url = 'http://birdnetpi.local:8080'; + header("location: $url;");} +} +?> From 840b071ffa6b6bfba0ebdff239d8cb8b12f3955d Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Fri, 25 Feb 2022 10:21:42 -0500 Subject: [PATCH 059/160] tweaks for this --- homepage/index.php | 54 ++++++++++++++++++++-------------------------- 1 file changed, 23 insertions(+), 31 deletions(-) diff --git a/homepage/index.php b/homepage/index.php index 31eb1c6..9793749 100644 --- a/homepage/index.php +++ b/homepage/index.php @@ -25,13 +25,16 @@ foreach($pages as $page){ echo $response; } if(isset($_POST['view'])){ + if($_POST['view'] == "System"){header('location:phpsysinfo/index.php');} + if($_POST['view'] == "Spectrogram"){include('spectrogram.php');} if($_POST['view'] == "Overview"){include('overview.php');} if($_POST['view'] == "Database"){include('viewdb.php');} if($_POST['view'] == "Species Stats"){ include('stats.php'); if(isset($_POST['species'])){ - $data = [ 'species' => $_POST['species'] ]; - httpPost('/stats.php', $data);} + $data = [ 'species' => $_POST['species'] ]; + httpPost('/stats.php', $data); + } } if($_POST['view'] == "History"){ include('history.php'); @@ -42,40 +45,30 @@ if(isset($_POST['view'])){ echo "
    - "; + "; } if($_POST['view'] == "Live Stream"){ - echo "
    ";} + echo "";} if($_POST['view'] == "Extractions"){ include('play.php'); $data = []; httpPost('/play.php', $data);} - while($_POST['view'] == "Spectrogram"){ - ob_start(); - $time = time(); - echo str_pad("", '4096'); - ob_flush(); - flush(); - sleep($config['RECORDING_LENGTH']); - ob_clean(); - ob_end_clean(); - ob_end_flush();} - if($_POST['view'] == "Settings"){ - if(isset($_POST['submit'])){ - $data = [ - 'latitude' => $_POST["latitude"], - 'longitude' => $_POST["longitude"], - 'birdweather_id' => $_POST["birdweather_id"], - 'pushed_app_key' => $_POST["pushed_app_key"], - 'pushed_app_secret' => $_POST["pushed_app_secret"], - 'language' => $_POST["language"], - 'submit' => $_POST["submit"], - ]; - $url = $_SERVER['HTTP_REFERER']; - httpPost("$url/scripts/update_config.php", $data); - } - include('scripts/config.php'); - } + if($_POST['view'] == "Settings"){ + if(isset($_POST['submit'])){ + $data = [ + 'latitude' => $_POST["latitude"], + 'longitude' => $_POST["longitude"], + 'birdweather_id' => $_POST["birdweather_id"], + 'pushed_app_key' => $_POST["pushed_app_key"], + 'pushed_app_secret' => $_POST["pushed_app_secret"], + 'language' => $_POST["language"], + 'submit' => $_POST["submit"], + ]; + $url = $_SERVER['HTTP_REFERER']; + httpPost("$url/scripts/update_config.php", $data); + } + include('scripts/config.php'); + } if($_POST['view'] == "Advanced"){ if(isset($_POST['submit'])){ $data = [ @@ -100,7 +93,6 @@ if(isset($_POST['view'])){ } include('scripts/advanced.php'); } - if($_POST['view'] == "System"){header('location:phpsysinfo/index.php');} if($_POST['view'] == "Log"){ $url = 'http://birdnetpi.local:8080'; header("location: $url;");} From 957a7d83905a985c0116810cc8fb78e84f3022be Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Fri, 25 Feb 2022 10:31:38 -0500 Subject: [PATCH 060/160] pulling sqlite changes --- scripts/update_caddyfile.sh | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/scripts/update_caddyfile.sh b/scripts/update_caddyfile.sh index 6b8982d..20503fb 100755 --- a/scripts/update_caddyfile.sh +++ b/scripts/update_caddyfile.sh @@ -70,12 +70,14 @@ fi sudo -u${USER} git -C /home/pi/BirdNET-Pi checkout -f homepage/* sudo -u${USER} git -C /home/pi/BirdNET-Pi checkout -f scripts/* sudo -u${USER} git -C /home/pi/BirdNET-Pi checkout -f scripts/*/* -sudo -u${USER} sed -i "s/https:\/\/v2.wttr.in\//https:\/\/v2.wttr.in\/"${LATITUDE},${LONGITUDE}"/g" $(dirname ${my_dir})/homepage/menu.html +sudo -u${USER} sed -i "s/wttr.in/wttr.in\/${LATITUDE},${LONGITUDE}/g" $(dirname ${my_dir})/homepage/menu.html if [ ! -z ${BIRDNETLOG_URL} ];then BIRDNETLOG_URL="$(echo ${BIRDNETLOG_URL} | sed 's/\/\//\\\/\\\//g')" +elif [ -z ${BIRDNETPI_URL} ];then + BIRDNETLOG_URL="http:\/\/$(hostname).local:8080" else - BIRDNETLOG_URL="$(echo http://$(hostname).local:8080 | sed 's/\/\//\\\/\\\//g')" + BIRDNETLOG_URL="${BIRDNETPI_URL}:8080" fi sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8080/${BIRDNETLOG_URL}/g" $(dirname ${my_dir})/homepage/*.html sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8080/${BIRDNETLOG_URL}/g" $(dirname ${my_dir})/scripts/*.html @@ -85,8 +87,10 @@ sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8080/${BIRDNETLOG_URL}/g" $(di if [ ! -z ${WEBTERMINAL_URL} ];then WEBTERMINAL_URL="$(echo ${WEBTERMINAL_URL} | sed 's/\/\//\\\/\\\//g')" +elif [ -z ${BIRDNETPI_URL} ];then + WEBTERMINAL_URL="http:\/\/$(hostname).local:8080" else - WEBTERMINAL_URL="$(echo http://$(hostname).local:8888 | sed 's/\/\//\\\/\\\//g')" + WEBTERMINAL_URL="${BIRDNETPI_URL}:8888" fi sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8888/${WEBTERMINAL_URL}/g" $(dirname ${my_dir})/homepage/*.html sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8888/${WEBTERMINAL_URL}/g" $(dirname ${my_dir})/scripts/*.html @@ -110,4 +114,4 @@ else sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local/${BIRDNETPI_URL}/g" $(dirname ${my_dir})/scripts/*/*.php fi -systemctl reload caddy +sudo systemctl reload caddy From 95c01b749ff2b4ac81f20f70504f7d5ffdcbb17f Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Fri, 25 Feb 2022 10:40:11 -0500 Subject: [PATCH 061/160] typo --- scripts/update_caddyfile.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/update_caddyfile.sh b/scripts/update_caddyfile.sh index 20503fb..180dcae 100755 --- a/scripts/update_caddyfile.sh +++ b/scripts/update_caddyfile.sh @@ -70,7 +70,6 @@ fi sudo -u${USER} git -C /home/pi/BirdNET-Pi checkout -f homepage/* sudo -u${USER} git -C /home/pi/BirdNET-Pi checkout -f scripts/* sudo -u${USER} git -C /home/pi/BirdNET-Pi checkout -f scripts/*/* -sudo -u${USER} sed -i "s/wttr.in/wttr.in\/${LATITUDE},${LONGITUDE}/g" $(dirname ${my_dir})/homepage/menu.html if [ ! -z ${BIRDNETLOG_URL} ];then BIRDNETLOG_URL="$(echo ${BIRDNETLOG_URL} | sed 's/\/\//\\\/\\\//g')" @@ -88,7 +87,7 @@ sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8080/${BIRDNETLOG_URL}/g" $(di if [ ! -z ${WEBTERMINAL_URL} ];then WEBTERMINAL_URL="$(echo ${WEBTERMINAL_URL} | sed 's/\/\//\\\/\\\//g')" elif [ -z ${BIRDNETPI_URL} ];then - WEBTERMINAL_URL="http:\/\/$(hostname).local:8080" + WEBTERMINAL_URL="http:\/\/$(hostname).local:8888" else WEBTERMINAL_URL="${BIRDNETPI_URL}:8888" fi From c5a49c1cca854466c7d75e0d0c75c0aaeb10c1c6 Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Fri, 25 Feb 2022 11:35:47 -0500 Subject: [PATCH 062/160] newif overhauls so far --- homepage/external.html | 60 ---- homepage/footer.html | 22 -- homepage/index.html | 42 --- homepage/index.php | 54 +++ homepage/menu.html | 92 ----- homepage/menu_de.html | 80 ----- homepage/mobile.html | 509 ---------------------------- homepage/top.html | 51 --- homepage/top_de.html | 51 --- scripts/add_to_exclude.php | 14 - scripts/add_to_include.php | 14 - scripts/clear_all_data.sh | 2 - scripts/del_from_exclude.php | 22 -- scripts/del_from_include.php | 22 -- scripts/exclude_list.php | 117 ++----- scripts/filemanager/filemanager.php | 2 +- scripts/include_list.php | 95 +----- scripts/index.html | 2 +- scripts/install_services.sh | 2 - 19 files changed, 83 insertions(+), 1170 deletions(-) delete mode 100644 homepage/external.html delete mode 100644 homepage/footer.html delete mode 100644 homepage/index.html delete mode 100644 homepage/menu.html delete mode 100644 homepage/menu_de.html delete mode 100644 homepage/mobile.html delete mode 100644 homepage/top.html delete mode 100644 homepage/top_de.html delete mode 100644 scripts/add_to_exclude.php delete mode 100644 scripts/add_to_include.php delete mode 100644 scripts/del_from_exclude.php delete mode 100644 scripts/del_from_include.php diff --git a/homepage/external.html b/homepage/external.html deleted file mode 100644 index ec8343d..0000000 --- a/homepage/external.html +++ /dev/null @@ -1,60 +0,0 @@ - - -HTML Frames Example - Content - - - -tbc.... -

    Thanks

    -stefan kahl -patrick mcguire -

    Similar Systems

    -

    Technical Details

    -machine learning -deep learning -

    Used Tools

    -SoX -ffmpeg -Python -Tensorfflow (Lite) -Rasberian OS -

    Disclaimer

    -

    Other Systems

    -links to other systems - - - -

    Content

    -

    Replacing the Contents of the Current Frame

    -

    Clicking on these links will open the new page within the current frame.

    - - -

    Replacing the Whole Frameset

    -

    When you click on any of the following links, the whole frameset is replaced with the new website. This is because we're using target="_top" in the anchor links.

    - - -

    Open a New Window

    -

    These links open in a new browser window. This is because we use target="_blank".

    - - - - \ No newline at end of file diff --git a/homepage/footer.html b/homepage/footer.html deleted file mode 100644 index 9741849..0000000 --- a/homepage/footer.html +++ /dev/null @@ -1,22 +0,0 @@ - - -HTML Frames Example - Footer - - - -

    Play Live Audio

    -

    - - diff --git a/homepage/index.html b/homepage/index.html deleted file mode 100644 index a1294b0..0000000 --- a/homepage/index.html +++ /dev/null @@ -1,42 +0,0 @@ - - - - - BirdNET-Pi - - - - - - - - - - - - - - - - <p>This section (everything between the 'noframes' tags) will only be displayed if the users' browser doesn't support frames. You can provide a link to a non-frames version of the website here. Feel free to use HTML tags within this section.</p> - - - - diff --git a/homepage/index.php b/homepage/index.php index 9793749..8bcb502 100644 --- a/homepage/index.php +++ b/homepage/index.php @@ -29,6 +29,58 @@ if(isset($_POST['view'])){ if($_POST['view'] == "Spectrogram"){include('spectrogram.php');} if($_POST['view'] == "Overview"){include('overview.php');} if($_POST['view'] == "Database"){include('viewdb.php');} + if($_POST['view'] == "Included"){ + if(isset($_POST['species']) && isset($_POST['add'])){ + $file='/home/pi/BirdNET-Pi/include_species_list.txt'; + $str=file_get_contents("$file"); + $str = preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $str); + file_put_contents("$file", "$str"); + if(isset($_POST['species'])){ + foreach ($_POST['species'] as $selectedOption) + file_put_contents("/home/pi/BirdNET-Pi/include_species_list.txt", $selectedOption."\n", FILE_APPEND); + } + } elseif(isset($_POST['species']) && isset($_POST['del'])){ + $file = '/home/pi/BirdNET-Pi/include_species_list.txt'; + $str = file_get_contents("$file"); + $str = preg_replace('/^\h*\v+/m', '', $str); + file_put_contents("$file", "$str"); + foreach($_POST['species'] as $selectedOption) { + $content = file_get_contents("/home/pi/BirdNET-Pi/include_species_list.txt"); + $newcontent = str_replace($selectedOption, "", "$content"); + file_put_contents("/home/pi/BirdNET-Pi/include_species_list.txt", "$newcontent"); + } + $file = '/home/pi/BirdNET-Pi/include_species_list.txt'; + $str = file_get_contents("$file"); + $str = preg_replace('/^\h*\v+/m', '', $str); + file_put_contents("$file", "$str"); + } + include('scripts/include_list.php'); + } + if($_POST['view'] == "Excluded"){ + if(isset($_POST['species']) && isset($_POST['add'])){ + $file = '/home/pi/BirdNET-Pi/exclude_species_list.txt'; + $str = file_get_contents("$file"); + $str = preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $str); + file_put_contents("$file", "$str"); + foreach ($_POST['species'] as $selectedOption) + file_put_contents("/home/pi/BirdNET-Pi/exclude_species_list.txt", $selectedOption."\n", FILE_APPEND); + } elseif (isset($_POST['species']) && isset($_POST['del'])){ + $file = '/home/pi/BirdNET-Pi/exclude_species_list.txt'; + $str = file_get_contents("$file"); + $str = preg_replace('/^\h*\v+/m', '', $str); + file_put_contents("$file", "$str"); + foreach($_POST['species'] as $selectedOption) { + $content = file_get_contents("/home/pi/BirdNET-Pi/exclude_species_list.txt"); + $newcontent = str_replace($selectedOption, "", "$content"); + file_put_contents("/home/pi/BirdNET-Pi/exclude_species_list.txt", "$newcontent"); + } + $file = '/home/pi/BirdNET-Pi/exclude_species_list.txt'; + $str = file_get_contents("$file"); + $str = preg_replace('/^\h*\v+/m', '', $str); + file_put_contents("$file", "$str"); + } + include('scripts/exclude_list.php'); + } if($_POST['view'] == "Species Stats"){ include('stats.php'); if(isset($_POST['species'])){ @@ -45,6 +97,8 @@ if(isset($_POST['view'])){ echo "
    + + "; } if($_POST['view'] == "Live Stream"){ diff --git a/homepage/menu.html b/homepage/menu.html deleted file mode 100644 index 2bfe9fe..0000000 --- a/homepage/menu.html +++ /dev/null @@ -1,92 +0,0 @@ - - - HTML Frames Example - Menu - - - - -
    Extractions
    -
    - - - -
    - - - - - Processed
    - -
    - -
    System
    - - Tools
    - - Info
    - - Log
    - -
    - -
    External
    - - BirdWeather
    - - Wiki Help Page
    - - Wttr.in Report
    - - BirdNET
    -
    - -
    Other
    BirdNET-Pis
    - - United States
    - - South Africa
    - - Sweden
    - - Germany - - - - - diff --git a/homepage/menu_de.html b/homepage/menu_de.html deleted file mode 100644 index 39c5652..0000000 --- a/homepage/menu_de.html +++ /dev/null @@ -1,80 +0,0 @@ - - - Menu - - - - -
    Extraktionen
    - - Nach Datum
    - - Nach Namen
    - - Nach wiss. Namen
    - - Verarbeitet
    - -
    - -
    System-Links
    - - Tools
    - - System Info
    - - BirdNET-Lite Log
    - - Extraction Log
    - -
    - -
    Externe Links
    - - BirdWeather
    - - Repository
    - - Wiki Hilfe-Seite
    - - Wttr.in Report
    - - BirdNET @ Cornell
    -
    - -
    Andere
    BirdNET-Pis
    - - United States
    - - South Africa
    - - Sweden - - Germany - - - - - diff --git a/homepage/mobile.html b/homepage/mobile.html deleted file mode 100644 index 90986c6..0000000 --- a/homepage/mobile.html +++ /dev/null @@ -1,509 +0,0 @@ - - - - BirdNET-Pi - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -

    - 🕊 BirdNET-Pi -

    -
    -
    -

    - - 🐦 Overview - -

    -
    -

    - - 🐦 Today's Top 10 - -

    -
    -

    - - 🐦 View the Database - -

    -
    -

    - - 🔊 Live Audio Stream - -

    -
    -
    -
    -
    TimeListen Scientific Name Common Name Confidence
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -

    Extractions

    -
    - - - By Common Name - -
    - - - By Date - -
    - - - By Scientific Name - -
    - - - Processed - -
    -

    Tools

    -
    - - - 🗎 Scripts - -
    - - - ⚙ Analysis Log - -
    - - - ⚝ Extraction Log - -
    - - System Information - -
    -
    - -
    - -
    - - - - - - - diff --git a/homepage/top.html b/homepage/top.html deleted file mode 100644 index c141a28..0000000 --- a/homepage/top.html +++ /dev/null @@ -1,51 +0,0 @@ - - - BirdNET-Pi - - - - - BirdNET-Pi - -

    BirdNET-Pi

    - -

    - Overview | - Database | - Species Stats | - History | - Spectrogram -

    - - diff --git a/homepage/top_de.html b/homepage/top_de.html deleted file mode 100644 index 30db041..0000000 --- a/homepage/top_de.html +++ /dev/null @@ -1,51 +0,0 @@ - - - - BirdNET-Pi - - - - - BirdNET-Pi - -

    BirdNET-Pi

    - -

    - Übersicht | - Datenbankansicht | - Tagesansicht | - Spektrogrammansicht -

    - - diff --git a/scripts/add_to_exclude.php b/scripts/add_to_exclude.php deleted file mode 100644 index 6922eb2..0000000 --- a/scripts/add_to_exclude.php +++ /dev/null @@ -1,14 +0,0 @@ - diff --git a/scripts/add_to_include.php b/scripts/add_to_include.php deleted file mode 100644 index 4f18653..0000000 --- a/scripts/add_to_include.php +++ /dev/null @@ -1,14 +0,0 @@ - diff --git a/scripts/clear_all_data.sh b/scripts/clear_all_data.sh index 1eba83b..bd44cb5 100755 --- a/scripts/clear_all_data.sh +++ b/scripts/clear_all_data.sh @@ -67,8 +67,6 @@ sudo -u ${USER} cp -f $(dirname ${my_dir})/templates/phpsysinfo.ini ${HOME}/phps sudo -u ${USER} cp -f $(dirname ${my_dir})/templates/green_bootstrap.css ${HOME}/phpsysinfo/templates/ sudo -u ${USER} cp -f $(dirname ${my_dir})/templates/index_bootstrap.html ${HOME}/phpsysinfo/templates/html -echo "Setting Wttr.in URL to "${LATITUDE}", "${LONGITUDE}"" -sudo -u${USER} sed -i "s/https:\/\/v2.wttr.in\//https:\/\/v2.wttr.in\/"${LATITUDE},${LONGITUDE}"/g" $(dirname ${my_dir})/homepage/menu.html sudo chmod -R g+rw $(dirname ${my_dir}) sudo chmod -R g+rw ${RECS_DIR} diff --git a/scripts/del_from_exclude.php b/scripts/del_from_exclude.php deleted file mode 100644 index 5fa7a48..0000000 --- a/scripts/del_from_exclude.php +++ /dev/null @@ -1,22 +0,0 @@ - diff --git a/scripts/del_from_include.php b/scripts/del_from_include.php deleted file mode 100644 index 219d88f..0000000 --- a/scripts/del_from_include.php +++ /dev/null @@ -1,22 +0,0 @@ - diff --git a/scripts/exclude_list.php b/scripts/exclude_list.php index 99e20fc..ebf4691 100644 --- a/scripts/exclude_list.php +++ b/scripts/exclude_list.php @@ -1,121 +1,42 @@ and add php start and close tag -//comment these two lines when code started working fine error_reporting(E_ALL); ini_set('display_errors',1); -$filename = 'labels.txt'; -$eachlines = file($filename, FILE_IGNORE_NEW_LINES); +$filename = 'scripts/labels.txt'; +$eachline = file($filename, FILE_IGNORE_NEW_LINES); ?> - -
    -
    +

    All Species Labels

    -
    - + $lines"; +foreach($eachline as $lines){ + echo ""; }?> +
    -
    -
    -
    - -
    +
    + -

    Excluded Species List

    -
    - + $lines"; + $filename = '/home/pi/BirdNET-Pi/exclude_species_list.txt'; +$eachline = file($filename, FILE_IGNORE_NEW_LINES); +foreach($eachline as $lines){ + echo ""; }?> +
    -
    -
    diff --git a/scripts/filemanager/filemanager.php b/scripts/filemanager/filemanager.php index 1db4bb8..79e9df1 100644 --- a/scripts/filemanager/filemanager.php +++ b/scripts/filemanager/filemanager.php @@ -3344,7 +3344,7 @@ function fm_show_nav_path($path)