Net_MAC
[ class tree: Net_MAC ] [ index: Net_MAC ] [ all elements ]

Source for file MAC.php

Documentation is available at MAC.php

  1. <?php
  2. /* 
  3.  * This file contains the MAC class
  4.  *
  5.  * Copyright (c) 2006 Andrew Teixeira
  6.  *
  7.  * LICENSE: This source file is subject to version 3.0 of the PHP license
  8.  * that is available through the world-wide-web at the following URI:
  9.  * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
  10.  * the PHP License and are unable to obtain it through the web, please
  11.  * send a note to license@php.net so we can mail you a copy immediately.
  12.  *
  13.  * $Id$
  14.  */
  15.  
  16. /**
  17.  * Require PEAR/Exception.php since we will be using PEAR Exceptions
  18.  * in this class.
  19.  */
  20. require_once 'PEAR/Exception.php';
  21.  
  22. /**
  23.  * Constant to represent the maximum length of a line in the
  24.  * manufacturers file.
  25.  */
  26. define('NET_MAC_LINE_MAXLENGTH'256);
  27.  
  28. /**
  29.  * Error constant: signifies no problem (OK)
  30.  */
  31. define ('NET_MAC_ERROR_OK'0);
  32.  
  33. /**
  34.  * Error constant: signifies a bad option being passed to a function
  35.  */
  36. define ('NET_MAC_ERROR_BADOPT'1);
  37.  
  38. /**
  39.  * Error constant: signifies bad data being passed to a function
  40.  */
  41. define ('NET_MAC_ERROR_BADDATA'2);
  42.  
  43. /**
  44.  * Error constant: signifies a bad database connection
  45.  */
  46. define ('NET_MAC_ERROR_BADDB'3);
  47.  
  48. /**
  49.  * Error constant: signifies a bad manufacturers file
  50.  */
  51. define ('NET_MAC_ERROR_BADFILE'4);
  52.  
  53.  
  54. /**
  55.  * Extension of the main PEAR_Exception Class for use with the Net_MAC
  56.  * class.
  57.  *
  58.  * @author  Andrew Teixeira <ateixeira@gmail.com>
  59.  * @package Net_MAC
  60.  * @version 1.0
  61.  * @access  public
  62.  */
  63. class Net_MAC_Exception extends PEAR_Exception {}
  64.  
  65.  
  66. /**
  67.  * Class to validate and cleanly format Media Access Control (MAC)
  68.  * addresses
  69.  *
  70.  * @author  Andrew Teixeira <ateixeira@gmail.com>
  71.  * @package Net_MAC
  72.  * @version 1.0
  73.  * @access  public
  74.  */
  75. class Net_MAC
  76. {
  77.     /**
  78.      * The MAC address to work on.
  79.      *
  80.      * @access protected
  81.      * @var string 
  82.      */
  83.     protected $_macaddr;
  84.  
  85.     /**
  86.      * A database instance to use in looking up MAC-to-vendor
  87.      * relationships.
  88.      *
  89.      * @access protected
  90.      * @var object 
  91.      */
  92.     protected $_db;
  93.  
  94.     /**
  95.      * The options to use while connecting to the database.
  96.      *
  97.      * @access protected
  98.      * @var array 
  99.      */
  100.     protected $_dbOptions;
  101.  
  102.     /**
  103.      * The default constructor
  104.      *
  105.      * This is the default constructor that will create and populate a
  106.      * valid Net_MAC object.
  107.      *
  108.      * @access public
  109.      *
  110.      * @param object $db A valid instantiated {@link }
  111.      *  http://pear.php.net/package/MDB2/ MDB2} object to use when
  112.      *  adding/retrieving information from the database for MAC address
  113.      *  vendors
  114.      * @param array $options An array of options to use with the
  115.      *  database in retrieving MAC address vendors.  The associative
  116.      *  array should have key/value pairs as follows:
  117.      *
  118.      *  <ul>
  119.      *   <li><b>tablename</b>: The name of the table where MAC address
  120.      *   vendor information lives</li>
  121.      *   <li><b>macaddrcol</b>: The name of the column containing the
  122.      *   MAC address prefixes</li>
  123.      *   <li><b>vendorcol</b>: The name of the column containing the
  124.      *   vendor name</li>
  125.      *   <li><b>desccol</b>: The name of the column containing any
  126.      *   extra descriptive information derived from the vendor list</li>
  127.      *  </ul>
  128.      *
  129.      * @return void No return value.  A {@link Net_MAC_Exception}
  130.      *  Net_MAC_Exception} Exception object will be thrown if there is
  131.      *  an error during construction so the constructor should be
  132.      *  called from a try/catch block
  133.      */
  134.     function __construct(&$db$options = NULL{
  135.         require_once 'MDB2.php';
  136.  
  137.         $this->_db = NULL;
  138.         $this->_macaddr = NULL;
  139.         $this->_dbOptions = NULL;
  140.     
  141.         if (!is_a($db'MDB2_Driver_Common')) {
  142.             throw new Net_MAC_Exception('Bad database object'NET_MAC_ERROR_BADDB);
  143.         }
  144.  
  145.         if (!is_array($options)) {
  146.             throw new Net_MAC_Exception('Second parameter must be an array'NET_MAC_ERROR_BADOPT);
  147.         }
  148.  
  149.         if (!isset($options['tablename'])) {
  150.             throw new Net_MAC_Exception('No table name given in options'NET_MAC_ERROR_BADDATA);
  151.         }
  152.  
  153.         if (!isset($options['macaddrcol'])) {
  154.             throw new Net_MAC_Exception('No MAC address column name given in options'NET_MAC_ERROR_BADDATA);
  155.         }
  156.  
  157.         if (!isset($options['vendorcol'])) {
  158.             throw new Net_MAC_Exception('No vendor column name given in options'NET_MAC_ERROR_BADDATA);
  159.         }
  160.  
  161.         if (!isset($options['desccol'])) {
  162.             throw new Net_MAC_Exception('No description column name given in options'NET_MAC_ERROR_BADDATA);
  163.         }
  164.  
  165.         $this->_db = $db;
  166.         $this->_db->loadModule('Extended');
  167.         $this->_dbOptions = $options;
  168.     /* end default constructor */
  169.  
  170.     /**
  171.      * Checks a MAC address
  172.      *
  173.      * This function will check a MAC address to make sure it is
  174.      * valid.
  175.      *
  176.      * @access static
  177.      *
  178.      * @param string $input The string containing the MAC Address
  179.      * @param string $delimiter The string representing the delimiter
  180.      *  to use when verifying the MAC Address
  181.      *
  182.      * @return string <b>true</b> if the MAC address is valid,
  183.      *  <b>false</b> otherwise
  184.      */
  185.     static function check($input$delimiter ':')
  186.     {
  187.         // Check for 6 octets without any punctuation
  188.         $retval preg_match('/^([0-9a-fA-F][0-9a-fA-F]\Q'.$delimiter.'\E){5}([0-9a-fA-F][0-9a-fA-F]){1}$/'$input);
  189.                     
  190.         return $retval;
  191.     /* end method check */
  192.  
  193.     /**
  194.      * Sets the MAC address
  195.      *
  196.      * This method will set the MAC address in the class.
  197.      *
  198.      * @access public
  199.      *
  200.      * @param string $macaddr The string representing the MAC address
  201.      * @param string $delimiter The string representing the delimiter
  202.      *  to use when verifying the MAC Address
  203.      *
  204.      * @return bool Returns <b>true</b> if the MAC address is set
  205.      *  correctly, <b>false</b> otherwise
  206.      */
  207.     function setMAC($macaddr$delimiter ':')
  208.     {
  209.         $validMAC = self::check($macaddr$delimiter);
  210.         if ($validMAC{
  211.             $this->_macaddr = $macaddr;
  212.             return true;
  213.         }
  214.  
  215.         return false;
  216.     /* end method setMac */
  217.  
  218.     /**
  219.      * Formats a MAC address
  220.      *
  221.      * This function will format a MAC address into XX:XX:XX:XX:XX:XX
  222.      * format from whatever format is passed to the function.  The
  223.      * delimiter (: in the example above) will be replaced with
  224.      * whatever string is passed to the $delimiter parameter
  225.      * (default :).
  226.      *
  227.      * @access static
  228.      *
  229.      * @param string $input The string containing the MAC Address
  230.      * @param string $delimiter The string representing the delimiter
  231.      *  to use when formatting the MAC Address
  232.      * @param bool $uppercase If set to true (default), the
  233.      *  hexadecimal values in the MAC Address will be returned in
  234.      *  uppercase.  If false, the hexadecimal values will be returned
  235.      *  in lowercase.
  236.      *
  237.      * @return string The formatted MAC Address or <b>false</b> on
  238.      *  error
  239.      */
  240.     static function format($input$delimiter ':'$uppercase = true)
  241.     {
  242.         /* Replace all characters not in a valid MAC address with
  243.          * nothing.  We are going to be testing for a MAC address as
  244.          * XXXXXXXXXXXX instead of XX:XX:XX:XX:XX:XX
  245.          */
  246.         $macaddr preg_replace('/[g-zG-Z]*\W*_*/'''$input);
  247.         
  248.         /* If $uppercase is true, set all the alpha characters to
  249.          * uppercase, otherwise set all the alpha characters to
  250.          * lowercase 
  251.          */
  252.         $macaddr ($uppercasestrtoupper($macaddrstrtolower($macaddr);
  253.  
  254.         // Check for 6 octets without any punctuation
  255.         if (!preg_match('/^([0-9a-fA-F][0-9a-fA-F]){6}$/'$macaddr)) {
  256.             return false;
  257.         }
  258.             
  259.         // Add back in the $delimiter delimiters
  260.         $macaddr preg_replace('/([0-9a-fA-F][0-9a-fA-F]){1}/''$1' $delimiter$macaddr);
  261.  
  262.         // Remove the trailing $delimiter
  263.         $macaddr preg_replace('/' $delimiter '$/'''$macaddr);
  264.  
  265.         return $macaddr;
  266.     /* end method format */
  267.  
  268.     /**
  269.      * Import a manufacturers' file to the database
  270.      *
  271.      * This method will parse a manufacturers' file, such as the one
  272.      * from {@link }
  273.      * http://anonsvn.wireshark.org/wireshark/trunk/manuf}, containing
  274.      * a list of MAC address prefix-to-vendor relationships.  If the
  275.      * $doReturn parameter is <b>false</b>, then the data will be
  276.      * imported into the database defined by the factory of this
  277.      * class.  However, if $doReturn is <b>true</b>, then the return
  278.      * will be an associative array with the key being the MAC address
  279.      * prefix and the data being an associative array with the keys
  280.      * 'vendor' and 'description'.
  281.      *
  282.      * @access public
  283.      *
  284.      * @param string $file The filename or URL of the manufacturers'
  285.      *  file to parse.
  286.      * @param bool $doReturn If <b>true</b>, an array will be
  287.      *  returned, if <b>false</b>, the data will be imported into the
  288.      *  database. (default: false)
  289.      *
  290.      * @return mixed If $doReturn is true, the method will return an
  291.      *  array.  Otherwise, the method will return <b>true</b> on
  292.      *  success.  A {@link Net_MAC_Exception Net_MAC_Exception}
  293.      *  Exception object will be thrown on failure in either case.
  294.      */
  295.     function importVendors($file$doReturn = false{
  296.         if ($file == NULL{
  297.             throw new Net_MAC_Exception('No file or URL given'NET_MAC_ERROR_BADFILE);
  298.         }
  299.  
  300.         $fp @fopen($file'r');
  301.         if ($fp == false{
  302.             throw new Net_MAC_Exception('Cannot open the file or URL given'NET_MAC_ERROR_BADFILE);
  303.         }
  304.  
  305.         if ($doReturn{
  306.             $retArr = array();
  307.         }
  308.         else {
  309.             // Prepare parameters for MDB2->buildManipSQL()
  310.             $fields = array ($this->_dbOptions['macaddrcol'],
  311.                              $this->_dbOptions['vendorcol'],
  312.                              $this->_dbOptions['desccol']);
  313.  
  314.             $sql $this->_db->buildManipSQL($this->_dbOptions['tablename'],
  315.                                              $fieldsMDB2_AUTOQUERY_INSERT);
  316.  
  317.             $query $this->_db->prepare($sql);
  318.         }
  319.  
  320.         while ($line fgets($fpNET_MAC_LINE_MAXLENGTH)) {
  321.             // Remove comments
  322.             if preg_match('/^\#/'$line) ) {
  323.                 continue;
  324.             }
  325.  
  326.             if preg_match('/^([0-9A-Fa-f][0-9A-Fa-f]:){2}([0-9A-Fa-f][0-9A-Fa-f]){1}/'$line) ) {
  327.                 $pieces preg_split('/\s+/'$line);
  328.  
  329.                 // Since the file is space-delimited, we now need to
  330.                 // reconstruct the description field if it existed
  331.                 $desc = NULL;
  332.                 for ($i = 3; $i count($pieces)$i++{
  333.                     $desc .= $pieces[$i].' ';
  334.                 }
  335.                 $desc rtrim($desc);
  336.  
  337.                 if ( (isset($pieces[0])) && (isset($pieces[1])) ) {
  338.                     if ($doReturn{
  339.                         $retArr[$pieces[0]] = array('vendor' => $pieces[1],
  340.                                                     'description' => $desc);
  341.                     }
  342.                     else {
  343.                         $values = array($pieces[0]$pieces[1]$desc);
  344.                         $result $query->execute($values);
  345.                     }
  346.                 }
  347.             }
  348.         }
  349.  
  350.         return ($doReturn$retArr : true;
  351.     /* end method importVendors */
  352.  
  353.     /**
  354.      * Finds the vendor for a MAC address
  355.      *
  356.      * This method will search through the database to find a vendor
  357.      * that matches the MAC address stored in the class using {@link }
  358.      * setMAC setMAC}.  If the $macList parameter is set, the method
  359.      * will use the array stored in $macList as the data source to
  360.      * find the MAC vendor instead of the database.  The array would
  361.      * have to be an array with the same characteristics as one
  362.      * returned from the {@link importVendors importVendors} method
  363.      * when using the $doReturn parameter.
  364.      *
  365.      * @access public
  366.      *
  367.      * @param bool $getDescription If set to true, the return value
  368.      *  will be an array with keys 'vendor' and 'description'.
  369.      *  Normally the method will simply return the vendor name.
  370.      * @param array $macList An optional list of MAC-to-vendor
  371.      *  relationships to search instead of using the
  372.      *  database. (default: NULL)
  373.      *
  374.      * @return mixed Returns an associative array if $getDescription
  375.      *  is <b>true</b>, returns a string with the vendor name if
  376.      *  $getDescription is <b>false</b>.  If the MAC vendor cannot be
  377.      *  found in the vendor list, <b>false</b> is returned.
  378.      */
  379.     function findVendor($getDescription = false$macList = NULL)
  380.     {
  381.         if ($macList == NULL{
  382.             $macaddrcol $this->_dbOptions['macaddrcol'];
  383.             $vendorcol $this->_dbOptions['vendorcol'];
  384.             $desccol $this->_dbOptions['desccol'];
  385.  
  386.             /* The manufacturers' list only uses the first 3 octets,
  387.              * so we need to get that portion of the stored MAC
  388.              * address. */
  389.             $macaddr substr(self::format($this->_macaddr':')08);
  390.  
  391.             // Prepare parameters for MDB2->buildManipSQL()
  392.             $fields = array ($macaddrcol$vendorcol$desccol);
  393.             $where = "$macaddrcol = '$macaddr'";
  394.  
  395.             $sql $this->_db->buildManipSQL($this->_dbOptions['tablename'],
  396.                                              $fieldsMDB2_AUTOQUERY_SELECT,
  397.                                              $where);
  398.  
  399.             $query $this->_db->prepare($sql);
  400.             $result $query->execute($values);
  401.  
  402.             if ( (MDB2::isError($result)) || ($result->numRows(== 0) ) {
  403.                 return false;
  404.             }
  405.  
  406.             $macInfo $result->fetchRow(MDB2_FETCHMODE_ASSOC);
  407.  
  408.             if ($getDescription{
  409.                 return array($vendorcol => $macInfo[$vendorcol],
  410.                              $desccol => $macInfo[$desccol]);
  411.             }
  412.             else {
  413.                 return $macInfo[$vendorcol];
  414.             }
  415.         }
  416.         else {
  417.             return false;
  418.         }
  419.     /* end method findVendor */
  420.  
  421. /* end class Net_MAC */
  422.  
  423. /*
  424.  * Local variables:
  425.  * tab-width: 4
  426.  * c-basic-offset: 4
  427.  * End:
  428.  */
  429. ?>

Documentation generated on Mon, 11 Mar 2019 14:52:55 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.