3 set_include_path(get_include_path() . PATH_SEPARATOR
. '../lib');
4 include_once("config.inc.php");
6 require_once('Archive/Tar.php');
8 include_once("aur.inc.php"); # access AUR common functions
9 include_once("pkgfuncs.inc.php"); # package functions
11 set_lang(); # this sets up the visitor's language
12 check_sid(); # see if they're still logged in
16 if ($_COOKIE["AURSID"]) {
17 $uid = uid_from_sid($_COOKIE['AURSID']);
28 if (isset($_REQUEST['pkgsubmit'])) {
30 # Before processing, make sure we even have a file
31 if ($_FILES['pfile']['size'] == 0){
32 $error = __("Error - No file uploaded");
35 # Check whether the file is gzip'ed
37 $fh = fopen($_FILES['pfile']['tmp_name'], 'rb');
38 fseek($fh, 0, SEEK_SET
);
39 list(, $magic) = unpack('v', fread($fh, 2));
41 if ($magic != 0x8b1f) {
42 $error = __("Error - unsupported file format (please submit gzip'ed tarballs generated by makepkg(8) only).");
46 # Check uncompressed file size (ZIP bomb protection)
47 if (!$error && $MAX_FILESIZE_UNCOMPRESSED) {
48 fseek($fh, -4, SEEK_END
);
49 list(, $filesize_uncompressed) = unpack('V', fread($fh, 4));
51 if ($filesize_uncompressed > $MAX_FILESIZE_UNCOMPRESSED) {
52 $error = __("Error - uncompressed file size too large.");
56 # Close file handle before extracting stuff
57 if (isset($fh) && is_resource($fh)) {
62 $tar = new Archive_Tar($_FILES['pfile']['tmp_name']);
64 # Extract PKGBUILD into a string
67 foreach ($tar->listContent() as $tar_file) {
68 if (preg_match('/^[^\/]+\/PKGBUILD$/', $tar_file['filename'])) {
69 $pkgbuild_raw = $tar->extractInString($tar_file['filename']);
71 elseif (preg_match('/^[^\/]+\/$/', $tar_file['filename'])) {
72 if (++
$dircount > 1) {
73 $error = __("Error - source tarball may not contain more than one directory.");
77 elseif (preg_match('/^[^\/]+$/', $tar_file['filename'])) {
78 $error = __("Error - source tarball may not contain files outside a directory.");
81 elseif (preg_match('/^[^\/]+\/[^\/]+\//', $tar_file['filename'])) {
82 $error = __("Error - source tarball may not contain nested subdirectories.");
87 if (!$error && empty($pkgbuild_raw)) {
88 $error = __("Error trying to unpack upload - PKGBUILD does not exist.");
92 # if no error, get list of directory contents and process PKGBUILD
93 # TODO: This needs to be completely rewritten to support stuff like arrays
94 # and variable substitution among other things.
96 # process PKGBUILD - remove line concatenation
101 $continuation_line = 0;
104 foreach (explode("\n", $pkgbuild_raw) as $line) {
107 $line = preg_replace('/\s*#.*/', '', $line);
109 $char_counts = count_chars($line, 0);
110 $paren_depth +
= $char_counts[ord('(')] - $char_counts[ord(')')];
111 if (substr($line, strlen($line)-1) == "\\") {
112 # continue appending onto existing line_no
114 $current_line .= substr($line, 0, strlen($line)-1);
115 $continuation_line = 1;
116 } elseif ($paren_depth > 0) {
117 # assumed continuation
118 # continue appending onto existing line_no
120 $current_line .= $line . " ";
121 $continuation_line = 1;
123 # maybe the last line in a continuation, or a standalone line?
125 if ($continuation_line) {
126 # append onto existing line_no
128 $current_line .= $line;
129 $lines[$line_no] = $current_line;
134 $lines[$line_no] = $line;
136 $continuation_line = 0;
141 # Now process the lines and put any var=val lines into the
143 while (list($k, $line) = each($lines)) {
144 # Neutralize parameter substitution
145 $line = preg_replace('/\${(\w+)#(\w*)}?/', '$1$2', $line);
148 # Match variable assignment only.
149 if (preg_match('/^\s*[_\w]+=[^=].*/', $line, $matches)) {
150 $lparts = explode("=", $matches[0], 2);
153 if (!empty($lparts)) {
154 # this is a variable/value pair, strip out
155 # array parens and any quoting, except in pkgdesc
156 # for pkgdesc, only remove start/end pairs of " or '
157 if ($lparts[0]=="pkgdesc") {
158 if ($lparts[1]{0} == '"' &&
159 $lparts[1]{strlen($lparts[1])-1} == '"') {
160 $pkgbuild[$lparts[0]] = substr($lparts[1], 1, -1);
163 ($lparts[1]{0} == "'" &&
164 $lparts[1]{strlen($lparts[1])-1} == "'") {
165 $pkgbuild[$lparts[0]] = substr($lparts[1], 1, -1);
167 $pkgbuild[$lparts[0]] = $lparts[1];
170 $pkgbuild[$lparts[0]] = str_replace(array("(",")","\"","'"), "",
176 # some error checking on PKGBUILD contents - just make sure each
177 # variable has a value. This does not do any validity checking
178 # on the values, or attempts to fix line continuation/wrapping.
179 $req_vars = array("url", "pkgdesc", "license", "pkgrel", "pkgver", "arch", "pkgname");
180 foreach ($req_vars as $var) {
181 if (!array_key_exists($var, $pkgbuild)) {
182 $error = __('Missing %s variable in PKGBUILD.', $var);
188 # TODO This is where other additional error checking can be
189 # performed. Examples: #md5sums == #sources?, md5sums of any
190 # included files match?, install scriptlet file exists?
193 # Check for http:// or other protocol in url
196 $parsed_url = parse_url($pkgbuild['url']);
197 if (!$parsed_url['scheme']) {
198 $error = __("Package URL is missing a protocol (ie. http:// ,ftp://)");
202 # Now, run through the pkgbuild array, and do "eval" and simple substituions.
204 while (list($k, $v) = each($pkgbuild)) {
205 if (strpos($k,'eval ') !== false) {
206 $k = preg_replace('/^eval[\s]*/', "", $k);
207 ##"eval" replacements
208 $pattern_eval = '/{\$({?)([\w]+)(}?)}/';
209 while (preg_match($pattern_eval,$v,$regs)) {
210 $pieces = explode(",",$pkgbuild["$regs[2]"]);
211 ## nongreedy matching! - preserving the order of "eval"
212 $pattern = '/([\S]*?){\$'.$regs[1].$regs[2].$regs[3].'}([\S]*)/';
213 while (preg_match($pattern,$v,$regs_replace)) {
215 for ($i = 0; $i < sizeof($pieces); $i++
) {
216 $replacement .= $regs_replace[1].$pieces[$i].$regs_replace[2]." ";
218 $v=preg_replace($pattern, $replacement, $v, 1);
223 # Simple variable replacement
224 $pattern_var = '/\$({?)([_\w]+)(}?)/';
226 while (preg_match($pattern_var, $v, $regs, PREG_OFFSET_CAPTURE
, $offset)) {
229 $len = strlen($regs[0][0]);
231 if (isset($new_pkgbuild[$var])) {
232 $replacement = substr($new_pkgbuild[$var], strpos($new_pkgbuild[$var], " "));
238 $v = substr_replace($v, $replacement, $pos, $len);
239 $offset = $pos +
strlen($replacement);
241 $new_pkgbuild[$k] = $v;
245 # Now we've parsed the pkgbuild, let's move it to where it belongs
247 $pkg_name = str_replace("'", "", $new_pkgbuild['pkgname']);
248 $pkg_name = escapeshellarg($pkg_name);
249 $pkg_name = str_replace("'", "", $pkg_name);
251 $presult = preg_match("/^[a-z0-9][a-z0-9\.+_-]*$/", $pkg_name);
254 $error = __("Invalid name: only lowercase letters are allowed.");
258 if (isset($pkg_name)) {
259 $incoming_pkgdir = INCOMING_DIR
. substr($pkg_name, 0, 2) . "/" . $pkg_name;
263 # First, see if this package already exists, and if it can be overwritten
264 $pkg_id = pkgid_from_name($pkg_name);
265 if (can_submit_pkg($pkg_name, $_COOKIE["AURSID"])) {
266 if (file_exists($incoming_pkgdir)) {
267 # Blow away the existing file/dir and contents
268 rm_tree($incoming_pkgdir);
271 # The mode is masked by the current umask, so not as scary as it looks
272 if (!mkdir($incoming_pkgdir, 0777, true)) {
273 $error = __( "Could not create directory %s.", $incoming_pkgdir);
276 $error = __( "You are not allowed to overwrite the %h%s%h package.", "<b>", $pkg_name, "</b>");
280 # Check if package name is blacklisted.
281 if (!$pkg_id && pkgname_is_blacklisted($pkg_name)) {
282 if (!canSubmitBlacklisted(account_from_sid($_COOKIE["AURSID"]))) {
283 $error = __( "%s is on the package blacklist, please check if it's available in the official repos.", $pkg_name);
290 if (!chdir($incoming_pkgdir)) {
291 $error = __("Could not change directory to %s.", $incoming_pkgdir);
294 file_put_contents('PKGBUILD', $pkgbuild_raw);
295 move_uploaded_file($_FILES['pfile']['tmp_name'], $pkg_name . '.tar.gz');
298 # Update the backend database
302 db_query("BEGIN", $dbh);
304 $q = "SELECT * FROM Packages WHERE Name = '" . mysql_real_escape_string($new_pkgbuild['pkgname']) . "'";
305 $result = db_query($q, $dbh);
306 $pdata = mysql_fetch_assoc($result);
308 if (isset($new_pkgbuild['epoch']) && (int)$new_pkgbuild['epoch'] > 0) {
309 $pkg_version = sprintf('%d:%s-%s', $new_pkgbuild['epoch'], $new_pkgbuild['pkgver'], $new_pkgbuild['pkgrel']);
311 $pkg_version = sprintf('%s-%s', $new_pkgbuild['pkgver'], $new_pkgbuild['pkgrel']);
315 # This is an overwrite of an existing package, the database ID
316 # needs to be preserved so that any votes are retained. However,
317 # PackageDepends and PackageSources can be purged.
318 $packageID = $pdata["ID"];
320 # Flush out old data that will be replaced with new data
321 $q = "DELETE FROM PackageDepends WHERE PackageID = " . $packageID;
323 $q = "DELETE FROM PackageSources WHERE PackageID = " . $packageID;
326 # If a new category was chosen, change it to that
327 if ($_POST['category'] > 1) {
328 $q = sprintf( "UPDATE Packages SET CategoryID = %d WHERE ID = %d",
329 mysql_real_escape_string($_REQUEST['category']),
335 # Update package data
336 $q = sprintf("UPDATE Packages SET ModifiedTS = UNIX_TIMESTAMP(), Name = '%s', Version = '%s', License = '%s', Description = '%s', URL = '%s', OutOfDateTS = NULL, MaintainerUID = %d WHERE ID = %d",
337 mysql_real_escape_string($new_pkgbuild['pkgname']),
338 mysql_real_escape_string($pkg_version),
339 mysql_real_escape_string($new_pkgbuild['license']),
340 mysql_real_escape_string($new_pkgbuild['pkgdesc']),
341 mysql_real_escape_string($new_pkgbuild['url']),
348 # This is a brand new package
349 $q = sprintf("INSERT INTO Packages (Name, License, Version, CategoryID, Description, URL, SubmittedTS, ModifiedTS, SubmitterUID, MaintainerUID) VALUES ('%s', '%s', '%s', %d, '%s', '%s', UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), %d, %d)",
350 mysql_real_escape_string($new_pkgbuild['pkgname']),
351 mysql_real_escape_string($new_pkgbuild['license']),
352 mysql_real_escape_string($pkg_version),
353 mysql_real_escape_string($_REQUEST['category']),
354 mysql_real_escape_string($new_pkgbuild['pkgdesc']),
355 mysql_real_escape_string($new_pkgbuild['url']),
360 $packageID = mysql_insert_id($dbh);
364 # Update package depends
365 $depends = explode(" ", $new_pkgbuild['depends']);
366 if ($depends !== false) {
367 foreach ($depends as $dep) {
368 $deppkgname = preg_replace("/(<|<=|=|>=|>).*/", "", $dep);
369 $depcondition = str_replace($deppkgname, "", $dep);
371 if ($deppkgname == "") {
374 else if ($deppkgname == "#") {
378 $q = sprintf("INSERT INTO PackageDepends (PackageID, DepName, DepCondition) VALUES (%d, '%s', '%s')",
380 mysql_real_escape_string($deppkgname),
381 mysql_real_escape_string($depcondition));
388 $sources = explode(" ", $new_pkgbuild['source']);
389 foreach ($sources as $src) {
391 $q = "INSERT INTO PackageSources (PackageID, Source) VALUES (";
392 $q .= $packageID . ", '" . mysql_real_escape_string($src) . "')";
397 # If we just created this package, or it was an orphan and we
398 # auto-adopted, add submitting user to the notification list.
399 if (!$pdata ||
$pdata["MaintainerUID"] === NULL) {
400 pkg_notify(account_from_sid($_COOKIE["AURSID"], $dbh), array($packageID), true, $dbh);
403 # Entire package creation process is atomic
404 db_query("COMMIT", $dbh);
406 header('Location: packages.php?ID=' . $packageID);
412 # Logic over, let's do some output
414 html_header("Submit");
418 <?php
if ($error): ?
>
419 <p
class="pkgoutput"><?php
print $error ?
></p
>
423 <div
class="pgboxtitle">
424 <span
class="f3"><?php
print __("Submit"); ?
></span
>
426 <div
class="pgboxbody">
427 <p
><?php
echo __("Upload your source packages here. Create source packages with `makepkg --source`.") ?
></p
>
430 if (empty($_REQUEST['pkgsubmit']) ||
$error):
431 # User is not uploading, or there were errors uploading - then
432 # give the visitor the default upload form
433 if (ini_get("file_uploads")):
435 $pkg_categories = pkgCategories();
438 <form action
='pkgsubmit.php' method
='post' enctype
='multipart/form-data'>
439 <div
> <input type
='hidden' name
='pkgsubmit' value
='1' /> </div
>
440 <table border
='0' cellspacing
='5'>
442 <td
class='f4' align
='right'><?php
print __("Package Category"); ?
>:</td
>
443 <td
class='f4' align
='left'>
444 <select name
='category'>
445 <option value
='1'><?php
print __("Select Category"); ?
></option
>
447 foreach ($pkg_categories as $num => $cat):
448 print "<option value='" . $num . "'";
449 if (isset($_POST['category']) && $_POST['category'] == $cat):
450 print " selected='selected'";
452 print ">" . $cat . "</option>";
459 <td
class='f4' align
='right'><?php
print __("Upload package file"); ?
>:</td
>
460 <td
class='f4' align
='left'>
461 <input type
='file' name
='pfile' size
='30' />
466 <input
class='button' type
='submit' value
='<?php print __("Upload"); ?>' />
474 print __("Sorry, uploads are not permitted by this server.");
483 # Visitor is not logged in
484 print __("You must create an account before you can upload packages.");
498 html_footer(AUR_VERSION
);