diff --git a/CHANGELOG.md b/CHANGELOG.md index 49aad0f..5076602 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,29 @@ The following is a history of the changes made to this project. +## v2.0.1 *(April 29th, 2016)* + +* Flight logging is now inserted properly into SQLite databases. *(advanced)* +* Remote MySQL database servers now handled properly by install scripts. *(advanced)* +* Separate flights now separated properly when viewing flight plots page. *(advanced)* +* Fixed issue where having the text "; " was causing issues when stored in XML. +* Flights with no positions no longer display a PHP error when viewing plots. *(advanced)* +* Flight search box hidden on non advanced installations. +* All times are now stored as UTC time. +* Added the ability to specify the timezone the portal uses to display data. +* MySQL root password check added during script installation. *(advanced)* +* Directory where install/upgrade PHP files reside has been changed. +* Added warning not to remove the adsb-receiver directory after installation. + +**Previous patches included in this release...** + +* Added the version setting to be used to identifying the currently installed release. +* Added the patch setting to identify the current patch installed. +* Fixed issue with wireless bandwidth not being displayed on the system information page. +* The Python script flights.py should now import the proper libraries. *(advanced)* +* Wlan0 traffic now be displayed by the system gauges. +* Fixed issues pertaining to updating settings using the administration backend. + ## v2.0.0 *(April 14th, 2016)* * Versioning no longer going by date. diff --git a/bash/image.sh b/bash/image.sh index 59df5f2..488fe8e 100644 --- a/bash/image.sh +++ b/bash/image.sh @@ -146,6 +146,17 @@ if [[ $ADVANCED =~ ^[yY]$ ]]; then echo " 2) SQLLite" echo -e "\033[37m" read -p "Use portal with advanced features? [1] " DATABASEENGINE + + # Check if the user is using a remote MySQL database. + if [[ $DATABASEENGINE == 1 ]]; then + echo -e "\033[31m" + echo "Will the database be hosted locally on this device or remotely?" + echo -e "\033[33m" + echo " 1) Locally" + echo " 2) Remotely" + echo -e "\033[37m" + read -p "Use portal with advanced features? [1] " LOCALDATABASE + fi fi # Check for prerequisite packages. @@ -158,8 +169,11 @@ if [[ $ADVANCED =~ ^[yY]$ ]]; then CheckPackage sqlite3 CheckPackage php5-sqlite else - CheckPackage mysql-server - CheckPackage mysql-client + if [[ $LOCALDATABASE != 2 ]]; then + # Install MySQL locally. + CheckPackage mysql-server + CheckPackage mysql-client + fi CheckPackage php5-mysql CheckPackage python-mysqldb fi @@ -169,37 +183,54 @@ fi if [[ $ADVANCED =~ ^[yY]$ ]]; then if [[ $DATABASEENGINE != 2 ]]; then echo -e "\033[31m" - echo "Create Database and User" + echo "Gathering Database Information" echo -e "\033[33m" - echo "A database will now be created for you." echo "Please supply the information pertaining to the new password when asked." + echo "" + echo "If the database will be hosted locally on this device a database will be" + echo "created automatically for you. If you are hosting your database remotely" + echo "you will need to manually create the database and user on the remote device." echo -e "\033[37m" + if [[ $LOCALDATABASE == 2 ]]; then + # Ask for remote MySQL address if the database is hosted remotely. + read -p "Remote MySQL Server Address: " DATABASEHOST + else + DATABASEHOST="localhost" + fi read -p "Password for MySQL root user: " MYSQLROOTPASSWORD read -p "New Database Name: " DATABASENAME read -p "New Database User Name: " DATABASEUSER read -p "New Database User Password: " DATABASEPASSWORD - if [[ $DATABASEENGINE == 1 ]] || [[ $DATABASEENGINE == "" ]]; then - echo -e "\033[33m" - echo -e "Creating MySQL database and user...\033[37m" - mysql -uroot -p${MYSQLROOTPASSWORD} -e "CREATE DATABASE ${DATABASENAME};" - mysql -uroot -p${MYSQLROOTPASSWORD} -e "CREATE USER '${DATABASEUSER}'@'localhost' IDENTIFIED BY \"${DATABASEPASSWORD}\";"; - mysql -uroot -p${MYSQLROOTPASSWORD} -e "GRANT ALL PRIVILEGES ON ${DATABASENAME}.* TO '${DATABASEUSER}'@'localhost';" - mysql -uroot -p${MYSQLROOTPASSWORD} -e "FLUSH PRIVILEGES;" + # Database creation can only be handled locally. + if [[ $LOCALDATABASE != 2 ]]; then + if [[ $DATABASEENGINE == 1 ]] || [[ $DATABASEENGINE == "" ]]; then + echo -e "\033[33m" + echo -e "Creating MySQL database and user...\033[37m" + mysql -uroot -p${MYSQLROOTPASSWORD} -e "CREATE DATABASE ${DATABASENAME};" + mysql -uroot -p${MYSQLROOTPASSWORD} -e "CREATE USER '${DATABASEUSER}'@'localhost' IDENTIFIED BY \"${DATABASEPASSWORD}\";"; + mysql -uroot -p${MYSQLROOTPASSWORD} -e "GRANT ALL PRIVILEGES ON ${DATABASENAME}.* TO '${DATABASEUSER}'@'localhost';" + mysql -uroot -p${MYSQLROOTPASSWORD} -e "FLUSH PRIVILEGES;" + fi fi echo -e "\033[31m" echo "BE SURE TO WRITE THIS INFORMATION DOWN." echo -e "\033[33m" - echo "Ii will be needed in order to complete the installation of the portal." + echo "This information will be needed in order to complete the installation of the portal." echo "" - echo "Database Server: localhost" + if [[ $LOCALDATABASE == 2 ]]; then + echo -e "\033[31mNOTE:" + echo "Being you are hosting your database remotely you will need this information to create" + echo "both the database and database user on your remote database server." + echo -e "\033[33m" + fi + echo "Database Server: ${DATABASEHOST}" echo "Database User: ${DATABASEUSER}" echo "Database Password: ${DATABASEPASSWORD}" echo "Database Name: ${DATABASENAME}" echo -e "\033[37m" read -p "Press enter to continue..." CONTINUE - fi # Setup the flight logging script. @@ -221,7 +252,7 @@ EOF tee ~/adsb-receiver/build/portal/logging/config.json > /dev/null < /dev/null < /dev/null < /dev/null < /dev/null < /dev/null < /dev/null <0)) && sudo sed -i "${lnum[$((${#lnum[@]}-1))]}i ${BUILDDIR}/portal/logging/flights-maint.sh &\n" /etc/rc.local + fi + + # Start flight logging. echo -e "\033[33m" - echo -e "Adding startup line to rc.local...\033[37m" - lnum=($(sed -n '/exit 0/=' /etc/rc.local)) - ((lnum>0)) && sudo sed -i "${lnum[$((${#lnum[@]}-1))]}i ${BUILDDIR}/portal/logging/flights-maint.sh &\n" /etc/rc.local + echo -e "Starting flight logging...\033[37m" + nohup ${BUILDDIR}/portal/logging/flights-maint.sh > /dev/null 2>&1 & fi - - # Start flight logging. - echo -e "\033[33m" - echo -e "Starting flight logging...\033[37m" - ${BUILDDIR}/portal/logging/flights-maint.sh & fi ## SETUP THE PORTAL WEBSITE @@ -207,9 +291,9 @@ sudo cp -R ${HTMLDIR}/* ${DOCUMENTROOT} echo -e "\033[33m" echo "Setting permissions on portal folders...\033[37m" sudo chmod 777 ${DOCUMENTROOT}/graphs/ +sudo chmod 777 ${DOCUMENTROOT}/classes/ sudo chmod 777 ${DOCUMENTROOT}/data/ sudo chmod 666 ${DOCUMENTROOT}/data/* -sudo chmod 666 ${DOCUMENTROOT}/classes/settings.class.php echo -e "\033[33m" echo "Setting up performance graphs..." @@ -325,7 +409,7 @@ echo -e "\033[37m" read -p "Press enter to continue..." CONTINUE # Display further portal setup instructions. -echo -e "\033[33m" +echo -e "\033[31m" echo "PORTAL SETUP IS NOT YET COMPLETE" echo -e "\033[33m" echo "In order to complete the portal setup process visit the following URL in your favorite web browser." diff --git a/build/portal/html/admin/blog/delete.php b/build/portal/html/admin/blog/delete.php index 491d730..66912e5 100644 --- a/build/portal/html/admin/blog/delete.php +++ b/build/portal/html/admin/blog/delete.php @@ -56,6 +56,10 @@ // Get titles and dates for all blog posts. $post = $blog->getPostByTitle(urldecode($_GET['title'])); + // Properly format the date and convert to slected time zone. + $date = new DateTime($post['date'], new DateTimeZone('UTC')); + $date->setTimezone(new DateTimeZone($common->getSetting('timeZone'))); + $postDate = $date->format($common->getSetting('dateFormat')); //////////////// // BEGIN HTML @@ -67,7 +71,7 @@

