Эх сурвалжийг харах

Cleanup and minor changes

DSR! 3 жил өмнө
parent
commit
9474e1907b

+ 10 - 2
README.md

@@ -14,11 +14,15 @@ The following functionalities are modified looking for a better user experience
  - Update Bootstrap to 3.4.1 (size +2K)
  - Fix mobile view
  - Add Chevron icon to accordions (size +1K)
- - Change notification time from 6000 to 20000 (decrease RPM from 10 to 3)
+ - Change notification time from 6000 to 30000 (decrease RPM from 10 to 2)
  - Added more refresh buttons
  - Fixed several bugs found in the panel
+ - Expose AngularJS Pineapple API in JS window
  - Project minification (Optional: use packer tools)
 
+## Dashboard
+ - Change update time from 5000 to 10000 (decrease RPM from 12 to 6)
+
 ## Recon:
  - Code refactor in module.php
  - Add results counter in titles with badges
@@ -53,13 +57,17 @@ The following functionalities are modified looking for a better user experience
 ## Setup:
  - Fix character bad used
 
+## Modules:
+ - Refactor in Modules.php
+ - Add support for injectJS in modules manifest
+
 
 # Notes
 
  1. For edit notification timer you can use this
  ```bash
  # sed -i 's/OLD-VALUE/NEW-VALUE/' FILE
- sed -i 's/20000/30000/' src/pineapple/js/controllers.js
+ sed -i 's/30000/60000/' src/pineapple/js/controllers.js
 ```
 
  2. To open the menu on hover uncomment this in src/pineapple/main.css

+ 6 - 30
src/etc/pineapple/changes

@@ -1,16 +1,12 @@
-<h3>Changelog for 2.7.0+:</h3>
+<h3>Changelog for 2.8.0+:</h3>
 <ul>
     <li>General</li>
     <ul>
-        <li>Compress PNG images (size -55K)</li>
-        <li>Compress SVG images (size -7K)</li>
-        <li>Update Bootstrap to 3.4.1 (size +2K)</li>
+        <li>Compress images</li>
+        <li>Update dependencies</li>
         <li>Fix mobile view</li>
-        <li>Add Chevron icon to accordions (size +1K)</li>
-        <li>Change notification time from 6000 to 20000 (decrease RPM from 10 to 3)</li>
-        <li>Added more refresh buttons</li>
-        <li>Fixed several bugs found in the panel</li>
-        <li>Project minification (Optional: use packer tools)</li>
+        <li>A completely updated panel with fixes and improvements</li>
+        <li>Decrease requests for less cpu usage</li>
     </ul>
 
     <li>Recon</li>
@@ -20,12 +16,6 @@
         <li>Fix column alignment</li>
     </ul>
 
-    <li>Clients</li>
-    <ul>
-        <li>Add loading indicator</li>
-        <li>Change default text logic</li>
-    </ul>
-
     <li>PineAP</li>
     <ul>
         <li>Configure used monitor interface (pineapd pineap_interface)</li>
@@ -33,35 +23,21 @@
         <li>Show pineapd service errors</li>
     </ul>
 
-    <li>Logging</li>
-    <ul>
-        <li>Fire data loading on open accordion</li>
-        <li>Add PineAP Logs loading indicator</li>
-        <li>Save filters in cookies</li>
-    </ul>
-
     <li>Network</li>
     <ul>
         <li>Add tabs</li>
         <li>Add "Wireless raw config editor" section</li>
         <li>Add "Info" section</li>
         <li>Add "Interface actions" section</li>
-        <li>Decrease initial requests (from 8 to 3)</li>
     </ul>
 
     <li>Advanced</li>
     <ul>
         <li>Add tabs</li>
         <li>Add "Manual upgrade" section</li>
-        <li>Decrease initial requests (from 8 to 3)</li>
-    </ul>
-
-    <li>Setup</li>
-    <ul>
-        <li>Fix character bad used</li>
     </ul>
 </ul>
 
 <p>
-    <span style="color: red">Mod by DSR!</span> - https://github.com/xchwarze/wifi-pineapple-panel<br/>
+    🚀 <a href="https://github.com/xchwarze/wifi-pineapple-panel">wifi-pineapple-panel by DSR!</a> - Full changelog in GitHub!<br/>
 </p>

+ 1 - 1
src/etc/pineapple/pineapple_version

@@ -1 +1 @@
-2.7.0+
+2.8.0+

+ 6 - 4
src/pineapple/api/API.php

@@ -47,10 +47,10 @@ class API
         if (isset($_SESSION['logged_in']) && $_SESSION['logged_in'] === true) {
             if (isset($_SERVER['HTTP_X_XSRF_TOKEN']) && $_SERVER['HTTP_X_XSRF_TOKEN'] === $_SESSION['XSRF-TOKEN']) {
                 return true;
-            } else {
-                $this->error = "Invalid CSRF token";
-                return false;
             }
+
+            $this->error = "Invalid CSRF token";
+            return false;
         } elseif (isset($this->request->system) && $this->request->system === 'authentication') {
             if (isset($this->request->action) && $this->request->action === 'login') {
                 return true;
@@ -66,11 +66,13 @@ class API
                 return true;
             }
         }
+
         if (file_exists('/etc/pineapple/setupRequired')) {
             $this->response = array('error' => 'Not Authenticated', 'setupRequired' => true);
         } else {
             $this->error = "Not Authenticated";
         }
+
         return false;
     }
 
@@ -115,7 +117,6 @@ class API
 
         $found = false;
         $moduleClass = "";
-
         foreach (glob('/pineapple/modules/*') as $moduleFolder) {
             if (str_replace('/pineapple/modules/', '', $moduleFolder) === $moduleName) {
                 $found = true;
@@ -128,6 +129,7 @@ class API
             $this->error = "Module {$moduleName} does not exist or is defined incorrectly";
             return null;
         }
+
         if (!class_exists($moduleClass)) {
             $this->error = "The class {$moduleClass} does not exist in {$moduleFolder}";
             return null;

+ 1 - 1
src/pineapple/api/Module.php

@@ -117,11 +117,11 @@ abstract class Module
 
         $destination = $installToSD ? '--dest sd' : '';
         $dependencyName = escapeshellarg($dependencyName);
-
         if (!$this->checkDependency($dependencyName)) {
             exec("opkg update");
             exec("opkg install {$dependencyName} {$destination}");
         }
+
         return $this->checkDependency($dependencyName);
     }
 

+ 0 - 1
src/pineapple/api/Notifications.php

@@ -4,7 +4,6 @@ require_once('DatabaseConnection.php');
 
 class Notifications extends APIModule
 {
-
     private $notifications;
     private $dbConnection;
     const DATABASE = "/etc/pineapple/pineapple.db";

+ 1 - 1
src/pineapple/css/main.css

@@ -80,7 +80,7 @@ body {
 }
 
 .log-pre {
-    max-height: 300px;
+    max-height: 30vw;
 }
 
 .btn-fixed-length {

+ 518 - 518
src/pineapple/js/directives.js

@@ -345,583 +345,583 @@
                     $scope.makeModalWithContent();
                 };
             }]
-            };
-        })
-        .directive('cloneModal', function(){
-            return {
-                restrict: 'E',
-                templateUrl: '/html/clone-modal.html',
-                scope: {
-                    hook: '=hook',
-                    content: '=content',
-                    disable: '=disable'
-                },
-                controller: ['$scope', '$api', '$rootScope', '$timeout', '$http', '$interval', function($scope, $api, $rootScope, $timeout, $http, $interval){
-                    $scope.error = '';
-                    $scope.currentBSSID = '';
-                    $scope.working = false;
-                    $scope.success = false;
-                    $scope.oui = null;
-                    $scope.ouiLoading = false;
-                    $scope.gettingOUI = false;
-                    $scope.fullHandshakeFound = false;
-                    $scope.partialHandshakeFound = false;
-                    $scope.handshakeWorking = false;
-                    $scope.handshakeStarting = false;
-                    $scope.handshakeForOtherBSSID = false;
-
-                    $scope.handleResponse = function(response){
-                        if (response.error === undefined) {
+        };
+    })
+    .directive('cloneModal', function(){
+        return {
+            restrict: 'E',
+            templateUrl: '/html/clone-modal.html',
+            scope: {
+                hook: '=hook',
+                content: '=content',
+                disable: '=disable'
+            },
+            controller: ['$scope', '$api', '$rootScope', '$timeout', '$http', '$interval', function($scope, $api, $rootScope, $timeout, $http, $interval){
+                $scope.error = '';
+                $scope.currentBSSID = '';
+                $scope.working = false;
+                $scope.success = false;
+                $scope.oui = null;
+                $scope.ouiLoading = false;
+                $scope.gettingOUI = false;
+                $scope.fullHandshakeFound = false;
+                $scope.partialHandshakeFound = false;
+                $scope.handshakeWorking = false;
+                $scope.handshakeStarting = false;
+                $scope.handshakeForOtherBSSID = false;
+
+                $scope.handleResponse = function(response){
+                    if (response.error === undefined) {
+                        $scope.success = true;
+                        $timeout(function() {
+                            $scope.success = false;
+                        }, 2000);
+                    } else {
+                        $scope.error = response.error;
+                    }
+                };
+                $scope.cloneEnterpriseAP = function(){
+                    $scope.working = true;
+
+                    x = '0x' + $scope.content.bssid.slice(-2);
+                    if (x === '0xFF')
+                        x = '0x00';
+                    newOctet = (parseInt(x, 16) + 0x1).toString(16);
+                    if (x.charAt(2) === '0')
+                        newOctet = ['0', newOctet.slice(0)].join('');
+                    newMac = $scope.content.bssid.slice(0, -2) + newOctet;
+
+                    let settings = {
+                        enabled: false,
+                        enableAssociations: false,
+                        ssid: $scope.content.ssid,
+                        mac: newMac,
+                        encryptionType: $scope.encryptionTranslate($scope.content.encryption)
+                    };
+                    $api.request({
+                        module: 'PineAP',
+                        action: 'setEnterpriseSettings',
+                        settings: settings
+                    }, function(response) {
+                        if (response.success === true) {
                             $scope.success = true;
-                            $timeout(function() {
+                            $scope.working = false;
+                            $timeout(function(){
                                 $scope.success = false;
                             }, 2000);
-                        } else {
-                            $scope.error = response.error;
                         }
-                    };
-                    $scope.cloneEnterpriseAP = function(){
-                        $scope.working = true;
-
-                        x = '0x' + $scope.content.bssid.slice(-2);
-                        if (x === '0xFF')
-                            x = '0x00';
-                        newOctet = (parseInt(x, 16) + 0x1).toString(16);
-                        if (x.charAt(2) === '0')
-                            newOctet = ['0', newOctet.slice(0)].join('');
-                        newMac = $scope.content.bssid.slice(0, -2) + newOctet;
-
-                        let settings = {
-                            enabled: false,
-                            enableAssociations: false,
-                            ssid: $scope.content.ssid,
-                            mac: newMac,
-                            encryptionType: $scope.encryptionTranslate($scope.content.encryption)
-                        };
-                        $api.request({
-                            module: 'PineAP',
-                            action: 'setEnterpriseSettings',
-                            settings: settings
-                        }, function(response) {
-                            if (response.success === true) {
-                                $scope.success = true;
-                                $scope.working = false;
-                                $timeout(function(){
-                                    $scope.success = false;
-                                }, 2000);
-                            }
-                        });
-                    };
-
-                    $scope.encryptionTranslate = function(uiVal) {
-                        let lookup = {
-                            "WPA2 Enterprise (CCMP)": "wpa2+ccmp",
-                            "WPA2 Enterprise (TKIP)": "wpa2+tkip",
-                            "WPA2 Enterprise (TKIP CCMP)": "wpa2+ccmp+tkip",
-                            "WPA Enterprise (CCMP)": "wpa+ccmp",
-                            "WPA Enterprise (TKIP)": "wpa+tkip",
-                            "WPA Enterprise (CCMP TKIP)": "wpa+ccmp+tkip",
-                            "WPA Mixed Enterprise (CCMP)": "wpa-mixed+ccmp",
-                            "WPA Mixed Enterprise (TKIP)": "wpa-mixed+tkip",
-                            "WPA Mixed Enterprise (CCMP TKIP)": "wpa-mixed+ccmp+tkip"
-                        };
-                        return lookup[uiVal];
-                    };
-                    $scope.translatedEncryption = $scope.encryptionTranslate($scope.content.encryption);
-
-                    $scope.checkifHandshakeExists = function() {
-                        $api.request({
-                            module: 'PineAP',
-                            action: 'getHandshake',
-                            bssid: $scope.content.bssid
-                        }, function(response) {
-                            if (response.handshakeExists) {
-                                if (response.partial) {
-                                    $scope.partialHandshakeFound = true;
-                                } else if (response.partial === false) {
-                                    $scope.fullHandshakeFound = true;
-                                }
-
-                                if ($scope.handshakeWorking) {
-                                    $scope.handshakeWorking = false;
-                                }
-
-                                $scope.stopHandshakeCapture();
-                            }
-                        })
-                    };
+                    });
+                };
 
-                    $scope.checkIfCaptureRunning = function() {
-                        $api.request({
-                            module: 'PineAP',
-                            action: 'checkCaptureStatus',
-                            bssid: $scope.content.bssid
-                        }, function(response) {
-                            if (response.running && response.currentBSSID) {
-                                // Running for current BSSID.
-                                $scope.handshakeWorking = true;
-                                $rootScope.captureRunning = true;
-                            } else if (response.running) {
-                                // Running for another BSSID.
-                                $scope.handshakeForOtherBSSID = true;
-                                $scope.currentBSSID = response.bssid;
-                                $rootScope.captureRunning = true;
-                            } else {
-                                // Not running at all.
-                                $scope.handshakeWorking = false;
-                                $rootScope.captureRunning = false;
-                            }
-                        })
+                $scope.encryptionTranslate = function(uiVal) {
+                    let lookup = {
+                        "WPA2 Enterprise (CCMP)": "wpa2+ccmp",
+                        "WPA2 Enterprise (TKIP)": "wpa2+tkip",
+                        "WPA2 Enterprise (TKIP CCMP)": "wpa2+ccmp+tkip",
+                        "WPA Enterprise (CCMP)": "wpa+ccmp",
+                        "WPA Enterprise (TKIP)": "wpa+tkip",
+                        "WPA Enterprise (CCMP TKIP)": "wpa+ccmp+tkip",
+                        "WPA Mixed Enterprise (CCMP)": "wpa-mixed+ccmp",
+                        "WPA Mixed Enterprise (TKIP)": "wpa-mixed+tkip",
+                        "WPA Mixed Enterprise (CCMP TKIP)": "wpa-mixed+ccmp+tkip"
                     };
+                    return lookup[uiVal];
+                };
+                $scope.translatedEncryption = $scope.encryptionTranslate($scope.content.encryption);
 
-                    $scope.stopHandshakeCapture = function() {
-                        $api.request({
-                            module: 'PineAP',
-                            action: 'stopHandshakeCapture'
-                        }, function(response) {
-                            if (response.success) {
-                                $scope.handshakeStarting = false;
-                                $scope.handshakeWorking = false;
-                                $scope.handshakeForOtherBSSID = false;
-                                $rootScope.captureRunning = false;
-                                $interval.cancel($scope.updateInterval);
+                $scope.checkifHandshakeExists = function() {
+                    $api.request({
+                        module: 'PineAP',
+                        action: 'getHandshake',
+                        bssid: $scope.content.bssid
+                    }, function(response) {
+                        if (response.handshakeExists) {
+                            if (response.partial) {
+                                $scope.partialHandshakeFound = true;
+                            } else if (response.partial === false) {
+                                $scope.fullHandshakeFound = true;
                             }
-                        })
-                    };
 
-                    $scope.startHandshakeCapture = function() {
-                        $scope.handshakeStarting = true;
-                        $api.request({
-                            module: 'PineAP',
-                            action: 'startHandshakeCapture',
-                            bssid: $scope.content.bssid,
-                            channel: $scope.content.channel
-                        }, function(response) {
-                            if (response.success) {
-                                $rootScope.captureRunning = true;
-                                $timeout(function(){
-                                    $scope.handshakeWorking = true;
-                                    $scope.handshakeStarting = false;
-                                }, 5000);
-                                $scope.updateInterval = $interval(function() {
-                                    $scope.checkifHandshakeExists();
-                                }, 5000)
-                            } else if (response.error) {
+                            if ($scope.handshakeWorking) {
                                 $scope.handshakeWorking = false;
-                                $scope.handshakeStarting = false;
-                                $scope.error = response.error;
                             }
-                        })
-                    };
 
-                    $scope.toggleHandshakeCapture = function() {
-                        if($scope.handshakeWorking) {
                             $scope.stopHandshakeCapture();
-                        } else {
-                            $scope.startHandshakeCapture();
                         }
-                    };
-
-                    $scope.downloadHandshake = function($type) {
-                        $api.request({
-                            module: 'PineAP',
-                            action: 'downloadHandshake',
-                            bssid: $scope.content.bssid,
-                            type: $type
-                        }, function(response) {
-                            if (response.error === undefined) {
-                                window.location = '/api?download=' + response.download;
-                            }
-                        });
-                    };
-
-                    $scope.deleteHandshake = function() {
-                        $api.request({
-                            module: 'PineAP',
-                            action: 'deleteHandshake',
-                            bssid: $scope.content.bssid
-                        }, function(response) {
-                            if (response.success) {
-                                $scope.deletedHandshake = true;
-                                $scope.fullHandshakeFound = false;
-                                $scope.partialHandshakeFound = false;
-                                $interval.cancel($scope.updateInterval);
-                                $timeout(function() {
-                                    $scope.deletedHandshake = false;
-                                }, 5000);
-                            }
-                        })
-                    };
+                    })
+                };
 
-                    $scope.deauthAP = function() {
-                        $scope.deauthing = true;
-                        $api.request({
-                            module: 'PineAP',
-                            action: 'deauth',
-                            sta: $scope.content.bssid,
-                            clients: $scope.content.clients,
-                            multiplier: 2,
-                            channel: $scope.content.channel
-                        }, function(response) {
-                            }
-                        );
+                $scope.checkIfCaptureRunning = function() {
+                    $api.request({
+                        module: 'PineAP',
+                        action: 'checkCaptureStatus',
+                        bssid: $scope.content.bssid
+                    }, function(response) {
+                        if (response.running && response.currentBSSID) {
+                            // Running for current BSSID.
+                            $scope.handshakeWorking = true;
+                            $rootScope.captureRunning = true;
+                        } else if (response.running) {
+                            // Running for another BSSID.
+                            $scope.handshakeForOtherBSSID = true;
+                            $scope.currentBSSID = response.bssid;
+                            $rootScope.captureRunning = true;
+                        } else {
+                            // Not running at all.
+                            $scope.handshakeWorking = false;
+                            $rootScope.captureRunning = false;
+                        }
+                    })
+                };
 
-                        $timeout(function(){
-                            $scope.deauthing = false;
-                        }, 5000);
-                    };
+                $scope.stopHandshakeCapture = function() {
+                    $api.request({
+                        module: 'PineAP',
+                        action: 'stopHandshakeCapture'
+                    }, function(response) {
+                        if (response.success) {
+                            $scope.handshakeStarting = false;
+                            $scope.handshakeWorking = false;
+                            $scope.handshakeForOtherBSSID = false;
+                            $rootScope.captureRunning = false;
+                            $interval.cancel($scope.updateInterval);
+                        }
+                    })
+                };
 
-                    $scope.startPineAPD = function(){
-                        $scope.error = '';
-                        $scope.pineAPStarting = true;
-                        $api.request({
-                            module: 'PineAP',
-                            action: 'enable'
-                        }, function(response){
+                $scope.startHandshakeCapture = function() {
+                    $scope.handshakeStarting = true;
+                    $api.request({
+                        module: 'PineAP',
+                        action: 'startHandshakeCapture',
+                        bssid: $scope.content.bssid,
+                        channel: $scope.content.channel
+                    }, function(response) {
+                        if (response.success) {
+                            $rootScope.captureRunning = true;
+                            $timeout(function(){
+                                $scope.handshakeWorking = true;
+                                $scope.handshakeStarting = false;
+                            }, 5000);
+                            $scope.updateInterval = $interval(function() {
+                                $scope.checkifHandshakeExists();
+                            }, 5000)
+                        } else if (response.error) {
+                            $scope.handshakeWorking = false;
+                            $scope.handshakeStarting = false;
                             $scope.error = response.error;
-                            $scope.pineAPStarting = false;
-                        });
-                    };
-
-                    $scope.loadOUIFile = (function() {
-                        if (typeof(Storage) === "undefined") {
-                            return false;
                         }
-                        var ouiText = localStorage.getItem("ouiText");
-                        if (ouiText === null) {
-                            $scope.gettingOUI = true;
-                            $http.get('https://www.wifipineapple.com/oui.txt').then(
-                                function(response) {
-                                    localStorage.setItem("ouiText", response.data);
-                                    $scope.populateDB();
-                                },
-                                function() {
-                                    $api.request({
-                                        module: "Networking",
-                                        action: "getOUI"
-                                    }, function(response) {
-                                        if (response.error === undefined) {
-                                            localStorage.setItem("ouiText", response.ouiText);
-                                            $scope.populateDB();
-                                        } else {
-                                            return false;
-                                        }
-                                    });
-                                });
+                    })
+                };
+
+                $scope.toggleHandshakeCapture = function() {
+                    if($scope.handshakeWorking) {
+                        $scope.stopHandshakeCapture();
+                    } else {
+                        $scope.startHandshakeCapture();
+                    }
+                };
+
+                $scope.downloadHandshake = function($type) {
+                    $api.request({
+                        module: 'PineAP',
+                        action: 'downloadHandshake',
+                        bssid: $scope.content.bssid,
+                        type: $type
+                    }, function(response) {
+                        if (response.error === undefined) {
+                            window.location = '/api?download=' + response.download;
                         }
-                        return true;
                     });
+                };
 
-                    $scope.lookupOUI = function() {
-                        $scope.ouiLoading = true;
-                        if (!$scope.ouiPresent()) {
-                            return;
+                $scope.deleteHandshake = function() {
+                    $api.request({
+                        module: 'PineAP',
+                        action: 'deleteHandshake',
+                        bssid: $scope.content.bssid
+                    }, function(response) {
+                        if (response.success) {
+                            $scope.deletedHandshake = true;
+                            $scope.fullHandshakeFound = false;
+                            $scope.partialHandshakeFound = false;
+                            $interval.cancel($scope.updateInterval);
+                            $timeout(function() {
+                                $scope.deletedHandshake = false;
+                            }, 5000);
                         }
+                    })
+                };
 
-                        var request = window.indexedDB.open("pineapple", 1);
-                        request.onsuccess = function() {
-                            var db = request.result;
-                            var prefix = $scope.content.bssid.substring(0,8).replace(/:/g,'');
-                            var transaction = db.transaction("oui");
-                            var objectStore = transaction.objectStore("oui");
-                            var lookupReq = objectStore.get(prefix);
-                            lookupReq.onerror = function() {
-                                window.indexedDB.deleteDatabase("pineapple");
-                                $scope.oui = "Error retrieving OUI";
-                            };
-                            lookupReq.onsuccess = function() {
-                                if (lookupReq.result) {
-                                    $scope.oui = lookupReq.result.name;
-                                } else {
-                                    $scope.oui = "Unknown MAC prefix";
-                                }
-                            };
-                            $scope.ouiLoading = false;
+                $scope.deauthAP = function() {
+                    $scope.deauthing = true;
+                    $api.request({
+                        module: 'PineAP',
+                        action: 'deauth',
+                        sta: $scope.content.bssid,
+                        clients: $scope.content.clients,
+                        multiplier: 2,
+                        channel: $scope.content.channel
+                    }, function(response) {
                         }
-                    };
+                    );
 
-                    $scope.ouiPresent = function() {
-                        return localStorage.getItem("ouiText") !== null;
-                    };
+                    $timeout(function(){
+                        $scope.deauthing = false;
+                    }, 5000);
+                };
 
-                    $scope.populateDB = function() {
-                        $scope.ouiLoading = true;
-                        var request = window.indexedDB.open("pineapple", 1);
+                $scope.startPineAPD = function(){
+                    $scope.error = '';
+                    $scope.pineAPStarting = true;
+                    $api.request({
+                        module: 'PineAP',
+                        action: 'enable'
+                    }, function(response){
+                        $scope.error = response.error;
+                        $scope.pineAPStarting = false;
+                    });
+                };
 
-                        request.onsuccess = function() {
-                            $scope.lookupOUI();
-                        };
+                $scope.loadOUIFile = (function() {
+                    if (typeof(Storage) === "undefined") {
+                        return false;
+                    }
+                    var ouiText = localStorage.getItem("ouiText");
+                    if (ouiText === null) {
+                        $scope.gettingOUI = true;
+                        $http.get('https://www.wifipineapple.com/oui.txt').then(
+                            function(response) {
+                                localStorage.setItem("ouiText", response.data);
+                                $scope.populateDB();
+                            },
+                            function() {
+                                $api.request({
+                                    module: "Networking",
+                                    action: "getOUI"
+                                }, function(response) {
+                                    if (response.error === undefined) {
+                                        localStorage.setItem("ouiText", response.ouiText);
+                                        $scope.populateDB();
+                                    } else {
+                                        return false;
+                                    }
+                                });
+                            });
+                    }
+                    return true;
+                });
 
-                        request.onerror = function(event) {
-                        };
+                $scope.lookupOUI = function() {
+                    $scope.ouiLoading = true;
+                    if (!$scope.ouiPresent()) {
+                        return;
+                    }
 
-                        request.onupgradeneeded = function(event) {
-                            var db = event.target.result;
-                            var objectStore = db.createObjectStore("oui", { keyPath: "macPrefix"});
-                            var text = localStorage.getItem("ouiText");
-                            var pos = 0;
-                            do {
-                                var line = text.substring(pos, text.indexOf("\n", pos + 1)).replace('\n', '');
-                                var arr = [line.substring(0, 6), line.substring(6)];
-                                objectStore.add({
-                                    macPrefix: arr[0],
-                                    name: arr[1]
-                                });
-                                pos += line.length + 1;
-                            } while (text.indexOf("\n", pos + 1) !== -1);
+                    var request = window.indexedDB.open("pineapple", 1);
+                    request.onsuccess = function() {
+                        var db = request.result;
+                        var prefix = $scope.content.bssid.substring(0,8).replace(/:/g,'');
+                        var transaction = db.transaction("oui");
+                        var objectStore = transaction.objectStore("oui");
+                        var lookupReq = objectStore.get(prefix);
+                        lookupReq.onerror = function() {
+                            window.indexedDB.deleteDatabase("pineapple");
+                            $scope.oui = "Error retrieving OUI";
                         };
-                    };
-                    $scope.deleteOUI = function() {
-                        localStorage.removeItem('ouiText');
-                        window.indexedDB.deleteDatabase('pineapple').onsuccess = function() {
-                            $scope.success = true;
-                            $scope.ouiLoading = false;
-                            $scope.gettingOUI = false;
-                            $timeout(function() {
-                                $scope.success = false;
-                            }, 2000);
+                        lookupReq.onsuccess = function() {
+                            if (lookupReq.result) {
+                                $scope.oui = lookupReq.result.name;
+                            } else {
+                                $scope.oui = "Unknown MAC prefix";
+                            }
                         };
-                    };
+                        $scope.ouiLoading = false;
+                    }
+                };
 
-                    $scope.lookupOUI();
-                    $scope.checkifHandshakeExists();
-                    $scope.checkIfCaptureRunning();
-                    $scope.destroyModal = function(){
-                        $('#clone-hook').modal('hide').detach();
+                $scope.ouiPresent = function() {
+                    return localStorage.getItem("ouiText") !== null;
+                };
+
+                $scope.populateDB = function() {
+                    $scope.ouiLoading = true;
+                    var request = window.indexedDB.open("pineapple", 1);
+
+                    request.onsuccess = function() {
+                        $scope.lookupOUI();
                     };
-                }]
-            };
-        })
-        .directive('cloneButton', function(){
-            return {
-                restrict: 'E',
-                template: '<button ng-disabled="disable" ng-click="showModal($event)" class="btn btn-xs btn-default" type="button"><span class="caret"></span></button>',
-                scope: {
-                    hook: '@hook',
-                    content: '=content',
-                    disable: '=disable'
-                },
-                controller: ['$scope', '$compile', function($scope, $compile){
-                    $scope.makeModalWithContent = function(){
-                        var html = '<clone-modal hook="hook" content="content"';
-                        html += '></clone-modal>';
-                        var el = $compile(html)($scope);
-                        $('body').append(el);
-                        $('#clone-hook').modal({
-                            show: true,
-                            keyboard: false,
-                            backdrop: 'static'
-                        });
+
+                    request.onerror = function(event) {
                     };
-                    $scope.showModal = function($event){
-                        $('#clone-hook').remove();
-                        $scope.makeModalWithContent();
+
+                    request.onupgradeneeded = function(event) {
+                        var db = event.target.result;
+                        var objectStore = db.createObjectStore("oui", { keyPath: "macPrefix"});
+                        var text = localStorage.getItem("ouiText");
+                        var pos = 0;
+                        do {
+                            var line = text.substring(pos, text.indexOf("\n", pos + 1)).replace('\n', '');
+                            var arr = [line.substring(0, 6), line.substring(6)];
+                            objectStore.add({
+                                macPrefix: arr[0],
+                                name: arr[1]
+                            });
+                            pos += line.length + 1;
+                        } while (text.indexOf("\n", pos + 1) !== -1);
                     };
-                }]
-            };
-        })
-        .directive('installModal', function(){
-            return {
-                restrict: 'E',
-                templateUrl: '/html/install-modal.html',
-                scope: {
-                    hook: '@hook',
-                    content: '=content'
-                },
-                controller: ['$scope', '$api', '$timeout', '$http', '$interval', '$templateCache', '$rootScope', function($scope, $api, $timeout, $http, $interval, $templateCache, $rootScope){
-                    $scope.device = '';
-                    $rootScope.installedModules = [];
-                    $scope.selectedModule = null;
-
-                    $scope.destroyModal = function(){
-                        $('#install-hook').modal('hide');
+                };
+                $scope.deleteOUI = function() {
+                    localStorage.removeItem('ouiText');
+                    window.indexedDB.deleteDatabase('pineapple').onsuccess = function() {
+                        $scope.success = true;
+                        $scope.ouiLoading = false;
+                        $scope.gettingOUI = false;
+                        $timeout(function() {
+                            $scope.success = false;
+                        }, 2000);
                     };
+                };
 
-                    $scope.getDevice = (function() {
-                        $api.request({
-                            module: "Configuration",
-                            action: "getDevice"
-                        }, function(response) {
-                            $scope.device = response.device;
-                        });
-                    });
-                    $scope.getDevice();
-
-                    $scope.getInstalledModules = (function() {
-                        $api.request({
-                            module: "ModuleManager",
-                            action: "getInstalledModules"
-                        }, function(response) {
-                            $rootScope.installedModules = response.installedModules;
-                            $scope.compareModuleLists();
-                        });
+                $scope.lookupOUI();
+                $scope.checkifHandshakeExists();
+                $scope.checkIfCaptureRunning();
+                $scope.destroyModal = function(){
+                    $('#clone-hook').modal('hide').detach();
+                };
+            }]
+        };
+    })
+    .directive('cloneButton', function(){
+        return {
+            restrict: 'E',
+            template: '<button ng-disabled="disable" ng-click="showModal($event)" class="btn btn-xs btn-default" type="button"><span class="caret"></span></button>',
+            scope: {
+                hook: '@hook',
+                content: '=content',
+                disable: '=disable'
+            },
+            controller: ['$scope', '$compile', function($scope, $compile){
+                $scope.makeModalWithContent = function(){
+                    var html = '<clone-modal hook="hook" content="content"';
+                    html += '></clone-modal>';
+                    var el = $compile(html)($scope);
+                    $('body').append(el);
+                    $('#clone-hook').modal({
+                        show: true,
+                        keyboard: false,
+                        backdrop: 'static'
                     });
+                };
+                $scope.showModal = function($event){
+                    $('#clone-hook').remove();
+                    $scope.makeModalWithContent();
+                };
+            }]
+        };
+    })
+    .directive('installModal', function(){
+        return {
+            restrict: 'E',
+            templateUrl: '/html/install-modal.html',
+            scope: {
+                hook: '@hook',
+                content: '=content'
+            },
+            controller: ['$scope', '$api', '$timeout', '$http', '$interval', '$templateCache', '$rootScope', function($scope, $api, $timeout, $http, $interval, $templateCache, $rootScope){
+                $scope.device = '';
+                $rootScope.installedModules = [];
+                $scope.selectedModule = null;
 
-                    $scope.compareModuleLists = (function() {
-                        angular.forEach($rootScope.availableModules, function(module, moduleName){
-                            if ($rootScope.installedModules[moduleName] === undefined){
-                                module['installable'] = true;
-                            } else if ($rootScope.availableModules[moduleName].version <= $rootScope.installedModules[moduleName].version) {
-                                module['installed'] = true;
-                            }
-                        });
+                $scope.destroyModal = function(){
+                    $('#install-hook').modal('hide');
+                };
+
+                $scope.getDevice = (function() {
+                    $api.request({
+                        module: "Configuration",
+                        action: "getDevice"
+                    }, function(response) {
+                        $scope.device = response.device;
                     });
+                });
+                $scope.getDevice();
 
-                    $scope.checkDestination = (function(moduleName, moduleSize, moduleType) {
-                        $(window).scrollTop(0);
+                $scope.getInstalledModules = (function() {
+                    $api.request({
+                        module: "ModuleManager",
+                        action: "getInstalledModules"
+                    }, function(response) {
+                        $rootScope.installedModules = response.installedModules;
+                        $scope.compareModuleLists();
+                    });
+                });
 
-                        if (moduleType === 'Sys') {
-                            $scope.selectedModule = {module: moduleName, internal: true, sd: false};
-                            return;
+                $scope.compareModuleLists = (function() {
+                    angular.forEach($rootScope.availableModules, function(module, moduleName){
+                        if ($rootScope.installedModules[moduleName] === undefined){
+                            module['installable'] = true;
+                        } else if ($rootScope.availableModules[moduleName].version <= $rootScope.installedModules[moduleName].version) {
+                            module['installed'] = true;
                         }
+                    });
+                });
 
-                        if ($scope.device === 'tetra') {
-                            $scope.selectedModule = {module: moduleName, internal: true, sd: false};
-                            return;
-                        }
+                $scope.checkDestination = (function(moduleName, moduleSize, moduleType) {
+                    $(window).scrollTop(0);
 
-                        $api.request({
-                            module: 'ModuleManager',
-                            action: 'checkDestination',
-                            name: moduleName,
-                            size: moduleSize
-                        }, function(response) {
-                            if (response.error === undefined) {
-                                $scope.selectedModule = response;
-                            }
-                        });
-                    });
-                    $scope.checkDestination($scope.content.name, $scope.content.module['size'], $scope.content.module['type']);
-
-                    $scope.downloadModule = (function(dest) {
-                        $api.request({
-                            module: 'ModuleManager',
-                            action: 'downloadModule',
-                            moduleName: $scope.selectedModule.module,
-                            destination: dest
-                        }, function(response) {
-                            if (response.error === undefined) {
-                                $scope.downloading = true;
-                                var ival = $interval(function() {
-                                    $api.request({
-                                        module: 'ModuleManager',
-                                        action: 'downloadStatus',
-                                        moduleName: $scope.selectedModule.module,
-                                        destination: dest,
-                                        checksum: $rootScope.availableModules[$scope.selectedModule.module]['checksum']
-                                    }, function(response) {
-                                        if (response.success === true) {
-                                            $interval.cancel(ival);
-                                            $scope.installModule(dest);
-                                        }
-                                    });
-                                }, 2000);
-                            }
-                        });
-                    });
+                    if (moduleType === 'Sys') {
+                        $scope.selectedModule = {module: moduleName, internal: true, sd: false};
+                        return;
+                    }
+
+                    if ($scope.device === 'tetra') {
+                        $scope.selectedModule = {module: moduleName, internal: true, sd: false};
+                        return;
+                    }
 
-                    $scope.installModule = (function(dest) {
-                        if ($scope.installing) {
-                            return;
+                    $api.request({
+                        module: 'ModuleManager',
+                        action: 'checkDestination',
+                        name: moduleName,
+                        size: moduleSize
+                    }, function(response) {
+                        if (response.error === undefined) {
+                            $scope.selectedModule = response;
                         }
-                        $scope.downloading = false;
-                        $scope.installing = true;
-
-                        $api.request({
-                            module: 'ModuleManager',
-                            action: 'installModule',
-                            moduleName: $scope.selectedModule.module,
-                            destination: dest
-                        }, function() {
+                    });
+                });
+                $scope.checkDestination($scope.content.name, $scope.content.module['size'], $scope.content.module['type']);
+
+                $scope.downloadModule = (function(dest) {
+                    $api.request({
+                        module: 'ModuleManager',
+                        action: 'downloadModule',
+                        moduleName: $scope.selectedModule.module,
+                        destination: dest
+                    }, function(response) {
+                        if (response.error === undefined) {
+                            $scope.downloading = true;
                             var ival = $interval(function() {
                                 $api.request({
                                     module: 'ModuleManager',
-                                    action: 'installStatus'
+                                    action: 'downloadStatus',
+                                    moduleName: $scope.selectedModule.module,
+                                    destination: dest,
+                                    checksum: $rootScope.availableModules[$scope.selectedModule.module]['checksum']
                                 }, function(response) {
                                     if (response.success === true) {
                                         $interval.cancel(ival);
-                                        $templateCache.removeAll();
-                                        $scope.installedModule = true;
-                                        $scope.installing = false;
-                                        $scope.getInstalledModules();
-                                        $api.reloadNavbar();
-                                        if ($scope.selectedModule.module === 'ModuleManager') {
-                                            window.location.reload();
-                                        } else {
-                                            $scope.selectedModule = null;
-                                            $scope.destroyModal();
-                                        }
-                                        $timeout(function(){
-                                            $scope.installedModule = false;
-                                        }, 2000);
+                                        $scope.installModule(dest);
                                     }
                                 });
-                            }, 500);
-                        });
+                            }, 2000);
+                        }
                     });
-                }]
-            };
-        })
-        .directive('installButton', function(){
-            return {
-                restrict: 'E',
-                template: '<button ng-disabled="disable" ng-click="showModal($event)" class="btn btn-default btn-xs btn-fixed-length" type="button">Install</button>',
-                scope: {
-                    hook: '@hook',
-                    content: '=content'
-                },
-                controller: ['$scope', '$compile', function($scope, $compile){
-                    $scope.makeModalWithContent = function(){
-                        var html = '<install-modal hook="hook" content="content"></install-modal>';
-                        var el = $compile(html)($scope);
-                        $('body').append(el);
-                        $('#install-hook').modal({
-                            show: true,
-                            keyboard: false,
-                            backdrop: 'static'
-                        });
-                    };
+                });
 
-                    $scope.showModal = function(){
-                        $('#install-hook').remove();
-                        $scope.makeModalWithContent();
-                    };
+                $scope.installModule = (function(dest) {
+                    if ($scope.installing) {
+                        return;
+                    }
+                    $scope.downloading = false;
+                    $scope.installing = true;
 
-                    $scope.destroyModal = function(){
-                        $('#install-hook').modal('hide');
-                    };
-                }]
-            };
-        })
-        .directive('updateButton', function(){
-            return {
-                restrict: 'E',
-                template: '<button ng-disabled="disable" ng-click="showModal($event)" class="btn btn-primary btn-xs btn-fixed-length" type="button">Update</button>',
-                scope: {
-                    hook: '@hook',
-                    content: '=content'
-                },
-                controller: ['$scope', '$compile', function($scope, $compile){
-                    $scope.makeModalWithContent = function(){
-                        var html = '<install-modal hook="hook" content="content"></install-modal>';
-                        var el = $compile(html)($scope);
-                        $('body').append(el);
-                        $('#install-hook').modal({
-                            show: true,
-                            keyboard: false,
-                            backdrop: 'static'
-                        });
-                    };
+                    $api.request({
+                        module: 'ModuleManager',
+                        action: 'installModule',
+                        moduleName: $scope.selectedModule.module,
+                        destination: dest
+                    }, function() {
+                        var ival = $interval(function() {
+                            $api.request({
+                                module: 'ModuleManager',
+                                action: 'installStatus'
+                            }, function(response) {
+                                if (response.success === true) {
+                                    $interval.cancel(ival);
+                                    $templateCache.removeAll();
+                                    $scope.installedModule = true;
+                                    $scope.installing = false;
+                                    $scope.getInstalledModules();
+                                    $api.reloadNavbar();
+                                    if ($scope.selectedModule.module === 'ModuleManager') {
+                                        window.location.reload();
+                                    } else {
+                                        $scope.selectedModule = null;
+                                        $scope.destroyModal();
+                                    }
+                                    $timeout(function(){
+                                        $scope.installedModule = false;
+                                    }, 2000);
+                                }
+                            });
+                        }, 500);
+                    });
+                });
+            }]
+        };
+    })
+    .directive('installButton', function(){
+        return {
+            restrict: 'E',
+            template: '<button ng-disabled="disable" ng-click="showModal($event)" class="btn btn-default btn-xs btn-fixed-length" type="button">Install</button>',
+            scope: {
+                hook: '@hook',
+                content: '=content'
+            },
+            controller: ['$scope', '$compile', function($scope, $compile){
+                $scope.makeModalWithContent = function(){
+                    var html = '<install-modal hook="hook" content="content"></install-modal>';
+                    var el = $compile(html)($scope);
+                    $('body').append(el);
+                    $('#install-hook').modal({
+                        show: true,
+                        keyboard: false,
+                        backdrop: 'static'
+                    });
+                };
 
-                    $scope.showModal = function(){
-                        $('#install-hook').remove();
-                        $scope.makeModalWithContent();
-                    };
+                $scope.showModal = function(){
+                    $('#install-hook').remove();
+                    $scope.makeModalWithContent();
+                };
 
-                    $scope.destroyModal = function(){
-                        $('#install-hook').modal('hide');
-                    };
-                }]
-            };
-        })
+                $scope.destroyModal = function(){
+                    $('#install-hook').modal('hide');
+                };
+            }]
+        };
+    })
+    .directive('updateButton', function(){
+        return {
+            restrict: 'E',
+            template: '<button ng-disabled="disable" ng-click="showModal($event)" class="btn btn-primary btn-xs btn-fixed-length" type="button">Update</button>',
+            scope: {
+                hook: '@hook',
+                content: '=content'
+            },
+            controller: ['$scope', '$compile', function($scope, $compile){
+                $scope.makeModalWithContent = function(){
+                    var html = '<install-modal hook="hook" content="content"></install-modal>';
+                    var el = $compile(html)($scope);
+                    $('body').append(el);
+                    $('#install-hook').modal({
+                        show: true,
+                        keyboard: false,
+                        backdrop: 'static'
+                    });
+                };
+
+                $scope.showModal = function(){
+                    $('#install-hook').remove();
+                    $scope.makeModalWithContent();
+                };
+
+                $scope.destroyModal = function(){
+                    $('#install-hook').modal('hide');
+                };
+            }]
+        };
+    })
 })();

+ 1 - 1
src/pineapple/modules/Dashboard/js/module.js

@@ -25,7 +25,7 @@ registerController("DashboardOverviewController", ['$api', '$scope', '$interval'
 
 	$scope.populateInterval = $interval(function(){
 		$scope.populateDashboard();
-	}, 5000);
+	}, 10000);
 
 	$scope.populateDashboard();
 	$scope.$on('$destroy', function() {