View source
<?php
function field_ipaddress_migrate_api() {
$api = array(
'api' => 2,
);
return $api;
}
function field_ipaddress_field_info() {
return array(
'field_ipaddress' => array(
'label' => t('IP Address'),
'description' => t('Stores a single IP address, or range of IP addresses.'),
'default_widget' => 'field_ipaddress_cidr',
'default_formatter' => 'field_ipaddress_cidr',
),
);
}
function field_ipaddress_field_is_empty($item, $field) {
return empty($item['start']);
}
function field_ipaddress_field_formatter_info() {
return array(
'field_ipaddress_shorthand' => array(
'label' => t('List of IPs (shorthand)'),
'field types' => array(
'field_ipaddress',
),
),
'field_ipaddress_cidr' => array(
'label' => t('List of IPs (CIDR)'),
'field types' => array(
'field_ipaddress',
),
),
);
}
function field_ipaddress_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
$element = array();
switch ($display['type']) {
case 'field_ipaddress_shorthand':
$networks = array();
foreach ($items as $delta => $item) {
if (!empty($item)) {
$networks[] = _field_ipaddress_long2shorthand($item['start'], $item['end']);
}
}
if (!empty($networks)) {
if (count($networks) === 1) {
$element[0] = array(
'#markup' => $networks[0],
);
}
else {
$element[0] = array(
'#theme' => 'item_list',
'#items' => $networks,
);
}
}
break;
case 'field_ipaddress_cidr':
$networks = array();
foreach ($items as $delta => $item) {
if (!empty($item)) {
$networks[] = _field_ipaddress_long2cidr($item['start'], $item['end']);
}
}
if (!empty($networks)) {
if (count($networks) === 1) {
$element[0] = array(
'#markup' => $networks[0],
);
}
else {
$element[0] = array(
'#theme' => 'item_list',
'#items' => $networks,
);
}
}
break;
}
return $element;
}
function field_ipaddress_field_widget_info() {
return array(
'field_ipaddress_shorthand' => array(
'label' => t('Shorthand input'),
'field types' => array(
'field_ipaddress',
),
),
'field_ipaddress_cidr' => array(
'label' => t('CIDR input'),
'field types' => array(
'field_ipaddress',
),
),
'field_ipaddress_long' => array(
'label' => t('Long input'),
'field types' => array(
'field_ipaddress',
),
),
);
}
function field_ipaddress_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
switch ($instance['widget']['type']) {
case 'field_ipaddress_long':
$element += array(
'#type' => 'fieldset',
'#element_validate' => array(
'_field_ipaddress_validate_long',
),
);
$element['start'] = array(
'#type' => 'textfield',
'#title' => t('Start'),
'#size' => 15,
'#default_value' => isset($items[$delta]['start']) ? long2ip($items[$delta]['start']) : '',
);
$element['end'] = array(
'#type' => 'textfield',
'#title' => t('End'),
'#size' => 15,
'#default_value' => isset($items[$delta]['end']) ? long2ip($items[$delta]['end']) : '',
);
break;
case 'field_ipaddress_shorthand':
$element += array(
'#element_validate' => array(
'_field_ipaddress_validate_shorthand',
),
);
$value = isset($items[$delta]['start']) && isset($items[$delta]['end']) ? _field_ipaddress_long2shorthand($items[$delta]['start'], $items[$delta]['end']) : '';
$element['start'] = array(
'#type' => 'textfield',
'#default_value' => $value,
'#size' => 30,
'#maxlength' => 100,
);
break;
case 'field_ipaddress_cidr':
$element += array(
'#element_validate' => array(
'_field_ipaddress_validate_cidr',
),
);
$value = isset($items[$delta]['start']) && isset($items[$delta]['end']) ? _field_ipaddress_long2cidr($items[$delta]['start'], $items[$delta]['end']) : '';
$element['start'] = array(
'#type' => 'textfield',
'#default_value' => $value,
'#size' => 30,
'#maxlength' => 100,
);
break;
}
return $element;
}
function field_ipaddress_field_widget_error($element, $error, $form, &$form_state) {
switch ($error['error']) {
case 'field_ipaddress_invalid':
form_error($element, $error['message']);
break;
}
}
function _field_ipaddress_validate_long($element, &$form_state) {
$delta = $element['#delta'];
$lang_code = $element['#language'];
$field = $form_state['field'][$element['#field_name']][$lang_code]['field'];
$field_name = $field['field_name'];
$startip = trim($form_state['values'][$field_name][$lang_code][$delta]['start']);
$endip = trim($form_state['values'][$field_name][$lang_code][$delta]['end']);
if (!empty($startip)) {
$start = ip2long($startip);
if (empty($endip)) {
$end = $start;
}
else {
$end = ip2long($endip);
}
$startip = long2ip($start);
$endip = long2ip($end);
if ($startip === '0.0.0.0' || $endip === '0.0.0.0') {
form_error($element, t('Invalid start or end IP.'));
}
else {
if ($start > $end) {
form_error($element, t('Wrong order of start and end IP.'));
}
else {
form_set_value($element['start'], $start, $form_state);
form_set_value($element['end'], $end, $form_state);
}
}
}
}
function _field_ipaddress_validate_cidr($element, &$form_state) {
$delta = $element['#delta'];
$lang_code = $element['#language'];
$field = $form_state['field'][$element['#field_name']][$lang_code]['field'];
$field_name = $field['field_name'];
$ipaddress = trim($form_state['values'][$field_name][$lang_code][$delta]['start']);
if (!empty($ipaddress)) {
list($ip, $bits) = explode('/', $ipaddress);
$minimumprefix = _field_ipaddress_minimum_cidr_prefix(ip2long($ip), 32);
if (!is_numeric($bits) || (int) $bits != $bits || $bits < 0 || $bits > 32) {
form_error($element, t('The prefix must be an integer between 0 and 32.'));
}
else {
if ($bits < $minimumprefix) {
form_error($element, t('The prefix is too small for the given IP address. ' . 'The minimum prefix is @value.', array(
'@value' => $minimumprefix,
)));
}
else {
$range = _field_ipaddress_cidr2long($ipaddress);
if ($range) {
form_set_value($element, $range, $form_state);
}
else {
form_error($element, t('Invalid IP range or address.'));
}
}
}
}
}
function _field_ipaddress_validate_shorthand($element, &$form_state) {
$delta = $element['#delta'];
$lang_code = $element['#language'];
$field = $form_state['field'][$element['#field_name']][$lang_code]['field'];
$field_name = $field['field_name'];
$ipaddress = trim($form_state['values'][$field_name][$lang_code][$delta]['start']);
if (!empty($ipaddress)) {
$value = _field_ipaddress_shorthand2long($ipaddress);
if ($value) {
form_set_value($element, $value, $form_state);
}
else {
form_error($element, t('Invalid IP range or address.'));
}
}
}
function _field_ipaddress_long2shorthand($start, $end) {
if ($start === $end) {
$output = long2ip($start);
}
else {
$s = explode('.', long2ip($start));
$e = explode('.', long2ip($end));
if ($s[0] === $e[0] && $s[1] === $e[1] && $s[2] === $e[2]) {
if ($s[3] === '0' && $e[3] === '255') {
$s[3] = '*';
$output = implode('.', $s);
}
else {
$s[3] = sprintf('%s-%s', $s[3], $e[3]);
$output = implode('.', $s);
}
}
else {
$output = long2ip($start) . ' - ' . long2ip($end);
}
}
return $output;
}
function _field_ipaddress_long2cidr($start, $end) {
$mask = (int) $start | ~(int) $end;
$cidr = 32 - log(abs($mask), 2);
$valid = (int) $cidr == $cidr;
if (!$valid) {
return _field_ipaddress_long2shorthand($start, $end);
}
return long2ip($start) . '/' . $cidr;
}
function _field_ipaddress_minimum_cidr_prefix($ibase, $tbit) {
while ($tbit > 0) {
$im = pow(2, 32) - pow(2, 32 - ($tbit - 1));
$imand = $ibase & $im;
if ($imand != $ibase) {
break;
}
$tbit--;
}
return $tbit;
}
function _field_ipaddress_cidr2long($cidr) {
list($ip, $bits) = explode('/', $cidr);
$start = long2ip(ip2long($ip));
$end = long2ip(ip2long($ip) + pow(2, 32 - $bits) - 1);
if ($start === '0.0.0.0' || $end === '0.0.0.0') {
return FALSE;
}
else {
return array(
'start' => ip2long($start),
'end' => ip2long($end),
);
}
}
function _field_ipaddress_shorthand2long($shorthand) {
$res = _field_ipaddress_shorthand2dottedquad($shorthand);
if (!$res) {
return FALSE;
}
list($start, $end) = $res;
return array(
'start' => ip2long($start),
'end' => ip2long($end),
);
}
function _field_ipaddress_shorthand2dottedquad($network) {
$star = strpos($network, '*');
$dash = strpos($network, '-');
if (ctype_alpha($network[strlen($network) - 1])) {
$start = $end = gethostbyname($network);
if ($start === $network) {
return FALSE;
}
}
else {
if ($star === false && $dash === false) {
$res = long2ip(ip2long($network));
$start = $end = $res;
if ($res === '0.0.0.0') {
return FALSE;
}
}
if ($star !== false) {
$start = long2ip(ip2long(str_replace('*', '0', $network)));
$end = long2ip(ip2long(str_replace('*', '255', $network)));
if ($start === '0.0.0.0' || $end === '0.0.0.0') {
return FALSE;
}
}
if ($dash !== FALSE) {
list($start, $end) = explode('-', $network);
if (strpos($end, '.') !== FALSE) {
$end = long2ip(ip2long(trim($end)));
}
else {
$classc = substr($start, 0, strrpos($start, '.'));
$classc .= '.' . $end;
$end = long2ip(ip2long(trim($classc)));
}
$start = long2ip(ip2long(trim($start)));
if ($start === '0.0.0.0' || $end === '0.0.0.0') {
return FALSE;
}
}
}
return array(
$start,
$end,
);
}
function _field_ipaddress_ip2long($ip) {
$octets = explode(".", $ip);
$ip = "";
$dot = "";
while (list($key, $val) = each($octets)) {
$ip = sprintf("%s%s%d", $ip, $dot, $val);
$dot = ".";
}
return ip2long($ip);
}