Delete Blog Post

-

Posted by getAdminstratorName($post['author']); ?>.

+

Posted by getAdminstratorName($post['author']); ?>.

-
\ No newline at end of file +
diff --git a/build/portal/html/admin/index.php b/build/portal/html/admin/index.php index 4c7f8bd..30acdf2 100644 --- a/build/portal/html/admin/index.php +++ b/build/portal/html/admin/index.php @@ -171,6 +171,7 @@ $common->updateSetting("measurementTemperature", $_POST['measurementTemperature']); $common->updateSetting("measurementBandwidth", $_POST['measurementBandwidth']); $common->updateSetting("networkInterface", $_POST['networkInterface']); + $common->updateSetting("timeZone", $_POST['timeZone']); // Purge older flight positions. if (isset($_POST['purgepositions'])) { @@ -217,6 +218,7 @@ $currentTemplate = $common->getSetting("template"); $defaultPage = $common->getSetting("defaultPage"); $dateFormat = $common->getSetting("dateFormat"); + $timeZone = $common->getSetting("timeZone"); // Get navigation settings from settings.xml. $enableFlights = $common->getSetting("enableFlights"); @@ -258,6 +260,13 @@ } closedir($directoryHandle); + // Function used to format offsets of timezones. + function formatOffset($offset) { + return sprintf('%+03d:%02u', floor($offset / 3600), floor(abs($offset) % 3600 / 60)); + } + $utc = new DateTimeZone('UTC'); + $dt = new DateTime('now', $utc); + //////////////// // BEGIN HTML @@ -317,19 +326,35 @@
- +
- +
- +
- +
+
+ + +
@@ -385,7 +410,7 @@
diff --git a/build/portal/html/blog.php b/build/portal/html/blog.php index 020c0bf..db181d2 100644 --- a/build/portal/html/blog.php +++ b/build/portal/html/blog.php @@ -54,7 +54,11 @@ $post['contents'] = substr($post['contents'], 0, strpos($post['contents'], '{more}')); } $post['author'] = $common->getAdminstratorName($post['author']); - $post['date'] = date_format(date_create($post['date']), $common->getSetting('dateFormat')); + + // Properly format the date and convert to slected time zone. + $date = new DateTime($post['date'], new DateTimeZone('UTC')); + $date->setTimezone(new DateTimeZone($common->getSetting('timeZone'))); + $post['date'] = $date->format($common->getSetting('dateFormat')); } // Pagination. @@ -66,4 +70,4 @@ $pageData['pageLinks'] = count($allPosts) / $itemsPerPage; $template->display($pageData); -?> \ No newline at end of file +?> diff --git a/build/portal/html/classes/blog.class.php b/build/portal/html/classes/blog.class.php index 7821135..973d235 100644 --- a/build/portal/html/classes/blog.class.php +++ b/build/portal/html/classes/blog.class.php @@ -115,7 +115,7 @@ $common = new common(); $dbh = $common->pdoOpen(); - "SELECT COUNT(*) FROM ".$settings::db_prefix."blogPosts WHERE title = :title"; + $sql = "SELECT COUNT(*) FROM ".$settings::db_prefix."blogPosts WHERE title = :title"; $sth = $dbh->prepare($sql); $sth->bindParam(':title', $title, PDO::PARAM_STR, 100); $sth->execute(); @@ -192,7 +192,7 @@ $blogPosts = simplexml_load_file($_SERVER['DOCUMENT_ROOT'].DIRECTORY_SEPARATOR."data".DIRECTORY_SEPARATOR."blogPosts.xml"); $blogPost = $blogPosts->addChild('blogPost', ''); $blogPost->addChild('title', $title); - $blogPost->addChild('date', date('Y-m-d H:i:s')); + $blogPost->addChild('date', gmdate('Y-m-d H:i:s', time())); $blogPost->addChild('author', $author); $blogPost->addChild('contents', $contents); $dom = dom_import_simplexml($blogPosts)->ownerDocument; @@ -207,7 +207,7 @@ $sql = "INSERT INTO ".$settings::db_prefix."blogPosts (title, date, author, contents) VALUES (:title, :date, :author, :contents)"; $sth = $dbh->prepare($sql); $sth->bindParam(':title', $title, PDO::PARAM_STR, 100); - $sth->bindParam(':date', date('Y-m-d H:i:s'), PDO::PARAM_STR, 20); + $sth->bindParam(':date', gmdate('Y-m-d H:i:s', time()), PDO::PARAM_STR, 20); $sth->bindParam(':author', $author, PDO::PARAM_STR, 100); $sth->bindParam(':contents', $contents, PDO::PARAM_STR, 20000); $sth->execute(); diff --git a/build/portal/html/classes/common.class.php b/build/portal/html/classes/common.class.php index 5d2368b..dc86b5b 100644 --- a/build/portal/html/classes/common.class.php +++ b/build/portal/html/classes/common.class.php @@ -69,6 +69,10 @@ require_once($_SERVER['DOCUMENT_ROOT'].DIRECTORY_SEPARATOR."classes".DIRECTORY_SEPARATOR."settings.class.php"); $settings = new settings(); + if ($name == "dataStorage") { + return $settings::db_driver; + } + if ($settings::db_driver == 'xml') { // XML $theseSettings = simplexml_load_file($_SERVER['DOCUMENT_ROOT'].DIRECTORY_SEPARATOR."data".DIRECTORY_SEPARATOR."settings.xml"); diff --git a/build/portal/html/classes/settings.class.php b/build/portal/html/classes/settings.class.sample.php similarity index 90% rename from build/portal/html/classes/settings.class.php rename to build/portal/html/classes/settings.class.sample.php index ceb7668..9541c66 100644 --- a/build/portal/html/classes/settings.class.php +++ b/build/portal/html/classes/settings.class.sample.php @@ -31,18 +31,18 @@ class settings { // Database Settings - const db_driver = 'mysql'; - const db_database = 'adsb'; - const db_username = 'adsbuser'; - const db_password = 'password'; - const db_host = 'localhost'; + const db_driver = 'xml'; + const db_database = ''; + const db_username = ''; + const db_password = ''; + const db_host = ''; const db_prefix = 'adsb_'; // Security Settings const sec_length = 6; // PDO Settings - const pdo_debug = TRUE; + const pdo_debug = FALSE; } ?> diff --git a/build/portal/html/classes/template.class.php b/build/portal/html/classes/template.class.php index c64f6cd..03f9c0d 100644 --- a/build/portal/html/classes/template.class.php +++ b/build/portal/html/classes/template.class.php @@ -35,8 +35,15 @@ function display(&$pageData) { $common = new common($this); - // The Base URL of this page (needed for Plane Finder client link) - $pageData['baseurl'] = $common->getBaseUrl(); + // Check if the portal is installed or needs upgraded. + if (!file_exists($_SERVER['DOCUMENT_ROOT']."/classes/settings.class.php")) { + header ("Location: /install/install.php"); + } elseif ($common->getSetting("version") != "2.0.1"){ + header ("Location: /install/upgrade.php"); + } + + // The Base URL of this page (needed for Plane Finder client link) + $pageData['baseurl'] = $common->getBaseUrl(); // Load the master template. $master = $this->readTemplate('master.tpl'); diff --git a/build/portal/html/flights.php b/build/portal/html/flights.php index c41eb25..fafbf3c 100644 --- a/build/portal/html/flights.php +++ b/build/portal/html/flights.php @@ -45,17 +45,31 @@ // The title of this page. $pageData['title'] = "Flights Seen"; - // Add blog post data to the $pageData array. + // Add flight data to the $pageData array using the search string if available. + if (isset($_POST['flight'])) { + $searchString = $_POST['flight']; + } else { + $searchString = ""; + } $dbh = $common->pdoOpen(); $sql = "SELECT * FROM ".$settings::db_prefix."flights WHERE flight LIKE ? ORDER BY lastSeen DESC, flight"; $sth = $dbh->prepare($sql); - $sth->bindValue(1, "%".$_POST['flight']."%", PDO::PARAM_STR); + $sth->bindValue(1, "%".$searchString."%", PDO::PARAM_STR); $sth->execute(); $flights = $sth->fetchAll(); $sth = NULL; $dbh = NULL; - //$pageData['flights'] = $flights; + // Change dates to the proper timezone and format. + foreach ($flights as &$flight) { + $date = new DateTime($flight['firstSeen'], new DateTimeZone('UTC')); + $date->setTimezone(new DateTimeZone($common->getSetting('timeZone'))); + $flight['firstSeen'] = $date->format($common->getSetting('dateFormat')); + + $date = new DateTime($flight['lastSeen'], new DateTimeZone('UTC')); + $date->setTimezone(new DateTimeZone($common->getSetting('timeZone'))); + $flight['lastSeen'] = $date->format($common->getSetting('dateFormat')); + } // Pagination. $itemsPerPage = 25; diff --git a/build/portal/html/admin/install.php b/build/portal/html/install/index.php similarity index 82% rename from build/portal/html/admin/install.php rename to build/portal/html/install/index.php index 43dc241..edadbe8 100644 --- a/build/portal/html/admin/install.php +++ b/build/portal/html/install/index.php @@ -31,16 +31,15 @@ require_once('../classes/common.class.php'); $common = new common(); - // THE FOLLOWING COMMENTED LINES WILL BE USED IN FUTURE RELEASES - /////////////////////////////////////////////////////////////////// - // The most current stable release. - //$currentRelease = "2016-02-18"; + $thisVersion = "2.0.1"; // Begin the upgrade process if this release is newer than what is installed. - //if ($currentRelease > $common->getRelease) { - // header ("Location: upgrade.php"); - //} + if (file_exists("../classes/settings.class.php")) { + header ("Location: upgrade.php"); + } + + // BEGIN FRESH INSTALLATION $installed = FALSE; //if ($common->postBack()) { @@ -73,9 +72,9 @@ if (isset($_POST['host'])) $dbHost = $_POST['host']; - $dbPrefix = ""; - if (isset($_POST['prefix'])) - $dbPrefix = $_POST['prefix']; + $dbPrefix = "adsb_"; + //if (isset($_POST['prefix'])) + // $dbPrefix = $_POST['prefix']; // Create or edit the settings.class.php file. $content = <<addSetting('version', $thisVersion); + $common->addSetting('patch', ''); $common->addSetting('siteName', 'ADS-B Receiver'); $common->addSetting('template', 'default'); $common->addSetting('defaultPage', 'blog.php'); - $common->addSetting('dateFormat', 'F jS, Y'); + $common->addSetting('dateFormat', 'F jS, Y g:i A'); $common->addSetting('enableBlog', TRUE); $common->addSetting('enableInfo', TRUE); $common->addSetting('enableGraphs', TRUE); @@ -376,6 +376,7 @@ EOF; $common->addSetting('enableFlightNotifications', FALSE); $common->addSetting('emailFrom', 'noreply@adsbreceiver.net'); $common->addSetting('emailReplyTo', 'noreply@adsbreceiver.net'); + $common->addSetting('timeZone', $_POST['timeZone']); if ($_POST['driver'] == "xml") $common->addSetting('enableFlights', FALSE); @@ -400,30 +401,46 @@ EOF; if (is_writable($applicationDirectory.'data')) $writableData = TRUE; - $writeableClass = FALSE; - if (is_writable($applicationDirectory.'classes/settings.class.php')) - $writeableClass = TRUE; + $writeableClasses = FALSE; + if (is_writable($applicationDirectory.'classes')) + $writeableClasses = TRUE; + + // Function used to format offsets of timezones. + /////////////////////////////////////////////////// + + function formatOffset($offset) { + return sprintf('%+03d:%02u', floor($offset / 3600), floor(abs($offset) % 3600 / 60)); + } + $utc = new DateTimeZone('UTC'); + $dt = new DateTime('now', $utc); // Display HTML ////////////////// - require_once('includes/header.inc.php'); + require_once('../admin/includes/header.inc.php'); // Display the instalation wizard. if (!$installed) { ?> + + + + + + +

