الحصول على إدخال الجذر DNS من PHP Server ؛ احصل على اسم المجال بدون www ، إلخ

StackOverflow https://stackoverflow.com/questions/1375647

  •  21-09-2019
  •  | 
  •  

سؤال

كيف يمكن للمرء الحصول على دخول الجذر DNS من $_SERVER['HTTP_HOST']?

مدخل:

example.co.uk
www.example.com
blog.example.com
forum.example.co.uk 

انتاج:

example.co.uk
example.com
example.com
example.co.uk

تحرير: قائمة البحث هي طويل جدا

هل كانت مفيدة؟

المحلول

لأجل هذا المشروع: http://drupal.org/project/paralled

الاستخدام:

echo parallel_get_domain("www.robknight.org.uk") . "<br>";
echo parallel_get_domain("www.google.com") . "<br>";
echo parallel_get_domain("www.yahoo.com") . "<br>";

المهام:

/**
 * Given host name returns top domain.
 *
 * @param $host
 *   String containing the host name: www.example.com
 *
 * @return string
 *   top domain: example.com
 */
function parallel_get_domain($host) {
  if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN' && strnatcmp(phpversion(),'5.3.0') < 0) {
    // This works 1/2 the time... CNAME doesn't work with nslookup
    for ($end_pieces = substr_count($host, '.'); $end_pieces > 0; $end_pieces--) {
      $test_domain = end(explode('.', $host, $end_pieces));
      if (checkdnsrr($test_domain)) {
          $domain = $test_domain;
          break;
      }
    }
    return isset($domain) ? $domain : FALSE;
  }
  else {
    // This always works
    $sections = explode('.', $host);
    array_unshift($sections, '');
    foreach($sections as $key => $value) {
      $parts[$key] = $value;
      $test_domain = implode('.', parallel_array_xor($parts, $sections));
      if (checkdnsrr($test_domain, 'NS') && !checkdnsrr($test_domain, 'CNAME')) {
        $domain = $test_domain;
        break;
      }
    }
    return isset($domain) ? $domain : FALSE;
  }
}

/**
 * Opposite of array_intersect().
 *
 * @param $array_a
 *   First array
 * @param $array_b
 *   Second array
 *
 * @return array
 */
function parallel_array_xor ($array_a, $array_b) {
  $union_array = array_merge($array_a, $array_b);
  $intersect_array = array_intersect($array_a, $array_b);
  return array_diff($union_array, $intersect_array);
}

/**
 * Win compatible version of checkdnsrr.
 *
 * checkdnsrr() support for Windows by HM2K <php [spat] hm2k.org>
 * http://us2.php.net/manual/en/function.checkdnsrr.php#88301
 *
 * @param $host
 *   String containing host name
 * @param $type
 *   String containing the DNS record type
 *
 * @return bool
 */
function parallel_win_checkdnsrr($host, $type='MX') {
  if (strtoupper(substr(PHP_OS, 0, 3)) != 'WIN') { return FALSE; }
  if (empty($host)) { return FALSE; }
  $types=array('A', 'MX', 'NS', 'SOA', 'PTR', 'CNAME', 'AAAA', 'A6', 'SRV', 'NAPTR', 'TXT', 'ANY');
  if (!in_array($type, $types)) {
    user_error("checkdnsrr() Type '$type' not supported", E_USER_WARNING);
    return FALSE;
  }
  @exec('nslookup -type=' . $type . ' ' . escapeshellcmd($host), $output);

  foreach($output as $line){
    if (preg_match('/^' . $host . '/', $line)) { return TRUE; }
  }
}

// Define checkdnsrr() if it doesn't exist
if (!function_exists('checkdnsrr')) {
  function checkdnsrr($host, $type='MX') {
    return parallel_win_checkdnsrr($host, $type);
  }
}

الإخراج - Windows:

org.uk
google.com
yahoo.com

الإخراج - Linux:

robknight.org.uk
google.com
yahoo.com

نصائح أخرى

أعتقد أن هذا غير محدد بعض الشيء.

يمكنك محاولة إجراء عمليات البحث عن DNS لكل سجل من الوالدين حتى تجد سجلًا لا يعيد سجلًا.

/[^\.]+\.[escaped|list|of|domains]$/

اظن انه يجب ان يعمل.

كما اكتشفت ، تستخدم بعض الدول TLD فقط (مثال: .TV ، .us) ، والبعض الآخر ينقسم بلادهم TLD (مثال: المملكة المتحدة).

