| 3 | rodolico | 1 | <?php
 | 
        
           |  |  | 2 |   | 
        
           |  |  | 3 | /*
 | 
        
           |  |  | 4 |  * Requires php-pear and libyaml under Debian Wheezy
 | 
        
           |  |  | 5 |  * apt-get install php-pear php5-dev libyaml0dev
 | 
        
           |  |  | 6 |  * I don't know if you also need libyaml-0-2 libyaml-0-2-dbg
 | 
        
           |  |  | 7 |  * pecl install yaml
 | 
        
           | 5 | rodolico | 8 |  *
 | 
        
           |  |  | 9 |  * V0.9 20160203 RWR
 | 
        
           |  |  | 10 |  * Changed to use yaml for the configuration file. Had to take the
 | 
        
           |  |  | 11 |  * anonymous functions which parsed the different file types and convert
 | 
        
           |  |  | 12 |  * them to simpl eval() blocks.
 | 
        
           |  |  | 13 |  * 
 | 
        
           | 3 | rodolico | 14 | */
 | 
        
           |  |  | 15 |   | 
        
           |  |  | 16 | require 'library.php';
 | 
        
           | 9 | rodolico | 17 | $VERSION='0.9.1';
 | 
        
           | 3 | rodolico | 18 |   | 
        
           |  |  | 19 |   | 
        
           |  |  | 20 | class sysinfo {
 | 
        
           |  |  | 21 |    private $report; // this will hold an entire report
 | 
        
           |  |  | 22 |    private $messages = array();
 | 
        
           |  |  | 23 |    private $FATAL = false;
 | 
        
           |  |  | 24 |    private $parsingArray;   // this is a required array that teaches how to properly parse the input
 | 
        
           |  |  | 25 |   | 
        
           |  |  | 26 |    // following are used internally to track important information
 | 
        
           |  |  | 27 |    private $clientID;   // id in database
 | 
        
           |  |  | 28 |    private $clientName; // name from report
 | 
        
           |  |  | 29 |    private $machineID;  // id in database
 | 
        
           |  |  | 30 |    private $machineName;// name in report
 | 
        
           |  |  | 31 |    private $reportDate; // unix timestamp of report
 | 
        
           |  |  | 32 |    private $reportDateSQL; // used for inserts and compares in the database
 | 
        
           |  |  | 33 |    private $serialNumber; // the serial number, which is assumed to be unique
 | 
        
           |  |  | 34 |    private $fileContents;
 | 
        
           |  |  | 35 |    private $processDuplicates = false; // used for testing; allows duplicate reports
 | 
        
           |  |  | 36 |    private $returnCode = 0; // how we returned from this
 | 
        
           |  |  | 37 |    private $errors = array( 1 => 'Could not process file, not xml, yaml or ini',
 | 
        
           |  |  | 38 |                             2 => 'Invalid report, does not have one or more of report date, client name or computer name',
 | 
        
           |  |  | 39 |                             3 => 'Invalid Report, invalid machine name',
 | 
        
           |  |  | 40 |                             4 => 'Duplicate Report',
 | 
        
           |  |  | 41 |                             5 => 'New Report, must be added to CAMP',
 | 
        
           |  |  | 42 |                             6 => 'Report is in queue for addition after updates to CAMP'
 | 
        
           |  |  | 43 |                           );
 | 
        
           |  |  | 44 |   | 
        
           |  |  | 45 |    /*
 | 
        
           |  |  | 46 |     * $parsingArray contains one or more rows, each of which have three rows, starttag, endtag and eval
 | 
        
           |  |  | 47 |     * starttag and endtag are regex's which match the beginning and end of a document (ie, --- and ... for yaml)
 | 
        
           |  |  | 48 |     * eval is an anonymous function which will evaluate a particular type of document, returning it as an
 | 
        
           |  |  | 49 |     * array which we store in $report
 | 
        
           |  |  | 50 |     */
 | 
        
           |  |  | 51 |   | 
        
           |  |  | 52 |    function __construct( $parsingArray ) {
 | 
        
           |  |  | 53 |       $this->parsingArray = $parsingArray;
 | 
        
           |  |  | 54 |    }
 | 
        
           |  |  | 55 |   | 
        
           |  |  | 56 |    public function processReport () {
 | 
        
           |  |  | 57 |       $this->validateReport(); // validate the report appears to be ok
 | 
        
           |  |  | 58 |       // prepend the name of the report to messages BEFORE any error messages that may have appeared
 | 
        
           |  |  | 59 |       array_unshift( $this->messages,
 | 
        
           |  |  | 60 |             "Report on $this->reportDateSQL, client $this->clientName, system $this->machineName ($this->fileType)");
 | 
        
           |  |  | 61 |       // now, we do every step in turn. If they set the FATAL flag, we exit.
 | 
        
           |  |  | 62 |       if ( $this->FATAL ) return $this->returnCode;
 | 
        
           |  |  | 63 |       $this->getMachineID();
 | 
        
           |  |  | 64 |       if ( empty( $this->machineID ) ) return $this->returnCode;
 | 
        
           | 9 | rodolico | 65 |       $this->checkDuplicate();
 | 
        
           | 3 | rodolico | 66 |       if ( $this->FATAL) return $this->returnCode;
 | 
        
           |  |  | 67 |       $this->updateComputerMakeup();
 | 
        
           |  |  | 68 |       $this->updateOS();
 | 
        
           |  |  | 69 |       $this->updateBootTime();
 | 
        
           |  |  | 70 |       $this->doIPAddresses();
 | 
        
           |  |  | 71 |       $this->processPCI();
 | 
        
           |  |  | 72 |       $this->processSoftwarePackages();
 | 
        
           | 9 | rodolico | 73 |       // at this point, we don't really need the report title information
 | 
        
           |  |  | 74 |       // so we will remove it before recordReport has a chance to put it
 | 
        
           |  |  | 75 |       // in database
 | 
        
           |  |  | 76 |       array_shift( $this->messages );
 | 
        
           |  |  | 77 |       // now record the report
 | 
        
           |  |  | 78 |       $this->recordReport();
 | 
        
           | 3 | rodolico | 79 |       return $this->returnCode;;
 | 
        
           |  |  | 80 |    } // function processReport
 | 
        
           |  |  | 81 |   | 
        
           |  |  | 82 |    /* 
 | 
        
           |  |  | 83 |     * Name: loadFromFile
 | 
        
           |  |  | 84 |     * Parameters: filename (path to load file from)
 | 
        
           |  |  | 85 |     * Returns: true if on success, false if not
 | 
        
           |  |  | 86 |     * Modifies: 
 | 
        
           |  |  | 87 |     *    report - added messages on why the report is not valid
 | 
        
           |  |  | 88 |     *    FATAL    - set to true if any of the required values do not exist
 | 
        
           |  |  | 89 |     */
 | 
        
           |  |  | 90 |   | 
        
           |  |  | 91 |    public function loadFromFile ( $filename ) {
 | 
        
           |  |  | 92 |       // load file into memory. Additionally, remove any \r's from it (leaving \n's for newlines)
 | 
        
           |  |  | 93 |       $this->fileContents = str_replace("\r","", file_get_contents( $filename ) );
 | 
        
           |  |  | 94 |       // try to parse the body out
 | 
        
           |  |  | 95 |       $this->getBody();
 | 
        
           |  |  | 96 |       if ( isset( $this->report ) ) {
 | 
        
           |  |  | 97 |          if ( $this->fileType == 'xml' ) $this->fixXML();
 | 
        
           |  |  | 98 |          if ( $this->fileType == 'ini' ) {
 | 
        
           |  |  | 99 |             $this->messages[] = 'We do not process ini files, but storing it instead';
 | 
        
           |  |  | 100 |          }
 | 
        
           |  |  | 101 |          return $this->fileType;
 | 
        
           |  |  | 102 |       } else { // we don't know what it is
 | 
        
           |  |  | 103 |          $this->FATAL = true;
 | 
        
           |  |  | 104 |          $this->messages[] = "Unable to parse [$filename] using YAML, XML or INI";
 | 
        
           |  |  | 105 |          return false;
 | 
        
           |  |  | 106 |       }
 | 
        
           |  |  | 107 |       //unset( $this->fileContents ); // free up memory
 | 
        
           |  |  | 108 |    } // function loadFromFile
 | 
        
           |  |  | 109 |   | 
        
           |  |  | 110 |   | 
        
           |  |  | 111 |    // once the file has been loaded, we need to figure out what kind of file it is
 | 
        
           |  |  | 112 |    // then use the function embedded in $parsingArray to import it.
 | 
        
           |  |  | 113 |    private function getBody ( ) {
 | 
        
           |  |  | 114 |       foreach ( $this->parsingArray as $key => $regexes ) {
 | 
        
           |  |  | 115 |          $matches;
 | 
        
           |  |  | 116 |          $pattern = $regexes['startTag'] . '.*' . $regexes['endTag'];
 | 
        
           |  |  | 117 |          if ( preg_match( "/$pattern/ms", $this->fileContents, $matches ) ) {
 | 
        
           |  |  | 118 |             $this->fileType = $key;
 | 
        
           |  |  | 119 |             $this->fileContents = $matches[0];
 | 
        
           | 5 | rodolico | 120 |             $body = $this->fileContents;
 | 
        
           |  |  | 121 |             $this->report = eval( $regexes['eval'] );
 | 
        
           |  |  | 122 |             if ( $this->report ) return true;
 | 
        
           | 3 | rodolico | 123 |          } // if
 | 
        
           |  |  | 124 |       } // foreach
 | 
        
           |  |  | 125 |       return false;
 | 
        
           |  |  | 126 |    }
 | 
        
           |  |  | 127 |   | 
        
           |  |  | 128 |    /*
 | 
        
           |  |  | 129 |     * Name: fixXML
 | 
        
           |  |  | 130 |     * Parameters: None
 | 
        
           |  |  | 131 |     * Returns: nothing
 | 
        
           |  |  | 132 |     * Modifies: $this->report
 | 
        
           |  |  | 133 |     * YAML creates the entries as ['network']['interface name']
 | 
        
           |  |  | 134 |     * XML  creates the entries as ["network"][x][name]=>
 | 
        
           |  |  | 135 |     * We will simply copy the XML information into a duplicate
 | 
        
           |  |  | 136 |     * in YAML style
 | 
        
           |  |  | 137 |     */
 | 
        
           |  |  | 138 |    private function fixXML() {
 | 
        
           |  |  | 139 |        $oldInfo = $this->report['network'];
 | 
        
           |  |  | 140 |        unset ($this->report['network']);
 | 
        
           |  |  | 141 |        foreach ( $oldInfo as $entry ) {
 | 
        
           |  |  | 142 |           #$this->messages[] = "Duplicating network entry for $entry[name]";
 | 
        
           |  |  | 143 |           foreach ($entry as $key => $value ) {
 | 
        
           |  |  | 144 |              $this->report['network'][$entry['name']][$key] = $value;
 | 
        
           |  |  | 145 |              #$this->messages[] = "  Adding  $value as value for network.name.$key";
 | 
        
           |  |  | 146 |           } // inner foreach
 | 
        
           |  |  | 147 |        } // outer foreach
 | 
        
           |  |  | 148 |    } // fixXML
 | 
        
           |  |  | 149 |   | 
        
           |  |  | 150 |   | 
        
           |  |  | 151 |    private function processINI() {
 | 
        
           |  |  | 152 |       return false;
 | 
        
           |  |  | 153 |    }
 | 
        
           |  |  | 154 |   | 
        
           |  |  | 155 |    public function dumpMessages () {
 | 
        
           | 9 | rodolico | 156 |       $return = '';
 | 
        
           |  |  | 157 |       if ( $this->messages ) {
 | 
        
           |  |  | 158 |          $return = implode( "\n", $this->messages );
 | 
        
           |  |  | 159 |          $return .= "\n";
 | 
        
           |  |  | 160 |       }
 | 
        
           | 3 | rodolico | 161 |       return $return;
 | 
        
           |  |  | 162 |    }
 | 
        
           |  |  | 163 |   | 
        
           |  |  | 164 |    /* 
 | 
        
           |  |  | 165 |     * Name: validateReport
 | 
        
           |  |  | 166 |     * Parameters: none
 | 
        
           |  |  | 167 |     * Returns: true if valid, false if not
 | 
        
           |  |  | 168 |     * Modifies: 
 | 
        
           |  |  | 169 |     *    messages - added messages on why the report is not valid
 | 
        
           |  |  | 170 |     *    FATAL    - set to true if any of the required values do not exist
 | 
        
           |  |  | 171 |     */
 | 
        
           |  |  | 172 |   | 
        
           |  |  | 173 |       public function validateReport () {
 | 
        
           |  |  | 174 |       /*
 | 
        
           |  |  | 175 |        * A report is considered valid if it has a date, client name and hostname
 | 
        
           |  |  | 176 |        * No check is made at this time for validity of that data
 | 
        
           |  |  | 177 |        */
 | 
        
           |  |  | 178 |       if ( empty( $this->report['report']['date']) ) {
 | 
        
           |  |  | 179 |          $this->messages[] = 'No report date';
 | 
        
           |  |  | 180 |       } else {
 | 
        
           |  |  | 181 |          $this->reportDate = strtotime( $this->report['report']['date'] ); // store in Unix timestamp
 | 
        
           |  |  | 182 |          $this->reportDateSQL = strftime( '%F %T', $this->reportDate ); // save a copy of the date in SQL format
 | 
        
           |  |  | 183 |          if ( empty( $this->reportDate ) )
 | 
        
           |  |  | 184 |             $this->messages[] = "Unable to parse report date [$this->report['report']['date']]";
 | 
        
           |  |  | 185 |       }
 | 
        
           |  |  | 186 |   | 
        
           |  |  | 187 |       if ( empty( $this->report['report']['client'] ) ) {
 | 
        
           |  |  | 188 |          $this->messages[] = 'No client name';
 | 
        
           |  |  | 189 |       } else {
 | 
        
           |  |  | 190 |          $this->clientName = $this->report['report']['client'];
 | 
        
           |  |  | 191 |       }
 | 
        
           |  |  | 192 |   | 
        
           |  |  | 193 |       if ( empty ( $this->report['system']['hostname'] ) ) {
 | 
        
           |  |  | 194 |          $this->messages[] = 'No Computer Name';
 | 
        
           |  |  | 195 |       } else {
 | 
        
           |  |  | 196 |          $this->machineName = $this->report['system']['hostname'];
 | 
        
           |  |  | 197 |       }
 | 
        
           |  |  | 198 |       $this->FATAL = ! empty( $this->messages );
 | 
        
           |  |  | 199 |   | 
        
           | 6 | rodolico | 200 |       /* removed for the time being.
 | 
        
           | 3 | rodolico | 201 |       // serial number is fairly new, so it is not a critical error
 | 
        
           |  |  | 202 |       // it will be set in getMachineID if we have it here, but not there
 | 
        
           |  |  | 203 |       if ( empty ( $this->report['system']['serial'] ) ) {
 | 
        
           |  |  | 204 |          $this->messages[] = 'No Serial Number';
 | 
        
           |  |  | 205 |       } else {
 | 
        
           |  |  | 206 |          $this->serialNumber = $this->report['system']['serial'];
 | 
        
           |  |  | 207 |       }
 | 
        
           | 6 | rodolico | 208 |       */
 | 
        
           | 3 | rodolico | 209 |   | 
        
           |  |  | 210 |    } // function validateReport
 | 
        
           |  |  | 211 |   | 
        
           |  |  | 212 |   | 
        
           |  |  | 213 |    /* 
 | 
        
           |  |  | 214 |     * Name: getMachineID
 | 
        
           |  |  | 215 |     * Parameters: none
 | 
        
           |  |  | 216 |     * Returns: true if found, false if not
 | 
        
           |  |  | 217 |     * Modifies: 
 | 
        
           |  |  | 218 |     *    clientID - index value of client in database
 | 
        
           |  |  | 219 |     *    machineID - index value of machine in database
 | 
        
           |  |  | 220 |     */
 | 
        
           |  |  | 221 |    private function getMachineID () {
 | 
        
           |  |  | 222 |       $this->clientID = getClientID( $this->clientName );
 | 
        
           |  |  | 223 |       if ( $this->clientID ) {
 | 
        
           |  |  | 224 |          $this->machineID = getMachineID( $this->machineName, $this->clientID, $this->serialNumber );
 | 
        
           |  |  | 225 |       }
 | 
        
           |  |  | 226 |       if ( empty( $this->machineID ) ) {
 | 
        
           |  |  | 227 |          $this->messages[] = $this->makeUnknown( $this->clientName, $this->machineName, $this->reportDateSQL );
 | 
        
           |  |  | 228 |          return false;
 | 
        
           |  |  | 229 |       }
 | 
        
           |  |  | 230 |       if ( $this->machineID == -1 ) {
 | 
        
           |  |  | 231 |          $this->messages[] = "Duplicate serial number found for serial [$this->serialNumber], aborting";
 | 
        
           |  |  | 232 |          return false;
 | 
        
           |  |  | 233 |       }
 | 
        
           |  |  | 234 |       return true;
 | 
        
           |  |  | 235 |    } // function getMachineID
 | 
        
           |  |  | 236 |   | 
        
           |  |  | 237 |    /* 
 | 
        
           |  |  | 238 |     * checks for a duplicate report, ie one that has already been run.
 | 
        
           |  |  | 239 |     * if this computer has a report already for this date/time
 | 
        
           |  |  | 240 |     */ 
 | 
        
           | 9 | rodolico | 241 |    private function checkDuplicate() {
 | 
        
           | 3 | rodolico | 242 |       $count = getOneDBValue("select count(*) from sysinfo_report where device_id = $this->machineID and report_date = '$this->reportDateSQL'");
 | 
        
           |  |  | 243 |       if ( $this->processDuplicates ) { $count = 0; } // for testing
 | 
        
           |  |  | 244 |       if ( $count ) {
 | 
        
           |  |  | 245 |          $this->messages[] = "Duplicate Report for $this->machineName (id $this->machineID) on $this->reportDateSQL";
 | 
        
           |  |  | 246 |          $this->returnCode = 4;
 | 
        
           |  |  | 247 |          $this->FATAL = true;
 | 
        
           |  |  | 248 |          return false;
 | 
        
           |  |  | 249 |       }
 | 
        
           | 9 | rodolico | 250 |       return true;
 | 
        
           |  |  | 251 |    } // recordReport
 | 
        
           |  |  | 252 |   | 
        
           |  |  | 253 |   | 
        
           |  |  | 254 |    /* 
 | 
        
           |  |  | 255 |     * Creates an entry in the sysinfo_report table
 | 
        
           |  |  | 256 |     */ 
 | 
        
           |  |  | 257 |    private function recordReport() {
 | 
        
           | 3 | rodolico | 258 |       $version = $this->report['report']['version'];
 | 
        
           | 9 | rodolico | 259 |       $messages = makeSafeSQLValue( $this->dumpMessages() );
 | 
        
           |  |  | 260 |       // if we made it this far, we are ok, so just add the report id
 | 
        
           |  |  | 261 |       queryDatabaseExtended("insert into sysinfo_report(device_id,version,report_date, notes,added_date) values ($this->machineID ,'$version','$this->reportDateSQL',$messages,now())");
 | 
        
           | 3 | rodolico | 262 |       $this->reportID = getOneDBValue("select max( sysinfo_report_id ) from sysinfo_report where device_id = $this->machineID and report_date = '$this->reportDateSQL'");
 | 
        
           |  |  | 263 |       return true;
 | 
        
           | 9 | rodolico | 264 |    } // recordReport
 | 
        
           | 3 | rodolico | 265 |   | 
        
           |  |  | 266 |   | 
        
           |  |  | 267 |    function makeUnknown( $clientName, $machineName, $reportDate ) {
 | 
        
           |  |  | 268 |       $result = getOneDBValue("select report_date from unknown_entry where client_name = '$clientName' and device_name = '$machineName'");
 | 
        
           |  |  | 269 |       if ( empty( $result ) ) {
 | 
        
           |  |  | 270 |          queryDatabaseExtended( "insert into unknown_entry(client_name,device_name,report_date) values ('$clientName', '$machineName', '$reportDate')");
 | 
        
           |  |  | 271 |          $this->returnCode = 5;
 | 
        
           |  |  | 272 |          return "New entry, client=$clientName, device=$machineName. You must update Camp before this report can be processed";
 | 
        
           |  |  | 273 |       } else {
 | 
        
           |  |  | 274 |          $this->returnCode = 6;
 | 
        
           |  |  | 275 |          return "New entry detected, but entry already made. You must update Camp before this can be processed";
 | 
        
           |  |  | 276 |       }
 | 
        
           |  |  | 277 |    }
 | 
        
           |  |  | 278 |   | 
        
           | 9 | rodolico | 279 |    // simply used to get an attrib_id. If it does not exit, will create it
 | 
        
           | 3 | rodolico | 280 |   | 
        
           |  |  | 281 |    private function getAttributeID ( $attributeName, $reportDate ) {
 | 
        
           |  |  | 282 |       $attributeName = makeSafeSQLValue( $attributeName );
 | 
        
           |  |  | 283 |       $result = getOneDBValue( "select attrib_id from attrib where name = $attributeName and removed_date is null" );
 | 
        
           |  |  | 284 |       if ( !isset( $result) ) {
 | 
        
           |  |  | 285 |          $result = queryDatabaseExtended( "insert into attrib (name,added_date) values ($attributeName,'$reportDate')");
 | 
        
           |  |  | 286 |          $this->messages[] = "Added a new attribute type [$attributeName]";
 | 
        
           |  |  | 287 |          $result = $result['insert_id'];
 | 
        
           |  |  | 288 |       }
 | 
        
           |  |  | 289 |       return $result;
 | 
        
           |  |  | 290 |    }
 | 
        
           |  |  | 291 |   | 
        
           |  |  | 292 |    /*
 | 
        
           |  |  | 293 |     * Checks an attribute from the device_attriburtes table. If the value has
 | 
        
           |  |  | 294 |     * changed, sets the old one's removed_date to this report date, then adds
 | 
        
           |  |  | 295 |     * new record for new value.
 | 
        
           |  |  | 296 |     * If the record does not exist, simply creates it
 | 
        
           |  |  | 297 |     */
 | 
        
           |  |  | 298 |    public function checkAndUpdateAttribute( $attribute, $value ) {
 | 
        
           |  |  | 299 |       if ( !isset($attribute) || !isset($value ) ) {
 | 
        
           |  |  | 300 |          $this->messages[] = "Error: attempt to use null value for [$attribute], value [$value] for ID $this->machineID in checkAndUPdateAttribute";
 | 
        
           |  |  | 301 |          return false;
 | 
        
           |  |  | 302 |       }
 | 
        
           |  |  | 303 |       $value = makeSafeSQLValue($value); # we want to always quote the value on this particular one
 | 
        
           |  |  | 304 |       //$attribute = makeSafeSQLValue( $attribute );
 | 
        
           |  |  | 305 |       $attrib_id = $this->getAttributeID( $attribute, $this->reportDateSQL );
 | 
        
           |  |  | 306 |       $result = getOneDBValue( "select device_attrib.value
 | 
        
           |  |  | 307 |          from device_attrib join attrib using (attrib_id)
 | 
        
           |  |  | 308 |          where device_attrib.device_id = $this->machineID
 | 
        
           |  |  | 309 |                and device_attrib.removed_date is null
 | 
        
           |  |  | 310 |                and attrib.attrib_id = $attrib_id
 | 
        
           |  |  | 311 |          ");
 | 
        
           |  |  | 312 |       $result = makeSafeSQLValue( $result ); # we must do this since we are comparing to $value which has had this done
 | 
        
           |  |  | 313 |       if ( isset( $result ) ) { # got it, now see if it compares ok
 | 
        
           |  |  | 314 |          if ( $value != $result ) { # nope, this has changed. Note, must use fixDatabaseValue for escapes already in $value
 | 
        
           |  |  | 315 |             $this->messages[] = "New value [$value] for $attribute for device $this->machineID, voiding previous";
 | 
        
           |  |  | 316 |             queryDatabaseExtended( "update device_attrib
 | 
        
           |  |  | 317 |                                        set removed_date = '$this->reportDateSQL'
 | 
        
           |  |  | 318 |                                     where device_id = $this->machineID
 | 
        
           |  |  | 319 |                                           and attrib_id = $attrib_id
 | 
        
           |  |  | 320 |                                           and removed_date is null");
 | 
        
           |  |  | 321 |             unset( $result ); # this will force the insert in the next block of code
 | 
        
           |  |  | 322 |          } # if $result ne $value
 | 
        
           |  |  | 323 |       } # if ($result)
 | 
        
           |  |  | 324 |       if ( ! isset( $result ) ) { # we have no valid entry for this attribute
 | 
        
           |  |  | 325 |          //$this->messages[] = "In checkAndUpdateAttribute, adding new record with insert into device_attrib(device_id,attrib_id,value,added_date) values ($this->machineID,$attrib_id,$value,$this->reportDateSQL)";
 | 
        
           |  |  | 326 |          queryDatabaseExtended( "insert into device_attrib(device_id,attrib_id,value,added_date)
 | 
        
           |  |  | 327 |                                  values ($this->machineID,$attrib_id,$value,'$this->reportDateSQL')");
 | 
        
           |  |  | 328 |          return true;
 | 
        
           |  |  | 329 |       }
 | 
        
           |  |  | 330 |       return false;
 | 
        
           |  |  | 331 |    } // checkAndUpdateAttribute
 | 
        
           |  |  | 332 |   | 
        
           |  |  | 333 |    # simply verifies some attributes of the computer
 | 
        
           |  |  | 334 |    private function updateComputerMakeup() {
 | 
        
           |  |  | 335 |       $this->checkAndUpdateAttribute('Memory',        $this->report['system']['memory']);
 | 
        
           |  |  | 336 |       $this->checkAndUpdateAttribute('Number of CPUs',$this->report['system']['num_cpu']);
 | 
        
           |  |  | 337 |       $this->checkAndUpdateAttribute('CPU Type',      $this->report['system']['cpu_type']);
 | 
        
           |  |  | 338 |       $this->checkAndUpdateAttribute('CPU SubType',   $this->report['system']['cpu_sub']);
 | 
        
           |  |  | 339 |       $this->checkAndUpdateAttribute('CPU Speed',     $this->report['system']['cpu_speed']);
 | 
        
           |  |  | 340 |    } // updateComputerMakeup
 | 
        
           |  |  | 341 |   | 
        
           |  |  | 342 |    // This is kind of funky, because column = null does not work, it must be column is null, so we have to look for it.
 | 
        
           |  |  | 343 |    function makeSQLEquals ( $field, $value ) {
 | 
        
           |  |  | 344 |       return "$field " . ( $value == 'null' ? 'is null' : '=' . $value );
 | 
        
           |  |  | 345 |    }
 | 
        
           |  |  | 346 |   | 
        
           |  |  | 347 |   | 
        
           |  |  | 348 |    private function updateOS () {
 | 
        
           |  |  | 349 |       // find os
 | 
        
           |  |  | 350 |       $osName =         makeSafeSQLValue( isset($this->report['operatingsystem']['os_name'])         ? $this->report['operatingsystem']['os_name'] : '');
 | 
        
           |  |  | 351 |       $kernel =         makeSafeSQLValue( isset($this->report['operatingsystem']['kernel'])          ? $this->report['operatingsystem']['kernel'] : '');
 | 
        
           |  |  | 352 |       $distro_name =    makeSafeSQLValue( isset($this->report['operatingsystem']['os_distribution']) ? $this->report['operatingsystem']['distribution'] : '');
 | 
        
           |  |  | 353 |       $release =        makeSafeSQLValue( isset($this->report['operatingsystem']['os_release'])      ? $this->report['operatingsystem']['release'] : '');
 | 
        
           |  |  | 354 |       $version =        makeSafeSQLValue( isset($this->report['operatingsystem']['os_version'])      ? $this->report['operatingsystem']['os_version'] : '');
 | 
        
           |  |  | 355 |       $description =    makeSafeSQLValue( isset($this->report['operatingsystem']['description'])     ? $this->report['operatingsystem']['description'] : '');
 | 
        
           |  |  | 356 |       $codename =       makeSafeSQLValue( isset($this->report['operatingsystem']['codename'])        ? $this->report['operatingsystem']['codename'] : '');
 | 
        
           |  |  | 357 |   | 
        
           |  |  | 358 |       $osID = getOneDBValue( "select operating_system_id from operating_system
 | 
        
           |  |  | 359 |                where " . $this->makeSQLEquals( 'name', $osName ) . "
 | 
        
           |  |  | 360 |                   and " . $this->makeSQLEquals( 'kernel', $kernel ) . "
 | 
        
           |  |  | 361 |                   and " . $this->makeSQLEquals( 'distro', $distro_name ) . "
 | 
        
           |  |  | 362 |                   and " . $this->makeSQLEquals( 'distro_release', $release ) );
 | 
        
           |  |  | 363 |       if ( !isset( $osID ) ) {
 | 
        
           |  |  | 364 |          $this->messages[] = "Creating a new OS with name = $osName, kernel = $kernel, distro = $distro_name,  distro_release = $release";
 | 
        
           |  |  | 365 |          $result = queryDatabaseExtended( "insert into operating_system (name,version,kernel,distro,distro_description,distro_release,distro_codename, added_date) values
 | 
        
           |  |  | 366 |                                           ($osName,$version,$kernel,$distro_name,$description,$release,$codename, '$this->reportDateSQL')" );
 | 
        
           |  |  | 367 |          $osID = $result['insert_id'];
 | 
        
           |  |  | 368 |       }
 | 
        
           |  |  | 369 |   | 
        
           |  |  | 370 |       # verify the operating system
 | 
        
           |  |  | 371 |       $registeredOS = getOneDBValue( "select operating_system_id from device_operating_system where device_id = $this->machineID and removed_date is null" );
 | 
        
           |  |  | 372 |       if ( ! $registeredOS || $registeredOS != $osID ) {
 | 
        
           |  |  | 373 |          if ( $registeredOS ) { #we have the same computer, but a new OS???
 | 
        
           |  |  | 374 |             queryDatabaseExtended( "update device_operating_system set removed_date = '$this->reportDateSQL' where device_id = $this->machineID and removed_date is null");
 | 
        
           |  |  | 375 |             $this->messages[] = "Computer $this->machineName has a new OS";
 | 
        
           |  |  | 376 |          }
 | 
        
           |  |  | 377 |          queryDatabaseExtended( "insert into device_operating_system( device_id,operating_system_id,added_date) values ($this->machineID,$osID,'$this->reportDateSQL')");
 | 
        
           |  |  | 378 |       }
 | 
        
           |  |  | 379 |    }
 | 
        
           |  |  | 380 |   | 
        
           | 6 | rodolico | 381 |    /* every time we get a report, we need to see if the computer was rebooted
 | 
        
           |  |  | 382 |     * There is some slop in the last reboot date, so we assume if it is less than
 | 
        
           |  |  | 383 |     * $fuzzyRebootTimes, it was not rebooted. $fuzzyRebootTimes is calculated in
 | 
        
           |  |  | 384 |     * seconds. Since most of our machines take a minimum of 5 minutes to reboot
 | 
        
           |  |  | 385 |     * we'll go with that (300), though it would be just as good to go with a day
 | 
        
           |  |  | 386 |     * (86400) since we only run this report daily
 | 
        
           |  |  | 387 |     * When one is found, we remove the old report and add a new one.
 | 
        
           |  |  | 388 |     */
 | 
        
           | 3 | rodolico | 389 |    private function updateBootTime() {
 | 
        
           | 6 | rodolico | 390 |       $fuzzyRebootTimes = 300; // this allows slop of this many seconds before we assume a machine has been rebooted, ie
 | 
        
           | 3 | rodolico | 391 |       $lastReboot;
 | 
        
           |  |  | 392 |       if ( isset( $this->report['system']['last_boot'] ) ) {
 | 
        
           |  |  | 393 |          $lastReboot = strftime( '%F %T',$this->report['system']['last_boot'] ); // convert unix timestamp to sql value
 | 
        
           |  |  | 394 |          if ( isset( $lastReboot ) ) {
 | 
        
           | 6 | rodolico | 395 |             //if ( ! getOneDBValue( "select computer_uptime_id from computer_uptime where device_id = $this->machineID and last_reboot = '$lastReboot'" ) ) {
 | 
        
           |  |  | 396 |             if ( ! getOneDBValue( "select computer_uptime_id from computer_uptime where abs(TIME_TO_SEC(timediff( last_reboot, '$lastReboot' ))) < 3600 and device_id = $this->machineID" ) ) {
 | 
        
           | 3 | rodolico | 397 |                $this->messages[] = "Computer was rebooted at $lastReboot";
 | 
        
           |  |  | 398 |                queryDatabaseExtended( "update computer_uptime set removed_date = '$this->reportDateSQL' where device_id = $this->machineID and removed_date is null" );
 | 
        
           |  |  | 399 |                queryDatabaseExtended( "insert into computer_uptime (device_id,added_date,last_reboot) values ($this->machineID,'$this->reportDateSQL','$lastReboot')");
 | 
        
           |  |  | 400 |             }
 | 
        
           |  |  | 401 |          } else {
 | 
        
           |  |  | 402 |             $this->messages[] = 'Invalid reboot time [' . $this->Report['system']['last_boot'] . ']';
 | 
        
           |  |  | 403 |          }
 | 
        
           |  |  | 404 |       } else {
 | 
        
           |  |  | 405 |          $this->messages[] = 'No Boot time given';
 | 
        
           |  |  | 406 |       }
 | 
        
           |  |  | 407 |    }
 | 
        
           |  |  | 408 |   | 
        
           |  |  | 409 |   | 
        
           |  |  | 410 |    // checks if the report and the database values are the same
 | 
        
           |  |  | 411 |    private function checkInterfaceEquals( $report, $database ) {
 | 
        
           |  |  | 412 |       //var_dump( $report );
 | 
        
           |  |  | 413 |       //var_dump( $database );
 | 
        
           |  |  | 414 |       return ( 
 | 
        
           |  |  | 415 |          $report['address'] == $database['address'] and
 | 
        
           |  |  | 416 |          $report['netmask'] == $database['netmask'] and
 | 
        
           |  |  | 417 |          $report['ip6address'] == $database['ip6'] and
 | 
        
           |  |  | 418 |          $report['ip6networkbits'] == $database['ip6net'] and
 | 
        
           |  |  | 419 |          $report['mtu'] == $database['mtu'] and
 | 
        
           |  |  | 420 |          $report['mac'] == $database['mac'] 
 | 
        
           |  |  | 421 |          );
 | 
        
           |  |  | 422 |    } // checkInterfaceEquals
 | 
        
           |  |  | 423 |   | 
        
           |  |  | 424 |   | 
        
           |  |  | 425 |    /*
 | 
        
           |  |  | 426 |     * routine will check for all IP addresses reported and check against those recorded in the
 | 
        
           |  |  | 427 |     * database. It will remove any no longer in the database, and add any new ones
 | 
        
           |  |  | 428 |     */
 | 
        
           |  |  | 429 |    private function doIPAddresses () {
 | 
        
           |  |  | 430 |       /*
 | 
        
           |  |  | 431 |        * get all interfaces from the database
 | 
        
           |  |  | 432 |        * remove any interfaces from database which are not in report
 | 
        
           |  |  | 433 |        * add any interfaces from report which are not in database or which have changed
 | 
        
           |  |  | 434 |        */
 | 
        
           |  |  | 435 |       $network = $this->report['network']; // make a copy so we don't modify the original report
 | 
        
           |  |  | 436 |       // we won't process lo
 | 
        
           |  |  | 437 |       unset ($network['lo']);
 | 
        
           |  |  | 438 |       // at this point, we could get rid of tun's also, if we wanted to
 | 
        
           |  |  | 439 |   | 
        
           |  |  | 440 |       // let's ensure that all rows in report have the minimum required data
 | 
        
           |  |  | 441 |       foreach ( array_keys( $network ) as $interface ) {
 | 
        
           |  |  | 442 |          foreach ( array( 'address','netmask','ip6address','ip6networkbits','mtu','mac' ) as $required ) {
 | 
        
           |  |  | 443 |             if ( ! isset( $network[$interface][$required] ) ) { 
 | 
        
           |  |  | 444 |                $network[$interface][$required]  = NULL; 
 | 
        
           |  |  | 445 |             }
 | 
        
           |  |  | 446 |          } // checking all keys
 | 
        
           |  |  | 447 |       } // checking all report rows
 | 
        
           |  |  | 448 |       // var_dump( $network );   
 | 
        
           |  |  | 449 |   | 
        
           |  |  | 450 |       // get current information on all active interfaces in the database
 | 
        
           |  |  | 451 |       $dbInterfaces = queryDatabaseExtended( "select network_id,interface,address,netmask,ip6,ip6net,mac,mtu from network where device_id = $this->machineID and removed_date is null" );
 | 
        
           |  |  | 452 |       //print "select network_id,interface,address,netmask,ip6,ip6net,mac,mtu from network where device_id = $this->machineID and removed_date is null\n";
 | 
        
           |  |  | 453 |       //var_dump($dbInterfaces);
 | 
        
           |  |  | 454 |   | 
        
           |  |  | 455 |       // now, get rid of any interfaces which are no longer in the database
 | 
        
           |  |  | 456 |       // get a list of interfaces being passed in by report as a comma delimited list for processing.
 | 
        
           |  |  | 457 |       foreach ( array_keys( $network) as $temp ) {
 | 
        
           |  |  | 458 |          $interfaces[] = "'$temp'";
 | 
        
           |  |  | 459 |       }
 | 
        
           |  |  | 460 |       $interfaces = implode( ',', $interfaces );
 | 
        
           |  |  | 461 |       if ( $interfaces ) { // are there any? Then simply remove anything not in their set.
 | 
        
           |  |  | 462 |          queryDatabaseExtended( "update network set removed_date = '$this->reportDateSQL' where device_id = $this->machineID and removed_date is null and interface not in ($interfaces)");
 | 
        
           |  |  | 463 |          // print "update network set removed_date = '$this->reportDateSQL' where device_id = $this->machineID and removed_date is null and interface not in ($interfaces)\n";
 | 
        
           |  |  | 464 |          // reload the database results to exclude the ones we removed above
 | 
        
           |  |  | 465 |          $dbInterfaces = queryDatabaseExtended( "select network_id,interface,address,netmask,ip6,ip6net,mac,mtu from network where device_id = $this->machineID and removed_date is null" );
 | 
        
           |  |  | 466 |          // print "select network_id,interface,address,netmask,ip6,ip6net,mac,mtu from network where device_id = $this->machineID and removed_date is null\n";
 | 
        
           |  |  | 467 |       } // if
 | 
        
           |  |  | 468 |       // at this point, the database is a subset of the report, ie there are no entries in the database which are not also in the report.
 | 
        
           |  |  | 469 |       // let's remove the ones which are the same from both sets.
 | 
        
           |  |  | 470 |       // we can take a shortcut since the database is a subset of the report, ie we can remove entries from the report as we process
 | 
        
           |  |  | 471 |       if ( $dbInterfaces ) { // do we have anything in the database?
 | 
        
           |  |  | 472 |          foreach ( $dbInterfaces['data'] as $row => $value ) {
 | 
        
           |  |  | 473 |             // print "checking if " . $network[$value['interface']] . " equals $value\n";
 | 
        
           |  |  | 474 |             if ( $this->checkInterfaceEquals( $network[$value['interface']], $value ) ) { // compare the two entries
 | 
        
           |  |  | 475 |                // print "\tIt Does, so deleting it from updates\n";
 | 
        
           |  |  | 476 |                unset( $network[$value['interface']] );
 | 
        
           |  |  | 477 |             } else { // they are not equal. We will simply void out the existing one and it will treat the report entry as a new entry.
 | 
        
           |  |  | 478 |                // print "\tit is an update, so setting to removed in database\n";
 | 
        
           |  |  | 479 |                queryDatabaseExtended( "update network set removed_date = '$this->reportDateSQL' where device_id = $this->machineID and removed_date is null and interface = '" . $value['interface'] . "'");
 | 
        
           |  |  | 480 |                // print "update network set removed_date = '$this->reportDateSQL' where device_id = $this->machineID and removed_date is null and interface = '" . $value['interface'] . "'\n";
 | 
        
           |  |  | 481 |             } // if..else
 | 
        
           |  |  | 482 |          } // foreach
 | 
        
           |  |  | 483 |       }
 | 
        
           |  |  | 484 |       // finally, we should have only new entries, or entries which have changed and have been voided
 | 
        
           |  |  | 485 |       // a new row should be created for anything left.
 | 
        
           |  |  | 486 |       foreach ( $network as $interface => $values ) {
 | 
        
           |  |  | 487 |          //var_dump( $values );
 | 
        
           |  |  | 488 |          $sql = implode ( ',', array( 
 | 
        
           |  |  | 489 |                               $this->machineID,
 | 
        
           |  |  | 490 |                               makeSafeSQLValue($this->reportDateSQL),
 | 
        
           |  |  | 491 |                               makeSafeSQLValue($interface),
 | 
        
           |  |  | 492 |                               makeSafeSQLValue($values['address']),
 | 
        
           |  |  | 493 |                               makeSafeSQLValue($values['netmask']),
 | 
        
           |  |  | 494 |                               makeSafeSQLValue($values['ip6address']),
 | 
        
           |  |  | 495 |                               makeSafeSQLValue($values['ip6networkbits']),
 | 
        
           |  |  | 496 |                               makeSafeSQLValue($values['mtu']),
 | 
        
           |  |  | 497 |                               makeSafeSQLValue($values['mac'])
 | 
        
           |  |  | 498 |                               )
 | 
        
           |  |  | 499 |                          );
 | 
        
           |  |  | 500 |          $sql = "insert into network (device_id,added_date,interface,address,netmask,ip6,ip6net,mtu,mac) values (" . $sql . ")";
 | 
        
           |  |  | 501 |          //$this->messages[] = $sql;
 | 
        
           |  |  | 502 |          queryDatabaseExtended( $sql );
 | 
        
           |  |  | 503 |          $this->messages[] = "Network Device $interface was added/modified";
 | 
        
           |  |  | 504 |       }
 | 
        
           |  |  | 505 |    } // doIPAddresses
 | 
        
           |  |  | 506 |   | 
        
           |  |  | 507 |   | 
        
           |  |  | 508 |    /*
 | 
        
           |  |  | 509 |     * function looks through every element of $report, for a subkey
 | 
        
           |  |  | 510 |     * named 'keyfield'. It turns those into a string appropriate for
 | 
        
           |  |  | 511 |     * inclusion in a query as 
 | 
        
           |  |  | 512 |     * where fieldname in ( $keylist )
 | 
        
           |  |  | 513 |     * For example, with values a, b, c, 54, q'
 | 
        
           |  |  | 514 |     * returns 'a','b','c','54','q\''
 | 
        
           |  |  | 515 |     * where $keylist is generated by this function
 | 
        
           |  |  | 516 |     * returns null if no values found
 | 
        
           |  |  | 517 |     */ 
 | 
        
           |  |  | 518 |    function getKeyList ( $report ) {
 | 
        
           |  |  | 519 |       $keys = array();
 | 
        
           |  |  | 520 |       $keyset = null;
 | 
        
           |  |  | 521 |       // every row should have a key 'keyfield'.Since we don't know 
 | 
        
           |  |  | 522 |       // what they are, be sure to make sure they are SQL Safe
 | 
        
           |  |  | 523 |       foreach ( $report as $key => $value ) {
 | 
        
           |  |  | 524 |          $keys[] = makeSafeSQLValue( $value['keyfield'] );
 | 
        
           |  |  | 525 |       }
 | 
        
           |  |  | 526 |       return $keys ? implode( ",\n", $keys ) : null;
 | 
        
           |  |  | 527 |    }
 | 
        
           |  |  | 528 |   | 
        
           |  |  | 529 |    /*
 | 
        
           |  |  | 530 |     * function checks all keys in $first and $second to see if they
 | 
        
           |  |  | 531 |     * match. If they do, returns true, else returns false
 | 
        
           |  |  | 532 |     * ignores any keys passed in as array $ignore
 | 
        
           |  |  | 533 |     */
 | 
        
           |  |  | 534 |    function rowMatches ( $first, $second, $ignore = array() ) {
 | 
        
           |  |  | 535 |       foreach ( $first as $fkey => $fValue ) {
 | 
        
           |  |  | 536 |          if ( in_array( $fkey, $ignore ) )
 | 
        
           |  |  | 537 |             continue;
 | 
        
           |  |  | 538 |          if ( $fValue == $second[$fkey] )
 | 
        
           |  |  | 539 |             continue;
 | 
        
           |  |  | 540 |          return false;
 | 
        
           |  |  | 541 |       }
 | 
        
           |  |  | 542 |       return true;
 | 
        
           |  |  | 543 |    } // rowMatches
 | 
        
           |  |  | 544 |   | 
        
           |  |  | 545 |    /* Generic function that will 
 | 
        
           |  |  | 546 |     * delete items in database not found in report
 | 
        
           |  |  | 547 |     * Clean up report to contain only those items which are to be added
 | 
        
           |  |  | 548 |     * Return a copy of the report.
 | 
        
           |  |  | 549 |     * 
 | 
        
           |  |  | 550 |     * NOTE: since we are deleting items not found in the report, we will then
 | 
        
           |  |  | 551 |     * subsequently add them. This is the update process since we never actually
 | 
        
           |  |  | 552 |     * "delete" anything from the database.
 | 
        
           |  |  | 553 |     * 
 | 
        
           |  |  | 554 |     * Requires the report, and report must have a key for each entry named
 | 
        
           |  |  | 555 |     * 'keyfield' which the query below may use (as special tag <keys>
 | 
        
           |  |  | 556 |     * Also uses the following queries. If a query does not exist, that
 | 
        
           |  |  | 557 |     * process is ignored
 | 
        
           |  |  | 558 |     * 'remove old' - should have an entry as <device_id> which will have the current
 | 
        
           |  |  | 559 |     *       machine ID placed in it
 | 
        
           |  |  | 560 |     * 'delete' - <ids> which will be replaced with a list of keys from the 
 | 
        
           |  |  | 561 |     *         report.
 | 
        
           |  |  | 562 |     * 'find' - should return a column named 'id' which is a primary key on the
 | 
        
           |  |  | 563 |     *          table (used by delete query), and a column named 'keyfield'
 | 
        
           |  |  | 564 |     *          which matches the same one in the report. Any other fields in
 | 
        
           |  |  | 565 |     *          the query are checked against the report, and the report and
 | 
        
           |  |  | 566 |     *          database entry are only considered matching if all query fields
 | 
        
           |  |  | 567 |     *          match a report entry.
 | 
        
           |  |  | 568 |     * 
 | 
        
           |  |  | 569 |     * Before passing in report, you should go through the entries and create
 | 
        
           |  |  | 570 |     * a new one called 'keyfield' for each entry which will be a unique key
 | 
        
           |  |  | 571 |     * for an entry. For example, software packages may be the package name
 | 
        
           |  |  | 572 |     * and the version.
 | 
        
           |  |  | 573 |     */
 | 
        
           |  |  | 574 |    private function AddDeleteUpdate ( $report, $queries, $reportLabel, $testing=false ) {
 | 
        
           |  |  | 575 |   | 
        
           |  |  | 576 |       if ( $testing ) {
 | 
        
           |  |  | 577 |          print "*****************Starting\n"; 
 | 
        
           |  |  | 578 |          print_r( $report ); 
 | 
        
           |  |  | 579 |          print "*****************Starting\n";
 | 
        
           |  |  | 580 |       }
 | 
        
           |  |  | 581 |       $database = null;
 | 
        
           |  |  | 582 |       $keySet = $this->getKeyList( $report );
 | 
        
           |  |  | 583 |       if ( is_null( $keySet ) ) // bail if we don't have any data
 | 
        
           |  |  | 584 |          return null;
 | 
        
           |  |  | 585 |   | 
        
           |  |  | 586 |       // find values which are in database but not in report and delete them from database
 | 
        
           |  |  | 587 |       if ( $queries['remove old'] ) {
 | 
        
           |  |  | 588 |          $queries['remove old'] = str_replace( '<keys>', $keySet, $queries['remove old'] );
 | 
        
           |  |  | 589 |          $queries['remove old'] = str_replace( '<device_id>', $this->machineID, $queries['remove old'] );
 | 
        
           |  |  | 590 |          if ( $testing )
 | 
        
           |  |  | 591 |             print "Remove Query***************************\n" . $queries['remove old'] . "\n***********************************\n";
 | 
        
           |  |  | 592 |          else {
 | 
        
           |  |  | 593 |             $database = queryDatabaseExtended( $queries['remove old'] );
 | 
        
           |  |  | 594 |             if ( $database and $database['affected_rows'] ) 
 | 
        
           |  |  | 595 |                $this->messages[] = $database['affected_rows'] . " $reportLabel removed from database because they were removed for superceded";
 | 
        
           |  |  | 596 |          } // else
 | 
        
           |  |  | 597 |       } // if
 | 
        
           |  |  | 598 |   | 
        
           |  |  | 599 |       // now, let's get all the values left in the database
 | 
        
           |  |  | 600 |       if ( $queries['find'] ) {
 | 
        
           |  |  | 601 |          $queries['find'] = str_replace( '<keys>', $keySet, $queries['find'] );
 | 
        
           |  |  | 602 |          $queries['find'] = str_replace( '<device_id>', $this->machineID, $queries['find'] );
 | 
        
           |  |  | 603 |          if ( $testing )
 | 
        
           |  |  | 604 |             print "Find Query***************************\n" . $queries['find'] . "\n***********************************\n";
 | 
        
           |  |  | 605 |          else
 | 
        
           |  |  | 606 |             $database = queryDatabaseExtended( $queries['find'] );
 | 
        
           |  |  | 607 |       }
 | 
        
           |  |  | 608 |       if ( $database ) { // there were entries in the database still
 | 
        
           |  |  | 609 |          $database = $database['data']; // get to the data
 | 
        
           |  |  | 610 |          $keysToDelete = array();
 | 
        
           |  |  | 611 |          // find values which are different in report, and delete the database entry
 | 
        
           |  |  | 612 |          foreach ( $database as $row => $entries ) {
 | 
        
           |  |  | 613 |             foreach ( $report as $key => $values ) {
 | 
        
           |  |  | 614 |                if ( $report[$key]['keyfield'] != $entries['keyfield'] )
 | 
        
           |  |  | 615 |                   continue;
 | 
        
           |  |  | 616 |                // if we made it here, our keyfields match, so we check
 | 
        
           |  |  | 617 |                // the contents of the other fields
 | 
        
           |  |  | 618 |                if ( $this->rowMatches( $entries, $values, array( 'keyfield', 'id' ) ) ) {
 | 
        
           |  |  | 619 |                   // they match, so remove it from the report
 | 
        
           |  |  | 620 |                   unset( $report[$key] );
 | 
        
           |  |  | 621 |                } else { // they are different in the report, so remove from database
 | 
        
           |  |  | 622 |                   $keysToDelete[] = $entries['id'];
 | 
        
           |  |  | 623 |                }
 | 
        
           |  |  | 624 |             } // inner foreach
 | 
        
           |  |  | 625 |          } // outer foreach
 | 
        
           |  |  | 626 |          if ( $keysToDelete and $queries['delete'] ) {
 | 
        
           |  |  | 627 |             $queries['delete'] = str_replace( '<ids>', implode( ',', $keysToDelete ), $queries['delete'] );
 | 
        
           |  |  | 628 |             if ( $testing )
 | 
        
           |  |  | 629 |                print "Delete Query***************************\n" . $queries['delete'] . "\n***********************************\n";
 | 
        
           |  |  | 630 |             else {
 | 
        
           |  |  | 631 |                $updates = queryDatabaseExtended( $queries['delete'] );
 | 
        
           |  |  | 632 |                $this->messages[] = $updates['affected_rows'] . " $reportLabel modified";
 | 
        
           |  |  | 633 |             }
 | 
        
           |  |  | 634 |          }
 | 
        
           |  |  | 635 |       } // if $database
 | 
        
           |  |  | 636 |       // return items to be added
 | 
        
           |  |  | 637 |       if ( $testing ) {
 | 
        
           |  |  | 638 |          print "*****************Ending\n"; 
 | 
        
           |  |  | 639 |          print_r( $report ); 
 | 
        
           |  |  | 640 |          print "*****************Ending\n";
 | 
        
           |  |  | 641 |       }
 | 
        
           |  |  | 642 |       return $report;
 | 
        
           |  |  | 643 |    } // function AddDeleteUpdate
 | 
        
           |  |  | 644 |   | 
        
           |  |  | 645 |   | 
        
           |  |  | 646 |    /*
 | 
        
           |  |  | 647 |     * routine to ensure the hardware returned as PCI hardware is in the attributes area
 | 
        
           |  |  | 648 |     */ 
 | 
        
           |  |  | 649 |    private function processPCI ( ) {
 | 
        
           |  |  | 650 |       // following are some of the synonyms we will use from the PCI
 | 
        
           |  |  | 651 |       // tables for the "name" of the device. They are listed in the
 | 
        
           |  |  | 652 |       // order of priority (ie, first one found is chosen).
 | 
        
           |  |  | 653 |       $nameSynomyms = array('name','device','sdevice','device0');
 | 
        
           |  |  | 654 |   | 
        
           |  |  | 655 |       // query which removes devices from database that are not in report
 | 
        
           |  |  | 656 |       // we assume if the report doesn't have it, it has been removed
 | 
        
           |  |  | 657 |       $queries['remove old'] = 
 | 
        
           |  |  | 658 |                     "update device
 | 
        
           |  |  | 659 |                         set removed_date = '$this->reportDateSQL'
 | 
        
           |  |  | 660 |                         where device_id in (
 | 
        
           |  |  | 661 |                            select device_id from (
 | 
        
           |  |  | 662 |                               select
 | 
        
           |  |  | 663 |                                     device_id
 | 
        
           |  |  | 664 |                                  from
 | 
        
           |  |  | 665 |                                     device join device_type using (device_type_id)
 | 
        
           |  |  | 666 |                                  where
 | 
        
           |  |  | 667 |                                     device.part_of = <device_id>
 | 
        
           |  |  | 668 |                                     and device.removed_date is null
 | 
        
           |  |  | 669 |                                     and device.name not in ( <keys> )
 | 
        
           |  |  | 670 |                               ) as b
 | 
        
           |  |  | 671 |                               )";
 | 
        
           |  |  | 672 |   | 
        
           |  |  | 673 |   | 
        
           |  |  | 674 |       $queries['find'] = 
 | 
        
           |  |  | 675 |                     "select
 | 
        
           |  |  | 676 |                         device_id id,
 | 
        
           |  |  | 677 |                         device.name  'keyfield',
 | 
        
           |  |  | 678 |                         device.notes 'info'
 | 
        
           |  |  | 679 |                      from device join device_type using (device_type_id) 
 | 
        
           |  |  | 680 |                      where
 | 
        
           |  |  | 681 |                         device_type.name = 'PCI Card' 
 | 
        
           |  |  | 682 |                         and device.removed_date is null
 | 
        
           |  |  | 683 |                         and device.part_of = <device_id>";
 | 
        
           |  |  | 684 |   | 
        
           |  |  | 685 |       $queries['delete'] =
 | 
        
           |  |  | 686 |                     "update device
 | 
        
           |  |  | 687 |                         set removed_date = '$this->reportDateSQL'
 | 
        
           |  |  | 688 |                         where device_id in ( <ids> )";
 | 
        
           |  |  | 689 |   | 
        
           |  |  | 690 |   | 
        
           |  |  | 691 |       if ( ! isset( $this->report['pci'] ) ) return;
 | 
        
           |  |  | 692 |       // make a local copy so we can modify as needed
 | 
        
           |  |  | 693 |       $pciHash = $this->report['pci'];
 | 
        
           |  |  | 694 |       # normalize the data
 | 
        
           |  |  | 695 |       foreach ( array_keys( $pciHash ) as $key ) {
 | 
        
           |  |  | 696 |          if ( ! is_array( $pciHash[$key] ) ) {
 | 
        
           |  |  | 697 |             $this->messages[] = 'Invalid PCI format, not recording';
 | 
        
           |  |  | 698 |             return false;
 | 
        
           |  |  | 699 |          }
 | 
        
           |  |  | 700 |          if ( ! isset( $pciHash[$key]['slot'] ) ) { // doesn't have a slot field
 | 
        
           |  |  | 701 |             $slotField = '';
 | 
        
           |  |  | 702 |             foreach ( array_keys( $pciHash[$key] ) as $subkey ) { // scan through all keys and see if there is something with a "slot looking" value in it
 | 
        
           |  |  | 703 |                if ( preg_match ( '/^[0-9a-f:.]+$/' , $pciHash[$key][$subkey] ) )
 | 
        
           |  |  | 704 |                   $slotField = $subkey;
 | 
        
           |  |  | 705 |             }
 | 
        
           |  |  | 706 |             if ( $slotField ) {
 | 
        
           |  |  | 707 |                $pciHash[$key]['slot'] = $pciHash[$key][$slotField];
 | 
        
           |  |  | 708 |             } else {
 | 
        
           |  |  | 709 |                $pciHash[$key]['slot'] = 'Unknown';
 | 
        
           |  |  | 710 |             }
 | 
        
           |  |  | 711 |          }
 | 
        
           |  |  | 712 |          // Each entry must have a name. Use 'device' if it doesn't exist
 | 
        
           |  |  | 713 |          // Basically, we try each option in turn, with the first test having
 | 
        
           |  |  | 714 |          // priority.
 | 
        
           |  |  | 715 |   | 
        
           |  |  | 716 |          if ( ! isset( $pciHash[$key]['name'] ) ) {
 | 
        
           |  |  | 717 |             // if there is no name, try to use one of the synonyms
 | 
        
           |  |  | 718 |             foreach ( $nameSynomyms as $testName ) {
 | 
        
           |  |  | 719 |                if ( isset ( $pciHash[$key][$testName] ) ) {
 | 
        
           |  |  | 720 |                   $pciHash[$key]['name'] = $pciHash[$key][$testName];
 | 
        
           |  |  | 721 |                   break;
 | 
        
           |  |  | 722 |                } // if
 | 
        
           |  |  | 723 |             } // foreach
 | 
        
           |  |  | 724 |             if ( empty( $pciHash[$key]['name'] ) ) {
 | 
        
           |  |  | 725 |                $this->messages[] = "No name given for one or more PCI devices at normalize, Computer ID: [$this->machineID], Report Date: [$this->reportDate]";
 | 
        
           |  |  | 726 |                //print_r( $pciHash ); 
 | 
        
           |  |  | 727 |                //die;
 | 
        
           |  |  | 728 |                return;
 | 
        
           |  |  | 729 |             }
 | 
        
           |  |  | 730 |          } elseif ( $pciHash[$key]['name'] == $pciHash[$key]['slot'] ) {
 | 
        
           |  |  | 731 |             $pciHash[$key]['name'] = $pciHash[$key]['device'];
 | 
        
           |  |  | 732 |          } // if..else
 | 
        
           |  |  | 733 |          // Following is what will actually be put in the device table, ie device.name
 | 
        
           |  |  | 734 |          $pciHash[$key]['keyfield'] = $pciHash[$key]['slot'] . ' - ' . $pciHash[$key]['name'];
 | 
        
           |  |  | 735 |          ksort( $pciHash[$key] );
 | 
        
           |  |  | 736 |          $ignore = array( 'keyfield' );
 | 
        
           |  |  | 737 |          $info = '';
 | 
        
           |  |  | 738 |          foreach ( $pciHash[$key] as $subkey => $value ) {
 | 
        
           |  |  | 739 |             if ( in_array( $subkey, $ignore ) )
 | 
        
           |  |  | 740 |                continue;
 | 
        
           |  |  | 741 |             $info .= "[$subkey]=$value\n";
 | 
        
           |  |  | 742 |          }
 | 
        
           |  |  | 743 |          $pciHash[$key]['info'] = $info;
 | 
        
           |  |  | 744 |       } // foreach
 | 
        
           |  |  | 745 |       // at this point, we should have a slot and a name field in all pci devices
 | 
        
           |  |  | 746 |       $toAdd = $this->AddDeleteUpdate( $pciHash, $queries, 'PCI Devices' );
 | 
        
           |  |  | 747 |       if ( $toAdd ) {
 | 
        
           |  |  | 748 |          $pciCardID = getOneDBValue( "select device_type_id from device_type where name = 'PCI Card'");
 | 
        
           |  |  | 749 |          $count = 0;
 | 
        
           |  |  | 750 |          foreach ( $toAdd as $entry => $values ) {
 | 
        
           |  |  | 751 |             $keyfield = makeSafeSQLValue( $values['keyfield'] );
 | 
        
           |  |  | 752 |             $info = makeSafeSQLValue( $values['info'] );
 | 
        
           |  |  | 753 |             $query = "insert into device 
 | 
        
           |  |  | 754 |                         select 
 | 
        
           |  |  | 755 |                            null,
 | 
        
           |  |  | 756 |                            site_id,
 | 
        
           |  |  | 757 |                            $pciCardID,
 | 
        
           |  |  | 758 |                            $keyfield,
 | 
        
           |  |  | 759 |                            $info,
 | 
        
           |  |  | 760 |                            device_id,
 | 
        
           |  |  | 761 |                            '$this->reportDateSQL',
 | 
        
           |  |  | 762 |                            null,
 | 
        
           |  |  | 763 |                            null 
 | 
        
           |  |  | 764 |                         from device 
 | 
        
           |  |  | 765 |                         where device_id = $this->machineID";
 | 
        
           |  |  | 766 |             queryDatabaseExtended( $query );
 | 
        
           |  |  | 767 |             $count++;
 | 
        
           |  |  | 768 |          } // foreach
 | 
        
           |  |  | 769 |          $this->messages[] = "$count PCI devices added/modified";
 | 
        
           |  |  | 770 |       } // if
 | 
        
           |  |  | 771 |    } // processPCI
 | 
        
           |  |  | 772 |   | 
        
           |  |  | 773 |    function getSoftwareID ( $packageName,$versionInfo,$description ) {
 | 
        
           |  |  | 774 |       $packageName = makeSafeSQLValue( $packageName );
 | 
        
           |  |  | 775 |       $versionInfo = makeSafeSQLValue( $versionInfo );
 | 
        
           |  |  | 776 |       $description = makeSafeSQLValue( $description );
 | 
        
           |  |  | 777 |       // does the package exist?
 | 
        
           |  |  | 778 |       $packageID = getOneDBValue("select software_id from software where package_name = $packageName and removed_date is null");
 | 
        
           |  |  | 779 |       if ( !$packageID ) { # NO, package doesn't exist, so add it to the database
 | 
        
           |  |  | 780 |          $packageID = queryDatabaseExtended( "insert into software (package_name,description, added_date) values ($packageName,$description, '$this->reportDateSQL')");
 | 
        
           |  |  | 781 |          if ( $packageID['insert_id'] )
 | 
        
           |  |  | 782 |             $packageID = $packageID['insert_id'];
 | 
        
           |  |  | 783 |          else {
 | 
        
           |  |  | 784 |             $this->messages[] = "ERROR: Software Packages - Could not find version $packageName and could not add to database";
 | 
        
           |  |  | 785 |             $packageID = null;
 | 
        
           |  |  | 786 |          }
 | 
        
           |  |  | 787 |       }
 | 
        
           |  |  | 788 |       // does this version number exist?
 | 
        
           |  |  | 789 |       $versionID = getOneDBValue( "select software_version_id from software_version where version = $versionInfo and removed_date is null" );
 | 
        
           |  |  | 790 |       if ( ! $versionID ) { # nope, so add it
 | 
        
           |  |  | 791 |          $versionID = queryDatabaseExtended( "insert into software_version ( version,added_date ) values ($versionInfo,'$this->reportDateSQL')");
 | 
        
           |  |  | 792 |          if ( $versionID['insert_id'] )
 | 
        
           |  |  | 793 |             $versionID = $versionID['insert_id'];
 | 
        
           |  |  | 794 |          else {
 | 
        
           |  |  | 795 |             $this->messages[] = "ERROR: Software Packages - Could not find version $versionInfo and could not add to database";
 | 
        
           |  |  | 796 |             $versionID = null;
 | 
        
           |  |  | 797 |          }
 | 
        
           |  |  | 798 |       }
 | 
        
           |  |  | 799 |       return array( 'package id' => $packageID,'version id' => $versionID);
 | 
        
           |  |  | 800 |    } // getSoftwareID
 | 
        
           |  |  | 801 |   | 
        
           |  |  | 802 |   | 
        
           |  |  | 803 |    function processSoftwarePackages (  ) {
 | 
        
           |  |  | 804 |       // query which removes devices from database that are not in report
 | 
        
           |  |  | 805 |       // we assume if the report doesn't have it, it has been removed
 | 
        
           |  |  | 806 |       $queries['remove old'] = 
 | 
        
           |  |  | 807 |                     "update installed_packages
 | 
        
           |  |  | 808 |                         set removed_date = '$this->reportDateSQL'
 | 
        
           |  |  | 809 |                         where installed_packages_id in (
 | 
        
           |  |  | 810 |                            select installed_packages_id from (
 | 
        
           |  |  | 811 |                               select
 | 
        
           |  |  | 812 |                                     installed_packages_id
 | 
        
           |  |  | 813 |                               from 
 | 
        
           |  |  | 814 |                                  installed_packages 
 | 
        
           |  |  | 815 |                                  join software using ( software_id )
 | 
        
           |  |  | 816 |                                  join software_version using (software_version_id)
 | 
        
           |  |  | 817 |                               where
 | 
        
           |  |  | 818 |                                     installed_packages.device_id = <device_id>
 | 
        
           |  |  | 819 |                                     and installed_packages.removed_date is null
 | 
        
           |  |  | 820 |                                     and concat(software.package_name,software_version.version) not in ( <keys> )
 | 
        
           |  |  | 821 |                               ) as b
 | 
        
           |  |  | 822 |                               )";
 | 
        
           |  |  | 823 |       $queries['find'] = 
 | 
        
           |  |  | 824 |            "select 
 | 
        
           |  |  | 825 |                installed_packages.installed_packages_id 'id',
 | 
        
           |  |  | 826 |                concat(software.package_name,software_version.version) 'keyfield'
 | 
        
           |  |  | 827 |             from 
 | 
        
           |  |  | 828 |                installed_packages 
 | 
        
           |  |  | 829 |                join software using ( software_id )
 | 
        
           |  |  | 830 |                join software_version using (software_version_id)
 | 
        
           |  |  | 831 |             where 
 | 
        
           |  |  | 832 |                device_id = <device_id>
 | 
        
           |  |  | 833 |                and installed_packages.removed_date is null";
 | 
        
           |  |  | 834 |       $queries['delete'] =
 | 
        
           |  |  | 835 |                     "update installed_packages
 | 
        
           |  |  | 836 |                         set removed_date = '$this->reportDateSQL'
 | 
        
           |  |  | 837 |                         where installed_packages_id in ( <ids> )";
 | 
        
           |  |  | 838 |   | 
        
           |  |  | 839 |       if ( ! isset( $this->report['software'] ) ) return;
 | 
        
           |  |  | 840 |       // make a local copy so we can modify as needed
 | 
        
           |  |  | 841 |       $softwareHash = $this->report['software'];
 | 
        
           |  |  | 842 |       foreach ( array_keys( $softwareHash ) as $key ) {
 | 
        
           |  |  | 843 |          if ( ! isset( $softwareHash[$key]['name'] ) )
 | 
        
           |  |  | 844 |             $softwareHash[$key]['name'] = $key;
 | 
        
           |  |  | 845 |          if ( ! isset( $softwareHash[$key]['description'] ) )
 | 
        
           |  |  | 846 |             $softwareHash[$key]['description'] = '';
 | 
        
           |  |  | 847 |          // This is needed for matching
 | 
        
           |  |  | 848 |          $softwareHash[$key]['keyfield'] = $softwareHash[$key]['name'] . $softwareHash[$key]['version'];
 | 
        
           |  |  | 849 |       } // foreach
 | 
        
           |  |  | 850 |       // at this point, we should have a slot and a name field in all pci devices
 | 
        
           |  |  | 851 |       $toAdd = $this->AddDeleteUpdate( $softwareHash, $queries, 'Software Packages' );
 | 
        
           |  |  | 852 |       if ( $toAdd ) {
 | 
        
           |  |  | 853 |          $count = 0;
 | 
        
           |  |  | 854 |          foreach ( $toAdd as $key => $value ) {
 | 
        
           |  |  | 855 |             $ids = $this->getSoftwareID ( $value['name'],$value['version'],$value['description'] );
 | 
        
           |  |  | 856 |             if ( is_null( $ids['package id'] ) or is_null( $ids['version id'] ) ) {
 | 
        
           |  |  | 857 |                $this->messages[] = "Could not create entry for package " . $value['name'] . ", version " . $value['version'];
 | 
        
           |  |  | 858 |             } else {
 | 
        
           |  |  | 859 |                $insertValues = implode( ',', array( $this->machineID, $ids['package id'], $ids['version id'], "'$this->reportDateSQL'" ) );
 | 
        
           |  |  | 860 |                $query = "insert into installed_packages
 | 
        
           |  |  | 861 |                            (device_id,software_id,software_version_id,added_date) 
 | 
        
           |  |  | 862 |                            values 
 | 
        
           |  |  | 863 |                            ( $insertValues )";
 | 
        
           |  |  | 864 |                $database = queryDatabaseExtended( $query );
 | 
        
           |  |  | 865 |                if ( $database )
 | 
        
           |  |  | 866 |                   $count++;
 | 
        
           |  |  | 867 |             } // if..else
 | 
        
           |  |  | 868 |          } // foreach
 | 
        
           |  |  | 869 |          if ( $count )
 | 
        
           |  |  | 870 |             $this->messages[] = "$count software packages added/updated";
 | 
        
           |  |  | 871 |       }
 | 
        
           |  |  | 872 |    } // processSoftwarePackages
 | 
        
           |  |  | 873 |   | 
        
           |  |  | 874 | } // class sysinfo
 | 
        
           |  |  | 875 |   | 
        
           |  |  | 876 |   | 
        
           |  |  | 877 |   | 
        
           | 5 | rodolico | 878 | /*
 | 
        
           |  |  | 879 |  * we don't know where the configuration file will be, so we have a list
 | 
        
           |  |  | 880 |  * below (searchPaths) to look for it. It will load the first one it 
 | 
        
           |  |  | 881 |  * finds, then exit. THUS, you could have multiple configuration files
 | 
        
           |  |  | 882 |  * but only the first one in the list will be used
 | 
        
           |  |  | 883 |  */
 | 
        
           | 3 | rodolico | 884 |   | 
        
           | 5 | rodolico | 885 | $confFileName = "sysinfoRead.conf.yaml";
 | 
        
           |  |  | 886 | $searchPaths = array( '/etc/camp', '/opt/camp', '/opt/camp/sysinfo', $_SERVER['SCRIPT_FILENAME'], getcwd() );
 | 
        
           |  |  | 887 | $configuration = array();
 | 
        
           |  |  | 888 | foreach ( $searchPaths as $path ) {
 | 
        
           |  |  | 889 |    if ( file_exists( "$path/$confFileName" ) ) {
 | 
        
           |  |  | 890 |       #print "Found $path/$confFileName\n";
 | 
        
           |  |  | 891 |       $configuration = yaml_parse_file( "$path/$confFileName" );
 | 
        
           |  |  | 892 |       #require "$path/$confFileName";
 | 
        
           |  |  | 893 |       break; // exit out of the loop; we don't try to load it more than once
 | 
        
           |  |  | 894 |    } // if
 | 
        
           |  |  | 895 | } // foreach
 | 
        
           | 3 | rodolico | 896 |   | 
        
           | 5 | rodolico | 897 | mysql_connect( $configuration['database']['databaseServer'], $configuration['database']['databaseUsername'], $configuration['database']['databasePassword'] ) or die(mysql_error());
 | 
        
           |  |  | 898 | mysql_select_db( $configuration['database']['database'] ) or die(mysql_error());
 | 
        
           |  |  | 899 |   | 
        
           |  |  | 900 |   | 
        
           |  |  | 901 | $thisReport = new sysinfo( $configuration['bodyContents'] );
 | 
        
           | 3 | rodolico | 902 | $result; 
 | 
        
           |  |  | 903 |   | 
        
           |  |  | 904 | $result = $thisReport->loadFromFile( $argc > 1 ? $argv[1] : "php://stdin" );
 | 
        
           |  |  | 905 | if ( $result == 'ini' ) {
 | 
        
           |  |  | 906 |    print $thisReport->dumpMessages();
 | 
        
           |  |  | 907 |    exit(0);
 | 
        
           |  |  | 908 | }
 | 
        
           |  |  | 909 | if ( ! $result )
 | 
        
           |  |  | 910 |    exit ( 1 );
 | 
        
           |  |  | 911 | $result = $thisReport->processReport();
 | 
        
           |  |  | 912 | print $thisReport->dumpMessages();
 | 
        
           |  |  | 913 | //var_dump( $thisReport );
 | 
        
           |  |  | 914 | exit ( $result );
 | 
        
           |  |  | 915 |   | 
        
           |  |  | 916 | ?>
 |