errorcode418/php
0
1<?php2/**3 * ua-parser4 *5 * Copyright (c) 2011-2012 Dave Olsen, http://dmolsen.com6 *7 * Released under the MIT license8 */9namespace UAParser\Command;10 11use Symfony\Component\Console\Command\Command;12use Symfony\Component\Console\Input\InputArgument;13use Symfony\Component\Console\Input\InputInterface;14use Symfony\Component\Console\Input\InputOption;15use Symfony\Component\Console\Output\OutputInterface;16use Symfony\Component\Filesystem\Filesystem;17use Symfony\Component\Finder\Finder;18use Symfony\Component\Finder\SplFileInfo;19use UAParser\Exception\InvalidArgumentException;20use UAParser\Exception\ReaderException;21use UAParser\Parser;22use UAParser\Result\Client;23use UAParser\Util\Logfile\AbstractReader;24 25class LogfileCommand extends Command26{27 protected function configure()28 {29 $this30 ->setName('ua-parser:log')31 ->setDescription('Parses the supplied webserver log file.')32 ->addArgument(33 'output',34 InputArgument::REQUIRED,35 'Path to output log file'36 )37 ->addOption(38 'log-file',39 'f',40 InputOption::VALUE_REQUIRED,41 'Path to a webserver log file'42 )43 ->addOption(44 'log-dir',45 'd',46 InputOption::VALUE_REQUIRED,47 'Path to webserver log directory'48 )49 ->addOption(50 'include',51 'i',52 InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED,53 'Include glob expressions for log files in the log directory',54 array('*.log', '*.log*.gz', '*.log*.bz2')55 )56 ->addOption(57 'exclude',58 'e',59 InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED,60 'Exclude glob expressions for log files in the log directory',61 array('*error*')62 )63 ;64 }65 66 protected function execute(InputInterface $input, OutputInterface $output)67 {68 if (!$input->getOption('log-file') && !$input->getOption('log-dir')) {69 throw InvalidArgumentException::oneOfCommandArguments('log-file', 'log-dir');70 }71 72 $parser = Parser::create();73 $undefinedClients = array();74 /** @var $file SplFileInfo */75 foreach ($this->getFiles($input) as $file) {76 77 $path = $this->getPath($file);78 $lines = file($path);79 80 if (empty($lines)) {81 $output->writeln(sprintf('Skipping empty file "%s"', $file->getPathname()));82 $output->writeln('');83 continue;84 }85 86 $firstLine = reset($lines);87 88 $reader = AbstractReader::factory($firstLine);89 if (!$reader) {90 $output->writeln(sprintf('Could not find reader for file "%s"', $file->getPathname()));91 $output->writeln('');92 continue;93 }94 95 $output->writeln('');96 $output->writeln(sprintf('Analyzing "%s"', $file->getPathname()));97 98 $count = 1;99 $totalCount = count($lines);100 foreach ($lines as $line) {101 102 try {103 $userAgentString = $reader->read($line);104 } catch (ReaderException $e) {105 $count = $this->outputProgress($output, 'E', $count, $totalCount);106 continue;107 }108 109 $client = $parser->parse($userAgentString);110 111 $result = $this->getResult($client);112 if ($result !== '.') {113 $undefinedClients[] = json_encode(114 array($client->toString(), $userAgentString),115 JSON_UNESCAPED_SLASHES116 );117 }118 119 $count = $this->outputProgress($output, $result, $count, $totalCount);120 }121 $this->outputProgress($output, '', $count - 1, $totalCount, true);122 $output->writeln('');123 }124 125 $undefinedClients = $this->filter($undefinedClients);126 127 $fs = new Filesystem();128 $fs->dumpFile($input->getArgument('output'), join(PHP_EOL, $undefinedClients));129 }130 131 private function outputProgress(OutputInterface $output, $result, $count, $totalCount, $end = false)132 {133 if (($count % 70) === 0 || $end) {134 $formatString = '%s %' . strlen($totalCount) . 'd / %-' . strlen($totalCount) . 'd (%3d%%)';135 $result = $end ? str_repeat(' ', 70 - ($count % 70)) : $result;136 $output->writeln(sprintf($formatString, $result, $count, $totalCount, $count / $totalCount * 100));137 } else {138 $output->write($result);139 }140 141 return $count + 1;142 }143 144 private function getResult(Client $client)145 {146 if ($client->device->family === 'Spider') {147 return '.';148 } elseif ($client->ua->family === 'Other') {149 return 'U';150 } elseif ($client->os->family === 'Other') {151 return 'O';152 } elseif ($client->device->family === 'Generic Smartphone') {153 return 'S';154 } elseif ($client->device->family === 'Generic Feature Phone') {155 return 'F';156 }157 158 return '.';159 }160 161 private function getFiles(InputInterface $input)162 {163 $finder = Finder::create();164 165 if ($input->getOption('log-file')) {166 $file = $input->getOption('log-file');167 $finder->append(Finder::create()->in(dirname($file))->name(basename($file)));168 }169 170 if ($input->getOption('log-dir')) {171 $dirFinder = Finder::create()172 ->in($input->getOption('log-dir'));173 array_map(array($dirFinder, 'name'), $input->getOption('include'));174 array_map(array($dirFinder, 'notName'), $input->getOption('exclude'));175 176 $finder->append($dirFinder);177 }178 179 return $finder;180 }181 182 private function filter(array $lines)183 {184 return array_values(array_unique($lines));185 }186 187 private function getPath(SplFileInfo $file)188 {189 switch ($file->getExtension()) {190 case 'gz':191 $path = 'compress.zlib://' . $file->getPathname();192 break;193 194 case 'bz2':195 $path = 'compress.bzip2://' . $file->getPathname();196 break;197 198 default:199 $path = $file->getPathname();200 break;201 }202 203 return $path;204 }205}206 