Skip to main content
Drupal API
User account menu
  • Log in

Breadcrumb

  1. Drupal Core 11.1.x

SystemNodeProvider.php

Namespace

Ramsey\Uuid\Provider\Node

File

vendor/ramsey/uuid/src/Provider/Node/SystemNodeProvider.php

View source
<?php


/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace Ramsey\Uuid\Provider\Node;

use Ramsey\Uuid\Exception\NodeException;
use Ramsey\Uuid\Provider\NodeProviderInterface;
use Ramsey\Uuid\Type\Hexadecimal;
use function array_filter;
use function array_map;
use function array_walk;
use function count;
use function ob_get_clean;
use function ob_start;
use function preg_match;
use function preg_match_all;
use function reset;
use function str_contains;
use function str_replace;
use function strtolower;
use function strtoupper;
use function substr;
use const GLOB_NOSORT;
use const PREG_PATTERN_ORDER;

/**
 * SystemNodeProvider retrieves the system node ID, if possible
 *
 * The system node ID, or host ID, is often the same as the MAC address for a
 * network interface on the host.
 */
class SystemNodeProvider implements NodeProviderInterface {
    
    /**
     * Pattern to match nodes in ifconfig and ipconfig output.
     */
    private const IFCONFIG_PATTERN = '/[^:]([0-9a-f]{2}([:-])[0-9a-f]{2}(\\2[0-9a-f]{2}){4})[^:]/i';
    
    /**
     * Pattern to match nodes in sysfs stream output.
     */
    private const SYSFS_PATTERN = '/^([0-9a-f]{2}:){5}[0-9a-f]{2}$/i';
    public function getNode() : Hexadecimal {
        $node = $this->getNodeFromSystem();
        if ($node === '') {
            throw new NodeException('Unable to fetch a node for this system');
        }
        return new Hexadecimal($node);
    }
    
    /**
     * Returns the system node, if it can find it
     */
    protected function getNodeFromSystem() : string {
        static $node = null;
        if ($node !== null) {
            return (string) $node;
        }
        // First, try a Linux-specific approach.
        $node = $this->getSysfs();
        if ($node === '') {
            // Search ifconfig output for MAC addresses & return the first one.
            $node = $this->getIfconfig();
        }
        $node = str_replace([
            ':',
            '-',
        ], '', $node);
        return $node;
    }
    
    /**
     * Returns the network interface configuration for the system
     *
     * @codeCoverageIgnore
     */
    protected function getIfconfig() : string {
        $disabledFunctions = strtolower((string) ini_get('disable_functions'));
        if (str_contains($disabledFunctions, 'passthru')) {
            return '';
        }
        
        /**
         * @psalm-suppress UnnecessaryVarAnnotation
         * @var string $phpOs
         */
        $phpOs = constant('PHP_OS');
        ob_start();
        switch (strtoupper(substr($phpOs, 0, 3))) {
            case 'WIN':
                passthru('ipconfig /all 2>&1');
                break;
            case 'DAR':
                passthru('ifconfig 2>&1');
                break;
            case 'FRE':
                passthru('netstat -i -f link 2>&1');
                break;
            case 'LIN':
            default:
                passthru('netstat -ie 2>&1');
                break;
        }
        $ifconfig = (string) ob_get_clean();
        if (preg_match_all(self::IFCONFIG_PATTERN, $ifconfig, $matches, PREG_PATTERN_ORDER)) {
            foreach ($matches[1] as $iface) {
                if ($iface !== '00:00:00:00:00:00' && $iface !== '00-00-00-00-00-00') {
                    return $iface;
                }
            }
        }
        return '';
    }
    
    /**
     * Returns MAC address from the first system interface via the sysfs interface
     */
    protected function getSysfs() : string {
        $mac = '';
        
        /**
         * @psalm-suppress UnnecessaryVarAnnotation
         * @var string $phpOs
         */
        $phpOs = constant('PHP_OS');
        if (strtoupper($phpOs) === 'LINUX') {
            $addressPaths = glob('/sys/class/net/*/address', GLOB_NOSORT);
            if ($addressPaths === false || count($addressPaths) === 0) {
                return '';
            }
            
            /** @var array<array-key, string> $macs */
            $macs = [];
            array_walk($addressPaths, function (string $addressPath) use (&$macs) : void {
                if (is_readable($addressPath)) {
                    $macs[] = file_get_contents($addressPath);
                }
            });
            
            /** @var callable $trim */
            $trim = 'trim';
            $macs = array_map($trim, $macs);
            // Remove invalid entries.
            $macs = array_filter($macs, function (string $address) {
                return $address !== '00:00:00:00:00:00' && preg_match(self::SYSFS_PATTERN, $address);
            });
            
            /** @var string|bool $mac */
            $mac = reset($macs);
        }
        return (string) $mac;
    }

}

Classes

Title Deprecated Summary
SystemNodeProvider SystemNodeProvider retrieves the system node ID, if possible

API Navigation

  • Drupal Core 11.1.x
  • Topics
  • Classes
  • Functions
  • Constants
  • Globals
  • Files
  • Namespaces
  • Deprecated
  • Services
RSS feed
Powered by Drupal