mirror of
https://gitlab.linphone.org/BC/public/flexisip-account-manager.git
synced 2026-04-17 11:48:28 +00:00
Add a SipUri validator with the Regex extracted from the RFC 3261
This commit is contained in:
parent
57381f1454
commit
1907d3b966
3 changed files with 98 additions and 4 deletions
|
|
@ -5,6 +5,7 @@ namespace App\Http\Controllers\Admin\Account;
|
|||
use App\Account;
|
||||
use App\CallForwarding;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Rules\SipUri;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
|
|
@ -20,19 +21,19 @@ class CallForwardingController extends Controller
|
|||
$request->validate([
|
||||
'always.forward_to' => $forwardTo,
|
||||
'always.sip_uri' => array_key_exists('enabled', $request->get('always'))
|
||||
? 'nullable|starts_with:sip:|required_if:always.forward_to,sip_uri'
|
||||
? ['nullable', new SipUri, 'required_if:always.forward_to,sip_uri']
|
||||
: 'nullable',
|
||||
'always.contact_id' => ['required_if:always.forward_to,contact', Rule::in($contactsIds)],
|
||||
|
||||
'away.forward_to' => $forwardTo,
|
||||
'away.sip_uri' => array_key_exists('enabled', $request->get('away'))
|
||||
? 'nullable|starts_with:sip:|required_if:away.forward_to,sip_uri'
|
||||
? ['nullable', new SipUri, 'required_if:away.forward_to,sip_uri']
|
||||
: 'nullable',
|
||||
'away.contact_id' => ['required_if:away.forward_to,contact', Rule::in($contactsIds)],
|
||||
|
||||
'busy.forward_to' => $forwardTo,
|
||||
'busy.sip_uri' => array_key_exists('enabled', $request->get('busy'))
|
||||
? 'nullable|starts_with:sip:|required_if:busy.forward_to,sip_uri'
|
||||
? ['nullable', new SipUri, 'required_if:busy.forward_to,sip_uri']
|
||||
: 'nullable',
|
||||
'busy.contact_id' => ['required_if:busy.forward_to,contact', Rule::in($contactsIds)],
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ use App\Account;
|
|||
use App\CallForwarding;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Rules\CallForwardingEnable;
|
||||
use App\Rules\SipUri;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
|
|
@ -26,7 +27,7 @@ class CallForwardingController extends Controller
|
|||
Rule::unique('call_forwardings', 'type')->where(fn($query) => $query->where('account_id', $accountId))
|
||||
],
|
||||
'forward_to' => 'required|in:sip_uri,contact,voicemail',
|
||||
'sip_uri' => 'nullable|starts_with:sip:|required_if:forward_to,sip_uri',
|
||||
'sip_uri' => ['nullable', new SipUri, 'required_if:forward_to,sip_uri'],
|
||||
'enabled' => ['required', 'boolean', new CallForwardingEnable($request, $account)],
|
||||
'contact_id' => ['required_if:forward_to,contact', Rule::in(resolveUserContacts($account)->pluck('id')->toArray())],
|
||||
]);
|
||||
|
|
|
|||
92
flexiapi/app/Rules/SipUri.php
Normal file
92
flexiapi/app/Rules/SipUri.php
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
<?php
|
||||
|
||||
namespace App\Rules;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Validation\ValidationRule;
|
||||
|
||||
class SipUri implements ValidationRule
|
||||
{
|
||||
/**
|
||||
* Run the validation rule.
|
||||
* Validates a SIP/SIPS URI against RFC 3261 §19.1 ABNF grammar.
|
||||
*/
|
||||
public function validate(string $attribute, mixed $value, Closure $fail): void
|
||||
{
|
||||
if (! is_string($value) || ! preg_match($this->buildPattern(), $value)) {
|
||||
$fail('The :attribute must be a valid SIP URI.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the RFC 3261 §19.1 compliant regex pattern.
|
||||
* Generated using Claude
|
||||
*/
|
||||
private function buildPattern(): string
|
||||
{
|
||||
// unreserved = alphanum / mark (mark = - _ . ! ~ * ' ( ))
|
||||
$unreserved = '[A-Za-z0-9\-_.!~*\'()]';
|
||||
|
||||
// escaped = "%" HEXDIG HEXDIG
|
||||
$escaped = '%[0-9A-Fa-f]{2}';
|
||||
|
||||
// user-unreserved = & = + $ , ; ? /
|
||||
$userUnreserved = '[&=+$,;?\/]';
|
||||
|
||||
// user = 1*( unreserved / escaped / user-unreserved )
|
||||
$user = "(?:{$unreserved}|{$escaped}|{$userUnreserved})+";
|
||||
|
||||
// password = *( unreserved / escaped / & = + $ , )
|
||||
$password = "(?:{$unreserved}|{$escaped}|[&=+$,])*";
|
||||
|
||||
// userinfo = user [ ":" password ] "@"
|
||||
$userinfo = "(?:{$user})(?::{$password})?@";
|
||||
|
||||
// domainlabel = alphanum / alphanum *( alphanum / "-" ) alphanum
|
||||
$domainLabel = '[A-Za-z0-9](?:[A-Za-z0-9\-]*[A-Za-z0-9])?';
|
||||
|
||||
// toplabel = ALPHA / ALPHA *( alphanum / "-" ) alphanum
|
||||
$topLabel = '[A-Za-z](?:[A-Za-z0-9\-]*[A-Za-z0-9])?';
|
||||
|
||||
// hostname = *( domainlabel "." ) toplabel [ "." ]
|
||||
$hostname = "(?:{$domainLabel}\.)*{$topLabel}\.?";
|
||||
|
||||
// IPv4address = 1*3DIGIT "." x3
|
||||
$ipv4 = '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}';
|
||||
|
||||
// IPv6 building blocks (RFC 5954)
|
||||
$h16 = '[0-9A-Fa-f]{1,4}';
|
||||
$ls32 = "(?:{$h16}:{$h16}|{$ipv4})";
|
||||
$ipv6 = "(?:"
|
||||
. "(?:{$h16}:){6}{$ls32}"
|
||||
. "|::(?:{$h16}:){5}{$ls32}"
|
||||
. "|{$h16}?::(?:{$h16}:){4}{$ls32}"
|
||||
. "|(?:{$h16}:)?{$h16}::(?:{$h16}:){3}{$ls32}"
|
||||
. "|(?:{$h16}:){0,2}{$h16}::(?:{$h16}:){2}{$ls32}"
|
||||
. "|(?:{$h16}:){0,3}{$h16}::{$h16}:{$ls32}"
|
||||
. "|(?:{$h16}:){0,4}{$h16}::{$ls32}"
|
||||
. "|(?:{$h16}:){0,5}{$h16}::{$h16}"
|
||||
. "|(?:{$h16}:){0,6}{$h16}::"
|
||||
. ")";
|
||||
|
||||
// IPv6reference = "[" IPv6address "]"
|
||||
$ipv6ref = "\[{$ipv6}\]";
|
||||
|
||||
// host = IPv6reference / IPv4address / hostname (order matters)
|
||||
$host = "(?:{$ipv6ref}|{$ipv4}|{$hostname})";
|
||||
|
||||
// hostport = host [ ":" port ]
|
||||
$hostport = "{$host}(?::\d+)?";
|
||||
|
||||
// uri-parameters: *( ";" pname [ "=" pvalue ] )
|
||||
$paramChar = "(?:{$unreserved}|{$escaped}|[\\[\\]\/:&+$])";
|
||||
$uriParams = "(?:;{$paramChar}*(?:={$paramChar}*)?)*";
|
||||
|
||||
// headers: "?" hname "=" hvalue *( "&" hname "=" hvalue )
|
||||
$hnvUnreserved = '[\\[\\]\/?:+$]';
|
||||
$headerChar = "(?:{$unreserved}|{$escaped}|{$hnvUnreserved})";
|
||||
$headers = "(?:\\?{$headerChar}+={$headerChar}*(?:&{$headerChar}+={$headerChar}*)*)?";
|
||||
|
||||
return '/^sips?:(?:' . $userinfo . ')?' . $hostport . $uriParams . $headers . '$/i';
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue