<commit_before><?php

/**
 * Project:  TorUtils: PHP classes for interacting with Tor
 * File:     DirectoryClient.php
 *
 * Copyright (c) 2017, <NAME>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * Any modifications to the library should be indicated clearly in the source code
 * to inform users that the changes are not a part of the original software.
 *
 * @copyright 2015 <NAME>
 * @author <NAME> <<EMAIL>>
 *
 */

namespace Dapphp\TorUtils;

require_once 'Parser.php';
require_once 'ProtocolReply.php';

use Dapphp\TorUtils\Parser;
use Dapphp\TorUtils\ProtocolReply;

/**
 * Class for getting router info from Tor directory authorities
 *
 */
class DirectoryClient
{
    /**
     * @var $directoryAuthorities List of directory authorities https://gitweb.torproject.org/tor.git/tree/src/app/config/auth_dirs.inc
     */
    protected $directoryAuthorities = array(
        '7BE683E65D48141321C5ED92F075C55364AC7123' => '172.16.58.3:80', // dannenberg
        '7EA6EAD6FD83083C538F44038BBFA077587DD755' => '192.168.127.12:80', // dizum
        'BA44A889E64B93FAA2B114E02C2A279A8555C533' => '192.168.127.12:9030', // Serge
        'CF6D0AAFB385BE71B8E111FC5CFF4B47923733BC' => '172.16.58.3:80', // Faravahar
        'F2044413DAC2E02E3D6BCF4735A19BCA1DE97281' => '192.168.3.11:80', // gabelmoo
        '74A910646BCEEFBCD2E874FC1DC997430F968145' => '172.16.58.3:80', // longclaw
        'BD6A829255CB08E66FBE7D3748363586E46B3810' => '172.16.17.32:443', // maatuska
        '9695DFC35FFEB861329B9F1AB04C46397020CE31' => '192.168.127.12:9131', // moria1
        '847B1F850344D7876491A54892F904934E4EB85D' => '172.16.31.10:80', // tor26
        '24E2F139121D4394C54B5BCC368B3B411857C413' => '192.168.3.11:80', // bastet
    );

    /**
     * @var array Array of directory fallbacks from https://gitweb.torproject.org/tor.git/tree/src/app/config/fallback_dirs.inc
     */
    protected $directoryFallbacks = array(
        // List updated 2018/12/27 (commit blob 9f60f309f88a7bcfccd3c56b76e583a68fe431c5)
        // NIA = Not In Atlas (atlas.torproject.org) - The fingerprint was not found in Atlas on the date given
        '0111BA9B604669E636FFD5B503F382A4B7AD6E80' => '172.16.58.3:80', // DigiGesTor1e1
        '01A9258A46E97FF8B2CAC7910577862C14F2C524' => '172.16.17.32:9030', // ins0
        '0B85617241252517E8ECF2CFC7F4C1A32DCD153F' => '192.168.3.11:80', // niij02
        '0C039F35C2E40DCB71CD8A07E97C7FD7787D42D6' => '5.200.21.144:80', // libel
        '0C2C599AFCB26F5CFC2C7592435924C1D63D9484' => '172.16.31.10:9030', // ATo
        '0E8C0C8315B66DB5F703804B3889A1DD66C67CE0' => '172.16.58.3:80', // saveyourprivacyex1
        '113143469021882C3A4B82F084F8125B08EE471E' => '172.16.58.3:9030', // parasol
        '11DF0017A43AF1F08825CD5D973297F81AB00FF3' => '172.16.58.3:80', // gGDHjdcC6zAlM8k08lX
        '12AD30E5D25AA67F519780E2111E611A455FDC89' => '172.16.31.10:9030', // mdfnet1
        '136F9299A5009A4E0E96494E723BDB556FB0A26B' => '172.16.17.32:80', // bakunin2
        '14419131033443AE6E21DA82B0D307F7CAE42BDB' => '172.16.58.3:110', // PedicaboMundi
        '14877C6384A9E793F422C8D1DDA447CACA4F7C4B' => '172.16.17.32:10009', // niftywoodmouse
        '1576BE143D8727745BB2BCDDF183291B3C3EFEFC' => '172.16.58.3:8080', // anotherone
        '15BE17C99FACE24470D40AF782D6A9C692AB36D6' => '172.16.31.10:9030', // rofltor07
        '185F2A57B0C4620582602761097D17DB81654F70' => '192.168.3.11:9030', // BoingBoing
        '1938EBACBB1A7BFA888D9623C90061130E63BB3F' => '192.168.3.11:9030', // Aerodynamik04
        '1AE039EE0B11DB79E4B4B29CBA9F752864A0259E' => '172.16.58.3:9001', // Ichotolot60
        '1C90D3AEADFF3BCD079810632C8B85637924A58E' => '172.16.58.3:143', // Multivac
        '1F6ABD086F40B890A33C93CC4606EE68B31C9556' => '192.168.127.12:80', // dao
        '20462CBA5DA4C2D963567D17D0B7249718114A68' => '192.168.3.11:9030', // scaletor
        '230A8B2A8BA861210D9B4BA97745AEC217A94207' => '172.16.31.10:80', // niij01
        '24E91955D969AEA1D80413C64FE106FAE7FD2EA9' => '172.16.58.3:10008', // niftymouse
        '2BA2C8E96B2590E1072AECE2BDB5C48921BF8510' => '192.168.127.12:9012', // storm
        '2CDCFED0142B28B002E89D305CBA2E26063FADE2' => '172.16.31.10:80', // jaures
        '2F0F32AB1E5B943CA7D062C03F18960C86E70D94' => '192.168.3.11:9030', // Minotaur
        '311A4533F7A2415F42346A6C8FA77E6FD279594C' => '172.16.31.10:8080', // DigiGesTor3e2
        '322C6E3A973BC10FC36DE3037AD27BC89F14723B' => '172.16.17.32:8080', // bauruine204
        '330CD3DB6AD266DC70CDB512B036957D03D9BC59' => '172.16.58.3:80', // TeamTardis
        '360CBA08D1E24F513162047BDB54A1015E531534' => '172.16.17.32:9030', // Aerodynamik06
        '361D33C96D0F161275EE67E2C91EE10B276E778B' => '172.16.58.3:9030', // cxx4freedom
        '36B9E7AC1E36B62A9D6F330ABEB6012BA7F0D400' => '172.16.17.32:9030', // kimsufi321
        '375DCBB2DBD94E5263BC0C015F0C9E756669617E' => '172.16.58.3:80', // ebola
        '387B065A38E4DAA16D9D41C2964ECBC4B31D30FF' => '172.16.17.32:9130', // redjohn1
        '39F096961ED2576975C866D450373A9913AFDC92' => '192.168.127.12:80', // thomas
        '3F092986E9B87D3FDA09B71FA3A602378285C77A' => '172.16.17.32:9030', // NYCBUG1
        '4061C553CA88021B8302F0814365070AAE617270' => '172.16.31.10:9030', // TorExitRomania
        '41A3C16269C7B63DB6EB741DBDDB4E1F586B1592' => '192.168.3.11:9030', // rofltor02
        '41C59606AFE1D1AA6EC6EF6719690B856F0B6587' => '172.16.17.32:9030', // TorExitMoldova2
        '45362E8ECD651CCAC521156FFBD2FF7F27FA8E88' => '172.16.58.3:80', // torpidsDEisppro2
        '4623A9EC53BFD83155929E56D6F7B55B5E718C24' => '172.16.58.3:8080', // Cotopaxi
        '4661DE96D3F8E923994B05218F23760C8D7935A4' => '172.16.17.32:9030', // toritounam
        '46791D156C9B6C255C2665D4D8393EC7DBAA7798' => '192.168.3.11:80', // KrigHaBandolo
        '47C42E2094EE482E7C9B586B10BABFB67557030B' => '192.168.3.11:10034', // niftysugarglider
        '484A10BA2B8D48A5F0216674C8DD50EF27BC32F3' => '192.168.3.11:9030', // Aerodynamik03
        '4CC9CC9195EC38645B699A33307058624F660CCF' => '172.16.31.10:9002', // devsum
        '4EB55679FA91363B97372554F8DC7C63F4E5B101' => '172.16.17.32:80', // torpidsDEisppro
        '50586E25BE067FD1F739998550EDDCB1A14CA5B2' => '192.168.127.12:9030', // Jans
        '51E1CF613FD6F9F11FE24743C91D6F9981807D82' => '172.16.58.3:80', // torpidsDEisppro3
        '52BFADA8BEAA01BA46C8F767F83C18E2FE50C1B9' => '172.16.58.3:995', // BeastieJoy63
        '547DA56F6B88B6C596B3E3086803CDA4F0EF8F21' => '172.16.58.3:80', // chaucer
        '557ACEC850F54EEE65839F83CACE2B0825BE811E' => '192.168.127.12:80', // ogopogo
        '587E0A9552E4274B251F29B5B2673D38442EE4BF' => '172.16.17.32:80', // Nuath
        '58ED9C9C35E433EE58764D62892B4FFD518A3CD0' => '172.16.17.32:9030', // SamAAdams2
        '5CF8AFA5E4B0BB88942A44A3F3AAE08C3BDFD60B' => '172.16.58.3:80', // jaures4
        '5E56738E7F97AA81DEEF59AF28494293DFBFCCDF' => '172.16.58.3:80', // Backplane
        '609E598FB6A00BCF7872906B602B705B64541C50' => '172.16.31.10:10028', // niftychipmunk
        '68F175CCABE727AA2D2309BCD8789499CEE36ED7' => '172.16.17.32:8080', // Pichincha
        '6EF897645B79B6CB35E853B32506375014DE3621' => '172.16.17.32:80', // d6relay
        '7088D485934E8A403B81531F8C90BDC75FA43C98' => '192.168.127.12:9030', // Basil
        '70C55A114C0EF3DC5784A4FAEE64388434A3398F' => '172.16.17.32:80', // torpidsFRplusserver
        '71CFDEB4D9E00CCC3E31EC4E8A29E109BBC1FB36' => '192.168.3.11:10030', // niftypedetidae
        '72B2B12A3F60408BDBC98C6DF53988D3A0B3F0EE' => '192.168.127.12:80', // TykRelay01
        '7600680249A22080ECC6173FBBF64D6FCF330A61' => '172.16.31.10:9001', // Ichotolot62
        '775B0FAFDE71AADC23FFC8782B7BEB1D5A92733E' => '192.168.3.11:9030', // Aerodynamik01
        '7BB70F8585DFC27E75D692970C0EEB0F22983A63' => '192.168.3.11:80', // torproxy02
        '7D05A38E39FC5D29AFE6BE487B9B4DC9E635D09E' => '192.168.127.12:80', // saveyourprivacyexit
        '80AAF8D5956A43C197104CEF2550CD42D165C6FB' => '172.16.31.10:9031', // mdfnet2
        '8101421BEFCCF4C271D5483C5AABCAAD245BBB9D' => '172.16.58.3:9030', // rofltor01
        '81AFA888F8F8F4A024AB58ECA0ADDEBB93FF01DA' => '172.16.17.32:80', // torpidsUAitlas
        '81B75D534F91BFB7C57AB67DA10BCEF622582AE8' => '172.16.31.10:80', // hviv104
        '823AA81E277F366505545522CEDC2F529CE4DC3F' => '172.16.31.10:80', // snowfall
        '844AE9CAD04325E955E2BE1521563B79FE7094B7' => '172.16.58.3:9030', // Smeerboel
        '8456DFA94161CDD99E480C2A2992C366C6564410' => '172.16.17.32:80', // turingmachine
        '86C281AD135058238D7A337D546C902BE8505DDE' => '192.168.127.12:80', // TykRelay05
        '8844D87E9B038BE3270938F05AF797E1D3C74C0F' => '172.16.17.32:9030', // BARACUDA
        '8B6556601612F1E2AFCE2A12FFFAF8482A76DD1F' => '192.168.127.12:9030', // titania1
        '8C00FA7369A7A308F6A137600F0FA07990D9D451' => '172.16.58.3:9030', // GrmmlLitavis
        '8FA37B93397015B2BC5A525C908485260BE9F422' => '192.168.127.12:9030', // Doedel22
        '91D23D8A539B83D2FB56AA67ECD4D75CC093AC55' => '192.168.3.11:80', // torpidsFRovh
        '9231DF741915AA1630031A93026D88726877E93A' => '192.168.3.11:9030', // PrisnCellRelayFR1
        '92412EA1B9AA887D462B51D816777002F4D58907' => '172.16.58.3:9030', // Aerodynamik05
        '924B24AFA7F075D059E8EEB284CC400B33D3D036' => '172.16.17.32:80', // NSDFreedom
        '92CFD9565B24646CAC2D172D3DB503D69E777B8A' => '193.234.15.57:80', // bakunin
        '94C4B7B8C50C86A92B6A20107539EE2678CF9A28' => '192.168.3.11:80', // BostonUCompSci
        '9772EFB535397C942C3AB8804FB35CFFAD012438' => '192.168.127.12:9030', // smallsweatnode
        '99E246DB480B313A3012BC3363093CC26CD209C7' => '172.16.31.10:31336', // ViDiSrv
        '9A0D54D3A6D2E0767596BF1515E6162A75B3293F' => '192.168.3.11:9030', // gordonkeybag
        '9A68B85A02318F4E7E87F2828039FBD5D75B0142' => '172.16.31.10:9030', // NYCBUG0
        '9B31F1F1C1554F9FFB3455911F82E818EF7C7883' => '172.16.58.3:9030', // TorExitFinland
        '9C900A7F6F5DD034CFFD192DAEC9CCAA813DB022' => '172.16.17.32:9030', // firstor2
        '9EAD5B2D3DBD96DBC80DCE423B0C345E920A758D' => '172.16.31.10:80', // Digitalcourage3ip1
        '9F7D6E6420183C2B76D3CE99624EBC98A21A967E' => '172.16.58.3:80', // Nivrim
        'A0F06C2FADF88D3A39AA3072B406F09D7095AC9E' => '172.16.31.10:80', // Dhalgren
        'A10C4F666D27364036B562823E5830BC448E046A' => '172.16.17.32:80', // DFRI1
        'A2A6616723B511D8E068BB71705191763191F6B2' => '172.16.31.10:80', // otheontelth
        'A2E6BB5C391CD46B38C55B4329C35304540771F1' => '172.16.58.3:993', // BeastieJoy62
        'A478E421F83194C114F41E94F95999672AED51FE' => '172.16.17.32:80', // DFRI4
        'A4C98CEA3F34E05299417E9F885A642C88EF6029' => '172.16.58.3:80', // jaures2
        'A53C46F5B157DD83366D45A8E99A244934A14C46' => '172.16.17.32:80', // csailmitexit
        'AA0D167E03E298F9A8CD50F448B81FBD7FA80D56' => '172.16.31.10:80', // rejozenger
        'AC66FFA4AB35A59EBBF5BF4C70008BF24D8A7A5C' => '172.16.58.3:80', // torpidsFRonline3
        'ACD889D86E02EDDAB1AFD81F598C0936238DC6D0' => '192.168.127.12:80', // ph3x
        'ACDD9E85A05B127BA010466C13C8C47212E8A38F' => '192.168.127.12:9030', // kramse
        'AD19490C7DBB26D3A68EFC824F67E69B0A96E601' => '192.168.3.11:9030', // sputnik
        'ADB2C26629643DBB9F8FE0096E7D16F9414B4F8D' => '172.16.31.10:80', // Digitalcourage3ip2
        'AEDAC7081AE14B8D241ECF0FF17A2858AB4383D0' => '192.168.127.12:9030', // linss
        'B0553175AADB0501E5A61FC61CEA3970BE130FF2' => '192.168.3.11:9030', // zwiubel
        'B06F093A3D4DFAD3E923F4F28A74901BD4F74EB1' => '172.16.17.32:9030', // TorExitMoldova
        'B143D439B72D239A419F8DCE07B8A8EB1B486FA7' => '172.16.58.3:80', // wardsback
        'B291D30517D23299AD7CEE3E60DFE60D0E3A4664' => '192.168.3.11:80', // TorKIT
        'B44FBE5366AD98B46D829754FA4AC599BAE41A6A' => '172.16.58.3:80', // jaures3
        'B5212DB685A2A0FCFBAE425738E478D12361710D' => '172.16.31.10:9030', // firstor
        'B6904ADD4C0D10CDA7179E051962350A69A63243' => '192.168.3.11:443', // torzabehlice
        'B771AA877687F88E6F1CA5354756DF6C8A7B6B24' => '192.168.127.12:10032', // niftypika
        'B83DC1558F0D34353BB992EF93AFEAFDB226A73E' => '172.16.17.32:9032', // mdfnet3
        'B84F248233FEA90CAD439F292556A3139F6E1B82' => '192.168.127.12:444', // tollana
        'B86137AE9681701901C6720E55C16805B46BD8E3' => '172.16.58.3:1080', // BeastieJoy60
        'BD552C165E2ED2887D3F1CCE9CFF155DDA2D86E6' => '192.168.3.11:9030', // Schakalium
        'BF0FB582E37F738CD33C3651125F2772705BB8E8' => '192.168.127.12:9030', // quadhead
        'BF735F669481EE1CCC348F0731551C933D1E2278' => '172.16.31.10:9030', // Freeway1a1
        'C0192FF43E777250084175F4E59AC1BA2290CE38' => '172.16.31.10:80', // manipogo
        'C08DE49658E5B3CFC6F2A952B453C4B608C9A16A' => '172.16.17.32:10006', // niftyvolcanorabbit
        'C2AAB088555850FC434E68943F551072042B85F1' => '192.168.3.11:80', // Digitalcourage3ip3
        'C37BC191AC389179674578C3E6944E925FE186C2' => '172.16.58.3:1338', // xzdsb
        'C414F28FD2BEC1553024299B31D4E726BEB8E788' => '172.16.58.3:1433', // zebra620
        'C4AEA05CF380BAD2230F193E083B8869B4A29937' => '172.16.17.32:80', // bakunin4
        'C793AB88565DDD3C9E4C6F15CCB9D8C7EF964CE9' => '192.168.127.12:443', // ori
        'C90CA3B7FE01A146B8268D56977DC4A2C024B9EA' => '192.168.127.12:80', // cowcat
        'CBD0D1BD110EC52963082D839AC6A89D0AE243E7' => '192.168.127.12:9030', // UV74S7mjxRcYVrGsAMw
        'CE47F0356D86CF0A1A2008D97623216D560FB0A8' => '172.16.31.10:465', // BeastieJoy61
        'D30E9D4D639068611D6D96861C95C2099140B805' => '172.16.17.32:9030', // mine
        'D405FCCF06ADEDF898DF2F29C9348DCB623031BA' => '192.168.3.11:80', // gGDHjdcC6zAlM8k08lY
        'D5039E1EBFD96D9A3F9846BF99EC9F75EDDE902A' => '172.16.31.10:9030', // Janky328891
        'D6BA940D3255AB40DC5EE5B0B285FA143E1F9865' => '192.168.127.12:80', // Cosworth02
        'D71B1CA1C9DC7E8CA64158E106AD770A21160FEE' => '172.16.31.10:9265', // lqdn
        'D8B7A3A6542AA54D0946B9DC0257C53B6C376679' => '172.16.17.32:9030', // sif
        'DAA39FC00B196B353C2A271459C305C429AF09E4' => '172.16.58.3:9030', // Arne
        'DB2682153AC0CCAECD2BD1E9EBE99C6815807A1E' => '192.168.127.12:80', // GermanCraft2
        'DD823AFB415380A802DCAEB9461AE637604107FB' => '172.16.58.3:80', // grenouille
        'DD8BD7307017407FCC36F8D04A688F74A0774C02' => '192.168.3.11:80', // DFRI0
        'DDBB2A38252ADDA53E4492DDF982CA6CC6E10EC0' => '192.168.127.12:80', // zouzounella
        'DED6892FF89DBD737BA689698A171B2392EB3E82' => '172.16.31.10:80', // ThorExit
        'E51620B90DCB310138ED89EDEDD0A5C361AAE24E' => '192.168.127.12:9030', // NormalCitizen
        'E81EF60A73B3809F8964F73766B01BAA0A171E20' => '172.16.17.32:8080', // Chimborazo
        'EB80A8D52F07238B576C42CEAB98ADD084EE075E' => '172.16.58.3:80', // Cosworth01
        'ED2338CAC2711B3E331392E1ED2831219B794024' => '192.168.127.12:9030', // SEC6xFreeBSD64
        'EFEACD781604EB80FBC025EDEDEA2D523AEAAA2F' => '172.16.17.32:9030', // Aerodynamik02
        'F10BDE279AE71515DDCCCC61DC19AC8765F8A3CC' => '172.16.17.32:80', // ParkBenchInd001
        'F2DFE5FA1E4CF54F8E761A6D304B9B4EC69BDAE8' => '192.168.127.12:80', // AlleKochenKaffee
        'F4263275CF54A6836EE7BD527B1328836A6F06E1' => '172.16.17.32:80', // EvilMoe
        'F6A358DD367B3282D6EF5824C9D45E1A19C7E815' => '192.168.3.11:80', // prawksi
        'F741E5124CB12700DA946B78C9B2DD175D6CD2A1' => '192.168.3.11:9030', // rofltor06
        'F8D27B163B9247B232A2EEE68DD8B698695C28DE' => '192.168.3.11:443', // fluxe3
        'F9246DEF2B653807236DA134F2AEAB103D58ABFE' => '192.168.127.12:80', // Freebird31
        'F93D8F37E35C390BCAD9F9069E13085B745EC216' => '192.168.127.12:80', // TykRelay06
        'FC9AC8EA0160D88BCCFDE066940D7DD9FA45495B' => '192.168.127.12:80', // ph3x
        'FE296180018833AF03A8EACD5894A614623D3F76' => '192.168.127.12:9030', // PyotrTorpotkinOne
    );