ADS-B Receiver Portal Setup

The following wizard will guide you through the setup process.

- +

Directory Permissions

The data directory is writable.
-
The settings.class.php file is writable.
+
The classes directory is writable.
- +

Please fix the permissions for the following directory and/or file to make sure they are writable before proceeding. Once you have made the necessary changes please reload this page to allow the installer to recheck permissions. @@ -434,7 +451,7 @@ EOF;

Data Storage

- @@ -462,6 +479,24 @@ EOF;

(*) Required

+

Portal Settings

+
+
+ + +
+
+

Administrator Account

@@ -499,8 +534,8 @@ EOF; At this time you should also ensure that the file containing the settings you specified is no longer writeable. Please log into your device and run the following commands to accomplish these tasks.

-
sudo rm -f /admin/install.php
-
sudo chmod -w /classes/settings.class.php
+
sudo rm -f /install/
+
sudo chmod -w /classes/settings.class.php

Once you have done so you can log in and administrate your portal here.

If you experienced any issues or have any questions or suggestions you would like to make regarding this project @@ -508,5 +543,5 @@ EOF;

diff --git a/build/portal/html/install/upgrade.php b/build/portal/html/install/upgrade.php new file mode 100644 index 0000000..217537d --- /dev/null +++ b/build/portal/html/install/upgrade.php @@ -0,0 +1,206 @@ +getSetting("version") == $thisVersion) { + header ("Location: /"); + } + + $error = FALSE; + #errorMessage = "No error message returned."; + + try { + // Change tables containing datetime data to datetime. + if ($settings::db_driver != "xml") { + + // ALter MySQL tables. + if ($settings::db_driver != "mysql") { + $dbh = $common->pdoOpen(); + + $sql = "ALTER TABLE ".$settings::db_prefix."aircraft MODIFY firstSeen DATETIME NOT NULL"; + $sth = $dbh->prepare($sql); + $sth->execute(); + $sth = NULL; + + $sql = "ALTER TABLE adsb_aircraft MODIFY lastSeen DATETIME NOT NULL"; + $sth = $dbh->prepare($sql); + $sth->execute(); + $sth = NULL; + + $sql = "ALTER TABLE adsb_blogPosts MODIFY date DATETIME NOT NULL"; + $sth = $dbh->prepare($sql); + $sth->execute(); + $sth = NULL; + + $sql = "ALTER TABLE adsb_flights MODIFY firstSeen DATETIME NOT NULL"; + $sth = $dbh->prepare($sql); + $sth->execute(); + $sth = NULL; + + $sql = "ALTER TABLE adsb_flights MODIFY firstSeen DATETIME NOT NULL"; + $sth = $dbh->prepare($sql); + $sth->execute(); + $sth = NULL; + + $sql = "ALTER TABLE adsb_positions MODIFY time DATETIME NOT NULL"; + $sth = $dbh->prepare($sql); + $sth->execute(); + $sth = NULL; + + $dbh = NULL; + } + + // Convert times to GMT. + + // You may wish to uncomment this block of code in order to convert existing times + // stored in the database to UTC/GMT time. Before doing so it is recommended that + // you set the setting max_execution_time setting to a large amount of time in your + // php.ini file. Depending on the amount of flight data logged this may take quite + // some time for this upgrade script to complete so be patient and let it run it's + // course. Afterwards set the max_execution_time back to it previous setting. + + /* + $dbh = $common->pdoOpen(); + $sql = "SELECT id, firstSeen, lastSeen FROM ".$settings::db_prefix."aircraft"; + $sth = $dbh->prepare($sql); + $sth->execute(); + $aircraft = $sth->fetchAll(); + $sth = NULL; + $dbh = NULL; + + foreach ($aircraft as $airframe) { + $dbh = $common->pdoOpen(); + $sql = "UPDATE ".$settings::db_prefix."aircraft SET firstSeen = :firstSeen, lastSeen = :lastSeen WHERE id = :id"; + $sth = $dbh->prepare($sql); + $sth->bindParam(':firstSeen', gmdate("Y-m-d H:i:s", $airframe["firstSeen"]), PDO::PARAM_STR); + $sth->bindParam(':lastSeen', gmdate("Y-m-d H:i:s", $airframe["lastSeen"]), PDO::PARAM_STR); + $sth->bindParam(':id', $airframe["id"], PDO::PARAM_INT); + $sth->execute(); + $sth = NULL; + $dbh = NULL; + } + + $dbh = $common->pdoOpen(); + $sql = "SELECT id, date FROM ".$settings::db_prefix."blogPosts"; + $sth = $dbh->prepare($sql); + $sth->execute(); + $blogPosts = $sth->fetchAll(); + $sth = NULL; + $dbh = NULL; + + foreach ($blogPosts as $post) { + $dbh = $common->pdoOpen(); + $sql = "UPDATE ".$settings::db_prefix."blogPosts SET date = :date WHERE id = :id"; + $sth = $dbh->prepare($sql); + $sth->bindParam(':date', gmdate("Y-m-d H:i:s", $post["date"]), PDO::PARAM_STR); + $sth->bindParam(':id', $post["id"], PDO::PARAM_INT); + $sth->execute(); + $sth = NULL; + $dbh = NULL; + } + + $dbh = $common->pdoOpen(); + $sql = "SELECT id, firstSeen, lastSeen FROM ".$settings::db_prefix."flights"; + $sth = $dbh->prepare($sql); + $sth->execute(); + $flights = $sth->fetchAll(); + $sth = NULL; + $dbh = NULL; + + foreach ($flights as $flight) { + $dbh = $common->pdoOpen(); + $sql = "UPDATE ".$settings::db_prefix."flights SET firstSeen = :firstSeen, lastSeen = lastSeen WHERE id = :id"; + $sth = $dbh->prepare($sql); + $sth->bindParam(':firstSeen', gmdate("Y-m-d H:i:s", $flight["firstSeen"]), PDO::PARAM_STR); + $sth->bindParam(':lastSeen', gmdate("Y-m-d H:i:s", $flight["lastSeen"]), PDO::PARAM_STR); + $sth->bindParam(':id', $flight["id"], PDO::PARAM_INT); + $sth->execute(); + $sth = NULL; + $dbh = NULL; + } + + $dbh = $common->pdoOpen(); + $sql = "SELECT id, time FROM ".$settings::db_prefix."positions"; + $sth = $dbh->prepare($sql); + $sth->execute(); + $positionss = $sth->fetchAll(); + $sth = NULL; + $dbh = NULL; + + foreach ($positions as $position) { + $dbh = $common->pdoOpen(); + $sql = "UPDATE ".$settings::db_prefix."positions SET time = :time WHERE id = :id"; + $sth = $dbh->prepare($sql); + $sth->bindParam(':time', gmdate("Y-m-d H:i:s", $position["time"]), PDO::PARAM_STR); + $sth->bindParam(':id', $position["id"], PDO::PARAM_INT); + $sth->execute(); + $sth = NULL; + $dbh = NULL; + } + */ + } + + // Add timezone setting. + $common->addSetting("timeZone", date_default_timezone_get()); + + // update version and patch settings. + $common->updateSetting("version", $thisVersion); + $common->updateSetting("patch", ""); + } catch(Exception $e) { + $error = TRUE; + $errorMessage = $e->getMessage(); + } + + require_once('../admin/includes/header.inc.php'); + + // Display the instalation wizard. + if (!$error) { +?> +

ADS-B Receiver Portal Updated

+

Your portal has been upgraded to v.

+ +

Error Encountered Upgrading Your ADS-B Receiver Portal

+

There was an error encountered when upgrading your portal to v.

+ + diff --git a/build/portal/html/plot.php b/build/portal/html/plot.php index 61b6024..4ed4380 100644 --- a/build/portal/html/plot.php +++ b/build/portal/html/plot.php @@ -57,7 +57,7 @@ $flightId = $row['id']; $dbh = $common->pdoOpen(); - $sql = "SELECT latitude, longitude, track FROM ".$settings::db_prefix."positions WHERE flight = :flight ORDER BY message"; + $sql = "SELECT time, message, latitude, longitude, track FROM ".$settings::db_prefix."positions WHERE flight = :flight ORDER BY time"; $sth = $dbh->prepare($sql); $sth->bindParam(':flight', $flightId, PDO::PARAM_STR, 50); $sth->execute(); @@ -65,13 +65,65 @@ $sth = NULL; $dbh = NULL; - $pageData['startingLatitude'] = array_values($positions)[0]['latitude']; - $pageData['startingLongitude'] = array_values($positions)[0]['longitude']; - $pageData['startingDegrees'] = array_values($positions)[0]['track']; - $pageData['finishingLatitude'] = array_values($positions)[count(array_values($positions)) - 1]['latitude']; - $pageData['finishingLongitude'] = array_values($positions)[count(array_values($positions)) - 1]['longitude']; - $pageData['finishingDegrees'] = array_values($positions)[count(array_values($positions)) - 1]['track']; - $pageData['positions'] = $positions; + $thisPath = array(); + $flightPath = array(); + $flightPaths = array(); + $lastMessage = 0; + $firstPass = TRUE; + $firstPosition = TRUE; + $totalPositions = count($positions); + $counter = 0; + foreach ($positions as $position) { + $counter++; + + if ($position["message"] < $lastMessage || $counter == $totalPositions) { + if ($firstPass == TRUE) { + $flightPath["startingLatitude"] = $startingLatitude; + $flightPath["startingLongitude"] = $startingLongitude; + $flightPath["startingTrack"] = $startingTrack; + $firstPass = FALSE; + } else { + $flightPath["startingLatitude"] = $position["latitude"]; + $flightPath["startingLongitude"] = $position["longitude"]; + $flightPath["startingTrack"] = $position["track"]; + } + $flightPath["finishingLatitude"] = $lastLatitude; + $flightPath["finishingLongitude"] = $lastLongitude; + $flightPath["finishingTrack"] = $lastTrack; + $flightPath["positions"] = json_encode($thisPath); + $flightPaths[] = $flightPath; + unset($thisPath); + unset($flightPath); + $thisPath = array(); + $flightPath = array(); + } + + if ($firstPosition == TRUE) { + $startingLatitude = $position["latitude"]; + $startingLongitude = $position["longitude"]; + $startingTrack = $position["track"]; + $firstPosition = FALSE; + } + + $thisPosition["time"] = $position["time"]; + $thisPosition["latitude"] = $position["latitude"]; + $thisPosition["longitude"] = $position["longitude"]; + $thisPosition["track"] = $position["track"]; + $thisPosition["message"] = $position["message"]; + $thisPath[] = $thisPosition; + + $lastMessage = $position["message"]; + $lastLatitude = $position["latitude"]; + $lastLongitude = $position["longitude"]; + $lastTrack = $position["track"]; + } + + if (count($flightPaths) > 0) { + $pageData['flightPathsAvailable'] = "TRUE"; + $pageData['flightPaths'] = $flightPaths; + } else { + $pageData['flightPathsAvailable'] = "FALSE"; + } $template->display($pageData); ?> diff --git a/build/portal/html/post.php b/build/portal/html/post.php index 3d13f69..c1126b8 100644 --- a/build/portal/html/post.php +++ b/build/portal/html/post.php @@ -50,9 +50,13 @@ // Add blog post data to the $pageData array. $pageData['postTitle'] = $post['title']; - $pageData['postDate'] = date_format(date_create($post['date']), $common->getSetting('dateFormat')); $pageData['postAuthor'] = $common->getAdminstratorName($post['author']); $pageData['postContents'] = $post['contents']; + // Properly format the date and convert to slected time zone. + $date = new DateTime($post['date'], new DateTimeZone('UTC')); + $date->setTimezone(new DateTimeZone($common->getSetting('timeZone'))); + $pageData['postDate'] = $date->format($common->getSetting('dateFormat')); + $template->display($pageData); ?> diff --git a/build/portal/html/templates/default/flights.tpl b/build/portal/html/templates/default/flights.tpl index f429dfb..a282547 100644 --- a/build/portal/html/templates/default/flights.tpl +++ b/build/portal/html/templates/default/flights.tpl @@ -28,12 +28,14 @@ Flight Last Seen + First Seen Links {foreach page:flights as flight} {flight->flight} {flight->lastSeen} + {flight->firstSeen} FlightAware | Planefinder | diff --git a/build/portal/html/templates/default/master.tpl b/build/portal/html/templates/default/master.tpl index e7b05b1..6036ad1 100644 --- a/build/portal/html/templates/default/master.tpl +++ b/build/portal/html/templates/default/master.tpl @@ -47,20 +47,22 @@
diff --git a/build/portal/html/templates/default/plot.tpl b/build/portal/html/templates/default/plot.tpl index 3a3f01d..41545fc 100644 --- a/build/portal/html/templates/default/plot.tpl +++ b/build/portal/html/templates/default/plot.tpl @@ -23,11 +23,40 @@ {/area} {area:contents} + {if page:flightPathsAvailable eq FALSE} + + {/if}
+
id="slide-panel"> + + Panel Content +
{/area} {area:scripts} + {if page:flightPathsAvailable eq FALSE} + + {/if} + {/area} diff --git a/build/portal/html/templates/default/system.tpl b/build/portal/html/templates/default/system.tpl index f978d52..fc88e0b 100644 --- a/build/portal/html/templates/default/system.tpl +++ b/build/portal/html/templates/default/system.tpl @@ -26,7 +26,7 @@

