1<?php
2
3/**
4 * Observium Network Management and Monitoring System
5 * Copyright (C) 2006-2015, Adam Armstrong - http://www.observium.org
6 *
7 * @package    observium
8 * @subpackage webui
9 * @author     Adam Armstrong <adama@observium.org>
10 * @copyright  (C) 2006-2013 Adam Armstrong, (C) 2013-2019 Observium Limited
11 *
12 */
13
14//r(auth_user_level_permissions($_SESSION['userlevel']));
15if ($_SESSION['userlevel'] >= 7)
16{
17  // Enable google code prettify
18  register_html_resource('js', 'google-code-prettify.js');
19  register_html_resource('css', 'google-code-prettify.css');
20
21  // Print device config navbar
22  $navbar = array();
23  $navbar['brand'] = "Config";
24  $navbar['class'] = "navbar-narrow";
25
26  $cmd_file = escapeshellarg($device_config_file);
27  $rev = array('count' => 0);
28  if (is_executable($config['svn']))
29  {
30    //$svnlogs = external_exec($config['svn'] . ' log -q -l 8 ' . $device_config_file); // Last 8 entries
31    $svnlogs = external_exec($config['svn'] . ' log -q ' . $cmd_file);
32    foreach (explode("\n", $svnlogs) as $line)
33    {
34      // r1884 | rancid | 2014-09-19 19:50:12 +0400 (Fri, 19 Sep 2014)
35      // ------------------------------------------------------------------------
36      if (preg_match('/r(?<rev>\d+) \| .+? \| (?<date>[\d\-]+ [\d:]+ [\+\-]?\d+)/', $line, $matches))
37      {
38        $rev['list'][] = array('rev' => $matches['rev'], 'date' => format_timestamp(trim($matches['date'])));
39        $rev['count']++;
40      }
41    }
42    if ($rev['count']) { $rev['type'] = 'svn'; }
43  }
44  if (!$rev['count'] && is_executable($config['git']))
45  {
46    // You should know, I hate git!
47    // Why git commands should be as:
48    // git --git-dir='/rancid_path/git_dir/.git' --work-tree='/rancid_path/git_dir' log --pretty=format:"%h %ci" 'absolute_config_path'
49    // git --git-dir='/rancid_path/git_dir/.git' --work-tree='/rancid_path/git_dir' show 96b30a1:'relative_git_file_path'
50    // git --git-dir='/rancid_path/git_dir/.git' --work-tree='/rancid_path/git_dir' diff 96b30a1 441b0e6 'absolude_config_path'
51    // and nothing else formats, else git return error
52    $file_base = basename($device_config_file);
53    $file_dir  = dirname($device_config_file);
54    if (is_dir($file_dir . '/.git'))
55    {
56      // Ok, do nothing
57      $git_file = escapeshellarg($file_base);
58    }
59    else if (is_dir($file_dir . '/../.git'))
60    {
61      // Rancid >= 3.2
62      $file_array = explode('/', $file_dir);
63      $end = array_pop($file_array);
64      $file_dir = implode('/', $file_array);
65      $git_file = escapeshellarg($end . '/' . $file_base);
66    }
67    $cmd_dir = escapeshellarg($file_dir);
68    $git_dir = escapeshellarg($file_dir . '/.git');
69    $gitlogs = external_exec($config['git'].' --git-dir='. $git_dir .' --work-tree='.$cmd_dir.' log --pretty=format:"%h %ci" '.$cmd_file);
70    foreach (explode("\n", $gitlogs) as $line)
71    {
72      // b6989b9 2014-11-10 00:16:53 +0100
73      // 66840ee 2014-11-02 23:34:18 +0100
74      if (preg_match('/(?<rev>\w+) (?<date>[\d\-]+ [\d:]+ [\+\-]?\d+)/', $line, $matches))
75      {
76        $rev['list'][] = array('rev' => $matches['rev'], 'date' => format_timestamp($matches['date']));
77        $rev['count']++;
78      }
79    }
80    if ($rev['count']) { $rev['type'] = 'git'; }
81  }
82
83  $navbar['options']['latest']['url']   = generate_url(array('page'=>'device','device'=>$device['device_id'],'tab'=>'showconfig'));
84  $navbar['options']['latest']['class'] = 'active';
85  if ($rev['count'])
86  {
87    $rev_active_index = 0;
88    $rev_max = intval($config['rancid_revisions']);
89    if ($rev_max <= 0)
90    {
91      $rev_max = 1;
92    }
93    else if ($rev_max > 32)
94    {
95      $rev_max = 32;
96    }
97    foreach ($rev['list'] as $i => $entry)
98    {
99      $rev_name = ($rev['type'] == 'svn' ? 'r'.$entry['rev'] : $entry['rev']);
100      if ($i > ($rev_max - 1))
101      {
102        break; // Show only last 10 revisions
103      }
104      else if ($i > 0)
105      {
106        $navbar['options'][$rev_name]['text'] = '['.$rev_name.', '.$entry['date'].']';
107        $navbar['options'][$rev_name]['url']  = generate_url(array('page'=>'device','device'=>$device['device_id'],'tab'=>'showconfig','rev'=>$entry['rev']));
108        if ($vars['rev'] == $entry['rev'])
109        {
110          unset($navbar['options']['latest']['class']);
111          $navbar['options'][$rev_name]['class'] = 'active';
112          $rev_active_index = $i;
113        }
114        else if ($rev['count'] > 4)
115        {
116          // Simplify too long revisions list
117          $navbar['options'][$rev_name]['alt'] = $navbar['options'][$rev_name]['text'];
118          $navbar['options'][$rev_name]['text'] = '['.$rev_name.']';
119        }
120      } else {
121        // Latest revision
122        $navbar['options']['latest']['text'] = 'Latest ['.$rev_name.', '.$entry['date'].']';
123      }
124    }
125  } else {
126    $navbar['options']['latest']['text'] = 'Latest';
127  }
128
129  // Print out the navbar defined above
130  print_navbar($navbar);
131  unset($navbar);
132
133  if ($rev['count'])
134  {
135    $rev['curr'] = $rev['list'][$rev_active_index]['rev'];
136    if (isset($rev['list'][$rev_active_index + 1]))
137    {
138      $rev['prev'] = $rev['list'][$rev_active_index + 1]['rev'];
139    }
140    switch ($rev['type'])
141    {
142      case 'svn':
143        if ($rev['count'] === 1)
144        {
145          // SVN not show initial revision in cat
146          $cmd_cat   = $config['svn'] . ' cat -rHEAD '.$cmd_file;
147        } else {
148          $cmd_cat   = $config['svn'] . ' cat -r'.$rev['curr'].' '.$cmd_file;
149        }
150        $cmd_diff  = $config['svn'] . ' diff -r'.$rev['prev'].':'.$rev['curr'].' '.$cmd_file;
151        $prev_name = 'r'.$rev['prev'];
152        break;
153      case 'git':
154        $cmd_cat   = $config['git'].' --git-dir='. $git_dir .' --work-tree='.$cmd_dir.' show '.$rev['curr'].':'.$git_file;
155        $cmd_diff  = $config['git'].' --git-dir='. $git_dir .' --work-tree='.$cmd_dir.' diff '.$rev['prev'].' '.$rev['curr'].' '.$cmd_file;
156        $prev_name = $rev['prev'];
157    }
158    $device_config = external_exec($cmd_cat);
159    if (!isset($rev['prev']))
160    {
161      $diff = '';
162      if (empty($device_config))
163      {
164        $device_config = '# Initial device added.';
165      }
166    } else {
167      $diff = external_exec($cmd_diff);
168      if (!$diff)
169      {
170        $diff = 'No Difference';
171      }
172    }
173  } else {
174    $fh = fopen($device_config_file, 'r') or die("Can't open file");
175    $device_config = fread($fh, filesize($device_config_file));
176    fclose($fh);
177  }
178
179  if ($config['rancid_ignorecomments'])
180  {
181    if (isset($config['os'][$device['os']]['comments']))
182    {
183      $comments_pattern = $config['os'][$device['os']]['comments'];
184    } else {
185      // Default pattern
186      $comments_pattern = $config['os_group']['default']['comments'];
187      //$comments_pattern = '/^\s*#/';
188    }
189    $lines = explode(PHP_EOL, $device_config);
190    foreach ($lines as $i => $line)
191    {
192      if (@preg_match($comments_pattern, $line)) { unset($lines[$i]); }
193    }
194    $device_config = implode(PHP_EOL, $lines);
195  }
196
197  if ($rev['count'])
198  {
199    $text = '';
200    ?>
201<div class="panel-group" id="accordion">
202    <?php
203    if (isset($rev['prev']))
204    {
205    ?>
206  <div class="panel panel-default">
207    <div class="panel-heading" data-toggle="collapse" data-parent="#accordion" data-target="#diff">
208      <h3 class="panel-title">
209        <a class="accordion-toggle">
210          Show difference with previous revision (<?php echo $prev_name; ?>):
211        </a>
212      </h3>
213    </div>
214    <div id="diff" class="panel-collapse collapse">
215      <div class="panel-body">
216
217<?php
218    // Disable pretty print for big files
219    $device_config_class = (strlen($diff) < 250000 ? 'prettyprint lang-sh' : '');
220
221    echo('<pre class="'.$device_config_class.'">' . PHP_EOL . escape_html($diff) . '</pre>' . PHP_EOL);
222?>
223
224      </div>
225    </div>
226  </div>
227  <hr />
228    <?php
229    } // End if (isset($rev['prev']))
230    ?>
231  <div class="panel panel-default">
232    <div class="panel-heading">
233      <h3 class="panel-title"  data-toggle="collapse" data-parent="#accordion" data-target="#device_config">
234        <a class="accordion-toggle">
235          Device configuration:
236        </a>
237      </h3>
238    </div>
239    <div id="device_config" class="panel-collapse collapse in">
240      <div class="panel-body">
241
242<?php
243    // Disable pretty print for big files
244    $device_config_class = (strlen($device_config) < 250000 ? 'prettyprint linenums lang-sh' : '');
245
246    echo('<pre class="'.$device_config_class.'">' . PHP_EOL . escape_html($device_config) . '</pre>' . PHP_EOL);
247?>
248
249      </div>
250    </div>
251  </div>
252</div>
253    <?php
254  } else {
255    //r(strlen($device_config));
256    // Disable pretty print for big files
257    $device_config_class = (strlen($device_config) < 250000 ? 'prettyprint linenums lang-sh' : '');
258
259    $text = '<pre class="'.$device_config_class.'">' . PHP_EOL . escape_html($device_config) . '</pre>' . PHP_EOL;
260  }
261  $text .= '<script type="text/javascript">window.prettyPrint && prettyPrint();</script>' . PHP_EOL;
262  echo($text);
263}
264
265register_html_title('Config');
266
267// Clean
268unset($text, $device_config, $diff, $rev, $rev_active_index);
269
270// EOF
271