    protected $preferredServer;

    protected $connectTimeout = 5;
    protected $readTimeout = 30;
    protected $userAgent = 'dapphp/TorUtils 1.1.10';

    protected $parser;
    protected $serverList;

    /**
     * DirectoryClient constructor
     */
    public function __construct()
    {
        $this->serverList = array_merge($this->directoryAuthorities, $this->directoryFallbacks);
        shuffle($this->serverList);

        $this->parser = new Parser();
    }

    /**
     * Set the preferred directory server to use for lookups.  This server will always be used
     * first.  If the preferred server times out or fails, the lookup will proceed using a random
     * server from the list of directory authorities and fallbacks.
     *
     * @param string $server The directory server to connect to (e.g. 192.168.3.11:80)
     * @return \Dapphp\TorUtils\DirectoryClient
     */<commit_msg>Update directory auth fallbacks; remove invalid relays<commit_after><?php

/**
 * Project:  TorUtils: PHP classes for interacting with Tor
 * File:     DirectoryClient.php
 *
 * Copyright (c) 2017, <NAME>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * Any modifications to the library should be indicated clearly in the source code
 * to inform users that the changes are not a part of the original software.
 *
 * @copyright 2015 <NAME>
 * @author <NAME> <<EMAIL>>
 *
 */

namespace Dapphp\TorUtils;

require_once 'Parser.php';
require_once 'ProtocolReply.php';

use Dapphp\TorUtils\Parser;
use Dapphp\TorUtils\ProtocolReply;

/**
 * Class for getting router info from Tor directory authorities
 *
 */
class DirectoryClient
{
    /**
     * @var array $directoryAuthorities List of directory authorities https://gitweb.torproject.org/tor.git/tree/src/app/config/auth_dirs.inc
     */
    protected $directoryAuthorities = array(
        '7BE683E65D48141321C5ED92F075C55364AC7123' => '172.16.58.3:80', // dannenberg
        '7EA6EAD6FD83083C538F44038BBFA077587DD755' => '192.168.127.12:80', // dizum
        'BA44A889E64B93FAA2B114E02C2A279A8555C533' => '192.168.127.12:9030', // Serge
        'CF6D0AAFB385BE71B8E111FC5CFF4B47923733BC' => '172.16.58.3:80', // Faravahar
        'F2044413DAC2E02E3D6BCF4735A19BCA1DE97281' => '192.168.3.11:80', // gabelmoo
        '74A910646BCEEFBCD2E874FC1DC997430F968145' => '172.16.58.3:80', // longclaw
        'BD6A829255CB08E66FBE7D3748363586E46B3810' => '172.16.17.32:443', // maatuska
        '9695DFC35FFEB861329B9F1AB04C46397020CE31' => '192.168.127.12:9131', // moria1
        '847B1F850344D7876491A54892F904934E4EB85D' => '172.16.31.10:80', // tor26
        '24E2F139121D4394C54B5BCC368B3B411857C413' => '192.168.3.11:80', // bastet
    );

    /**
     * @var array Array of directory fallbacks from https://gitweb.torproject.org/tor.git/tree/src/app/config/fallback_dirs.inc
     */
    protected $directoryFallbacks = array(
        // List updated 2019/05/25 (commit blob 9f60f309f88a7bcfccd3c56b76e583a68fe431c5)
        // NIA = Not In Atlas (atlas.torproject.org) - The fingerprint was not found in Atlas on the date given
        // RF = Read failed when trying to query for directory info on the date given.
        // Exit Relay = This is a busy exit relay so we should not bug it for directory info.
        '0111BA9B604669E636FFD5B503F382A4B7AD6E80' => '172.16.58.3:80', // DigiGesTor1e1
        //'01A9258A46E97FF8B2CAC7910577862C14F2C524' => '172.16.17.32:9030', // ins0 (NIA - 2019/05/25)
        '0B85617241252517E8ECF2CFC7F4C1A32DCD153F' => '192.168.3.11:80', // niij02
        '0C039F35C2E40DCB71CD8A07E97C7FD7787D42D6' => '192.168.127.12:80', // libel
        //'0C2C599AFCB26F5CFC2C7592435924C1D63D9484' => '172.16.31.10:9030', // ATo (NIA - 2019/05/25)
        '0E8C0C8315B66DB5F703804B3889A1DD66C67CE0' => '172.16.58.3:80', // saveyourprivacyex1
        '113143469021882C3A4B82F084F8125B08EE471E' => '172.16.58.3:9030', // parasol
        '11DF0017A43AF1F08825CD5D973297F81AB00FF3' => '172.16.58.3:80', // gGDHjdcC6zAlM8k08lX
        '12AD30E5D25AA67F519780E2111E611A455FDC89' => '172.16.31.10:9030', // mdfnet1
        //'136F9299A5009A4E0E96494E723BDB556FB0A26B' => '172.16.17.32:80', // bakunin2 (NIA - 2019/05/25)
        //'14419131033443AE6E21DA82B0D307F7CAE42BDB' => '172.16.58.3:110', // PedicaboMundi (NIA - 2019/05/25)
        //'14877C6384A9E793F422C8D1DDA447CACA4F7C4B' => '172.16.17.32:10009', // niftywoodmouse (NIA - 2019/05/25)
        //'1576BE143D8727745BB2BCDDF183291B3C3EFEFC' => '172.16.58.3:8080', // anotherone (NIA - 2019/05/25)
        '15BE17C99FACE24470D40AF782D6A9C692AB36D6' => '172.16.31.10:9030', // rofltor07
        '185F2A57B0C4620582602761097D17DB81654F70' => '192.168.3.11:9030', // BoingBoing
        '1938EBACBB1A7BFA888D9623C90061130E63BB3F' => '192.168.3.11:9030', // Aerodynamik04
        '1AE039EE0B11DB79E4B4B29CBA9F752864A0259E' => '172.16.58.3:9001', // Ichotolot60
        '1C90D3AEADFF3BCD079810632C8B85637924A58E' => '172.16.58.3:143', // Multivac
        '1F6ABD086F40B890A33C93CC4606EE68B31C9556' => '192.168.127.12:80', // dao
        '20462CBA5DA4C2D963567D17D0B7249718114A68' => '192.168.3.11:9030', // scaletor
        '230A8B2A8BA861210D9B4BA97745AEC217A94207' => '172.16.31.10:80', // niij01
        //'24E91955D969AEA1D80413C64FE106FAE7FD2EA9' => '172.16.58.3:10008', // niftymouse (NIA - 2019/05/25)
        '2BA2C8E96B2590E1072AECE2BDB5C48921BF8510' => '192.168.127.12:9012', // storm
        //'2CDCFED0142B28B002E89D305CBA2E26063FADE2' => '172.16.31.10:80', // jaures (NIA - 2019/05/25)
        '2F0F32AB1E5B943CA7D062C03F18960C86E70D94' => '192.168.3.11:9030', // Minotaur
        '311A4533F7A2415F42346A6C8FA77E6FD279594C' => '172.16.31.10:8080', // DigiGesTor3e2
        '322C6E3A973BC10FC36DE3037AD27BC89F14723B' => '172.16.17.32:8080', // bauruine204
        '330CD3DB6AD266DC70CDB512B036957D03D9BC59' => '172.16.58.3:80', // TeamTardis
        //'360CBA08D1E24F513162047BDB54A1015E531534' => '172.16.17.32:9030', // Aerodynamik06 (NIA - 2019/05/25)
        '361D33C96D0F161275EE67E2C91EE10B276E778B' => '172.16.58.3:9030', // cxx4freedom
        //'36B9E7AC1E36B62A9D6F330ABEB6012BA7F0D400' => '172.16.17.32:9030', // kimsufi321 (NIA - 2019/05/25)
        '375DCBB2DBD94E5263BC0C015F0C9E756669617E' => '172.16.58.3:80', // ebola
        //'387B065A38E4DAA16D9D41C2964ECBC4B31D30FF' => '172.16.17.32:9130', // redjohn1 (NIA - 2019/05/25)
        //'39F096961ED2576975C866D450373A9913AFDC92' => '192.168.127.12:80', // thomas (NIA - 2019/05/25)
        '3F092986E9B87D3FDA09B71FA3A602378285C77A' => '172.16.17.32:9030', // NYCBUG1
        '4061C553CA88021B8302F0814365070AAE617270' => '172.16.31.10:9030', // TorExitRomania
        '41A3C16269C7B63DB6EB741DBDDB4E1F586B1592' => '192.168.3.11:9030', // rofltor02
        //'41C59606AFE1D1AA6EC6EF6719690B856F0B6587' => '172.16.17.32:9030', // TorExitMoldova2 (NIA - 2019/05/25)
        //'45362E8ECD651CCAC521156FFBD2FF7F27FA8E88' => '172.16.58.3:80', // torpidsDEisppro2 (NIA - 2019/05/25)
        '4623A9EC53BFD83155929E56D6F7B55B5E718C24' => '172.16.58.3:8080', // Cotopaxi
        '4661DE96D3F8E923994B05218F23760C8D7935A4' => '172.16.17.32:9030', // toritounam
        '46791D156C9B6C255C2665D4D8393EC7DBAA7798' => '192.168.3.11:80', // KrigHaBandolo
        '47C42E2094EE482E7C9B586B10BABFB67557030B' => '192.168.3.11:10034', // niftysugarglider
        '484A10BA2B8D48A5F0216674C8DD50EF27BC32F3' => '192.168.3.11:9030', // Aerodynamik03
        //'4CC9CC9195EC38645B699A33307058624F660CCF' => '172.16.31.10:9002', // devsum (NIA - 2019/05/25)
        '4EB55679FA91363B97372554F8DC7C63F4E5B101' => '172.16.17.32:80', // torpidsDEisppro
        '50586E25BE067FD1F739998550EDDCB1A14CA5B2' => '192.168.127.12:9030', // Jans
        '51E1CF613FD6F9F11FE24743C91D6F9981807D82' => '172.16.58.3:80', // torpidsDEisppro3
        '52BFADA8BEAA01BA46C8F767F83C18E2FE50C1B9' => '172.16.58.3:995', // BeastieJoy63
        '547DA56F6B88B6C596B3E3086803CDA4F0EF8F21' => '172.16.58.3:80', // chaucer
        '557ACEC850F54EEE65839F83CACE2B0825BE811E' => '192.168.127.12:80', // ogopogo
        //'587E0A9552E4274B251F29B5B2673D38442EE4BF' => '172.16.17.32:80', // Nuath (NIA - 2019/05/25)
        '58ED9C9C35E433EE58764D62892B4FFD518A3CD0' => '172.16.17.32:9030', // SamAAdams2
        //'5CF8AFA5E4B0BB88942A44A3F3AAE08C3BDFD60B' => '172.16.58.3:80', // jaures4 (NIA - 2019/05/25)
        '5E56738E7F97AA81DEEF59AF28494293DFBFCCDF' => '172.16.58.3:80', // Backplane
        '609E598FB6A00BCF7872906B602B705B64541C50' => '172.16.31.10:10028', // niftychipmunk
        '68F175CCABE727AA2D2309BCD8789499CEE36ED7' => '172.16.17.32:8080', // Pichincha
        '6EF897645B79B6CB35E853B32506375014DE3621' => '172.16.17.32:80', // d6relay
        '7088D485934E8A403B81531F8C90BDC75FA43C98' => '192.168.127.12:9030', // Basil
        '70C55A114C0EF3DC5784A4FAEE64388434A3398F' => '172.16.17.32:80', // torpidsFRplusserver
        '71CFDEB4D9E00CCC3E31EC4E8A29E109BBC1FB36' => '192.168.3.11:10030', // niftypedetidae
        '72B2B12A3F60408BDBC98C6DF53988D3A0B3F0EE' => '192.168.127.12:80', // TykRelay01
        '7600680249A22080ECC6173FBBF64D6FCF330A61' => '172.16.31.10:9001', // Ichotolot62
        '775B0FAFDE71AADC23FFC8782B7BEB1D5A92733E' => '192.168.3.11:9030', // Aerodynamik01
        '7BB70F8585DFC27E75D692970C0EEB0F22983A63' => '192.168.3.11:80', // torproxy02
        //'7D05A38E39FC5D29AFE6BE487B9B4DC9E635D09E' => '192.168.127.12:80', // saveyourprivacyexit (NIA - 2019/05/25)
        '80AAF8D5956A43C197104CEF2550CD42D165C6FB' => '172.16.31.10:9031', // mdfnet2
        '8101421BEFCCF4C271D5483C5AABCAAD245BBB9D' => '172.16.58.3:9030', // rofltor01
        '81AFA888F8F8F4A024AB58ECA0ADDEBB93FF01DA' => '172.16.17.32:80', // torpidsUAitlas
        '81B75D534F91BFB7C57AB67DA10BCEF622582AE8' => '172.16.31.10:80', // hviv104
        '823AA81E277F366505545522CEDC2F529CE4DC3F' => '172.16.31.10:80', // snowfall
        '844AE9CAD04325E955E2BE1521563B79FE7094B7' => '172.16.58.3:9030', // Smeerboel
        '8456DFA94161CDD99E480C2A2992C366C6564410' => '172.16.17.32:80', // turingmachine
        '86C281AD135058238D7A337D546C902BE8505DDE' => '192.168.127.12:80', // TykRelay05
        '8844D87E9B038BE3270938F05AF797E1D3C74C0F' => '172.16.17.32:9030', // BARACUDA
        //'8B6556601612F1E2AFCE2A12FFFAF8482A76DD1F' => '192.168.127.12:9030', // titania1 (NIA - 2019/05/25)
        '8C00FA7369A7A308F6A137600F0FA07990D9D451' => '172.16.58.3:9030', // GrmmlLitavis
        '8FA37B93397015B2BC5A525C908485260BE9F422' => '192.168.127.12:9030', // Doedel22
        '91D23D8A539B83D2FB56AA67ECD4D75CC093AC55' => '192.168.3.11:80', // torpidsFRovh
        '9231DF741915AA1630031A93026D88726877E93A' => '192.168.3.11:9030', // PrisnCellRelayFR1
        //'92412EA1B9AA887D462B51D816777002F4D58907' => '172.16.58.3:9030', // Aerodynamik05 (NIA - 2019/05/25)
        '924B24AFA7F075D059E8EEB284CC400B33D3D036' => '172.16.17.32:80', // NSDFreedom
        //'92CFD9565B24646CAC2D172D3DB503D69E777B8A' => '172.16.58.3:80', // bakunin (NIA - 2019/05/25)
        '94C4B7B8C50C86A92B6A20107539EE2678CF9A28' => '192.168.3.11:80', // BostonUCompSci
        '9772EFB535397C942C3AB8804FB35CFFAD012438' => '192.168.127.12:9030', // smallsweatnode
        '99E246DB480B313A3012BC3363093CC26CD209C7' => '172.16.31.10:31336', // ViDiSrv
        '9A0D54D3A6D2E0767596BF1515E6162A75B3293F' => '192.168.3.11:9030', // gordonkeybag
        '9A68B85A02318F4E7E87F2828039FBD5D75B0142' => '172.16.31.10:9030', // NYCBUG0
        '9B31F1F1C1554F9FFB3455911F82E818EF7C7883' => '172.16.58.3:9030', // TorExitFinland
        '9C900A7F6F5DD034CFFD192DAEC9CCAA813DB022' => '172.16.17.32:9030', // firstor2
        '9EAD5B2D3DBD96DBC80DCE423B0C345E920A758D' => '172.16.31.10:80', // Digitalcourage3ip1
        '9F7D6E6420183C2B76D3CE99624EBC98A21A967E' => '172.16.58.3:80', // Nivrim
        'A0F06C2FADF88D3A39AA3072B406F09D7095AC9E' => '172.16.31.10:80', // Dhalgren
        'A10C4F666D27364036B562823E5830BC448E046A' => '172.16.17.32:80', // DFRI1
        //'A2A6616723B511D8E068BB71705191763191F6B2' => '172.16.31.10:80', // otheontelth (NIA - 2019/05/25)
        'A2E6BB5C391CD46B38C55B4329C35304540771F1' => '172.16.58.3:993', // BeastieJoy62
        'A478E421F83194C114F41E94F95999672AED51FE' => '172.16.17.32:80', // DFRI4
        //'A4C98CEA3F34E05299417E9F885A642C88EF6029' => '172.16.58.3:80', // jaures2 (NIA - 2019/05/25)
        //'A53C46F5B157DD83366D45A8E99A244934A14C46' => '172.16.17.32:80', // csailmitexit (NIA - 2019/05/25)
        //'AA0D167E03E298F9A8CD50F448B81FBD7FA80D56' => '172.16.31.10:80', // rejozenger (NIA - 2019/05/25)
        'AC66FFA4AB35A59EBBF5BF4C70008BF24D8A7A5C' => '172.16.58.3:80', // torpidsFRonline3
        'ACD889D86E02EDDAB1AFD81F598C0936238DC6D0' => '192.168.127.12:80', // ph3x
        'ACDD9E85A05B127BA010466C13C8C47212E8A38F' => '192.168.127.12:9030', // kramse
        'AD19490C7DBB26D3A68EFC824F67E69B0A96E601' => '192.168.3.11:9030', // sputnik
        'ADB2C26629643DBB9F8FE0096E7D16F9414B4F8D' => '172.16.31.10:80', // Digitalcourage3ip2
        'AEDAC7081AE14B8D241ECF0FF17A2858AB4383D0' => '192.168.127.12:9030', // linss
        'B0553175AADB0501E5A61FC61CEA3970BE130FF2' => '192.168.3.11:9030', // zwiubel
        'B06F093A3D4DFAD3E923F4F28A74901BD4F74EB1' => '172.16.17.32:9030', // TorExitMoldova
        'B143D439B72D239A419F8DCE07B8A8EB1B486FA7' => '172.16.58.3:80', // wardsback
        'B291D30517D23299AD7CEE3E60DFE60D0E3A4664' => '192.168.3.11:80', // TorKIT
        //'B44FBE5366AD98B46D829754FA4AC599BAE41A6A' => '172.16.58.3:80', // jaures3 (NIA - 2019/05/25)
        'B5212DB685A2A0FCFBAE425738E478D12361710D' => '172.16.31.10:9030', // firstor
        //'B6904ADD4C0D10CDA7179E051962350A69A63243' => '192.168.3.11:443', // torzabehlice (NIA - 2019/05/25)
        'B771AA877687F88E6F1CA5354756DF6C8A7B6B24' => '192.168.127.12:10032', // niftypika
        'B83DC1558F0D34353BB992EF93AFEAFDB226A73E' => '172.16.17.32:9032', // mdfnet3
        'B84F248233FEA90CAD439F292556A3139F6E1B82' => '192.168.127.12:444', // tollana
        'B86137AE9681701901C6720E55C16805B46BD8E3' => '172.16.58.3:1080', // BeastieJoy60
        'BD552C165E2ED2887D3F1CCE9CFF155DDA2D86E6' => '192.168.3.11:9030', // Schakalium
        'BF0FB582E37F738CD33C3651125F2772705BB8E8' => '192.168.127.12:9030', // quadhead
        //'BF735F669481EE1CCC348F0731551C933D1E2278' => '172.16.31.10:9030', // Freeway1a1 (NIA - 2019/05/25)
        'C0192FF43E777250084175F4E59AC1BA2290CE38' => '172.16.31.10:80', // manipogo
        'C08DE49658E5B3CFC6F2A952B453C4B608C9A16A' => '172.16.17.32:10006', // niftyvolcanorabbit
        'C2AAB088555850FC434E68943F551072042B85F1' => '192.168.3.11:80', // Digitalcourage3ip3
        //'C37BC191AC389179674578C3E6944E925FE186C2' => '172.16.58.3:1338', // xzdsb (NIA - 2019/05/25)
        'C414F28FD2BEC1553024299B31D4E726BEB8E788' => '172.16.58.3:1433', // zebra620
        //'C4AEA05CF380BAD2230F193E083B8869B4A29937' => '172.16.17.32:80', // bakunin4 (NIA - 2019/05/25)
        'C793AB88565DDD3C9E4C6F15CCB9D8C7EF964CE9' => '192.168.127.12:443', // ori
        'C90CA3B7FE01A146B8268D56977DC4A2C024B9EA' => '192.168.127.12:80', // cowcat
        'CBD0D1BD110EC52963082D839AC6A89D0AE243E7' => '192.168.127.12:9030', // UV74S7mjxRcYVrGsAMw
        'CE47F0356D86CF0A1A2008D97623216D560FB0A8' => '172.16.31.10:465', // BeastieJoy61
        'D30E9D4D639068611D6D96861C95C2099140B805' => '172.16.17.32:9030', // mine
        'D405FCCF06ADEDF898DF2F29C9348DCB623031BA' => '192.168.3.11:80', // gGDHjdcC6zAlM8k08lY
        'D5039E1EBFD96D9A3F9846BF99EC9F75EDDE902A' => '172.16.31.10:9030', // Janky328891
        'D6BA940D3255AB40DC5EE5B0B285FA143E1F9865' => '192.168.127.12:80', // Cosworth02
        //'D71B1CA1C9DC7E8CA64158E106AD770A21160FEE' => '172.16.31.10:9265', // lqdn (NIA - 2019/05/25)
        'D8B7A3A6542AA54D0946B9DC0257C53B6C376679' => '172.16.17.32:9030', // sif
        'DAA39FC00B196B353C2A271459C305C429AF09E4' => '172.16.58.3:9030', // Arne
        'DB2682153AC0CCAECD2BD1E9EBE99C6815807A1E' => '192.168.127.12:80', // GermanCraft2
        'DD823AFB415380A802DCAEB9461AE637604107FB' => '172.16.58.3:80', // grenouille
        'DD8BD7307017407FCC36F8D04A688F74A0774C02' => '192.168.3.11:80', // DFRI0
        //'DDBB2A38252ADDA53E4492DDF982CA6CC6E10EC0' => '192.168.127.12:80', // zouzounella (NIA - 2019/05/25)
        'DED6892FF89DBD737BA689698A171B2392EB3E82' => '172.16.31.10:80', // ThorExit
        'E51620B90DCB310138ED89EDEDD0A5C361AAE24E' => '192.168.127.12:9030', // NormalCitizen
        'E81EF60A73B3809F8964F73766B01BAA0A171E20' => '172.16.17.32:8080', // Chimborazo
        'EB80A8D52F07238B576C42CEAB98ADD084EE075E' => '172.16.58.3:80', // Cosworth01
        'ED2338CAC2711B3E331392E1ED2831219B794024' => '192.168.127.12:9030', // SEC6xFreeBSD64
        'EFEACD781604EB80FBC025EDEDEA2D523AEAAA2F' => '172.16.17.32:9030', // Aerodynamik02
        'F10BDE279AE71515DDCCCC61DC19AC8765F8A3CC' => '172.16.17.32:80', // ParkBenchInd001
        'F2DFE5FA1E4CF54F8E761A6D304B9B4EC69BDAE8' => '192.168.127.12:80', // AlleKochenKaffee
        'F4263275CF54A6836EE7BD527B1328836A6F06E1' => '172.16.17.32:80', // EvilMoe
        'F6A358DD367B3282D6EF5824C9D45E1A19C7E815' => '192.168.3.11:80', // prawksi
        'F741E5124CB12700DA946B78C9B2DD175D6CD2A1' => '192.168.3.11:9030', // rofltor06
        'F8D27B163B9247B232A2EEE68DD8B698695C28DE' => '192.168.3.11:443', // fluxe3
        //'F9246DEF2B653807236DA134F2AEAB103D58ABFE' => '192.168.127.12:80', // Freebird31 (NIA - 2019/05/25)
        'F93D8F37E35C390BCAD9F9069E13085B745EC216' => '192.168.127.12:80', // TykRelay06
        //'FC9AC8EA0160D88BCCFDE066940D7DD9FA45495B' => '192.168.127.12:80', // ph3x (NIA - 2019/05/25)
        'FE296180018833AF03A8EACD5894A614623D3F76' => '192.168.127.12:9030', // PyotrTorpotkinOne
    );

    protected $preferredServer;

    protected $connectTimeout = 5;
    protected $readTimeout = 30;
    protected $userAgent = 'dapphp/TorUtils 1.1.13';

    protected $parser;
    protected $serverList;

    /**
     * DirectoryClient constructor
     */
    public function __construct()
    {
        $this->serverList = array_merge($this->directoryAuthorities, $this->directoryFallbacks);
        shuffle($this->serverList);

        $this->parser = new Parser();
    }

    /**
     * Set the preferred directory server to use for lookups.  This server will always be used
     * first.  If the preferred server times out or fails, the lookup will proceed using a random
     * server from the list of directory authorities and fallbacks.
     *
     * @param string $server The directory server to connect to (e.g. 192.168.3.11:80)
     * @return \Dapphp\TorUtils\DirectoryClient
     */
{'fraction_non_alphanumeric': 0.13792270531400966, 'fraction_numerical': 0.35475040257648954, 'mean_word_length': 3.7195693476884104, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 357, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 336, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '479725', 'n_tokens_mistral': 24394, 'n_tokens_neox': 17390, 'n_words': 1866}