Aggregate Sites Statistics

diff --git a/build/portal/logging/flights.py b/build/portal/logging/flights.py index 0071911..9fef0a1 100644 --- a/build/portal/logging/flights.py +++ b/build/portal/logging/flights.py @@ -37,10 +37,6 @@ import datetime import json -if config["database"]["type"] == "mysql": - import MySQLdb -if config["database"]["type"] == "sqlite": - import sqlite3 import time import os #import urllib2 @@ -51,6 +47,12 @@ while True: with open(os.path.dirname(os.path.realpath(__file__)) + '/config.json') as config_file: config = json.load(config_file) + # Import the needed database library. + if config["database"]["type"] == "mysql": + import MySQLdb + if config["database"]["type"] == "sqlite": + import sqlite3 + # Read dump1090-mutability's aircraft.json. with open('/run/dump1090-mutability/aircraft.json') as data_file: data = json.load(data_file) @@ -66,22 +68,38 @@ while True: db = MySQLdb.connect(host=config["database"]["host"], user=config["database"]["user"], passwd=config["database"]["passwd"], db=config["database"]["db"]) # Assign the time to a variable. - time_now = datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S") + time_now = datetime.datetime.utcnow().strftime("%Y/%m/%d %H:%M:%S") cursor = db.cursor() for aircraft in data["aircraft"]: # Check if this aircraft was already seen. - cursor.execute("SELECT COUNT(*) FROM adsb_aircraft WHERE icao = %s", aircraft["hex"]) + if config["database"]["type"] == "sqlite": + params = (aircraft["hex"],) + cursor.execute("SELECT COUNT(*) FROM adsb_aircraft WHERE icao = ?", params) + else: + cursor.execute("SELECT COUNT(*) FROM adsb_aircraft WHERE icao = %s", aircraft["hex"]) row_count = cursor.fetchone() if row_count[0] == 0: # Insert the new aircraft. #print("Added Aircraft: " + aircraft["hex"]) - cursor.execute("INSERT INTO adsb_aircraft (icao, firstSeen, lastSeen) VALUES (%s, %s, %s)", (aircraft["hex"], time_now, time_now)) + if config["database"]["type"] == "sqlite": + params = (aircraft["hex"], time_now, time_now,) + cursor.execute("INSERT INTO adsb_aircraft (icao, firstSeen, lastSeen) VALUES (?, ?, ?)", params) + else: + cursor.execute("INSERT INTO adsb_aircraft (icao, firstSeen, lastSeen) VALUES (%s, %s, %s)", (aircraft["hex"], time_now, time_now)) else: # Update the existing aircraft. - cursor.execute("UPDATE adsb_aircraft SET lastSeen = %s WHERE icao = %s", (time_now, aircraft["hex"])) + if config["database"]["type"] == "sqlite": + params = (time_now, aircraft["hex"],) + cursor.execute("UPDATE adsb_aircraft SET lastSeen = ? WHERE icao = ?", params) + else: + cursor.execute("UPDATE adsb_aircraft SET lastSeen = %s WHERE icao = %s", (time_now, aircraft["hex"])) # Get the ID of this aircraft. - cursor.execute("SELECT id FROM adsb_aircraft WHERE icao = %s", aircraft["hex"]) + if config["database"]["type"] == "sqlite": + params = (aircraft["hex"],) + cursor.execute("SELECT id FROM adsb_aircraft WHERE icao = ?", params) + else: + cursor.execute("SELECT id FROM adsb_aircraft WHERE icao = %s", aircraft["hex"]) rows = cursor.fetchall() for row in rows: aircraft_id = row[0] @@ -89,17 +107,33 @@ while True: # Check that a flight is tied to this track. if aircraft.has_key('flight'): # Check to see if the flight already exists in the database. - cursor.execute("SELECT COUNT(*) FROM adsb_flights WHERE flight = %s", aircraft["flight"].strip()) + if config["database"]["type"] == "sqlite": + params = (aircraft["flight"].strip(),) + cursor.execute("SELECT COUNT(*) FROM adsb_flights WHERE flight = ?", params) + else: + cursor.execute("SELECT COUNT(*) FROM adsb_flights WHERE flight = %s", aircraft["flight"].strip()) row_count = cursor.fetchone() if row_count[0] == 0: # If the flight does not exist in the database add it. - cursor.execute("INSERT INTO adsb_flights (aircraft, flight, firstSeen, lastSeen) VALUES (%s, %s, %s, %s)", (aircraft_id, aircraft["flight"].strip(), time_now, time_now)) + if config["database"]["type"] == "sqlite": + params = (aircraft_id, aircraft["flight"].strip(), time_now, time_now,) + cursor.execute("INSERT INTO adsb_flights (aircraft, flight, firstSeen, lastSeen) VALUES (?, ?, ?, ?)", params) + else: + cursor.execute("INSERT INTO adsb_flights (aircraft, flight, firstSeen, lastSeen) VALUES (%s, %s, %s, %s)", (aircraft_id, aircraft["flight"].strip(), time_now, time_now)) #print("Added Flight: " + aircraft["flight"].strip()) else: # If it already exists pdate the time it was last seen. - cursor.execute("UPDATE adsb_flights SET aircraft = %s, lastSeen = %s WHERE flight = %s", (aircraft_id, time_now, aircraft["flight"].strip())) + if config["database"]["type"] == "sqlite": + params =(aircraft_id, time_now, aircraft["flight"].strip(),) + cursor.execute("UPDATE adsb_flights SET aircraft = ?, lastSeen = ? WHERE flight = ?", params) + else: + cursor.execute("UPDATE adsb_flights SET aircraft = %s, lastSeen = %s WHERE flight = %s", (aircraft_id, time_now, aircraft["flight"].strip())) # Get the ID of this flight. - cursor.execute("SELECT id FROM adsb_flights WHERE flight = %s", aircraft["flight"].strip()) + if config["database"]["type"] == "sqlite": + params = (aircraft["flight"].strip(),) + cursor.execute("SELECT id FROM adsb_flights WHERE flight = ?", params) + else: + cursor.execute("SELECT id FROM adsb_flights WHERE flight = %s", aircraft["flight"].strip()) rows = cursor.fetchall() for row in rows: flight_id = row[0] @@ -107,17 +141,30 @@ while True: # Check if position data is available. if aircraft.has_key('lat') and aircraft.has_key('lon') and aircraft.has_key('altitude') and aircraft.has_key('speed') and aircraft.has_key('track') and aircraft.has_key('vert_rate') and aircraft["altitude"] != "ground": # Check that this message has not already been added to the database. - cursor.execute("SELECT message FROM adsb_positions WHERE flight = %s AND message = %s ORDER BY time DESC", (flight_id, aircraft["messages"])) + if config["database"]["type"] == "sqlite": + params = (flight_id, aircraft["messages"],) + cursor.execute("SELECT message FROM adsb_positions WHERE flight = ? AND message = ? ORDER BY time DESC", params) + else: + cursor.execute("SELECT message FROM adsb_positions WHERE flight = %s AND message = %s ORDER BY time DESC", (flight_id, aircraft["messages"])) rows = cursor.fetchall() row_count = cursor.rowcount + last_message = 0 for row in rows: last_message = row[0] if row_count == 0 or last_message != aircraft["messages"]: # Add this position to the database. if aircraft.has_key('squawk'): - cursor.execute("INSERT INTO adsb_positions (flight, time, message, squawk, latitude, longitude, track, altitude, verticleRate, speed) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)", (flight_id, time_now, aircraft["messages"], aircraft["squawk"], aircraft["lat"], aircraft["lon"], aircraft["track"], aircraft["altitude"], aircraft["vert_rate"], aircraft["speed"])) + if config["database"]["type"] == "sqlite": + params = (flight_id, time_now, aircraft["messages"], aircraft["squawk"], aircraft["lat"], aircraft["lon"], aircraft["track"], aircraft["altitude"], aircraft["vert_rate"], aircraft["speed"],) + cursor.execute("INSERT INTO adsb_positions (flight, time, message, squawk, latitude, longitude, track, altitude, verticleRate, speed) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", params) + else: + cursor.execute("INSERT INTO adsb_positions (flight, time, message, squawk, latitude, longitude, track, altitude, verticleRate, speed) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)", (flight_id, time_now, aircraft["messages"], aircraft["squawk"], aircraft["lat"], aircraft["lon"], aircraft["track"], aircraft["altitude"], aircraft["vert_rate"], aircraft["speed"])) else: - cursor.execute("INSERT INTO adsb_positions (flight, time, message, latitude, longitude, track, altitude, verticleRate, speed) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)", (flight_id, time_now, aircraft["messages"], aircraft["lat"], aircraft["lon"], aircraft["track"], aircraft["altitude"], aircraft["vert_rate"], aircraft["speed"])) + if config["database"]["type"] == "sqlite": + params = (flight_id, time_now, aircraft["messages"], aircraft["lat"], aircraft["lon"], aircraft["track"], aircraft["altitude"], aircraft["vert_rate"], aircraft["speed"],) + cursor.execute("INSERT INTO adsb_positions (flight, time, message, latitude, longitude, track, altitude, verticleRate, speed) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", params) + else: + cursor.execute("INSERT INTO adsb_positions (flight, time, message, latitude, longitude, track, altitude, verticleRate, speed) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)", (flight_id, time_now, aircraft["messages"], aircraft["lat"], aircraft["lon"], aircraft["track"], aircraft["altitude"], aircraft["vert_rate"], aircraft["speed"])) # Close the database connection. db.commit() diff --git a/install.sh b/install.sh index 27b51eb..2254df3 100755 --- a/install.sh +++ b/install.sh @@ -251,6 +251,10 @@ NOTHINGTODO="Nothing has been selected to be installed so the script will exit n read -d '' INSTALLATIONCOMPLETE <<"EOF" INSTALLATION COMPLETE +DO NOT DELETE THIS DIRECTORY! + +Files needed for certain items to run properly are contained within this directory. Deleting this directory may result in your receiver not working properly. + It is hoped these scripts and files were found useful while setting up your ADS-B Receiver. Feedback regarding this software is always welcome. If you ran into any problems or wish to submit feed back feel free to do so on the project's GitHub site. https://github.com/jprochazka/adsb-receiver @@ -564,7 +568,7 @@ fi ## INSTALLATION COMPLETE # Display the installation complete message box. -whiptail --backtitle "$BACKTITLE" --title "Software Installation Complete" --msgbox "$INSTALLATIONCOMPLETE" 16 65 +whiptail --backtitle "$BACKTITLE" --title "Software Installation Complete" --msgbox "$INSTALLATIONCOMPLETE" 19 65 # Once again cannot make the whiptail checkbox not create this file and still work... # Will work on figuring this out at a later date but until then we will delete the file created.