من الناحية المثالية ، ستحتاج إلى قائمة بحث (لن تكون طويلة) من TLDs المعتمدة ، وإذا تم تقسيمها ، فإن TLD مع كل قسم فرعي (على سبيل المثال ".co.uk" بدلاً من ".uk"). سيخبرك ذلك "النقاط" (من اليمين) التي يجب الاحتفاظ بها. ثم انقل نقطة واحدة إلى يسار ذلك (إذا وجدت) وقم بتقطيع كل شيء قبل ذلك.

بدون قائمة بحث ، يمكنك استغلال حقيقة أن التقسيمات الفرعية (.co ، وما إلى ذلك) مخصصة فقط للبلدان (التي لديها TLDs من حرفيين) وهي لا تزيد عن 3 أحرف وأنفسها دائمًا ، لذلك يمكنك على الأرجح التعرف عليهم بنمط regex.

تعديل: فما باللك ، القائمة الفعلية لللواحق العامة أكثر تعقيدًا. ستحتاج إلى استخدام جدول بحث لمعرفة ماهية اللاحقة ، والعودة إلى النقطة السابقة ، وتقليم اليسار. Regex هو حل ضعيف هنا. بدلاً من ذلك ، قم بتخزين قائمة اللواحق في قاموس ، ثم اختبرها مقابل اسم المجال الخاص بك ، وقم بإعداد جزء واحد منقط في وقت واحد من اليسار حتى تضغط على المباراة ، ثم أضف الجزء الذي قمت بقطعه للتو.

ملاحظة: كما هو موضح في التعليقات ، لا تعمل هذه الطريقة فعليًا في جميع الحالات. والسبب في ذلك هو أن بعض المجالات ذات المستوى الأعلى يتم حلها إلى عناوين IP ، حتى لو لم يفعل معظمها. لذلك ، لا يمكن اكتشاف ما إذا كان الاسم المعطى هو اسم المجال على المستوى الأعلى أو المزيف فقط فقط عن طريق التحقق مما إذا كان لديه عنوان IP. لسوء الحظ ، ربما يعني هذا أن الحل الوحيد هو قائمة بحث ، بالنظر إلى كيفية تعامل المجالات ذات المستوى الأعلى بشكل غير متسق في الممارسة العملية.

أكرر: لا تعتمد على الكود أدناه للعمل من أجلك. أترك الأمر هنا لأغراض تعليمية فقط.

هناك طريقة للقيام بذلك بدون قائمة بحث. قد تكون القائمة غير موثوقة أو غير مكتملة ، في حين أن هذه الطريقة مضمونة للعمل:

<?php

function get_domain($url) {
    $dots = substr_count($url, '.');
    $domain = '';

    for ($end_pieces = $dots; $end_pieces > 0; $end_pieces--) {
        $test_domain = end(explode('.', $url, $end_pieces));

        if (dns_check_record($test_domain, 'A')) {
            $domain = $test_domain;
            break;
        }
    }

    return $domain;
}

$my_domain = get_domain('www.robknight.org.uk');

echo $my_domain;

?>

في هذه الحالة ، سوف يخرج "robknight.org.uk". سيعمل بشكل جيد على قدم المساواة مع .com أو .edu أو .com.au أو أي مجال آخر من المستوى الأعلى الذي تعمل عليه.

إنه يعمل من خلال البدء من اليمين والقيام بفحص DNS على أول شيء يبدو أنه قد يكون اسمًا للقابل للتطبيق. في المثال أعلاه ، يبدأ بـ "org.uk" ، لكنه يكتشف أن هذا ليس اسم مجال فعلي ، ولكنه CCTLD. ثم ينتقل للتحقق من "robknight.org.uk" ، والتي هو صالح ، ويعيد ذلك. إذا كان اسم المجال قد كان ، على سبيل المثال ، "www.php.net" ، لكان قد بدأ من خلال التحقق من "php.net" ، وهو اسم مجال صالح ، وكان من الممكن أن يعيد ذلك على الفور دون حلق. أود أن أشير أيضًا إلى أنه إذا لم يتم العثور على اسم مجال صالح ، فسيتم إرجاع سلسلة فارغة ('').

قد يكون هذا الرمز غير مناسب لمعالجة عدد كبير من أسماء النطاقات في فترة زمنية قصيرة بسبب الوقت المستغرق لبحث DNS ، ولكنه جيد تمامًا للبحث أو الرمز المفرد الذي ليس محظوظًا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top