3496 $return .= $alts . '\.'; |
3514 $return .= $alts . '\.'; |
3497 } |
3515 } |
3498 $return = substr($return, 0, -2); |
3516 $return = substr($return, 0, -2); |
3499 $return .= '$'; |
3517 $return .= '$'; |
3500 return $return; |
3518 return $return; |
|
3519 } |
|
3520 |
|
3521 /** |
|
3522 * Parses a valid IPv6 address range into a regular expression. |
|
3523 * @param string IP range string |
|
3524 * @return string |
|
3525 */ |
|
3526 |
|
3527 function parse_ipv6_range_regex($range) |
|
3528 { |
|
3529 $range = strtolower(trim($range)); |
|
3530 $valid = '/^'; |
|
3531 $valid .= '(?:[0-9a-f]{0,4}|[0-9a-f]{1,4}-[0-9a-f]{1,4}):'; |
|
3532 $valid .= '(?:[0-9a-f]{0,4}|[0-9a-f]{1,4}-[0-9a-f]{1,4}):'; |
|
3533 $valid .= '(?:[0-9a-f]{0,4}|[0-9a-f]{1,4}-[0-9a-f]{1,4}:|:)?'; |
|
3534 $valid .= '(?:[0-9a-f]{0,4}|[0-9a-f]{1,4}-[0-9a-f]{1,4}:|:)?'; |
|
3535 $valid .= '(?:[0-9a-f]{0,4}|[0-9a-f]{1,4}-[0-9a-f]{1,4}:|:)?'; |
|
3536 $valid .= '(?:[0-9a-f]{0,4}|[0-9a-f]{1,4}-[0-9a-f]{1,4}:|:)?'; |
|
3537 $valid .= '(?:[0-9a-f]{0,4}|[0-9a-f]{1,4}-[0-9a-f]{1,4}:|:)?'; |
|
3538 $valid .= '(?:[0-9a-f]{0,4}|[0-9a-f]{1,4}-[0-9a-f]{1,4})$/'; |
|
3539 if ( !preg_match($valid, $range) ) |
|
3540 return false; |
|
3541 |
|
3542 // expand address range. |
|
3543 // this takes short ranges like: |
|
3544 // 2001:470-471:054-b02b::5-bb |
|
3545 // up to: |
|
3546 // 2001:0470-0471:0054-b02b:0000:0000:0000:0005-00bb |
|
3547 $range = explode(':', $range); |
|
3548 $expanded = ''; |
|
3549 $size = count($range); |
|
3550 foreach ( $range as $byteset ) |
|
3551 { |
|
3552 if ( empty($byteset) ) |
|
3553 { |
|
3554 // :: |
|
3555 while ( $size < 9 ) |
|
3556 { |
|
3557 $expanded .= '0000:'; |
|
3558 $size++; |
|
3559 } |
|
3560 } |
|
3561 else |
|
3562 { |
|
3563 if ( strstr($byteset, '-') ) |
|
3564 { |
|
3565 // this is a range |
|
3566 $sides = explode('-', $byteset); |
|
3567 foreach ( $sides as &$bytepair ) |
|
3568 { |
|
3569 while ( strlen($bytepair) < 4 ) |
|
3570 { |
|
3571 $bytepair = "0$bytepair"; |
|
3572 } |
|
3573 } |
|
3574 $byteset = implode('-', $sides); |
|
3575 } |
|
3576 else |
|
3577 { |
|
3578 while ( strlen($byteset) < 4 ) |
|
3579 { |
|
3580 $byteset = "0$byteset"; |
|
3581 } |
|
3582 } |
|
3583 $expanded .= "$byteset:"; |
|
3584 } |
|
3585 } |
|
3586 $expanded = explode(':', rtrim($expanded, ':')); |
|
3587 |
|
3588 // ready to dive in and start generating range regexes. |
|
3589 // this has to be pretty optimized... we want to end up with regexes like: |
|
3590 // range: 54-b12b |
|
3591 /* |
|
3592 /005[4-9a-f]| |
|
3593 00[6-9a-f][0-9a-f]| |
|
3594 0[1-9a-f][0-9a-f][0-9a-f]| |
|
3595 [1-9a][0-9a-f][0-9a-f][0-9a-f]| |
|
3596 b[0-0][0-1][0-9a-f]| |
|
3597 b0[0-1][0-9a-f]| |
|
3598 b02[0-9a-b]/x |
|
3599 */ |
|
3600 foreach ( $expanded as &$word ) |
|
3601 { |
|
3602 if ( strstr($word, '-') ) |
|
3603 { |
|
3604 // oh... damn. |
|
3605 $word = '(?:' . generate_hex_numeral_range($word) . ')'; |
|
3606 } |
|
3607 } |
|
3608 |
|
3609 // return print_r($expanded, true); |
|
3610 return '^' . implode(':', $expanded) . '$'; |
|
3611 } |
|
3612 |
|
3613 /** |
|
3614 * Take a hex numeral range and parse it in to a PCRE. |
|
3615 * @param string |
|
3616 * @return string |
|
3617 * @access private |
|
3618 */ |
|
3619 |
|
3620 function generate_hex_numeral_range($word) |
|
3621 { |
|
3622 list($low, $high) = explode('-', $word); |
|
3623 |
|
3624 if ( hexdec($low) > hexdec($high) ) |
|
3625 { |
|
3626 $_ = $low; |
|
3627 $low = $high; |
|
3628 $high = $_; |
|
3629 unset($_); |
|
3630 } |
|
3631 |
|
3632 while ( strlen($low) < strlen($high) ) |
|
3633 { |
|
3634 $low = "0$low"; |
|
3635 } |
|
3636 |
|
3637 // trim off everything that's the same |
|
3638 $trimmed = ''; |
|
3639 $len = strlen($low); |
|
3640 for ( $i = 0; $i < $len; $i++ ) |
|
3641 { |
|
3642 if ( $low{0} === $high{0} ) |
|
3643 { |
|
3644 $trimmed .= $low{0}; |
|
3645 $low = substr($low, 1); |
|
3646 $high = substr($high, 1); |
|
3647 } |
|
3648 else |
|
3649 { |
|
3650 break; |
|
3651 } |
|
3652 } |
|
3653 |
|
3654 $len = strlen($high); |
|
3655 if ( $len == 1 ) |
|
3656 { |
|
3657 // this does happen sometimes, so we can save a bit of CPU power here. |
|
3658 return $trimmed . __hexdigitrange($low, $high); |
|
3659 } |
|
3660 |
|
3661 $return = ''; |
|
3662 // lower half |
|
3663 for ( $i = $len - 1; $i > 0; $i-- ) |
|
3664 { |
|
3665 if ( $low{$i} == 'f' ) |
|
3666 continue; |
|
3667 $return .= $trimmed; |
|
3668 for ( $j = 0; $j < $len; $j++ ) |
|
3669 { |
|
3670 if ( $j < $i ) |
|
3671 { |
|
3672 $return .= $low{$j}; |
|
3673 } |
|
3674 else if ( $j == $i && ( $i == $len - 1 || $low{$j} == 'f' ) ) |
|
3675 { |
|
3676 $return .= __hexdigitrange($low{$j}, 'f'); |
|
3677 } |
|
3678 else if ( $j == $i && $i != $len - 1 ) |
|
3679 { |
|
3680 $return .= __hexdigitrange(dechex(hexdec($low{$j}) + 1), 'f'); |
|
3681 } |
|
3682 else |
|
3683 { |
|
3684 $return .= __hexdigitrange('0', 'f'); |
|
3685 } |
|
3686 } |
|
3687 $return .= '|'; |
|
3688 } |
|
3689 // middle block |
|
3690 if ( hexdec($low{0}) + 1 < hexdec($high{0}) ) |
|
3691 { |
|
3692 if ( hexdec($low{0}) + 1 < hexdec($high{0}) - 1 ) |
|
3693 $return .= $trimmed . __hexdigitrange(dechex(hexdec($low{0}) + 1), dechex(hexdec($high{0}) - 1)); |
|
3694 else |
|
3695 $return .= $trimmed . __hexdigitrange($low{0}, $high{0}); |
|
3696 if ( $len - 1 > 0 ) |
|
3697 $return .= '[0-9a-f]{' . ( $len - 1 ) . '}|'; |
|
3698 } |
|
3699 // higher half |
|
3700 for ( $i = 1; $i < $len; $i++ ) |
|
3701 { |
|
3702 if ( $high{$i} == '0' ) |
|
3703 continue; |
|
3704 $return .= $trimmed; |
|
3705 for ( $j = 0; $j < $len; $j++ ) |
|
3706 { |
|
3707 if ( $j < $i ) |
|
3708 { |
|
3709 $return .= $high{$j}; |
|
3710 } |
|
3711 else if ( $j == $i && ( $i == $len - 1 || $high{$j} == '0' ) ) |
|
3712 { |
|
3713 $return .= __hexdigitrange('0', $high{$j}); |
|
3714 } |
|
3715 else if ( $j == $i && $i != $len - 1 ) |
|
3716 { |
|
3717 $return .= __hexdigitrange('0', dechex(hexdec($high{$j}) - 1)); |
|
3718 } |
|
3719 else if ( $j > $i ) |
|
3720 { |
|
3721 $return .= __hexdigitrange('0', 'f'); |
|
3722 } |
|
3723 else |
|
3724 { |
|
3725 die("I don't know what to do! i $i j $j"); |
|
3726 } |
|
3727 } |
|
3728 $return .= '|'; |
|
3729 } |
|
3730 |
|
3731 return rtrim($return, '|'); |
|
3732 } |
|
3733 |
|
3734 function __hexdigitrange($low, $high) |
|
3735 { |
|
3736 if ( $low == $high ) |
|
3737 return $low; |
|
3738 if ( empty($low) ) |
|
3739 $low = '0'; |
|
3740 |
|
3741 $low_type = ( preg_match('/[0-9]/', $low) ) ? 'num' : 'alph'; |
|
3742 $high_type = ( preg_match('/[0-9]/', $high) ) ? 'num' : 'alph'; |
|
3743 if ( ( $low_type == 'num' && $high_type == 'num') || ( $low_type == 'alph' && $high_type == 'alph' ) ) |
|
3744 { |
|
3745 return "[$low-$high]"; |
|
3746 } |
|
3747 else if ( $low_type == 'num' && $high_type == 'alph' ) |
|
3748 { |
|
3749 $ret = '['; |
|
3750 |
|
3751 if ( $low == '9' ) |
|
3752 $ret .= '9'; |
|
3753 else |
|
3754 $ret .= "$low-9"; |
|
3755 if ( $high == 'a' ) |
|
3756 $ret .= 'a'; |
|
3757 else |
|
3758 $ret .= "a-$high"; |
|
3759 |
|
3760 $ret .= "]"; |
|
3761 return $ret; |
|
3762 } |
|
3763 else if ( $low_type == 'alph' && $high_type == 'num' ) |
|
3764 { |
|
3765 // ???? this should never happen |
|
3766 return __hexdigitrange($high, $low); |
|
3767 } |
3501 } |
3768 } |
3502 |
3769 |
3503 /** |
3770 /** |
3504 * Validates an e-mail address. Uses a compacted version of the regular expression generated by the scripts at <http://examples.oreilly.com/regex/>. |
3771 * Validates an e-mail address. Uses a compacted version of the regular expression generated by the scripts at <http://examples.oreilly.com/regex/>. |
3505 * @param string E-mail address |
3772 * @param string E-mail address |