summaryrefslogtreecommitdiff
path: root/httpdocs/index.php
blob: e6874fe2f3f3e543d4d07d643aa4afd0eda541f3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
<?php

$work_dir = dirname(dirname(__FILE__)) . '/work/';

if (isset($_GET['r'])) {

  if (base64_decode($_GET['r'],true)===false)
    die('Invalid base64');

  if (!isset($_GET['t']))
    die('Repository type not given');

  if ($_GET['t']!='git')
    die('Repository type not implemented');

  if (!is_dir($work_dir . 'repositories/' . $_GET['t'] . '/' . $_GET['r'])) {
    $wish_list = fopen($work_dir . 'wish-list','a');
    if ($wish_list === false)
      die('Cannot open wish-list');
    fwrite($wish_list, $_GET['t'] . " " . $_GET['r'] . "\n");
    fclose($wish_list);
    die('I put repository onto wish-list');
  }

  if (isset($_GET['tag'])) {
    if (base64_decode($_GET['tag'],true)===false)
      $_GET['tag'] = base64_encode($_GET['tag']);

    $commit_identifier = '$(' .
        'echo "' . $_GET['tag'] . '" | ' .
          'base64 -d' .
      ')';
  } elseif (isset($_GET['commit'])) {
    if (!preg_match('/^[A-Fa-f0-9]{40}$/', $_GET['commit']))
      die('The given commit does not have exactly 40 hex digits');
    $commit_identifier = $_GET['commit'];
  }

  function expand_key($key) {
    if (preg_match('/^[A-Fa-f0-9]{16}$/', $key))
      return '.\{24\}' . $key;
    elseif (preg_match('/^[A-Fa-f0-9]{40}$/', $key))
      return $key;
    else
      die('The given key does not have exactly 16 or 40 hex digits');
  }

  if (isset($commit_identifier)) {
    if (isset($_GET['valid_keys'])) {

      $key_regex = '\(' . implode(
        '\|',
        array_map(
          'expand_key',
          explode(
            ',',
            $_GET['valid_keys']
          )
        )
      ) . '\)';

      shell_exec(
        'GNUPGHOME="' . $work_dir . 'gnupg" gpg ' .
        '--keyserver=hkp://keys.gnupg.net ' .
        '--recv-keys ' . implode(' ',explode(',',$_GET['valid_keys']))
      );

      if (trim(shell_exec(
        'GNUPGHOME="' . $work_dir . 'gnupg" git -C "' . $work_dir . 'repositories/' . $_GET['t'] . '/' . $_GET['r'] . '" verify-tag --raw "' . $commit_identifier . '" 2>&1 | ' .
        'grep -c "\[GNUPG:\] VALIDSIG ' . $key_regex . ' "'
      )) == '0')
        die('Commit ' . $commit_identifier . ' is not signed by ' . $_GET['valid_keys']);
    }
    if (isset($_GET['p'])) {
      if (base64_decode($_GET['p'],true)===false)
        die('Invalid base64');
      $prefix = ' --prefix="$(' .
        'echo "' . $_GET['p'] . '" | ' .
        'base64 -d' .
        ')"';
    } else {
      $prefix = '';
    }
    $handle = popen(
      'git -C "../work/repositories/' . $_GET['t'] . '/' . $_GET['r'] . '" archive' . $prefix . ' "' . $commit_identifier . '" | ' .
      'gzip -nc',
      'r'
    );
    if ($handle === false)
      die('Unable to create archive');
    header('Content-type: application/x-gzip');
    header('Content-Disposition: attachment; filename="archive.tar.gz"');
    fpassthru($handle);
    pclose($handle);
    die();
  }

  die('errrm, this is not yet implemented');

}

print 'Hi, this is an <a href="https://git.eckner.net/Erich/archive-server/">archive server</a>!<br>' . "\n";
print 'I provide archives of these upstreams:<br>' . "\n";

print
  implode(
    "<br>\n",
    array_map(
      "base64_decode",
      explode(
        "\n",
        shell_exec(
          'find "' . $work_dir . 'repositories" -mindepth 2 -maxdepth 2 -printf "%f\n" | sort'
        )
      )
    )
  );

die();