Path: blob/master/src/infrastructure/log/PhabricatorProtocolLog.php
12241 views
<?php12final class PhabricatorProtocolLog3extends Phobject {45private $logfile;6private $mode;7private $buffer = array();89public function __construct($logfile) {10$this->logfile = $logfile;11}1213public function didStartSession($session_name) {14$this->setMode('!');15$this->buffer[] = $session_name;16$this->flush();17}1819public function didEndSession() {20$this->setMode('_');21$this->buffer[] = pht('<End of Session>');22$this->flush();23}2425public function didWriteBytes($bytes) {26if (!strlen($bytes)) {27return;28}2930$this->setMode('>');31$this->buffer[] = $bytes;32}3334public function didReadBytes($bytes) {35if (!strlen($bytes)) {36return;37}3839$this->setMode('<');40$this->buffer[] = $bytes;41}4243public function didReadFrame($frame) {44$this->writeFrame('<*', $frame);45}4647public function didWriteFrame($frame) {48$this->writeFrame('>*', $frame);49}5051private function writeFrame($header, $frame) {52$this->flush();5354$frame = explode("\n", $frame);55foreach ($frame as $key => $line) {56$frame[$key] = $header.' '.$this->escapeBytes($line);57}58$frame = implode("\n", $frame)."\n\n";5960$this->writeMessage($frame);61}6263private function setMode($mode) {64if ($this->mode === $mode) {65return $this;66}6768if ($this->mode !== null) {69$this->flush();70}7172$this->mode = $mode;7374return $this;75}7677private function flush() {78$mode = $this->mode;79$bytes = $this->buffer;8081$this->mode = null;82$this->buffer = array();8384$bytes = implode('', $bytes);8586if (strlen($bytes)) {87$this->writeBytes($mode, $bytes);88}89}9091private function writeBytes($mode, $bytes) {92$header = $mode;93$len = strlen($bytes);9495$out = array();96switch ($mode) {97case '<':98$out[] = pht('%s Write [%s bytes]', $header, new PhutilNumber($len));99break;100case '>':101$out[] = pht('%s Read [%s bytes]', $header, new PhutilNumber($len));102break;103default:104$out[] = pht(105'%s %s',106$header,107$this->escapeBytes($bytes));108break;109}110111switch ($mode) {112case '<':113case '>':114$out[] = $this->renderBytes($header, $bytes);115break;116}117118$out = implode("\n", $out)."\n\n";119120$this->writeMessage($out);121}122123private function renderBytes($header, $bytes) {124$bytes_per_line = 48;125$bytes_per_chunk = 4;126127// Compute the width of the "bytes" display section, which looks like128// this:129//130// > 00112233 44556677 abcdefgh131// ^^^^^^^^^^^^^^^^^132//133// We need to figure this out so we can align the plain text in the far134// right column appropriately.135136// The character width of the "bytes" part of a full display line. If137// we're rendering 48 bytes per line, we'll need 96 characters, since138// each byte is printed as a 2-character hexadecimal code.139$display_bytes = ($bytes_per_line * 2);140141// The character width of the number of spaces in between the "bytes"142// chunks. If we're rendering 12 chunks per line, we'll put 11 spaces143// in between them to separate them.144$display_spaces = (($bytes_per_line / $bytes_per_chunk) - 1);145146$pad_bytes = $display_bytes + $display_spaces;147148// When the protocol is plaintext, try to break it on newlines so it's149// easier to read.150$pos = 0;151$lines = array();152while (true) {153$next_break = strpos($bytes, "\n", $pos);154if ($next_break === false) {155$len = strlen($bytes) - $pos;156} else {157$len = ($next_break - $pos) + 1;158}159$len = min($bytes_per_line, $len);160161$next_bytes = substr($bytes, $pos, $len);162163$chunk_parts = array();164foreach (str_split($next_bytes, $bytes_per_chunk) as $chunk) {165$chunk_display = '';166for ($ii = 0; $ii < strlen($chunk); $ii++) {167$chunk_display .= sprintf('%02x', ord($chunk[$ii]));168}169$chunk_parts[] = $chunk_display;170}171$chunk_parts = implode(' ', $chunk_parts);172173$chunk_parts = str_pad($chunk_parts, $pad_bytes, ' ');174175176$lines[] = $header.' '.$chunk_parts.' '.$this->escapeBytes($next_bytes);177178$pos += $len;179180if ($pos >= strlen($bytes)) {181break;182}183}184185$lines = implode("\n", $lines);186187return $lines;188}189190private function escapeBytes($bytes) {191$result = '';192for ($ii = 0; $ii < strlen($bytes); $ii++) {193$c = $bytes[$ii];194$o = ord($c);195196if ($o >= 0x20 && $o <= 0x7F) {197$result .= $c;198} else {199$result .= '.';200}201}202return $result;203}204205private function writeMessage($message) {206$f = fopen($this->logfile, 'a');207fwrite($f, $message);208fflush($f);209fclose($f);210}211212}213214215