housekeep: remove PHP implementation

removal of the PHP codebase

Signed-off-by: moson-mo <mo-son@mailbox.org>
This commit is contained in:
moson-mo 2023-04-28 16:10:32 +02:00
parent 97d0eac303
commit 8ca63075e9
No known key found for this signature in database
GPG key ID: 4A4760AB4EE15296
128 changed files with 27 additions and 16046 deletions

View file

@ -8,6 +8,3 @@ root = true
end_of_line = lf end_of_line = lf
insert_final_newline = true insert_final_newline = true
charset = utf-8 charset = utf-8
[*.{php,t}]
indent_style = tab

1
.env
View file

@ -1,7 +1,6 @@
FASTAPI_BACKEND="uvicorn" FASTAPI_BACKEND="uvicorn"
FASTAPI_WORKERS=2 FASTAPI_WORKERS=2
MARIADB_SOCKET_DIR="/var/run/mysqld/" MARIADB_SOCKET_DIR="/var/run/mysqld/"
AURWEB_PHP_PREFIX=https://localhost:8443
AURWEB_FASTAPI_PREFIX=https://localhost:8444 AURWEB_FASTAPI_PREFIX=https://localhost:8444
AURWEB_SSHD_PREFIX=ssh://aur@localhost:2222 AURWEB_SSHD_PREFIX=ssh://aur@localhost:2222
GIT_DATA_DIR="./aur.git/" GIT_DATA_DIR="./aur.git/"

View file

@ -71,7 +71,6 @@ deploy:
variables: variables:
FASTAPI_BACKEND: gunicorn FASTAPI_BACKEND: gunicorn
FASTAPI_WORKERS: 5 FASTAPI_WORKERS: 5
AURWEB_PHP_PREFIX: https://aur-dev.archlinux.org
AURWEB_FASTAPI_PREFIX: https://aur-dev.archlinux.org AURWEB_FASTAPI_PREFIX: https://aur-dev.archlinux.org
AURWEB_SSHD_PREFIX: ssh://aur@aur-dev.archlinux.org:2222 AURWEB_SSHD_PREFIX: ssh://aur@aur-dev.archlinux.org:2222
COMMIT_HASH: $CI_COMMIT_SHA COMMIT_HASH: $CI_COMMIT_SHA

View file

@ -91,7 +91,6 @@ browser if desired.
Accessible services (on the host): Accessible services (on the host):
- https://localhost:8444 (python via nginx) - https://localhost:8444 (python via nginx)
- https://localhost:8443 (php via nginx)
- localhost:13306 (mariadb) - localhost:13306 (mariadb)
- localhost:16379 (redis) - localhost:16379 (redis)

View file

@ -14,8 +14,7 @@ read the instructions below.
$ cd aurweb $ cd aurweb
$ poetry install $ poetry install
2) Setup a web server with PHP and MySQL. Configure the web server to redirect 2) Setup a web server with MySQL. The following block can be used with nginx:
all URLs to /index.php/foo/bar/. The following block can be used with nginx:
server { server {
# https is preferred and can be done easily with LetsEncrypt # https is preferred and can be done easily with LetsEncrypt

View file

@ -26,7 +26,6 @@ Directory Layout
* `schema`: schema for the SQL database * `schema`: schema for the SQL database
* `test`: test suite and test cases * `test`: test suite and test cases
* `upgrading`: instructions for upgrading setups from one release to another * `upgrading`: instructions for upgrading setups from one release to another
* `web`: PHP-based web interface for the AUR
Documentation Documentation
------------- -------------

View file

@ -29,7 +29,6 @@ docker-compose
4) Browse to local aurweb development server. 4) Browse to local aurweb development server.
Python: https://localhost:8444/ Python: https://localhost:8444/
PHP: https://localhost:8443/
5) [Optionally] populate the database with dummy data: 5) [Optionally] populate the database with dummy data:

View file

@ -364,7 +364,7 @@ class ConnectionExecutor:
def execute(self, query, params=()): # pragma: no cover def execute(self, query, params=()): # pragma: no cover
# TODO: SQLite support has been removed in FastAPI. It remains # TODO: SQLite support has been removed in FastAPI. It remains
# here to fund its support for PHP until it is removed. # here to fund its support for the Sharness testsuite.
if self._paramstyle in ("format", "pyformat"): if self._paramstyle in ("format", "pyformat"):
query = query.replace("%", "%%").replace("?", "%s") query = query.replace("%", "%%").replace("?", "%s")
elif self._paramstyle == "qmark": elif self._paramstyle == "qmark":
@ -410,7 +410,7 @@ class Connection:
) )
elif aur_db_backend == "sqlite": # pragma: no cover elif aur_db_backend == "sqlite": # pragma: no cover
# TODO: SQLite support has been removed in FastAPI. It remains # TODO: SQLite support has been removed in FastAPI. It remains
# here to fund its support for PHP until it is removed. # here to fund its support for Sharness testsuite.
import math import math
import sqlite3 import sqlite3

View file

@ -20,7 +20,6 @@ from typing import Iterable
import aurweb.config import aurweb.config
import aurweb.schema import aurweb.schema
from aurweb.exceptions import AurwebException
children = [] children = []
temporary_dir = None temporary_dir = None
@ -28,9 +27,6 @@ verbosity = 0
asgi_backend = "" asgi_backend = ""
workers = 1 workers = 1
PHP_BINARY = os.environ.get("PHP_BINARY", "php")
PHP_MODULES = ["pdo_mysql", "pdo_sqlite"]
PHP_NGINX_PORT = int(os.environ.get("PHP_NGINX_PORT", 8001))
FASTAPI_NGINX_PORT = int(os.environ.get("FASTAPI_NGINX_PORT", 8002)) FASTAPI_NGINX_PORT = int(os.environ.get("FASTAPI_NGINX_PORT", 8002))
@ -47,42 +43,12 @@ class ProcessExceptions(Exception):
super().__init__("\n- ".join(messages)) super().__init__("\n- ".join(messages))
def validate_php_config() -> None:
"""
Perform a validation check against PHP_BINARY's configuration.
AurwebException is raised here if checks fail to pass. We require
the 'pdo_mysql' and 'pdo_sqlite' modules to be enabled.
:raises: AurwebException
:return: None
"""
try:
proc = subprocess.Popen(
[PHP_BINARY, "-m"], stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
out, _ = proc.communicate()
except FileNotFoundError:
raise AurwebException(f"Unable to locate the '{PHP_BINARY}' " "executable.")
assert proc.returncode == 0, (
"Received non-zero error code " f"{proc.returncode} from '{PHP_BINARY}'."
)
modules = out.decode().splitlines()
for module in PHP_MODULES:
if module not in modules:
raise AurwebException(f"PHP does not have the '{module}' module enabled.")
def generate_nginx_config(): def generate_nginx_config():
""" """
Generate an nginx configuration based on aurweb's configuration. Generate an nginx configuration based on aurweb's configuration.
The file is generated under `temporary_dir`. The file is generated under `temporary_dir`.
Returns the path to the created configuration file. Returns the path to the created configuration file.
""" """
php_bind = aurweb.config.get("php", "bind_address")
php_host = php_bind.split(":")[0]
fastapi_bind = aurweb.config.get("fastapi", "bind_address") fastapi_bind = aurweb.config.get("fastapi", "bind_address")
fastapi_host = fastapi_bind.split(":")[0] fastapi_host = fastapi_bind.split(":")[0]
config_path = os.path.join(temporary_dir, "nginx.conf") config_path = os.path.join(temporary_dir, "nginx.conf")
@ -101,12 +67,6 @@ def generate_nginx_config():
fastcgi_temp_path {os.path.join(temporary_dir, "fastcgi")}1 2; fastcgi_temp_path {os.path.join(temporary_dir, "fastcgi")}1 2;
uwsgi_temp_path {os.path.join(temporary_dir, "uwsgi")}; uwsgi_temp_path {os.path.join(temporary_dir, "uwsgi")};
scgi_temp_path {os.path.join(temporary_dir, "scgi")}; scgi_temp_path {os.path.join(temporary_dir, "scgi")};
server {{
listen {php_host}:{PHP_NGINX_PORT};
location / {{
proxy_pass http://{php_bind};
}}
}}
server {{ server {{
listen {fastapi_host}:{FASTAPI_NGINX_PORT}; listen {fastapi_host}:{FASTAPI_NGINX_PORT};
location / {{ location / {{
@ -154,7 +114,7 @@ def start():
terminal_width = 80 terminal_width = 80
print( print(
"{ruler}\n" "{ruler}\n"
"Spawing PHP and FastAPI, then nginx as a reverse proxy.\n" "Spawing FastAPI, then nginx as a reverse proxy.\n"
"Check out {aur_location}\n" "Check out {aur_location}\n"
"Hit ^C to terminate everything.\n" "Hit ^C to terminate everything.\n"
"{ruler}".format( "{ruler}".format(
@ -163,12 +123,6 @@ def start():
) )
) )
# PHP
php_address = aurweb.config.get("php", "bind_address")
php_host = php_address.split(":")[0]
htmldir = aurweb.config.get("php", "htmldir")
spawn_child(["php", "-S", php_address, "-t", htmldir])
# FastAPI # FastAPI
fastapi_host, fastapi_port = aurweb.config.get("fastapi", "bind_address").rsplit( fastapi_host, fastapi_port = aurweb.config.get("fastapi", "bind_address").rsplit(
":", 1 ":", 1
@ -210,10 +164,7 @@ def start():
f""" f"""
> Started nginx. > Started nginx.
> >
> PHP backend: http://{php_address}
> FastAPI backend: http://{fastapi_host}:{fastapi_port} > FastAPI backend: http://{fastapi_host}:{fastapi_port}
>
> PHP frontend: http://{php_host}:{PHP_NGINX_PORT}
> FastAPI frontend: http://{fastapi_host}:{FASTAPI_NGINX_PORT} > FastAPI frontend: http://{fastapi_host}:{FASTAPI_NGINX_PORT}
> >
> Frontends are hosted via nginx and should be preferred. > Frontends are hosted via nginx and should be preferred.
@ -307,12 +258,6 @@ if __name__ == "__main__":
) )
args = parser.parse_args() args = parser.parse_args()
try:
validate_php_config()
except AurwebException as exc:
print(f"error: {str(exc)}")
sys.exit(1)
verbosity = args.verbose verbosity = args.verbose
asgi_backend = args.backend asgi_backend = args.backend
workers = args.workers workers = args.workers

View file

@ -38,11 +38,9 @@ enable-maintenance = 1
maintenance-exceptions = 127.0.0.1 maintenance-exceptions = 127.0.0.1
render-comment-cmd = /usr/bin/aurweb-rendercomment render-comment-cmd = /usr/bin/aurweb-rendercomment
localedir = /srv/http/aurweb/web/locale/ localedir = /srv/http/aurweb/web/locale/
; memcache, apc, or redis ; cache: redis is supported in Python.
; memcache/apc are supported in PHP, redis is supported in Python.
cache = none cache = none
cache_pkginfo_ttl = 86400 cache_pkginfo_ttl = 86400
memcache_servers = 127.0.0.1:11211
salt_rounds = 12 salt_rounds = 12
redis_address = redis://localhost redis_address = redis://localhost
; Toggles traceback display in templates/errors/500.html. ; Toggles traceback display in templates/errors/500.html.
@ -125,12 +123,12 @@ sync-dbs = core extra community multilib testing community-testing
server = https://mirrors.kernel.org/archlinux/%s/os/x86_64 server = https://mirrors.kernel.org/archlinux/%s/os/x86_64
[mkpkglists] [mkpkglists]
archivedir = /srv/http/aurweb/web/html archivedir = /srv/http/aurweb/archives
packagesfile = /srv/http/aurweb/web/html/packages.gz packagesfile = /srv/http/aurweb/archives/packages.gz
packagesmetafile = /srv/http/aurweb/web/html/packages-meta-v1.json.gz packagesmetafile = /srv/http/aurweb/archives/packages-meta-v1.json.gz
packagesmetaextfile = /srv/http/aurweb/web/html/packages-meta-ext-v1.json.gz packagesmetaextfile = /srv/http/aurweb/archives/packages-meta-ext-v1.json.gz
pkgbasefile = /srv/http/aurweb/web/html/pkgbase.gz pkgbasefile = /srv/http/aurweb/archives/pkgbase.gz
userfile = /srv/http/aurweb/web/html/users.gz userfile = /srv/http/aurweb/archives/users.gz
[git-archive] [git-archive]
author = git_archive.py author = git_archive.py

View file

@ -6,7 +6,6 @@
; development-specific options too. ; development-specific options too.
[database] [database]
; PHP options: mysql, sqlite.
; FastAPI options: mysql. ; FastAPI options: mysql.
backend = mysql backend = mysql
@ -31,9 +30,6 @@ localedir = YOUR_AUR_ROOT/web/locale
salt_rounds = 4 salt_rounds = 4
; See config.defaults comment about cache. ; See config.defaults comment about cache.
cache = none cache = none
; In docker, the memcached host is available. On a user's system,
; this should be set to localhost (most likely).
memcache_servers = memcached:11211
; If cache = 'redis' this address is used to connect to Redis. ; If cache = 'redis' this address is used to connect to Redis.
redis_address = redis://127.0.0.1 redis_address = redis://127.0.0.1
aur_request_ml = aur-requests@localhost aur_request_ml = aur-requests@localhost
@ -51,13 +47,6 @@ openid_configuration = http://127.0.0.1:8083/auth/realms/aurweb/.well-known/open
client_id = aurweb client_id = aurweb
client_secret = client_secret =
[php]
; Address PHP should bind when spawned in development mode by aurweb.spawn.
bind_address = 127.0.0.1:8081
; Directory containing aurweb's PHP code, required by aurweb.spawn.
htmldir = YOUR_AUR_ROOT/web/html
[fastapi] [fastapi]
; Address uvicorn should bind when spawned in development mode by aurweb.spawn. ; Address uvicorn should bind when spawned in development mode by aurweb.spawn.
bind_address = 127.0.0.1:8082 bind_address = 127.0.0.1:8082

View file

@ -65,12 +65,9 @@ Services
| [mariadb](#mariadb) | 127.0.0.1:13306 | | [mariadb](#mariadb) | 127.0.0.1:13306 |
| [git](#git) | 127.0.0.1:2222 | | [git](#git) | 127.0.0.1:2222 |
| redis | 127.0.0.1:16379 | | redis | 127.0.0.1:16379 |
| [php-fpm](#php-fpm) | 127.0.0.1:19000 |
| cgit-php | |
| [fastapi](#fastapi) | 127.0.0.1:18000 | | [fastapi](#fastapi) | 127.0.0.1:18000 |
| cgit-fastapi | | | cgit-fastapi | |
| [nginx](#nginx) (fastapi) | 127.0.0.1:8444 | | [nginx](#nginx) (fastapi) | 127.0.0.1:8444 |
| [nginx](#nginx) (php) | 127.0.0.1:8443 |
There are more services which have not been referred to here; There are more services which have not been referred to here;
the services listed above encompass all notable services. Some the services listed above encompass all notable services. Some
@ -113,16 +110,6 @@ to be used for the AUR.
This service will perform setup in either case if the repository This service will perform setup in either case if the repository
is not yet initialized. is not yet initialized.
#### php-fpm
When running any services which use the _php-fpm_ backend or other
php-related services, users should define:
- `AURWEB_PHP_PREFIX`
- Default: `https://localhost:8443`
- `AURWEB_SSHD_PREFIX`
- Default: `ssh://aur@localhost:2222`
#### fastapi #### fastapi
The _fastapi_ service hosts a `gunicorn`, `uvicorn` or `hypercorn` The _fastapi_ service hosts a `gunicorn`, `uvicorn` or `hypercorn`
@ -145,20 +132,17 @@ backend or other fastapi-related services, users should define:
#### nginx #### nginx
The _nginx_ service binds to two host endpoints: 127.0.0.1:8444 (fastapi) The _nginx_ service binds to host endpoint: 127.0.0.1:8444 (fastapi).
and 127.0.0.1:8443 (php). Each instance is available over the `https` The instance is available over the `https`
protocol as noted in the table below. protocol as noted in the table below.
| Impl | Host Binding | URL | | Impl | Host Binding | URL |
|--------|----------------|------------------------| |--------|----------------|------------------------|
| Python | 127.0.0.1:8444 | https://localhost:8444 | | Python | 127.0.0.1:8444 | https://localhost:8444 |
| PHP | 127.0.0.1:8443 | https://localhost:8443 |
When running this service, the following variables should be defined: When running this service, the following variables should be defined:
- `AURWEB_FASTAPI_PREFIX` - `AURWEB_FASTAPI_PREFIX`
- Default: `https://localhost:8444` - Default: `https://localhost:8444`
- `AURWEB_PHP_PREFIX`
- Default: `https://localhost:8443`
- `AURWEB_SSHD_PREFIX` - `AURWEB_SSHD_PREFIX`
- Default: `ssh://aur@localhost:2222` - Default: `ssh://aur@localhost:2222`

View file

@ -21,7 +21,7 @@ The RPC interface can be used to query package information via HTTP.
Installation Installation
------------ ------------
The web backend requires a web server with PHP and an SQL database. The Git/SSH The web backend requires a web server and an SQL database. The Git/SSH
interface requires Python, several Python modules and an up-to-date version of interface requires Python, several Python modules and an up-to-date version of
Git. APCu or memcached can be used to reduce load on the database server. Git. APCu or memcached can be used to reduce load on the database server.

View file

@ -6,9 +6,6 @@ services:
- data:/data - data:/data
- step:/root/.step - step:/root/.step
memcached:
restart: always
redis: redis:
restart: always restart: always
@ -32,11 +29,6 @@ services:
- data:/data - data:/data
- smartgit_run:/var/run/smartgit - smartgit_run:/var/run/smartgit
cgit-php:
restart: always
volumes:
- ${GIT_DATA_DIR}:/aurweb/aur.git
cgit-fastapi: cgit-fastapi:
restart: always restart: always
volumes: volumes:
@ -48,14 +40,6 @@ services:
- mariadb_run:/var/run/mysqld - mariadb_run:/var/run/mysqld
- archives:/var/lib/aurweb/archives - archives:/var/lib/aurweb/archives
php-fpm:
restart: always
environment:
- AURWEB_PHP_PREFIX=${AURWEB_PHP_PREFIX}
- AURWEB_SSHD_PREFIX=${AURWEB_SSHD_PREFIX}
volumes:
- data:/data
fastapi: fastapi:
restart: always restart: always
environment: environment:

View file

@ -25,26 +25,12 @@ services:
mariadb: mariadb:
condition: service_healthy condition: service_healthy
php-fpm:
volumes:
- ./data:/data
- ./aurweb:/aurweb/aurweb
- ./migrations:/aurweb/migrations
- ./test:/aurweb/test
- ./web/html:/aurweb/web/html
- ./web/template:/aurweb/web/template
- ./web/lib:/aurweb/web/lib
- ./templates:/aurweb/templates
fastapi: fastapi:
volumes: volumes:
- ./data:/data - ./data:/data
- ./aurweb:/aurweb/aurweb - ./aurweb:/aurweb/aurweb
- ./migrations:/aurweb/migrations - ./migrations:/aurweb/migrations
- ./test:/aurweb/test - ./test:/aurweb/test
- ./web/html:/aurweb/web/html
- ./web/template:/aurweb/web/template
- ./web/lib:/aurweb/web/lib
- ./templates:/aurweb/templates - ./templates:/aurweb/templates
nginx: nginx:

View file

@ -10,11 +10,9 @@
# - `ca` - Certificate Authority generation # - `ca` - Certificate Authority generation
# - `git` - `port 2222` - Git over SSH server # - `git` - `port 2222` - Git over SSH server
# - `fastapi` - hypercorn service for aurweb's FastAPI app # - `fastapi` - hypercorn service for aurweb's FastAPI app
# - `php-fpm` - Execution server for PHP aurweb # - `nginx` - `port 8444 (FastAPI)
# - `nginx` - `ports 8444 (FastAPI), 8443 (PHP)` - Everything # - You can reach `nginx` via FastAPI at `https://localhost:8444/`.
# - You can reach `nginx` via FastAPI at `https://localhost:8444/` # CGit can be reached via the `/cgit/` request uri on either server.
# or via PHP at `https://localhost:8443/`. CGit can be reached
# via the `/cgit/` request uri on either server.
# #
# Copyright (C) 2021 aurweb Development # Copyright (C) 2021 aurweb Development
# All Rights Reserved. # All Rights Reserved.
@ -36,14 +34,6 @@ services:
volumes: volumes:
- step:/root/.step - step:/root/.step
memcached:
image: aurweb:latest
init: true
command: /docker/scripts/run-memcached.sh
healthcheck:
test: "bash /docker/health/memcached.sh"
interval: 3s
redis: redis:
image: aurweb:latest image: aurweb:latest
init: true init: true
@ -133,26 +123,6 @@ services:
test: "bash /docker/health/smartgit.sh" test: "bash /docker/health/smartgit.sh"
interval: 3s interval: 3s
cgit-php:
image: aurweb:latest
init: true
environment:
- AUR_CONFIG=/aurweb/conf/config
- CGIT_CLONE_PREFIX=${AURWEB_PHP_PREFIX}
- CGIT_CSS=/css/cgit.css
entrypoint: /docker/cgit-entrypoint.sh
command: /docker/scripts/run-cgit.sh 3000
healthcheck:
test: "bash /docker/health/cgit.sh 3000"
interval: 3s
depends_on:
git:
condition: service_healthy
ports:
- "127.0.0.1:13000:3000"
volumes:
- git_data:/aurweb/aur.git
cgit-fastapi: cgit-fastapi:
image: aurweb:latest image: aurweb:latest
init: true init: true
@ -189,32 +159,6 @@ services:
- mariadb_run:/var/run/mysqld - mariadb_run:/var/run/mysqld
- archives:/var/lib/aurweb/archives - archives:/var/lib/aurweb/archives
php-fpm:
image: aurweb:latest
init: true
environment:
- AUR_CONFIG=/aurweb/conf/config
- AURWEB_PHP_PREFIX=${AURWEB_PHP_PREFIX}
- AURWEB_SSHD_PREFIX=${AURWEB_SSHD_PREFIX}
- AUR_CONFIG_IMMUTABLE=${AUR_CONFIG_IMMUTABLE:-0}
entrypoint: /docker/php-entrypoint.sh
command: /docker/scripts/run-php.sh
healthcheck:
test: "bash /docker/health/php.sh"
interval: 3s
depends_on:
git:
condition: service_healthy
memcached:
condition: service_healthy
cron:
condition: service_started
volumes:
- mariadb_run:/var/run/mysqld
- archives:/var/lib/aurweb/archives
ports:
- "127.0.0.1:19000:9000"
fastapi: fastapi:
image: aurweb:latest image: aurweb:latest
init: true init: true
@ -252,7 +196,6 @@ services:
entrypoint: /docker/nginx-entrypoint.sh entrypoint: /docker/nginx-entrypoint.sh
command: /docker/scripts/run-nginx.sh command: /docker/scripts/run-nginx.sh
ports: ports:
- "127.0.0.1:8443:8443" # PHP
- "127.0.0.1:8444:8444" # FastAPI - "127.0.0.1:8444:8444" # FastAPI
healthcheck: healthcheck:
test: "bash /docker/health/nginx.sh" test: "bash /docker/health/nginx.sh"
@ -260,16 +203,12 @@ services:
depends_on: depends_on:
ca: ca:
condition: service_healthy condition: service_healthy
cgit-php:
condition: service_healthy
cgit-fastapi: cgit-fastapi:
condition: service_healthy condition: service_healthy
smartgit: smartgit:
condition: service_healthy condition: service_healthy
fastapi: fastapi:
condition: service_healthy condition: service_healthy
php-fpm:
condition: service_healthy
sharness: sharness:
image: aurweb:latest image: aurweb:latest
@ -290,9 +229,6 @@ services:
- ./aurweb:/aurweb/aurweb - ./aurweb:/aurweb/aurweb
- ./migrations:/aurweb/migrations - ./migrations:/aurweb/migrations
- ./test:/aurweb/test - ./test:/aurweb/test
- ./web/html:/aurweb/web/html
- ./web/template:/aurweb/web/template
- ./web/lib:/aurweb/web/lib
- ./templates:/aurweb/templates - ./templates:/aurweb/templates
pytest-mysql: pytest-mysql:
@ -319,9 +255,6 @@ services:
- ./aurweb:/aurweb/aurweb - ./aurweb:/aurweb/aurweb
- ./migrations:/aurweb/migrations - ./migrations:/aurweb/migrations
- ./test:/aurweb/test - ./test:/aurweb/test
- ./web/html:/aurweb/web/html
- ./web/template:/aurweb/web/template
- ./web/lib:/aurweb/web/lib
- ./templates:/aurweb/templates - ./templates:/aurweb/templates
test: test:
@ -346,9 +279,6 @@ services:
- ./aurweb:/aurweb/aurweb - ./aurweb:/aurweb/aurweb
- ./migrations:/aurweb/migrations - ./migrations:/aurweb/migrations
- ./test:/aurweb/test - ./test:/aurweb/test
- ./web/html:/aurweb/web/html
- ./web/template:/aurweb/web/template
- ./web/lib:/aurweb/web/lib
- ./templates:/aurweb/templates - ./templates:/aurweb/templates
volumes: volumes:

View file

@ -55,8 +55,7 @@ can proceed.
### Querying the RPC ### Querying the RPC
The Fast (Python) API runs on Port 8444, while the legacy PHP version runs The Fast (Python) API runs on Port 8444. You can query one like so:
on 8443. You can query one like so:
```sh ```sh
curl -k "https://localhost:8444/rpc/?v=5&type=search&arg=python" curl -k "https://localhost:8444/rpc/?v=5&type=search&arg=python"

View file

@ -27,10 +27,6 @@ http {
server fastapi:8000; server fastapi:8000;
} }
upstream cgit-php {
server cgit-php:3000;
}
upstream cgit-fastapi { upstream cgit-fastapi {
server cgit-fastapi:3000; server cgit-fastapi:3000;
} }
@ -39,54 +35,6 @@ http {
server unix:/var/run/smartgit/smartgit.sock; server unix:/var/run/smartgit/smartgit.sock;
} }
server {
listen 8443 ssl http2;
server_name localhost default_server;
ssl_certificate /etc/ssl/certs/web.cert.pem;
ssl_certificate_key /etc/ssl/private/web.key.pem;
root /aurweb/web/html;
index index.php;
location ~ "^/([a-z0-9][a-z0-9.+_-]*?)(\.git)?/(git-(receive|upload)-pack|HEAD|info/refs|objects/(info/(http-)?alternates|packs)|[0-9a-f]{2}/[0-9a-f]{38}|pack/pack-[0-9a-f]{40}\.(pack|idx))$" {
include uwsgi_params;
uwsgi_pass smartgit;
uwsgi_modifier1 9;
uwsgi_param SCRIPT_FILENAME /usr/lib/git-core/git-http-backend;
uwsgi_param PATH_INFO /aur.git/$3;
uwsgi_param GIT_HTTP_EXPORT_ALL "";
uwsgi_param GIT_NAMESPACE $1;
uwsgi_param GIT_PROJECT_ROOT /aurweb;
}
location ~ ^/cgit {
include uwsgi_params;
rewrite ^/cgit/([^?/]+/[^?]*)?(?:\?(.*))?$ /cgit.cgi?url=$1&$2 last;
uwsgi_modifier1 9;
uwsgi_param CGIT_CONFIG /etc/cgitrc;
uwsgi_pass uwsgi://cgit-php;
}
location ~ ^/[^/]+\.php($|/) {
fastcgi_pass php-fpm:9000;
fastcgi_index index.php;
fastcgi_split_path_info ^(/[^/]+\.php)(/.*)$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
include fastcgi_params;
}
location ~ .+\.(css|js?|jpe?g|png|svg|ico)/?$ {
try_files $uri =404;
}
location ~ .* {
rewrite ^/(.*)$ /index.php/$1 last;
}
}
server { server {
listen 8444 ssl http2; listen 8444 ssl http2;
server_name localhost default_server; server_name localhost default_server;

View file

@ -1,2 +0,0 @@
#!/bin/bash
exec pgrep memcached

View file

@ -1,2 +0,0 @@
#!/bin/bash
exec printf "" >>/dev/tcp/127.0.0.1/9000

View file

@ -12,7 +12,7 @@ while ! mysqladmin ping 2>/dev/null; do
done done
# Configure databases. # Configure databases.
DATABASE="aurweb" # Persistent database for fastapi/php-fpm. DATABASE="aurweb" # Persistent database for fastapi.
echo "Taking care of primary database '${DATABASE}'..." echo "Taking care of primary database '${DATABASE}'..."
mysql -u root -e "CREATE USER IF NOT EXISTS 'aur'@'localhost' IDENTIFIED BY 'aur';" mysql -u root -e "CREATE USER IF NOT EXISTS 'aur'@'localhost' IDENTIFIED BY 'aur';"

View file

@ -1,32 +0,0 @@
#!/bin/bash
set -eou pipefail
for archive in packages pkgbase users packages-meta-v1.json packages-meta-ext-v1.json; do
ln -vsf /var/lib/aurweb/archives/${archive}.gz /aurweb/web/html/${archive}.gz
done
# Setup database.
NO_INITDB=1 /docker/mariadb-init-entrypoint.sh
# Setup some other options.
aurweb-config set options cache 'memcache'
aurweb-config set options aur_location "$AURWEB_PHP_PREFIX"
aurweb-config set options git_clone_uri_anon "${AURWEB_PHP_PREFIX}/%s.git"
aurweb-config set options git_clone_uri_priv "${AURWEB_SSHD_PREFIX}/%s.git"
# Listen on :9000.
sed -ri 's/^(listen).*/\1 = 0.0.0.0:9000/' /etc/php/php-fpm.d/www.conf
sed -ri 's/^;?(clear_env).*/\1 = no/' /etc/php/php-fpm.d/www.conf
# Log to stderr. View logs via `docker-compose logs php-fpm`.
sed -ri 's|^(error_log) = .*$|\1 = /proc/self/fd/2|g' /etc/php/php-fpm.conf
sed -ri 's|^;?(access\.log) = .*$|\1 = /proc/self/fd/2|g' \
/etc/php/php-fpm.d/www.conf
sed -ri 's/^;?(extension=pdo_mysql)/\1/' /etc/php/php.ini
sed -ri 's/^;?(open_basedir).*$/\1 = \//' /etc/php/php.ini
# Use the sqlite3 extension line for memcached.
sed -ri 's/^;(extension)=sqlite3$/\1=memcached/' /etc/php/php.ini
exec "$@"

View file

@ -15,9 +15,8 @@ pacman -Sy --noconfirm --noprogressbar archlinux-keyring
pacman -Syu --noconfirm --noprogressbar \ pacman -Syu --noconfirm --noprogressbar \
--cachedir .pkg-cache git gpgme nginx redis openssh \ --cachedir .pkg-cache git gpgme nginx redis openssh \
mariadb mariadb-libs cgit-aurweb uwsgi uwsgi-plugin-cgi \ mariadb mariadb-libs cgit-aurweb uwsgi uwsgi-plugin-cgi \
php php-fpm memcached php-memcached python-pip pyalpm \ python-pip pyalpm python-srcinfo curl libeatmydata cronie \
python-srcinfo curl libeatmydata cronie python-poetry \ python-poetry python-poetry-core step-cli step-ca asciidoc \
python-poetry-core step-cli step-ca asciidoc \
python-virtualenv python-pre-commit python-virtualenv python-pre-commit
exec "$@" exec "$@"

View file

@ -1,2 +0,0 @@
#!/bin/bash
exec /usr/bin/memcached -u memcached -m 64 -c 1024 -l 0.0.0.0

View file

@ -5,8 +5,6 @@ echo
echo " Services:" echo " Services:"
echo " - FastAPI : https://localhost:8444/" echo " - FastAPI : https://localhost:8444/"
echo " (cgit) : https://localhost:8444/cgit/" echo " (cgit) : https://localhost:8444/cgit/"
echo " - PHP : https://localhost:8443/"
echo " (cgit) : https://localhost:8443/cgit/"
echo echo
echo " Note: Copy root CA (./data/ca.root.pem) to ca-certificates or browser." echo " Note: Copy root CA (./data/ca.root.pem) to ca-certificates or browser."
echo echo

View file

@ -1,4 +0,0 @@
#!/bin/bash
set -eou pipefail
exec php-fpm --fpm-config /etc/php/php-fpm.conf --nodaemonize

View file

@ -48,20 +48,12 @@ all: ${MOFILES}
lang=`echo $@ | sed -e 's/\.po-update$$//'`; \ lang=`echo $@ | sed -e 's/\.po-update$$//'`; \
msgmerge -U --no-location --lang="$$lang" $< aurweb.pot msgmerge -U --no-location --lang="$$lang" $< aurweb.pot
POTFILES-php:
find ../web -type f -name '*.php' -printf '%P\n' | sort >POTFILES-php
POTFILES-py: POTFILES-py:
find ../aurweb -type f -name '*.py' -printf '%P\n' | sort >POTFILES-py find ../aurweb -type f -name '*.py' -printf '%P\n' | sort >POTFILES-py
update-pot: POTFILES-php POTFILES-py update-pot: POTFILES-py
pkgname=AURWEB; \ pkgname=AURWEB; \
pkgver=`sed -n 's/.*"AURWEB_VERSION", "\(.*\)".*/\1/p' ../web/lib/version.inc.php`; \ pkgver=`sed -n 's/version\s*=\s*"\(.*\)"/\1/p' ../pyproject.toml`; \
xgettext --default-domain=aurweb -L php --keyword=__ --keyword=_n:1,2 \
--add-location=file --add-comments=TRANSLATORS: \
--package-name="$$pkgname" --package-version="$$pkgver" \
--msgid-bugs-address='${MSGID_BUGS_ADDRESS}' \
--directory ../web --files-from POTFILES-php -o aurweb.pot; \
xgettext --default-domain=aurweb -L python --join-existing \ xgettext --default-domain=aurweb -L python --join-existing \
--keyword=translate \ --keyword=translate \
--add-location=file --add-comments=TRANSLATORS: \ --add-location=file --add-comments=TRANSLATORS: \
@ -73,7 +65,7 @@ update-po:
${MAKE} ${UPDATEPOFILES} ${MAKE} ${UPDATEPOFILES}
clean: clean:
rm -f *.mo *.po\~ POTFILES-php POTFILES-py rm -f *.mo *.po\~ POTFILES-py
install: all install: all
for l in ${LOCALES}; do mkdir -p ${DESTDIR}${PREFIX}/$$l/LC_MESSAGES/; done for l in ${LOCALES}; do mkdir -p ${DESTDIR}${PREFIX}/$$l/LC_MESSAGES/; done
@ -82,4 +74,4 @@ install: all
uninstall: uninstall:
for l in ${LOCALES}; do rm -rf ${DESTDIR}${PREFIX}/$$l/LC_MESSAGES/; done for l in ${LOCALES}; do rm -rf ${DESTDIR}${PREFIX}/$$l/LC_MESSAGES/; done
.PHONY: all update-pot update-po clean install uninstall POTFILES-php POTFILES-py .PHONY: all update-pot update-po clean install uninstall POTFILES-py

View file

@ -7,10 +7,9 @@ import pytest
import aurweb.config import aurweb.config
import aurweb.spawn import aurweb.spawn
from aurweb.exceptions import AurwebException
# Some os.environ overrides we use in this suite. # Some os.environ overrides we use in this suite.
TEST_ENVIRONMENT = {"PHP_NGINX_PORT": "8001", "FASTAPI_NGINX_PORT": "8002"} TEST_ENVIRONMENT = {"FASTAPI_NGINX_PORT": "8002"}
class FakeProcess: class FakeProcess:
@ -49,34 +48,6 @@ class MockFakeProcess:
return proc return proc
@mock.patch("aurweb.spawn.PHP_BINARY", "does-not-exist")
def test_spawn():
match = r"^Unable to locate the '.*' executable\.$"
with pytest.raises(AurwebException, match=match):
aurweb.spawn.validate_php_config()
@mock.patch("subprocess.Popen", side_effect=MockFakeProcess(1).process)
def test_spawn_non_zero_php_binary(fake_process: FakeProcess):
match = r"^Received non-zero error code.*$"
with pytest.raises(AssertionError, match=match):
aurweb.spawn.validate_php_config()
def test_spawn_missing_modules():
side_effect = MockFakeProcess(stdout=b"pdo_sqlite").process
with mock.patch("subprocess.Popen", side_effect=side_effect):
match = r"PHP does not have the 'pdo_mysql' module enabled\.$"
with pytest.raises(AurwebException, match=match):
aurweb.spawn.validate_php_config()
side_effect = MockFakeProcess(stdout=b"pdo_mysql").process
with mock.patch("subprocess.Popen", side_effect=side_effect):
match = r"PHP does not have the 'pdo_sqlite' module enabled\.$"
with pytest.raises(AurwebException, match=match):
aurweb.spawn.validate_php_config()
@mock.patch.dict("os.environ", TEST_ENVIRONMENT) @mock.patch.dict("os.environ", TEST_ENVIRONMENT)
def test_spawn_generate_nginx_config(): def test_spawn_generate_nginx_config():
ctx = tempfile.TemporaryDirectory() ctx = tempfile.TemporaryDirectory()
@ -86,13 +57,9 @@ def test_spawn_generate_nginx_config():
with open(nginx_config_path) as f: with open(nginx_config_path) as f:
nginx_config = f.read().rstrip() nginx_config = f.read().rstrip()
php_address = aurweb.config.get("php", "bind_address")
php_host = php_address.split(":")[0]
fastapi_address = aurweb.config.get("fastapi", "bind_address") fastapi_address = aurweb.config.get("fastapi", "bind_address")
fastapi_host = fastapi_address.split(":")[0] fastapi_host = fastapi_address.split(":")[0]
expected_content = [ expected_content = [
f'listen {php_host}:{TEST_ENVIRONMENT.get("PHP_NGINX_PORT")}',
f"proxy_pass http://{php_address}",
f'listen {fastapi_host}:{TEST_ENVIRONMENT.get("FASTAPI_NGINX_PORT")}', f'listen {fastapi_host}:{TEST_ENVIRONMENT.get("FASTAPI_NGINX_PORT")}',
f"proxy_pass http://{fastapi_address}", f"proxy_pass http://{fastapi_address}",
] ]

View file

@ -1,47 +0,0 @@
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . '../lib');
$path = $_SERVER['PATH_INFO'];
$tokens = explode('/', $path);
if (isset($tokens[1]) && preg_match('/^([a-z0-9][a-z0-9.+_-]*?)(\.git)?$/', $tokens[1], $matches)) {
$gitpkg = $matches[1];
if (pkg_from_name($gitpkg)) {
$gitcmd = 'git clone ' . sprintf(config_get('options', 'git_clone_uri_anon'), htmlspecialchars($gitpkg));
$gitlink = get_pkgbase_uri($gitpkg);
} else {
unset($gitpkg);
}
} else {
unset($gitpkg);
}
html_header( __("Page Not Found") );
?>
<div id="error-page" class="box 404">
<h2>404 - <?= __("Page Not Found") ?></h2>
<p><?= __("Sorry, the page you've requested does not exist.") ?></p>
<?php if (isset($gitpkg)): ?>
<ul>
<li>
<strong><?= __("Note") ?>:</strong>
<?= __("Git clone URLs are not meant to be opened in a browser.") ?>
</li>
<li>
<?= __("To clone the Git repository of %s, run %s.",
'<strong>' . htmlspecialchars($gitpkg) . '</strong>',
'<code>' . htmlspecialchars($gitcmd) . '</code>') ?>
</li>
<li>
<?= __("Click %shere%s to return to the %s details page.",
'<a href="' . htmlspecialchars($gitlink, ENT_QUOTES) . '">', '</a>',
'<strong>' . htmlspecialchars($gitpkg) . '</strong>') ?>
</li>
</ul>
<?php endif; ?>
</div>
<?php
html_footer(AURWEB_VERSION);

View file

@ -1,14 +0,0 @@
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . '../lib');
html_header( __("Service Unavailable") );
?>
<div id="error-page" class="box 503">
<h2>503 - <?= __("Service Unavailable") ?></h2>
<p><?= __("Don't panic! This site is down due to maintenance. We will be back soon.") ?></p>
</div>
<?php
html_footer(AURWEB_VERSION);

View file

@ -1,223 +0,0 @@
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . '../lib');
include_once('aur.inc.php'); # access AUR common functions
include_once('acctfuncs.inc.php'); # access Account specific functions
$action = in_request("Action");
$need_userinfo = array(
"DisplayAccount", "DeleteAccount", "AccountInfo", "UpdateAccount", "ListComments"
);
if (in_array($action, $need_userinfo)) {
$row = account_details(in_request("ID"), in_request("U"));
$PK = implode("\n", account_get_ssh_keys($row["ID"]));
}
/* This has to be done before the navigation headers are written,
* because html_header() fetches the current username from the database,
* which could be changed by process_account_form()
*/
if ($action == "UpdateAccount") {
$success = false;
$update_account_message = '';
/* Details for account being updated */
/* Verify user permissions and that the request is a valid POST */
if ($row && can_edit_account($row) && check_token()) {
/* Update the details for the existing account */
list($success, $update_account_message) = process_account_form(
"edit", "UpdateAccount",
in_request("U"),
in_request("T"),
in_request("S"),
in_request("E"),
in_request("BE"),
in_request("H"),
in_request("P"),
in_request("C"),
in_request("R"),
in_request("L"),
in_request("TZ"),
in_request("HP"),
in_request("I"),
in_request("K"),
in_request("PK"),
in_request("J"),
in_request("CN"),
in_request("UN"),
in_request("ON"),
in_request("ID"),
$row["Username"],
in_request("passwd")
);
}
}
if ($row && $action == "AccountInfo") {
html_header(__('Account') . ' ' . $row['Username']);
} else {
html_header(__('Accounts'));
}
# Main page processing here
#
echo "<div class=\"box\">\n";
echo " <h2>".__("Accounts")."</h2>\n";
if (isset($_COOKIE["AURSID"])) {
if ($action == "SearchAccounts") {
# security check
#
if (has_credential(CRED_ACCOUNT_SEARCH)) {
# the user has entered search criteria, find any matching accounts
#
search_results_page(in_request("O"), in_request("SB"),
in_request("U"), in_request("T"), in_request("S"),
in_request("E"), in_request("R"), in_request("I"),
in_request("K"));
} else {
# a non-privileged user is trying to access the search page
#
print __("You are not allowed to access this area.")."<br />\n";
}
} elseif ($action == "DisplayAccount") {
# the user has clicked 'edit', display the account details in a form
#
if (empty($row)) {
print __("Could not retrieve information for the specified user.");
} else {
/* Verify user has permission to edit the account */
if (can_edit_account($row)) {
display_account_form("UpdateAccount",
$row["Username"],
$row["AccountTypeID"],
$row["Suspended"],
$row["Email"],
$row["BackupEmail"],
$row["HideEmail"],
"",
"",
$row["RealName"],
$row["LangPreference"],
$row["Timezone"],
$row["Homepage"],
$row["IRCNick"],
$row["PGPKey"],
$PK,
$row["InactivityTS"] ? 1 : 0,
$row["CommentNotify"],
$row["UpdateNotify"],
$row["OwnershipNotify"],
$row["ID"],
$row["Username"]);
} else {
print __("You do not have permission to edit this account.");
}
}
} elseif ($action == "DeleteAccount") {
/* Details for account being deleted. */
if ($row && can_edit_account($row)) {
$uid_removal = $row['ID'];
$uid_session = uid_from_sid($_COOKIE['AURSID']);
$username = $row['Username'];
if (in_request('confirm') && check_token()) {
if (check_passwd($uid_session, $_REQUEST['passwd']) == 1) {
user_delete($uid_removal);
header('Location: /');
} else {
echo "<ul class='errorlist'><li>";
echo __("Invalid password.");
echo "</li></ul>";
include("account_delete.php");
}
} else {
include("account_delete.php");
}
} else {
print __("You do not have permission to edit this account.");
}
} elseif ($action == "AccountInfo") {
# no editing, just looking up user info
#
if (empty($row)) {
print __("Could not retrieve information for the specified user.");
} else {
include("account_details.php");
}
} elseif ($action == "UpdateAccount") {
print $update_account_message;
if ($row && !$success) {
display_account_form("UpdateAccount",
in_request("U"),
in_request("T"),
in_request("S"),
in_request("E"),
in_request("BE"),
in_request("H"),
in_request("P"),
in_request("C"),
in_request("R"),
in_request("L"),
in_request("TZ"),
in_request("HP"),
in_request("I"),
in_request("K"),
in_request("PK"),
in_request("J"),
in_request("CN"),
in_request("UN"),
in_request("ON"),
in_request("ID"),
$row["Username"]);
}
} elseif ($action == "ListComments") {
if ($row && has_credential(CRED_ACCOUNT_LIST_COMMENTS, array($row["ID"]))) {
# display the comment list if they're a TU/dev
$total_comment_count = account_comments_count($row["ID"]);
list($pagination_templs, $per_page, $offset) = calculate_pagination($total_comment_count);
$username = $row["Username"];
$uid = $row["ID"];
$comments = account_comments($uid, $per_page, $offset);
$comment_section = "account";
include('pkg_comments.php');
} else {
print __("You are not allowed to access this area.");
}
} else {
if (has_credential(CRED_ACCOUNT_SEARCH)) {
# display the search page if they're a TU/dev
#
print __("Use this form to search existing accounts.")."<br />\n";
include('search_accounts_form.php');
} else {
print __("You are not allowed to access this area.");
}
}
} else {
# visitor is not logged in
#
print __("You must log in to view user information.");
}
echo "</div>";
html_footer(AURWEB_VERSION);
?>

View file

@ -1,116 +0,0 @@
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . '../lib');
include_once("aur.inc.php");
$title = __("Add Proposal");
html_header($title);
if (isset($_COOKIE["AURSID"])) {
$uid = uid_from_sid($_COOKIE["AURSID"]);
}
if (has_credential(CRED_TU_ADD_VOTE)) {
if (!empty($_POST['addVote']) && !check_token()) {
$error = __("Invalid token for user action.");
}
if (!empty($_POST['addVote']) && check_token()) {
$error = "";
if (!empty($_POST['user'])) {
if (!uid_from_username($_POST['user'])) {
$error.= __("Username does not exist.");
} else {
if (open_user_proposals($_POST['user'])) {
$error.= __("%s already has proposal running for them.", htmlentities($_POST['user']));
}
}
}
if (!empty($_POST['type'])) {
switch ($_POST['type']) {
case "add_tu":
/* Addition of a TU */
$len = 7 * 24 * 60 * 60;
$quorum = 0.66;
break;
case "remove_tu":
/* Removal of a TU */
$len = 7 * 24 * 60 * 60;
$quorum = 0.75;
break;
case "remove_inactive_tu":
/* Removal of a TU (undeclared inactivity) */
$len = 5 * 24 * 60 * 60;
$quorum = 0.66;
break;
case "bylaws":
/* Amendment of Bylaws */
$len = 7 * 24 * 60 * 60;
$quorum = 0.75;
break;
default:
$error.= __("Invalid type.") ;
break;
}
} else {
$error.= __("Invalid type.") ;
}
if (empty($_POST['agenda'])) {
$error.= __("Proposal cannot be empty.");
}
}
if (!empty($_POST['addVote']) && empty($error)) {
// Convert $quorum to a String of maximum length "12.34" (5).
add_tu_proposal($_POST['agenda'], $_POST['user'],
$len, strval($quorum), $uid);
print "<p class=\"pkgoutput\">" . __("New proposal submitted.") . "</p>\n";
} else {
?>
<?php if (!empty($error)): ?>
<p style="color: red;" class="pkgoutput"><?= $error ?></p>
<?php endif; ?>
<div class="box">
<h2><?= __("Submit a proposal to vote on.") ?></h2>
<form action="<?= get_uri('/addvote/'); ?>" method="post">
<p>
<label for="id_user"><?= __("Applicant/TU") ?></label>
<input type="text" name="user" id="id_user" value="<?php if (!empty($_POST['user'])) { print htmlentities($_POST['user'], ENT_QUOTES); } ?>" />
<?= __("(empty if not applicable)") ?>
</p>
<p>
<label for="id_type"><?= __("Type") ?></label>
<select name="type" id="id_type">
<option value="add_tu"><?= __("Addition of a TU") ?></option>
<option value="remove_tu"><?= __("Removal of a TU") ?></option>
<option value="remove_inactive_tu"><?= __("Removal of a TU (undeclared inactivity)") ?></option>
<option value="bylaws"><?= __("Amendment of Bylaws") ?></option>
</select>
</p>
<p>
<label for="id_agenda"><?= __("Proposal") ?></label><br />
<textarea name="agenda" id="id_agenda" rows="15" cols="80"><?php if (!empty($_POST['agenda'])) { print htmlentities($_POST['agenda']); } ?></textarea><br />
<input type="hidden" name="addVote" value="1" />
<input type="hidden" name="token" value="<?= htmlspecialchars($_COOKIE['AURSID']) ?>" />
<input type="submit" class="button" value="<?= __("Submit"); ?>" />
</p>
</form>
</div>
<?php
}
} else {
print __("You are not allowed to access this area.");
}
html_footer(AURWEB_VERSION);

View file

@ -1,16 +0,0 @@
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . '../lib');
include_once("aur.inc.php");
include_once("pkgbasefuncs.inc.php");
if (!isset($base_id) || !has_credential(CRED_PKGBASE_EDIT_COMAINTAINERS, array(pkgbase_maintainer_uid($base_id)))) {
header('Location: /');
exit();
}
html_header(__("Manage Co-maintainers"));
$users = pkgbase_get_comaintainers($base_id);
include('comaintainers_form.php');
html_footer(AURWEB_VERSION);

View file

@ -1,18 +0,0 @@
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . '../lib');
include_once("aur.inc.php");
include_once("pkgbasefuncs.inc.php");
$comment_id = intval($_REQUEST['comment_id']);
list($user_id, $comment) = comment_by_id($comment_id);
if (!isset($base_id) || !has_credential(CRED_COMMENT_EDIT, array($user_id)) || is_null($comment)) {
header('Location: /');
exit();
}
html_header(__("Edit comment"));
include('pkg_comment_box.php');
html_footer(AURWEB_VERSION);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

View file

@ -1,26 +0,0 @@
/*
* ARCH GLOBAL NAVBAR
* We're forcing all generic selectors with !important
* to help prevent other stylesheets from interfering.
*/
/* container for the entire bar */
#archnavbar { min-height: 40px !important; padding: 10px 15px !important; background: #333 !important; border-bottom: 5px #08c solid !important; }
#archnavbarlogo { background: url('archlogo.png') no-repeat !important; }
/* move the heading/paragraph text offscreen */
#archnavbarlogo p { margin: 0 !important; padding: 0 !important; text-indent: -9999px !important; }
#archnavbarlogo h1 { margin: 0 !important; padding: 0 !important; text-indent: -9999px !important; }
/* make the link the same size as the logo */
#archnavbarlogo a { display: block !important; height: 40px !important; width: 190px !important; }
/* display the list inline, float it to the right and style it */
[dir="rtl"] #archnavbar ul { text-align: left !important; }
#archnavbar ul { display: block !important; list-style: none !important; margin: 0 !important; padding: 0 !important; font-size: 0px !important; text-align: right !important; }
[dir="rtl"] #archnavbar ul li { padding: 14px 0px 0px 15px !important; }
#archnavbar ul li { display: inline-block !important; font-size: 14px !important; font-family: sans-serif !important; line-height: 14px !important; padding: 14px 15px 0px !important; }
/* style the links */
#archnavbar ul#archnavbarlist li a { color: #999; font-weight: bold !important; text-decoration: none !important; }
#archnavbar ul li a:hover { color: white !important; text-decoration: underline !important; }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

File diff suppressed because it is too large Load diff

View file

@ -1,292 +0,0 @@
/* aurweb-specific customizations to archweb.css */
#archnavbar.anb-aur ul li#anb-aur a {
color: white !important;
}
#archnavbarlogo {
background: url('archnavbar/aurlogo.png') !important;
}
[dir="rtl"] #lang_sub {
float: left;
}
#lang_sub {
float: right;
}
.pkglist-nav .page {
margin: 0 .25em;
}
#pkg-stats td.stat-desc {
white-space: normal;
}
#actionlist form {
margin: 0;
padding: 0;
}
.arch-bio-entry ul {
list-style: none;
padding: 0;
}
#pkg-updates table {
table-layout: fixed;
width:100%;
}
#pkg-updates td.pkg-name {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
[dir="rtl"] #pkg-updates td.pkg-date {
text-align:left;
}
#pkg-updates td.pkg-date {
text-align:right;
}
[dir="rtl"] .keyword:link, .keyword:visited {
float: right;
}
.keyword:link, .keyword:visited {
float: left;
margin: 1px .5ex 1px 0;
padding: 0 1em;
color: white;
background-color: #36a;
border: 1px solid transparent;
border-radius: 2px;
}
.keyword:hover {
cursor: pointer;
}
.keyword:focus {
border: 1px dotted #000;
}
.text-button {
background: transparent;
border: none !important;
margin: 0 !important;
padding: 0 !important;
font: normal 100% sans-serif;
text-decoration: none;
color: #07b;
cursor: pointer;
}
.text-button:hover {
text-decoration: underline;
color: #666;
}
.text-button::-moz-focus-inner {
padding: 0;
border: none;
}
.comment-deleted {
color: #999;
}
.edited {
font-size: 0.9em;
color: #999;
}
[dir="rtl"] .delete-comment-form, .undelete-comment-form, .pin-comment-form, .edit-comment {
float: left;
margin-right: 8px;
}
.delete-comment-form, .undelete-comment-form, .pin-comment-form, .edit-comment {
float: right;
margin-left: 8px;
}
.edit-comment {
height: 11px;
position: relative;
top: 1px;
}
.comment-enable-notifications {
display: inline-block;
margin-left: 1em;
}
.rss-icon, .delete-comment, .undelete-comment, .edit-comment, .pin-comment {
filter: grayscale(100%);
opacity: 0.6;
}
.rss-icon:hover, .delete-comment:hover, .undelete-comment:hover, .edit-comment:hover, .pin-comment:hover {
filter: none;
opacity: 1;
}
[dir="rtl"] .ajax-loader {
float: left;
}
.ajax-loader {
float: right;
position: relative;
top: 4px;
}
.flagged a {
color: inherit;
}
legend {
padding: 1em 0;
}
p.important {
font-weight: bold;
}
span.hover-help {
border-bottom: 1px dotted black;
cursor:help;
}
label.confirmation {
width: auto;
}
#pkgdepslist .broken {
color: red;
font-weight: bold;
}
.package-comments {
margin-top: 1.5em;
}
.comments-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
}
/* arrowed headings */
.comments-header h3 span.text {
display: block;
background: #1794D1;
font-size: 15px;
padding: 2px 10px;
color: white;
}
.comments-header .comments-header-nav {
align-self: flex-end;
}
.comments-footer {
display: flex;
justify-content: flex-end;
}
.comment-header {
clear: both;
font-size: 1em;
margin-top: 1.5em;
border-bottom: 1px dotted #bbb;
}
.comments div {
margin-bottom: 1em;
}
.comments div p {
margin-bottom: 0.5em;
}
.comments .more {
font-weight: normal;
}
.error {
color: red;
}
.article-content > div {
overflow: hidden;
transition: height 1s;
}
.proposal.details {
margin: .33em 0 1em;
}
button[type="submit"],
button[type="reset"] {
padding: 0 0.6em;
}
.results tr td[align="left"] fieldset {
text-align: left;
}
.results tr td[align="right"] fieldset {
text-align: right;
}
input#search-action-submit {
width: 80px;
}
.success {
color: green;
}
/* Styling used to clone <a> styles for a form.link button. */
form.link, form.link button {
display: inline;
font-family: sans-serif;
}
form.link button {
padding: 0 0.5em;
color: #07b;
background: none;
border: none;
font-family: inherit;
font-size: inherit;
}
form.link button:hover {
cursor: pointer;
text-decoration: underline;
}
/* Customize form.link when used inside of a page. */
div.box form.link p {
margin: .33em 0 1em;
}
div.box form.link button {
padding: 0;
}
pre.traceback {
/* https://css-tricks.com/snippets/css/make-pre-text-wrap/ */
white-space: pre-wrap;
word-wrap: break-all;
}
/* By default, tables use 100% width, which we do not always want. */
table.no-width {
width: auto;
}
table.no-width > tbody > tr > td {
padding-right: 2px;
}

View file

@ -1,866 +0,0 @@
/*
* ARCH GLOBAL NAVBAR
* We're forcing all generic selectors with !important
* to help prevent other stylesheets from interfering.
*/
/* container for the entire bar */
#archnavbar { height: 40px !important; padding: 10px 15px !important; background: #333 !important; border-bottom: 5px #08c solid !important; }
#archnavbarlogo { float: left !important; margin: 0 !important; padding: 0 !important; height: 40px !important; width: 190px !important; background: url('archnavbar/archlogo.png') no-repeat !important; }
/* move the heading text offscreen */
#archnavbarlogo h1 { margin: 0 !important; padding: 0 !important; text-indent: -9999px !important; }
/* make the link the same size as the logo */
#archnavbarlogo a { display: block !important; height: 40px !important; width: 190px !important; }
/* display the list inline, float it to the right and style it */
#archnavbarlist { display: inline !important; float: right !important; list-style: none !important; margin: 0 !important; padding: 0 !important; }
#archnavbarlist li { float: left !important; font-size: 14px !important; font-family: sans-serif !important; line-height: 45px !important; padding-right: 15px !important; padding-left: 15px !important; }
/* style the links */
#archnavbarlist li a { color: #999; font-weight: bold !important; text-decoration: none !important; }
#archnavbarlist li a:hover { color: white !important; text-decoration: underline !important; }
/* END ARCH GLOBAL NAVBAR */
#footer {
clear: both;
margin: 0;
}
#footer p {
margin: 1em;
}
#archnavbar.anb-aur ul li#anb-aur a {
color: white !important;
}
#archnavbarlogo {
background: url('archnavbar/aurlogo.png') !important;
}
body {
padding: 0;
margin: 0;
font-family: sans-serif;
font-size: 10pt;
color: #333;
background: white;
}
div#cgit a {
color: blue;
text-decoration: none;
}
div#cgit a:hover {
text-decoration: underline;
}
div#cgit table {
border-collapse: collapse;
}
div#cgit table#header {
width: 100%;
margin-bottom: 1em;
}
div#cgit table#header td.logo {
width: 96px;
vertical-align: top;
}
div#cgit table#header td.main {
font-size: 250%;
padding-left: 10px;
white-space: nowrap;
}
div#cgit table#header td.main a {
color: #000;
}
div#cgit table#header td.form {
text-align: right;
vertical-align: bottom;
padding-right: 1em;
padding-bottom: 2px;
white-space: nowrap;
}
div#cgit table#header td.form form,
div#cgit table#header td.form input,
div#cgit table#header td.form select {
font-size: 90%;
}
div#cgit table#header td.sub {
color: #777;
border-top: solid 1px #ccc;
padding-left: 10px;
}
div#cgit table.tabs {
border-bottom: solid 3px #ccc;
border-collapse: collapse;
margin-top: 2em;
margin-bottom: 0px;
width: 100%;
}
div#cgit table.tabs td {
padding: 0px 1em;
vertical-align: bottom;
}
div#cgit table.tabs td a {
padding: 2px 0.75em;
color: #777;
font-size: 110%;
}
div#cgit table.tabs td a.active {
color: #000;
background-color: #ccc;
}
div#cgit table.tabs td.form {
text-align: right;
}
div#cgit table.tabs td.form form {
padding-bottom: 2px;
font-size: 90%;
white-space: nowrap;
}
div#cgit table.tabs td.form input,
div#cgit table.tabs td.form select {
font-size: 90%;
}
div#cgit div.path {
margin: 0px;
padding: 5px 2em 2px 2em;
color: #000;
background-color: #eee;
}
div#cgit div.content {
margin: 0px;
padding: 2em;
border-bottom: solid 3px #ccc;
}
div#cgit table.list {
width: 100%;
border: none;
border-collapse: collapse;
}
div#cgit table.list tr {
background: white;
}
div#cgit table.list tr.logheader {
background: #eee;
}
div#cgit table.list tr:hover {
background: #eee;
}
div#cgit table.list tr.nohover:hover {
background: white;
}
div#cgit table.list th {
font-weight: bold;
/* color: #888;
border-top: dashed 1px #888;
border-bottom: dashed 1px #888;
*/
padding: 0.1em 0.5em 0.05em 0.5em;
vertical-align: baseline;
}
div#cgit table.list td {
border: none;
padding: 0.1em 0.5em 0.1em 0.5em;
}
div#cgit table.list td.commitgraph {
font-family: monospace;
white-space: pre;
}
div#cgit table.list td.commitgraph .column1 {
color: #a00;
}
div#cgit table.list td.commitgraph .column2 {
color: #0a0;
}
div#cgit table.list td.commitgraph .column3 {
color: #aa0;
}
div#cgit table.list td.commitgraph .column4 {
color: #00a;
}
div#cgit table.list td.commitgraph .column5 {
color: #a0a;
}
div#cgit table.list td.commitgraph .column6 {
color: #0aa;
}
div#cgit table.list td.logsubject {
font-family: monospace;
font-weight: bold;
}
div#cgit table.list td.logmsg {
font-family: monospace;
white-space: pre;
padding: 0 0.5em;
}
div#cgit table.list td a {
color: black;
}
div#cgit table.list td a.ls-dir {
font-weight: bold;
color: #00f;
}
div#cgit table.list td a:hover {
color: #00f;
}
div#cgit img {
border: none;
}
div#cgit input#switch-btn {
margin: 2px 0px 0px 0px;
}
div#cgit td#sidebar input.txt {
width: 100%;
margin: 2px 0px 0px 0px;
}
div#cgit table#grid {
margin: 0px;
}
div#cgit td#content {
vertical-align: top;
padding: 1em 2em 1em 1em;
border: none;
}
div#cgit div#summary {
vertical-align: top;
margin-bottom: 1em;
}
div#cgit table#downloads {
float: right;
border-collapse: collapse;
border: solid 1px #777;
margin-left: 0.5em;
margin-bottom: 0.5em;
}
div#cgit table#downloads th {
background-color: #ccc;
}
div#cgit div#blob {
border: solid 1px black;
}
div#cgit div.error {
color: red;
font-weight: bold;
margin: 1em 2em;
}
div#cgit a.ls-blob, div#cgit a.ls-dir, div#cgit a.ls-mod {
font-family: monospace;
}
div#cgit td.ls-size {
text-align: right;
font-family: monospace;
width: 10em;
}
div#cgit td.ls-mode {
font-family: monospace;
width: 10em;
}
div#cgit table.blob {
margin-top: 0.5em;
border-top: solid 1px black;
}
div#cgit table.blob td.lines {
margin: 0; padding: 0 0 0 0.5em;
vertical-align: top;
color: black;
}
div#cgit table.blob td.linenumbers {
margin: 0; padding: 0 0.5em 0 0.5em;
vertical-align: top;
text-align: right;
border-right: 1px solid gray;
}
div#cgit table.blob pre {
padding: 0; margin: 0;
}
div#cgit table.blob a.no, div#cgit table.ssdiff a.no {
color: gray;
text-align: right;
text-decoration: none;
}
div#cgit table.blob a.no a:hover {
color: black;
}
div#cgit table.bin-blob {
margin-top: 0.5em;
border: solid 1px black;
}
div#cgit table.bin-blob th {
font-family: monospace;
white-space: pre;
border: solid 1px #777;
padding: 0.5em 1em;
}
div#cgit table.bin-blob td {
font-family: monospace;
white-space: pre;
border-left: solid 1px #777;
padding: 0em 1em;
}
div#cgit table.nowrap td {
white-space: nowrap;
}
div#cgit table.commit-info {
border-collapse: collapse;
margin-top: 1.5em;
}
div#cgit div.cgit-panel {
float: right;
margin-top: 1.5em;
}
div#cgit div.cgit-panel table {
border-collapse: collapse;
border: solid 1px #aaa;
background-color: #eee;
}
div#cgit div.cgit-panel th {
text-align: center;
}
div#cgit div.cgit-panel td {
padding: 0.25em 0.5em;
}
div#cgit div.cgit-panel td.label {
padding-right: 0.5em;
}
div#cgit div.cgit-panel td.ctrl {
padding-left: 0.5em;
}
div#cgit table.commit-info th {
text-align: left;
font-weight: normal;
padding: 0.1em 1em 0.1em 0.1em;
vertical-align: top;
}
div#cgit table.commit-info td {
font-weight: normal;
padding: 0.1em 1em 0.1em 0.1em;
}
div#cgit div.commit-subject {
font-weight: bold;
font-size: 125%;
margin: 1.5em 0em 0.5em 0em;
padding: 0em;
}
div#cgit div.commit-msg {
white-space: pre;
font-family: monospace;
}
div#cgit div.notes-header {
font-weight: bold;
padding-top: 1.5em;
}
div#cgit div.notes {
white-space: pre;
font-family: monospace;
border: solid 1px #ee9;
background-color: #ffd;
padding: 0.3em 2em 0.3em 1em;
float: left;
}
div#cgit div.notes-footer {
clear: left;
}
div#cgit div.diffstat-header {
font-weight: bold;
padding-top: 1.5em;
}
div#cgit table.diffstat {
border-collapse: collapse;
border: solid 1px #aaa;
background-color: #eee;
}
div#cgit table.diffstat th {
font-weight: normal;
text-align: left;
text-decoration: underline;
padding: 0.1em 1em 0.1em 0.1em;
font-size: 100%;
}
div#cgit table.diffstat td {
padding: 0.2em 0.2em 0.1em 0.1em;
font-size: 100%;
border: none;
}
div#cgit table.diffstat td.mode {
white-space: nowrap;
}
div#cgit table.diffstat td span.modechange {
padding-left: 1em;
color: red;
}
div#cgit table.diffstat td.add a {
color: green;
}
div#cgit table.diffstat td.del a {
color: red;
}
div#cgit table.diffstat td.upd a {
color: blue;
}
div#cgit table.diffstat td.graph {
width: 500px;
vertical-align: middle;
}
div#cgit table.diffstat td.graph table {
border: none;
}
div#cgit table.diffstat td.graph td {
padding: 0px;
border: 0px;
height: 7pt;
}
div#cgit table.diffstat td.graph td.add {
background-color: #5c5;
}
div#cgit table.diffstat td.graph td.rem {
background-color: #c55;
}
div#cgit div.diffstat-summary {
color: #888;
padding-top: 0.5em;
}
div#cgit table.diff {
width: 100%;
}
div#cgit table.diff td {
font-family: monospace;
white-space: pre;
}
div#cgit table.diff td div.head {
font-weight: bold;
margin-top: 1em;
color: black;
}
div#cgit table.diff td div.hunk {
color: #009;
}
div#cgit table.diff td div.add {
color: green;
}
div#cgit table.diff td div.del {
color: red;
}
div#cgit .sha1 {
font-family: monospace;
font-size: 90%;
}
div#cgit .left {
text-align: left;
}
div#cgit .right {
text-align: right;
float: none !important;
width: auto !important;
padding: 0 !important;
}
div#cgit table.list td.reposection {
font-style: italic;
color: #888;
}
div#cgit a.button {
font-size: 80%;
padding: 0em 0.5em;
}
div#cgit a.primary {
font-size: 100%;
}
div#cgit a.secondary {
font-size: 90%;
}
div#cgit td.toplevel-repo {
}
div#cgit table.list td.sublevel-repo {
padding-left: 1.5em;
}
div#cgit ul.pager {
list-style-type: none;
text-align: center;
margin: 1em 0em 0em 0em;
padding: 0;
}
div#cgit ul.pager li {
display: inline-block;
margin: 0.25em 0.5em;
}
div#cgit ul.pager a {
color: #777;
}
div#cgit ul.pager .current {
font-weight: bold;
}
div#cgit span.age-mins {
font-weight: bold;
color: #080;
}
div#cgit span.age-hours {
color: #080;
}
div#cgit span.age-days {
color: #040;
}
div#cgit span.age-weeks {
color: #444;
}
div#cgit span.age-months {
color: #888;
}
div#cgit span.age-years {
color: #bbb;
}
div#cgit div.footer {
margin-top: 0.5em;
text-align: center;
font-size: 80%;
color: #ccc;
}
div#cgit a.branch-deco {
color: #000;
margin: 0px 0.5em;
padding: 0px 0.25em;
background-color: #88ff88;
border: solid 1px #007700;
}
div#cgit a.tag-deco {
color: #000;
margin: 0px 0.5em;
padding: 0px 0.25em;
background-color: #ffff88;
border: solid 1px #777700;
}
div#cgit a.remote-deco {
color: #000;
margin: 0px 0.5em;
padding: 0px 0.25em;
background-color: #ccccff;
border: solid 1px #000077;
}
div#cgit a.deco {
color: #000;
margin: 0px 0.5em;
padding: 0px 0.25em;
background-color: #ff8888;
border: solid 1px #770000;
}
div#cgit div.commit-subject a.branch-deco,
div#cgit div.commit-subject a.tag-deco,
div#cgit div.commit-subject a.remote-deco,
div#cgit div.commit-subject a.deco {
margin-left: 1em;
font-size: 75%;
}
div#cgit table.stats {
border: solid 1px black;
border-collapse: collapse;
}
div#cgit table.stats th {
text-align: left;
padding: 1px 0.5em;
background-color: #eee;
border: solid 1px black;
}
div#cgit table.stats td {
text-align: right;
padding: 1px 0.5em;
border: solid 1px black;
}
div#cgit table.stats td.total {
font-weight: bold;
text-align: left;
}
div#cgit table.stats td.sum {
color: #c00;
font-weight: bold;
/* background-color: #eee; */
}
div#cgit table.stats td.left {
text-align: left;
}
div#cgit table.vgraph {
border-collapse: separate;
border: solid 1px black;
height: 200px;
}
div#cgit table.vgraph th {
background-color: #eee;
font-weight: bold;
border: solid 1px white;
padding: 1px 0.5em;
}
div#cgit table.vgraph td {
vertical-align: bottom;
padding: 0px 10px;
}
div#cgit table.vgraph div.bar {
background-color: #eee;
}
div#cgit table.hgraph {
border: solid 1px black;
width: 800px;
}
div#cgit table.hgraph th {
background-color: #eee;
font-weight: bold;
border: solid 1px black;
padding: 1px 0.5em;
}
div#cgit table.hgraph td {
vertical-align: middle;
padding: 2px 2px;
}
div#cgit table.hgraph div.bar {
background-color: #eee;
height: 1em;
}
div#cgit table.ssdiff {
width: 100%;
}
div#cgit table.ssdiff td {
font-size: 75%;
font-family: monospace;
white-space: pre;
padding: 1px 4px 1px 4px;
border-left: solid 1px #aaa;
border-right: solid 1px #aaa;
}
div#cgit table.ssdiff td.add {
color: black;
background: #cfc;
min-width: 50%;
}
div#cgit table.ssdiff td.add_dark {
color: black;
background: #aca;
min-width: 50%;
}
div#cgit table.ssdiff span.add {
background: #cfc;
font-weight: bold;
}
div#cgit table.ssdiff td.del {
color: black;
background: #fcc;
min-width: 50%;
}
div#cgit table.ssdiff td.del_dark {
color: black;
background: #caa;
min-width: 50%;
}
div#cgit table.ssdiff span.del {
background: #fcc;
font-weight: bold;
}
div#cgit table.ssdiff td.changed {
color: black;
background: #ffc;
min-width: 50%;
}
div#cgit table.ssdiff td.changed_dark {
color: black;
background: #cca;
min-width: 50%;
}
div#cgit table.ssdiff td.lineno {
color: black;
background: #eee;
text-align: right;
width: 3em;
min-width: 3em;
}
div#cgit table.ssdiff td.hunk {
color: black;
background: #ccf;
border-top: solid 1px #aaa;
border-bottom: solid 1px #aaa;
}
div#cgit table.ssdiff td.head {
border-top: solid 1px #aaa;
border-bottom: solid 1px #aaa;
}
div#cgit table.ssdiff td.head div.head {
font-weight: bold;
color: black;
}
div#cgit table.ssdiff td.foot {
border-top: solid 1px #aaa;
border-left: none;
border-right: none;
border-bottom: none;
}
div#cgit table.ssdiff td.space {
border: none;
}
div#cgit table.ssdiff td.space div {
min-height: 3em;
}
/*
* Style definitions generated by highlight 3.14, http://www.andre-simon.de/
* Highlighting theme: Kwrite Editor
*/
div#cgit table.blob .num { color:#b07e00; }
div#cgit table.blob .esc { color:#ff00ff; }
div#cgit table.blob .str { color:#bf0303; }
div#cgit table.blob .pps { color:#818100; }
div#cgit table.blob .slc { color:#838183; font-style:italic; }
div#cgit table.blob .com { color:#838183; font-style:italic; }
div#cgit table.blob .ppc { color:#008200; }
div#cgit table.blob .opt { color:#000000; }
div#cgit table.blob .ipl { color:#0057ae; }
div#cgit table.blob .lin { color:#555555; }
div#cgit table.blob .kwa { color:#000000; font-weight:bold; }
div#cgit table.blob .kwb { color:#0057ae; }
div#cgit table.blob .kwc { color:#000000; font-weight:bold; }
div#cgit table.blob .kwd { color:#010181; }

View file

@ -1,215 +0,0 @@
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . '../lib');
include_once("aur.inc.php");
include_once('stats.inc.php');
if (isset($_COOKIE["AURSID"])) {
html_header( __("Dashboard") );
} else {
html_header( __("Home") );
}
?>
<div id="content-left-wrapper">
<div id="content-left">
<?php if (isset($_COOKIE["AURSID"])): ?>
<div id="intro" class="box">
<h2><?= __("Dashboard"); ?></h2>
<h3><?= __("My Flagged Packages"); ?></h3>
<?php
$params = array(
'PP' => 50,
'SeB' => 'M',
'K' => username_from_sid($_COOKIE["AURSID"]),
'outdated' => 'on',
'SB' => 'l',
'SO' => 'a'
);
pkg_search_page($params, false, $_COOKIE["AURSID"]);
?>
<h3><?= __("My Requests"); ?></h3>
<?php
$archive_time = config_get_int('options', 'request_archive_time');
$from = time() - $archive_time;
$results = pkgreq_list(0, 50, uid_from_sid($_COOKIE["AURSID"]), $from);
$show_headers = false;
include('pkgreq_results.php');
?>
</div>
<div id="intro" class="box">
<h2><?= __("My Packages"); ?></h2>
<p><a href="<?= get_uri('/packages/') ?>?SeB=m&amp;K=<?= username_from_sid($_COOKIE["AURSID"]); ?>"><?= __('Search for packages I maintain') ?></a></p>
<?php
$params = array(
'PP' => 50,
'SeB' => 'm',
'K' => username_from_sid($_COOKIE["AURSID"]),
'SB' => 'l',
'SO' => 'd'
);
pkg_search_page($params, false, $_COOKIE["AURSID"]);
?>
</div>
<div id="intro" class="box">
<h2><?= __("Co-Maintained Packages"); ?></h2>
<p><a href="<?= get_uri('/packages/') ?>?SeB=c&amp;K=<?= username_from_sid($_COOKIE["AURSID"]); ?>"><?= __('Search for packages I co-maintain') ?></a></p>
<?php
$params = array(
'PP' => 50,
'SeB' => 'c',
'K' => username_from_sid($_COOKIE["AURSID"]),
'SB' => 'l',
'SO' => 'd'
);
pkg_search_page($params, false, $_COOKIE["AURSID"]);
?>
</div>
<?php else: ?>
<div id="intro" class="box">
<h2>AUR <?= __("Home"); ?></h2>
<p>
<?php
echo __(
'Welcome to the AUR! Please read the %sAUR User Guidelines%s and %sAUR TU Guidelines%s for more information.',
'<a href="https://wiki.archlinux.org/title/AUR_User_Guidelines">',
'</a>',
'<a href="https://wiki.archlinux.org/title/AUR_Trusted_User_Guidelines">',
'</a>'
);
?>
<?php
echo __(
'Contributed PKGBUILDs %smust%s conform to the %sArch Packaging Standards%s otherwise they will be deleted!',
'<strong>', '</strong>',
'<a href="https://wiki.archlinux.org/title/Arch_Packaging_Standards">',
'</a>'
);
?>
<?= __('Remember to vote for your favourite packages!'); ?>
<?= __('Some packages may be provided as binaries in [community].'); ?>
</p>
<p class="important">
<?= __('DISCLAIMER') ?>:
<?= __('AUR packages are user produced content. Any use of the provided files is at your own risk.'); ?>
</p>
<p class="readmore"><a href="https://wiki.archlinux.org/title/AUR"><?= __('Learn more...') ?></a></p>
</div>
<div id="news">
<h3><a><?= __('Support') ?></a><span class="arrow"></span></h3>
<h4><?= __('Package Requests') ?></h4>
<div class="article-content">
<p>
<?php
echo __(
'There are three types of requests that can be filed in the %sPackage Actions%s box on the package details page:',
'<var>',
'</var>'
);
?>
</p>
<ul>
<li><em><?= __('Orphan Request') ?></em>: <?= __('Request a package to be disowned, e.g. when the maintainer is inactive and the package has been flagged out-of-date for a long time.') ?></li>
<li><em><?= __('Deletion Request') ?></em>: <?= __('Request a package to be removed from the Arch User Repository. Please do not use this if a package is broken and can be fixed easily. Instead, contact the package maintainer and file orphan request if necessary.') ?></li>
<li><em><?= __('Merge Request') ?></em>: <?= __('Request a package to be merged into another one. Can be used when a package needs to be renamed or replaced by a split package.') ?></li>
</ul>
<p>
<?php
echo __(
'If you want to discuss a request, you can use the %saur-requests%s mailing list. However, please do not use that list to file requests.',
'<a href="https://mailman.archlinux.org/mailman/listinfo/aur-requests">',
'</a>'
);
?>
</p>
</div>
<h4><?= __('Submitting Packages') ?></h4>
<div class="article-content">
<p>
<?php
echo __(
'Git over SSH is now used to submit packages to the AUR. See the %sSubmitting packages%s section of the Arch User Repository ArchWiki page for more details.',
'<a href="https://wiki.archlinux.org/title/Arch_User_Repository#Submitting_packages">',
'</a>'
);
?>
</p>
<?php if (config_section_exists('fingerprints')): ?>
<p>
<?= __('The following SSH fingerprints are used for the AUR:') ?>
</p>
<ul>
<?php foreach (config_items('fingerprints') as $type => $fingerprint): ?>
<li><code><?= htmlspecialchars($type) ?></code>: <code><?= htmlspecialchars($fingerprint) ?></code></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</div>
<h4><?= __('Discussion') ?></h4>
<div class="article-content">
<p>
<?php
echo __(
'General discussion regarding the Arch User Repository (AUR) and Trusted User structure takes place on %saur-general%s. For discussion relating to the development of the AUR web interface, use the %saur-dev%s mailing list.',
'<a href="https://mailman.archlinux.org/mailman/listinfo/aur-general">',
'</a>',
'<a href="https://mailman.archlinux.org/mailman/listinfo/aur-dev">',
'</a>'
);
?>
</p>
</div>
<h4><?= __('Bug Reporting') ?></h4>
<div class="article-content">
<p>
<?php
echo __(
'If you find a bug in the AUR web interface, please fill out a bug report on our %sbug tracker%s. Use the tracker to report bugs in the AUR web interface %sonly%s. To report packaging bugs contact the package maintainer or leave a comment on the appropriate package page.',
'<a href="https://bugs.archlinux.org/index.php?project=2">',
'</a>',
'<strong>',
'</strong>'
);
?>
</p>
</div>
</div>
<?php endif; ?>
</div>
</div>
<div id="content-right">
<div id="pkgsearch" class="widget">
<form id="pkgsearch-form" method="get" action="<?= get_uri('/packages/'); ?>">
<fieldset>
<label for="pkgsearch-field"><?= __('Package Search') ?>:</label>
<input type="hidden" name="O" value="0" />
<input id="pkgsearch-field" type="text" name="K" size="30" value="<?php if (isset($_REQUEST["K"])) { print stripslashes(trim(htmlspecialchars($_REQUEST["K"], ENT_QUOTES))); } ?>" maxlength="35" autocomplete="off"/>
</fieldset>
</form>
</div>
<div id="pkg-updates" class="widget box">
<?php updates_table(); ?>
</div>
<div id="pkg-stats" class="widget box">
<?php general_stats_table(); ?>
</div>
<?php if (isset($_COOKIE["AURSID"])): ?>
<div id="pkg-stats" class="widget box">
<?php user_table(uid_from_sid($_COOKIE["AURSID"])); ?>
</div>
<?php endif; ?>
</div>
<script type="text/javascript" src="/js/typeahead.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
const input = document.getElementById('pkgsearch-field');
const form = document.getElementById('pkgsearch-form');
const type = "suggest";
typeahead.init(type, input, form);
});
</script>
<?php
html_footer(AURWEB_VERSION);

View file

@ -1,26 +0,0 @@
The icons used in aurweb originate from the Open Iconic project and are
licensed under the following terms:
----
The MIT License (MIT)
Copyright (c) 2014 Waybury
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
----

View file

@ -1,3 +0,0 @@
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="8" width="8" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" viewBox="0 0 8 8">
<path d="m4.5 0c-1.93 0-3.5 1.57-3.5 3.5v0.5h-1l2 2 2-2h-1v-0.5c0-1.38 1.12-2.5 2.5-2.5s2.5 1.12 2.5 2.5c0-1.93-1.57-3.5-3.5-3.5z" transform="translate(0 1)" fill="#36a"/>
</svg>

Before

Width:  |  Height:  |  Size: 415 B

View file

@ -1,32 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
id="svg2"
viewBox="0 0 8 8"
height="8"
width="8">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<path
style="fill:#3366aa;fill-opacity:1"
id="path4"
transform="translate(0 1)"
d="M4.5 0c-1.93 0-3.5 1.57-3.5 3.5v.5h-1l2 2 2-2h-1v-.5c0-1.38 1.12-2.5 2.5-2.5s2.5 1.12 2.5 2.5c0-1.93-1.57-3.5-3.5-3.5z" />
</svg>

Before

Width:  |  Height:  |  Size: 924 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 723 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 575 B

View file

@ -1,3 +0,0 @@
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="8" width="8" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" viewBox="0 0 8 8">
<path fill="#36a" d="m6 0l-1 1 2 2 1-1-2-2zm-2 2l-4 4v2h2l4-4-2-2z"/>
</svg>

Before

Width:  |  Height:  |  Size: 313 B

View file

@ -1,55 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="8"
height="8"
viewBox="0 0 8 8"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="pencil-arch.svg">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="659"
inkscape:window-height="480"
id="namedview6"
showgrid="false"
inkscape:zoom="29.5"
inkscape:cx="4"
inkscape:cy="4"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="svg2" />
<path
d="M6 0l-1 1 2 2 1-1-2-2zm-2 2l-4 4v2h2l4-4-2-2z"
id="path4"
style="fill:#3366aa;fill-opacity:1" />
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

View file

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="8" height="8" viewBox="0 0 8 8"><path style="fill:#3366aa;fill-opacity:1" d="M1.34 0a.5.5 0 0 0 .16 1h.5v2h-1c-.55 0-1 .45-1 1h3v3l.44 1 .56-1v-3h3c0-.55-.45-1-1-1h-1v-2h.5a.5.5 0 1 0 0-1h-4a.5.5 0 0 0-.09 0 .5.5 0 0 0-.06 0z" /></svg>

Before

Width:  |  Height:  |  Size: 283 B

View file

@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="8" height="8" viewBox="0 0 8 8">
<path style="fill:#3366aa;fill-opacity:1" d="M1.34 0a.5.5 0 0 0 .16 1h.5v2h-1c-.55 0-1 .45-1 1h3v3l.44 1 .56-1v-3h3c0-.55-.45-1-1-1h-1v-2h.5a.5.5 0 1 0 0-1h-4a.5.5 0 0 0-.09 0 .5.5 0 0 0-.06 0z" />
</svg>

Before

Width:  |  Height:  |  Size: 287 B

View file

@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="8" height="8" viewBox="0 0 8 8">
<path style="fill:#3366aa;fill-opacity:1" d="M0 0v2c3.33 0 6 2.67 6 6h2c0-4.41-3.59-8-8-8zm0 3v2c1.67 0 3 1.33 3 3h2c0-2.75-2.25-5-5-5zm0 3v2h2c0-1.11-.9-2-2-2z" />
</svg>

Before

Width:  |  Height:  |  Size: 254 B

View file

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="8" height="8" viewBox="0 0 8 8"><path style="fill:#3366aa;fill-opacity:1" d="M1.34 0a.5.5 0 0 0 .16 1h.5v2h-1c-.55 0-1 .45-1 1h3v3l.44 1 .56-1v-3h3c0-.55-.45-1-1-1h-1v-2h.5a.5.5 0 1 0 0-1h-4a.5.5 0 0 0-.09 0 .5.5 0 0 0-.06 0z" /><path style="fill:#3366aa;fill-opacity:1" d="m6.4 0l1 1-6.4 6.8-1-1z" /></svg>

Before

Width:  |  Height:  |  Size: 355 B

View file

@ -1,4 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="8" height="8" viewBox="0 0 8 8">
<path style="fill:#3366aa;fill-opacity:1" d="M1.34 0a.5.5 0 0 0 .16 1h.5v2h-1c-.55 0-1 .45-1 1h3v3l.44 1 .56-1v-3h3c0-.55-.45-1-1-1h-1v-2h.5a.5.5 0 1 0 0-1h-4a.5.5 0 0 0-.09 0 .5.5 0 0 0-.06 0z" />
<path style="fill:#3366aa;fill-opacity:1" d="m6.4 0l1 1 -6.4 6.8 -1 -1z" />
</svg>

Before

Width:  |  Height:  |  Size: 365 B

View file

@ -1,3 +0,0 @@
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 8" height="8" width="8" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
<path fill="#36a" d="m1.41 0l-1.41 1.41 0.72 0.72 1.78 1.81-1.78 1.78-0.72 0.69 1.41 1.44 0.72-0.72 1.81-1.81 1.78 1.81 0.69 0.72 1.44-1.44-0.72-0.69-1.81-1.78 1.81-1.81 0.72-0.72-1.44-1.41-0.69 0.72-1.78 1.78-1.81-1.78-0.72-0.72z"/>
</svg>

Before

Width:  |  Height:  |  Size: 477 B

View file

@ -1,31 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
id="svg2"
viewBox="0 0 8 8"
height="8"
width="8">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<path
style="fill:#3366aa;fill-opacity:1"
id="path4"
d="M1.41 0l-1.41 1.41.72.72 1.78 1.81-1.78 1.78-.72.69 1.41 1.44.72-.72 1.81-1.81 1.78 1.81.69.72 1.44-1.44-.72-.69-1.81-1.78 1.81-1.81.72-.72-1.44-1.41-.69.72-1.78 1.78-1.81-1.78-.72-.72z" />
</svg>

Before

Width:  |  Height:  |  Size: 959 B

View file

@ -1,205 +0,0 @@
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . '../lib');
include_once("aur.inc.php");
include_once("pkgfuncs.inc.php");
$path = $_SERVER['PATH_INFO'];
$tokens = explode('/', $path);
if (config_get_bool('options', 'enable-maintenance') && (empty($tokens[1]) || ($tokens[1] != "css" && $tokens[1] != "images"))) {
if (!in_array($_SERVER['REMOTE_ADDR'], explode(" ", config_get('options', 'maintenance-exceptions')))) {
header("HTTP/1.0 503 Service Unavailable");
include "./503.php";
return;
}
}
if (!empty($tokens[1]) && '/' . $tokens[1] == get_pkg_route()) {
if (!empty($tokens[2])) {
/* TODO: Create a proper data structure to pass variables from
* the routing framework to the individual pages instead of
* initializing arbitrary variables here. */
$pkgname = $tokens[2];
$pkgid = pkg_from_name($pkgname);
if (!$pkgid) {
header("HTTP/1.0 404 Not Found");
include "./404.php";
return;
}
}
include get_route('/' . $tokens[1]);
} elseif (!empty($tokens[1]) && '/' . $tokens[1] == get_pkgbase_route()) {
if (!empty($tokens[2])) {
/* TODO: Create a proper data structure to pass variables from
* the routing framework to the individual pages instead of
* initializing arbitrary variables here. */
$pkgbase_name = $tokens[2];
$base_id = pkgbase_from_name($pkgbase_name);
if (!$base_id) {
header("HTTP/1.0 404 Not Found");
include "./404.php";
return;
}
if (!empty($tokens[3])) {
/* TODO: Remove support for legacy URIs and move these
* actions to separate modules. */
switch ($tokens[3]) {
case "adopt":
$_POST['do_Adopt'] = __('Adopt');
break;
case "disown":
include('pkgdisown.php');
return;
case "vote":
$_POST['do_Vote'] = __('Vote');
break;
case "unvote":
$_POST['do_UnVote'] = __('UnVote');
break;
case "notify":
$_POST['do_Notify'] = __('Notify');
break;
case "unnotify":
$_POST['do_UnNotify'] = __('UnNotify');
break;
case "flag":
include('pkgflag.php');
return;
case "unflag":
$_POST['do_UnFlag'] = __('UnFlag');
break;
case "flag-comment":
include('pkgflagcomment.php');
return;
case "delete":
include('pkgdel.php');
return;
case "merge":
include('pkgmerge.php');
return;
case "voters":
$_GET['N'] = $tokens[2];
include('voters.php');
return;
case "request":
include('pkgreq.php');
return;
case "comaintainers":
include('comaintainers.php');
return;
case "edit-comment":
include('commentedit.php');
return;
default:
header("HTTP/1.0 404 Not Found");
include "./404.php";
return;
}
$_POST['IDs'] = array(pkgbase_from_name($tokens[2]) => '1');
}
}
include get_route('/' . $tokens[1]);
} elseif (!empty($tokens[1]) && '/' . $tokens[1] == get_pkgreq_route()) {
if (!empty($tokens[2])) {
/* TODO: Create a proper data structure to pass variables from
* the routing framework to the individual pages instead of
* initializing arbitrary variables here. */
if (!empty($tokens[3]) && $tokens[3] == 'close') {
$pkgreq_id = $tokens[2];
} else {
$pkgreq_id = null;
}
if (!$pkgreq_id) {
header("HTTP/1.0 404 Not Found");
include "./404.php";
return;
}
}
include get_route('/' . $tokens[1]);
} elseif (!empty($tokens[1]) && '/' . $tokens[1] == get_user_route()) {
if (!empty($tokens[2])) {
$_REQUEST['ID'] = uid_from_username($tokens[2]);
if (!$_REQUEST['ID']) {
header("HTTP/1.0 404 Not Found");
include "./404.php";
return;
}
if (!empty($tokens[3])) {
if ($tokens[3] == 'edit') {
$_REQUEST['Action'] = "DisplayAccount";
} elseif ($tokens[3] == 'update') {
$_REQUEST['Action'] = "UpdateAccount";
} elseif ($tokens[3] == 'delete') {
$_REQUEST['Action'] = "DeleteAccount";
} elseif ($tokens[3] == 'comments') {
$_REQUEST['Action'] = "ListComments";
} else {
header("HTTP/1.0 404 Not Found");
include "./404.php";
return;
}
} else {
$_REQUEST['Action'] = "AccountInfo";
}
}
include get_route('/' . $tokens[1]);
} elseif (get_route($path) !== NULL) {
include get_route($path);
} else {
switch ($path) {
case "/css/archweb.css":
case "/css/aurweb.css":
case "/css/cgit.css":
case "/css/archnavbar/archnavbar.css":
header("Content-Type: text/css");
readfile("./$path");
break;
case "/images/ajax-loader.gif":
header("Content-Type: image/gif");
readfile("./$path");
break;
case "/css/archnavbar/archlogo.png":
case "/css/archnavbar/aurlogo.png":
case "/images/favicon.ico":
header("Content-Type: image/png");
readfile("./$path");
break;
case "/images/x.min.svg":
case "/images/action-undo.min.svg":
case "/images/pencil.min.svg":
case "/images/pin.min.svg":
case "/images/unpin.min.svg":
case "/images/rss.svg":
header("Content-Type: image/svg+xml");
readfile("./$path");
break;
case "/js/typeahead.js":
header("Content-Type: application/javascript");
readfile("./$path");
break;
case "/packages.gz":
case "/packages-meta-v1.json.gz":
case "/packages-meta-ext-v1.json.gz":
case "/pkgbase.gz":
case "/users.gz":
header("Content-Type: text/plain");
header("Content-Encoding: gzip");
readfile("./$path");
break;
default:
header("HTTP/1.0 404 Not Found");
include "./404.php";
break;
}
}

View file

@ -1,61 +0,0 @@
function add_busy_indicator(sibling) {
const img = document.createElement('img');
img.src = "/static/images/ajax-loader.gif";
img.classList.add('ajax-loader');
img.style.height = 11;
img.style.width = 16;
img.alt = "Busy…";
sibling.insertAdjacentElement('afterend', img);
}
function remove_busy_indicator(sibling) {
const elem = sibling.nextElementSibling;
elem.parentNode.removeChild(elem);
}
function getParentsUntil(elem, className) {
// Limit to 10 depth
for ( ; elem && elem !== document; elem = elem.parentNode) {
if (elem.matches(className)) {
break;
}
}
return elem;
}
function handleEditCommentClick(event, pkgbasename) {
event.preventDefault();
const parent_element = getParentsUntil(event.target, '.comment-header');
const parent_id = parent_element.id;
const comment_id = parent_id.substr(parent_id.indexOf('-') + 1);
// The div class="article-content" which contains the comment
const edit_form = parent_element.nextElementSibling;
const url = "/pkgbase/" + pkgbasename + "/comments/" + comment_id + "/form?";
add_busy_indicator(event.target);
fetch(url + new URLSearchParams({ next: window.location.pathname }), {
method: 'GET',
credentials: 'same-origin'
})
.then(function(response) {
if (!response.ok) {
throw Error(response.statusText);
}
return response.json();
})
.then(function(data) {
remove_busy_indicator(event.target);
edit_form.innerHTML = data.form;
edit_form.querySelector('textarea').focus();
})
.catch(function(error) {
remove_busy_indicator(event.target);
console.error(error);
});
return false;
}

View file

@ -1,9 +0,0 @@
document.addEventListener('DOMContentLoaded', function() {
let elements = document.querySelectorAll('.copy');
elements.forEach(function(el) {
el.addEventListener('click', function(e) {
e.preventDefault();
navigator.clipboard.writeText(e.target.text);
});
});
});

View file

@ -1,6 +0,0 @@
document.addEventListener('DOMContentLoaded', function() {
const input = document.getElementById('pkgsearch-field');
const form = document.getElementById('pkgsearch-form');
const type = 'suggest';
typeahead.init(type, input, form);
});

View file

@ -1,6 +0,0 @@
document.addEventListener('DOMContentLoaded', function() {
const input = document.getElementById('merge_into');
const form = document.getElementById('merge-form');
const type = "suggest-pkgbase";
typeahead.init(type, input, form, false);
});

View file

@ -1,36 +0,0 @@
function showHideMergeSection() {
const elem = document.getElementById('id_type');
const merge_section = document.getElementById('merge_section');
if (elem.value == 'merge') {
merge_section.style.display = '';
} else {
merge_section.style.display = 'none';
}
}
function showHideRequestHints() {
document.getElementById('deletion_hint').style.display = 'none';
document.getElementById('merge_hint').style.display = 'none';
document.getElementById('orphan_hint').style.display = 'none';
const elem = document.getElementById('id_type');
document.getElementById(elem.value + '_hint').style.display = '';
}
document.addEventListener('DOMContentLoaded', function() {
showHideMergeSection();
showHideRequestHints();
const input = document.getElementById('id_merge_into');
const form = document.getElementById('request-form');
const type = "suggest-pkgbase";
typeahead.init(type, input, form, false);
});
// Bind the change event here, otherwise we have to inline javascript,
// which angers CSP (Content Security Policy).
document.getElementById("id_type").addEventListener("change", function() {
showHideMergeSection();
showHideRequestHints();
});

View file

@ -1,151 +0,0 @@
"use strict";
const typeahead = (function() {
var input;
var form;
var suggest_type;
var list;
var submit = true;
function resetResults() {
if (!list) return;
list.style.display = "none";
list.innerHTML = "";
}
function getCompleteList() {
if (!list) {
list = document.createElement("UL");
list.setAttribute("class", "pkgsearch-typeahead");
form.appendChild(list);
setListLocation();
}
return list;
}
function onListClick(e) {
let target = e.target;
while (!target.getAttribute('data-value')) {
target = target.parentNode;
}
input.value = target.getAttribute('data-value');
if (submit) {
form.submit();
}
}
function setListLocation() {
if (!list) return;
const rects = input.getClientRects()[0];
list.style.top = (rects.top + rects.height) + "px";
list.style.left = rects.left + "px";
}
function loadData(letter, data) {
const pkgs = data.slice(0, 10); // Show maximum of 10 results
resetResults();
if (pkgs.length === 0) {
return;
}
const ul = getCompleteList();
ul.style.display = "block";
const fragment = document.createDocumentFragment();
for (let i = 0; i < pkgs.length; i++) {
const item = document.createElement("li");
const text = pkgs[i].replace(letter, '<b>' + letter + '</b>');
item.innerHTML = '<a href="#">' + text + '</a>';
item.setAttribute('data-value', pkgs[i]);
fragment.appendChild(item);
}
ul.appendChild(fragment);
ul.addEventListener('click', onListClick);
}
function fetchData(letter) {
const url = '/rpc?v=5&type=' + suggest_type + '&arg=' + letter;
fetch(url).then(function(response) {
return response.json();
}).then(function(data) {
loadData(letter, data);
});
}
function onInputClick() {
if (input.value === "") {
resetResults();
return;
}
fetchData(input.value);
}
function onKeyDown(e) {
if (!list) return;
const elem = document.querySelector(".pkgsearch-typeahead li.active");
switch(e.keyCode) {
case 13: // enter
if (!submit) {
return;
}
if (elem) {
input.value = elem.getAttribute('data-value');
form.submit();
} else {
form.submit();
}
e.preventDefault();
break;
case 38: // up
if (elem && elem.previousElementSibling) {
elem.className = "";
elem.previousElementSibling.className = "active";
}
e.preventDefault();
break;
case 40: // down
if (elem && elem.nextElementSibling) {
elem.className = "";
elem.nextElementSibling.className = "active";
} else if (!elem && list.childElementCount !== 0) {
list.children[0].className = "active";
}
e.preventDefault();
break;
}
}
// debounce https://davidwalsh.name/javascript-debounce-function
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
}
return {
init: function(type, inputfield, formfield, submitdata = true) {
suggest_type = type;
input = inputfield;
form = formfield;
submit = submitdata;
input.addEventListener("input", onInputClick);
input.addEventListener("keydown", onKeyDown);
window.addEventListener('resize', debounce(setListLocation, 150));
document.addEventListener("click", resetResults);
}
}
}());

View file

@ -1,68 +0,0 @@
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . '../lib');
include_once("aur.inc.php");
$disable_http_login = config_get_bool('options', 'disable_http_login');
if (!$disable_http_login || (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'])) {
$login = try_login();
$login_error = $login['error'];
}
$referer = in_request('referer');
if ($referer === '')
$referer = $_SERVER['HTTP_REFERER'];
html_header('AUR ' . __("Login"));
?>
<div id="dev-login" class="box">
<h2>AUR <?= __('Login') ?></h2>
<?php if (isset($_COOKIE["AURSID"])): ?>
<p>
<?= __("Logged-in as: %s", '<strong>' . username_from_sid($_COOKIE["AURSID"]) . '</strong>'); ?>
<a href="<?= get_uri('/logout/'); ?>">[<?= __("Logout"); ?>]</a>
</p>
<?php elseif (!$disable_http_login || (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'])): ?>
<form method="post" action="<?= get_uri('/login') ?>">
<fieldset>
<legend><?= __('Enter login credentials') ?></legend>
<?php if (!empty($login_error)): ?>
<ul class="errorlist"><li><?= $login_error ?></li></ul>
<?php endif; ?>
<p>
<label for="id_username"><?= __('User name or primary email address') . ':'; ?></label>
<input id="id_username" type="text" name="user" size="30" maxlength="<?= max(config_get_int('options', 'username_max_len'), 254); ?>" value="<?php if (isset($_POST['user'])) { print htmlspecialchars($_POST['user'], ENT_QUOTES); } ?>" autofocus="autofocus" />
</p>
<p>
<label for="id_password"><?= __('Password') . ':'; ?></label>
<input id="id_password" type="password" name="passwd" size="30" />
</p>
<p>
<input type="checkbox" name="remember_me" id="id_remember_me" />
<label for="id_remember_me"><?= __("Remember me"); ?></label>
</p>
<p>
<input type="submit" class="button" value="<?php print __("Login"); ?>" />
<a href="<?= get_uri('/passreset/') ?>">[<?= __('Forgot Password') ?>]</a>
<?php if (config_get('sso', 'openid_configuration')):
$sso_login_url = get_uri('/sso/login');
if (isset($referer))
$sso_login_url .= '?redirect=' . urlencode($referer);
?>
<a href="<?= htmlspecialchars($sso_login_url, ENT_QUOTES) ?>">[<?= __('Login through SSO') ?>]</a>
<?php endif; ?>
<?php if (isset($referer)): ?>
<input id="id_referer" type="hidden" name="referer" value="<?= htmlspecialchars($referer, ENT_QUOTES) ?>" />
<?php endif; ?>
</p>
</fieldset>
</form>
<?php else: ?>
<p>
<?php printf(__("HTTP login is disabled. Please %sswitch to HTTPs%s if you want to login."),
'<a href="' . get_uri('/login', true) . '">', '</a>'); ?>
</p>
<?php endif; ?>
</div>
<?php
html_footer(AURWEB_VERSION);

View file

@ -1,31 +0,0 @@
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . '../lib');
include_once("aur.inc.php"); # access AUR common functions
include_once("acctfuncs.inc.php"); # access AUR common functions
$redirect_uri = '/';
# if they've got a cookie, log them out - need to do this before
# sending any HTML output.
#
if (isset($_COOKIE["AURSID"])) {
$uid = uid_from_sid($_COOKIE['AURSID']);
delete_session_id($_COOKIE["AURSID"]);
# setting expiration to 1 means '1 second after midnight January 1, 1970'
setcookie("AURSID", "", 1, "/", null, !empty($_SERVER['HTTPS']), true);
unset($_COOKIE['AURSID']);
clear_expired_sessions();
# If the account is linked to an SSO account, disconnect the user from the SSO too.
if (isset($uid)) {
$dbh = DB::connect();
$sso_account_id = $dbh->query("SELECT SSOAccountID FROM Users WHERE ID = " . $dbh->quote($uid))
->fetchColumn();
if ($sso_account_id)
$redirect_uri = '/sso/logout';
}
}
header("Location: $redirect_uri");

View file

@ -1,62 +0,0 @@
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . '../lib' . PATH_SEPARATOR . '../lang');
include_once("aur.inc.php");
include_once("pkgfuncs.inc.php");
include_once("feedcreator.class.php");
#detect prefix
$protocol = isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"]=='on' ? "https" : "http";
$host = $_SERVER['HTTP_HOST'];
$feed_key = 'modified-pkg-feed-' . $protocol;
header("Content-Type: application/rss+xml");
$bool = false;
$ret = get_cache_value($feed_key, $bool);
if ($bool) {
echo $ret;
exit();
}
$rss = new RSSCreator20();
$rss->cssStyleSheet = false;
$rss->xslStyleSheet = false;
# Use UTF-8 (fixes FS#10706).
$rss->encoding = "UTF-8";
#All the general RSS setup
$rss->title = "AUR Latest Modified Packages";
$rss->description = "The latest modified packages in the AUR";
$rss->link = "${protocol}://{$host}";
$rss->syndicationURL = "{$protocol}://{$host}" . get_uri('/rss/');
$image = new FeedImage();
$image->title = "AUR Latest Modified Packages";
$image->url = "{$protocol}://{$host}/css/archnavbar/aurlogo.png";
$image->link = $rss->link;
$image->description = "AUR Latest Modified Packages Feed";
$rss->image = $image;
#Get the latest packages and add items for them
$packages = latest_modified_pkgs(100);
foreach ($packages as $indx => $row) {
$item = new FeedItem();
$item->title = $row["Name"];
$item->link = "{$protocol}://{$host}" . get_pkg_uri($row["Name"]);
$item->description = $row["Description"];
$item->date = intval($row["ModifiedTS"]);
$item->source = "{$protocol}://{$host}";
$item->author = username_from_id($row["MaintainerUID"]);
$item->guidIsPermaLink = true;
$item->guid = $row["Name"] . "-" . $row["ModifiedTS"];
$rss->addItem($item);
}
#save it so that useCached() can find it
$feedContent = $rss->createFeed();
set_cache_value($feed_key, $feedContent, 600);
echo $feedContent;
?>

View file

@ -1,173 +0,0 @@
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . '../lib');
include_once("aur.inc.php"); # access AUR common functions
include_once('pkgfuncs.inc.php'); # package specific functions
# Retrieve package ID and name, unless initialized by the routing framework
if (!isset($pkgid) || !isset($pkgname)) {
if (isset($_GET['ID'])) {
$pkgid = intval($_GET['ID']);
} else if (isset($_GET['N'])) {
$pkgid = pkg_from_name($_GET['N']);
} else {
unset($pkgid);
}
}
$details = array();
if (isset($pkgid)) {
$details = pkg_get_details($pkgid);
if (isset($details['Name'])) {
$pkgname = $details['Name'];
} else {
$pkgname = null;
}
} else {
unset($pkgname);
}
if (isset($pkgid) && ($pkgid == 0 || $pkgid == NULL || $pkgname == NULL)) {
header("HTTP/1.0 404 Not Found");
include "./404.php";
return;
}
# Set the title to the current query or package name
if (isset($pkgname)) {
$title = $pkgname;
} else if (!empty($_GET['K'])) {
$title = __("Search Criteria") . ": " . $_GET['K'];
} else {
$title = __("Packages");
}
html_header($title, $details);
?>
<script type="text/javascript">
function collapseDependsList(list) {
list = document.getElementById(list);
// Packages overview page also triggers collapseDependsList, ideally the Javascript
// is only included for the package details view.
if (!list) {
return;
}
// Hide everything past a given limit. Don't do anything if we don't have
// enough items, or the link already exists.
const limit = 20;
const linkid = list.getAttribute('id') + 'link';
const items = Array.from(list.querySelectorAll('li')).slice(limit);
if (items.length <= 1 || document.getElementById(linkid)) {
return;
}
items.forEach(function(item) {
item.style.display = 'none';
});
const link = document.createElement('a');
link.id = linkid;
link.href = '#';
link.textContent = 'Show More…';
const showMore = document.createElement('p');
showMore.appendChild(link);
list.insertAdjacentElement('afterend', showMore);
// add link and wire it up to show the hidden items
link.addEventListener('click', function(event) {
event.preventDefault();
items.forEach(function(item) {
item.style.display = '';
});
// remove the full <p/> node from the DOM
event.target.parentNode.removeChild(event.target);
});
}
function collapseComment(div) {
const linkid = div.getAttribute('id') + 'link';
const inner = div.querySelector('div');
// max height of a collapsed comment.
const maxheight = 200;
const height = inner.offsetHeight;
if (height <= maxheight)
return;
inner.style.height = maxheight + 'px';
inner.classList.add('collapsed');
const link = document.createElement('a');
link.id = linkid;
link.href = '#';
link.textContent = 'Show More…';
const showMore = document.createElement('p');
showMore.appendChild(link);
inner.insertAdjacentElement('afterend', showMore);
link.addEventListener('click', function(event) {
const showMoreLink = event.target;
const inner = showMoreLink.parentNode.parentNode.querySelector('div');
var newheight;
if (inner.classList.contains('collapsed')) {
inner.style.height = height + 'px';
showMoreLink.textContent = 'Collapse';
} else {
newheight = maxheight + 'px';
inner.style.height = newheight;
showMoreLink.textContent = 'Show More…';
}
inner.classList.toggle('collapsed');
event.preventDefault();
});
}
document.addEventListener('DOMContentLoaded', function() {
collapseDependsList("pkgdepslist");
collapseDependsList("pkgreqslist");
collapseDependsList("pkgsrcslist");
Array.from(document.querySelectorAll('.article-content')).forEach(collapseComment);
});
</script>
<?php
include('pkg_search_form.php');
if (isset($pkgid)) {
if ($pkgid) {
if (isset($_COOKIE["AURSID"])) {
pkg_display_details($pkgid, $details, $_COOKIE["AURSID"]);
}
else {
pkg_display_details($pkgid, $details, null);
}
} else {
print __("Error trying to retrieve package details.")."<br />\n";
}
} else {
if (!isset($_GET['K']) && !isset($_GET['SB'])) {
$_GET['SB'] = 'p';
$_GET['SO'] = 'd';
}
echo '<div id="pkglist-results" class="box">';
if (isset($_COOKIE["AURSID"])) {
pkg_search_page($_GET, true, $_COOKIE["AURSID"]);
} else {
pkg_search_page($_GET, true);
}
echo '</div>';
}
html_footer(AURWEB_VERSION);

View file

@ -1,100 +0,0 @@
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . '../lib');
include_once("aur.inc.php"); # access AUR common functions
if (isset($_COOKIE["AURSID"])) {
header('Location: /');
exit();
}
$error = '';
if (isset($_GET['resetkey'], $_POST['user'], $_POST['password'], $_POST['confirm'])) {
$resetkey = $_GET['resetkey'];
$user = $_POST['user'];
$password = $_POST['password'];
$confirm = $_POST['confirm'];
$uid = uid_from_loginname($user);
if (empty($user) || empty($password)) {
$error = __('Missing a required field.');
} elseif ($password != $confirm) {
$error = __('Password fields do not match.');
} elseif (!good_passwd($password)) {
$length_min = config_get_int('options', 'passwd_min_len');
$error = __("Your password must be at least %s characters.",
$length_min);
} elseif ($uid == null) {
$error = __('Invalid e-mail.');
}
if (empty($error)) {
$error = password_reset($password, $resetkey, $user);
}
} elseif (isset($_POST['user'])) {
$user = $_POST['user'];
if (empty($user)) {
$error = __('Missing a required field.');
} else {
send_resetkey($user);
header('Location: ' . get_uri('/passreset/') . '?step=confirm');
exit();
}
}
$step = isset($_GET['step']) ? $_GET['step'] : NULL;
html_header(__("Password Reset"));
?>
<div class="box">
<h2><?= __("Password Reset"); ?></h2>
<?php if ($step == 'confirm'): ?>
<p><?= __('Check your e-mail for the confirmation link.') ?></p>
<?php elseif ($step == 'complete'): ?>
<p><?= __('Your password has been reset successfully.') ?></p>
<?php elseif (isset($_GET['resetkey'])): ?>
<?php if ($error): ?>
<ul class="errorlist"><li><?= $error ?></li></ul>
<?php endif; ?>
<form action="" method="post">
<table>
<tr>
<td><?= __("Confirm your user name or primary e-mail address:"); ?></td>
<td><input type="text" name="user" size="30" maxlength="64" /></td>
</tr>
<tr>
<td><?= __("Enter your new password:"); ?></td>
<td><input type="password" name="password" size="30" /></td>
</tr>
<tr>
<td><?= __("Confirm your new password:"); ?></td>
<td><input type="password" name="confirm" size="30" /></td>
</tr>
</table>
<br />
<input type="submit" class="button" value="<?= __('Continue') ?>" />
</form>
<?php else: ?>
<p><?= __('If you have forgotten the user name and the primary e-mail address you used to register, please send a message to the %saur-general%s mailing list.',
'<a href="https://mailman.archlinux.org/mailman/listinfo/aur-general">',
'</a>'); ?></p>
<?php if ($error): ?>
<ul class="errorlist"><li><?= $error ?></li></ul>
<?php endif; ?>
<form action="" method="post">
<p><?= __("Enter your user name or your primary e-mail address:"); ?>
<input type="text" name="user" size="30" maxlength="64" /></p>
<input type="submit" class="button" value="<?= __('Continue') ?>" />
</form>
<?php endif; ?>
</div>
<?php
html_footer(AURWEB_VERSION);

View file

@ -1,195 +0,0 @@
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . '../lib');
include_once("aur.inc.php");
include_once('pkgfuncs.inc.php');
/*
* Retrieve package base ID and name, unless initialized by the routing
* framework.
*/
if (!isset($base_id) || !isset($pkgbase_name)) {
if (isset($_GET['ID'])) {
$base_id = intval($_GET['ID']);
$pkgbase_name = pkgbase_name_from_id($_GET['ID']);
} else if (isset($_GET['N'])) {
$base_id = pkgbase_from_name($_GET['N']);
$pkgbase_name = $_GET['N'];
} else {
unset($base_id, $pkgbase_name);
}
if (isset($base_id) && ($base_id == 0 || $base_id == NULL || $pkgbase_name == NULL)) {
header("HTTP/1.0 404 Not Found");
include "./404.php";
return;
}
}
/* Set the title to package base name. */
$title = isset($pkgbase_name) ? $pkgbase_name : __("Package Bases");
/* Grab the list of package base IDs to be operated on. */
$ids = array();
if (isset($_POST['IDs'])) {
foreach ($_POST['IDs'] as $id => $i) {
$id = intval($id);
if ($id > 0) {
$ids[] = $id;
}
}
}
/* Perform package base actions. */
$via = isset($_POST['via']) ? $_POST['via'] : NULL;
$return_to = isset($_POST['return_to']) ? $_POST['return_to'] : NULL;
$ret = false;
$output = "";
$fragment = "";
if (check_token()) {
if (current_action("do_Flag")) {
list($ret, $output) = pkgbase_flag($ids, $_POST['comments']);
} elseif (current_action("do_UnFlag")) {
list($ret, $output) = pkgbase_unflag($ids);
} elseif (current_action("do_Adopt")) {
list($ret, $output) = pkgbase_adopt($ids, true, NULL);
} elseif (current_action("do_Disown")) {
if (isset($_POST['confirm'])) {
list($ret, $output) = pkgbase_adopt($ids, false, $via);
} else {
$output = __("The selected packages have not been disowned, check the confirmation checkbox.");
$ret = false;
}
} elseif (current_action("do_DisownComaintainer")) {
$uid = uid_from_sid($_COOKIE["AURSID"]);
list($ret, $output) = pkgbase_remove_comaintainer($base_id, $uid);
} elseif (current_action("do_Vote")) {
list($ret, $output) = pkgbase_vote($ids, true);
} elseif (current_action("do_UnVote")) {
list($ret, $output) = pkgbase_vote($ids, false);
} elseif (current_action("do_Delete")) {
if (isset($_POST['confirm'])) {
if (!isset($_POST['merge_Into']) || empty($_POST['merge_Into'])) {
list($ret, $output) = pkgbase_delete($ids, NULL, $via);
unset($_GET['ID']);
unset($base_id);
}
else {
$merge_base_id = pkgbase_from_name($_POST['merge_Into']);
if (!$merge_base_id) {
$output = __("Cannot find package to merge votes and comments into.");
$ret = false;
} elseif (in_array($merge_base_id, $ids)) {
$output = __("Cannot merge a package base with itself.");
$ret = false;
} else {
list($ret, $output) = pkgbase_delete($ids, $merge_base_id, $via);
unset($_GET['ID']);
unset($base_id);
}
}
}
else {
$output = __("The selected packages have not been deleted, check the confirmation checkbox.");
$ret = false;
}
} elseif (current_action("do_Notify")) {
list($ret, $output) = pkgbase_notify($ids);
} elseif (current_action("do_UnNotify")) {
list($ret, $output) = pkgbase_notify($ids, false);
} elseif (current_action("do_DeleteComment")) {
list($ret, $output) = pkgbase_delete_comment();
} elseif (current_action("do_UndeleteComment")) {
list($ret, $output) = pkgbase_delete_comment(true);
if ($ret && isset($_POST["comment_id"])) {
$fragment = '#comment-' . intval($_POST["comment_id"]);
}
} elseif (current_action("do_PinComment")) {
list($ret, $output) = pkgbase_pin_comment();
} elseif (current_action("do_UnpinComment")) {
list($ret, $output) = pkgbase_pin_comment(true);
} elseif (current_action("do_SetKeywords")) {
list($ret, $output) = pkgbase_set_keywords($base_id, preg_split("/[\s,;]+/", $_POST['keywords'], -1, PREG_SPLIT_NO_EMPTY));
} elseif (current_action("do_FileRequest")) {
list($ret, $output) = pkgreq_file($ids, $_POST['type'], $_POST['merge_into'], $_POST['comments']);
} elseif (current_action("do_CloseRequest")) {
list($ret, $output) = pkgreq_close($_POST['reqid'], $_POST['reason'], $_POST['comments']);
} elseif (current_action("do_EditComaintainers")) {
list($ret, $output) = pkgbase_set_comaintainers($base_id, explode("\n", $_POST['users']));
} elseif (current_action("do_AddComment")) {
$uid = uid_from_sid($_COOKIE["AURSID"]);
list($ret, $output) = pkgbase_add_comment($base_id, $uid, $_REQUEST['comment']);
if ($ret && isset($_REQUEST['enable_notifications'])) {
list($ret, $output) = pkgbase_notify(array($base_id));
}
$fragment = '#news';
} elseif (current_action("do_EditComment")) {
list($ret, $output) = pkgbase_edit_comment($_REQUEST['comment']);
if ($ret && isset($_POST["comment_id"])) {
$fragment = '#comment-' . intval($_POST["comment_id"]);
}
}
if ($ret) {
if (current_action("do_CloseRequest") ||
(current_action("do_Delete") && $via)) {
/* Redirect back to package request page on success. */
header('Location: ' . get_pkgreq_route());
exit();
} elseif ((current_action("do_DeleteComment") ||
current_action("do_UndeleteComment")) && $return_to) {
header('Location: ' . $return_to);
exit();
} elseif (current_action("do_PinComment") && $return_to) {
header('Location: ' . $return_to);
exit();
} elseif (isset($base_id)) {
/* Redirect back to package base page on success. */
header('Location: ' . get_pkgbase_uri($pkgbase_name) . $fragment);
exit();
} else {
/* Redirect back to package search page. */
header('Location: ' . get_pkg_route());
exit();
}
}
}
if (isset($base_id)) {
$pkgs = pkgbase_get_pkgnames($base_id);
if (!$output && count($pkgs) == 1) {
/* Not a split package. Redirect to the package page. */
if (empty($_SERVER['QUERY_STRING'])) {
header('Location: ' . get_pkg_uri($pkgs[0]) . $fragment);
} else {
header('Location: ' . get_pkg_uri($pkgs[0]) . '?' . $_SERVER['QUERY_STRING'] . $fragment);
}
}
$details = pkgbase_get_details($base_id);
} else {
$details = array();
}
html_header($title, $details);
?>
<?php if ($output): ?>
<?php if ($ret): ?>
<p class="pkgoutput"><?= htmlspecialchars($output) ?></p>
<?php else: ?>
<ul class="errorlist"><li><?= htmlspecialchars($output) ?></li></ul>
<?php endif; ?>
<?php endif; ?>
<?php
include('pkg_search_form.php');
if (isset($base_id)) {
if (isset($_COOKIE["AURSID"])) {
pkgbase_display_details($base_id, $details, $_COOKIE["AURSID"]);
} else {
pkgbase_display_details($base_id, $details, null);
}
}
html_footer(AURWEB_VERSION);

View file

@ -1,45 +0,0 @@
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . '../lib');
include_once("aur.inc.php");
include_once("pkgfuncs.inc.php");
html_header(__("Package Deletion"));
if (has_credential(CRED_PKGBASE_DELETE)): ?>
<div class="box">
<h2><?= __('Delete Package') ?>: <?= htmlspecialchars($pkgbase_name) ?></h2>
<p>
<?= __('Use this form to delete the package base %s%s%s and the following packages from the AUR: ',
'<strong>', htmlspecialchars($pkgbase_name), '</strong>'); ?>
</p>
<ul>
<?php foreach(pkgbase_get_pkgnames($base_id) as $pkgname): ?>
<li><?= htmlspecialchars($pkgname) ?></li>
<?php endforeach; ?>
</ul>
<p>
<?= __('Deletion of a package is permanent. '); ?>
<?= __('Select the checkbox to confirm action.') ?>
</p>
<form action="<?= get_pkgbase_uri($pkgbase_name); ?>" method="post">
<fieldset>
<input type="hidden" name="IDs[<?= $base_id ?>]" value="1" />
<input type="hidden" name="ID" value="<?= $base_id ?>" />
<input type="hidden" name="token" value="<?= htmlspecialchars($_COOKIE['AURSID']) ?>" />
<?php if (isset($_GET['via'])): ?>
<input type="hidden" name="via" value="<?= intval($_GET['via']) ?>" />
<?php endif; ?>
<p><label class="confirmation"><input type="checkbox" name="confirm" value="1" />
<?= __("Confirm package deletion") ?></label></p>
<p><input type="submit" class="button" name="do_Delete" value="<?= __("Delete") ?>" /></p>
</fieldset>
</form>
</div>
<?php else:
print __("Only Trusted Users and Developers can delete packages.");
endif;
html_footer(AURWEB_VERSION);

View file

@ -1,59 +0,0 @@
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . '../lib');
include_once("aur.inc.php");
include_once("pkgfuncs.inc.php");
html_header(__("Disown Package"));
$action = "do_Disown";
$maintainer_uids = array(pkgbase_maintainer_uid($base_id));
$comaintainers = pkgbase_get_comaintainers($base_id);
$comaintainer_uids = pkgbase_get_comaintainer_uids(array($base_id));
if (has_credential(CRED_PKGBASE_DISOWN, array_merge($maintainer_uids, $comaintainer_uids))): ?>
<div class="box">
<h2><?= __('Disown Package') ?>: <?= htmlspecialchars($pkgbase_name) ?></h2>
<p>
<?= __('Use this form to disown the package base %s%s%s which includes the following packages: ',
'<strong>', htmlspecialchars($pkgbase_name), '</strong>'); ?>
</p>
<ul>
<?php foreach(pkgbase_get_pkgnames($base_id) as $pkgname): ?>
<li><?= htmlspecialchars($pkgname) ?></li>
<?php endforeach; ?>
</ul>
<p>
<?php if (in_array(uid_from_sid($_COOKIE["AURSID"]), $comaintainer_uids) && !has_credential(CRED_PKGBASE_DISOWN)):
$action = "do_DisownComaintainer"; ?>
<?= __("By selecting the checkbox, you confirm that you want to no longer be a package co-maintainer.") ?>
<?php elseif (count($comaintainers) > 0 && !has_credential(CRED_PKGBASE_DISOWN)): ?>
<?= __('By selecting the checkbox, you confirm that you want to disown the package and transfer ownership to %s%s%s.',
'<strong>', $comaintainers[0], '</strong>'); ?>
<?php else: ?>
<?= __('By selecting the checkbox, you confirm that you want to disown the package.') ?>
<?php endif; ?>
</p>
<form action="<?= get_pkgbase_uri($pkgbase_name); ?>" method="post">
<fieldset>
<input type="hidden" name="IDs[<?= $base_id ?>]" value="1" />
<input type="hidden" name="ID" value="<?= $base_id ?>" />
<input type="hidden" name="token" value="<?= htmlspecialchars($_COOKIE['AURSID']) ?>" />
<?php if (isset($_GET['via'])): ?>
<input type="hidden" name="via" value="<?= intval($_GET['via']) ?>" />
<?php endif; ?>
<p><label class="confirmation"><input type="checkbox" name="confirm" value="1" />
<?= __("Confirm to disown the package") ?></label</p>
<p><input type="submit" class="button" name="<?= $action ?>" value="<?= __("Disown") ?>" /></p>
</fieldset>
</form>
</div>
<?php else:
print __("Only Trusted Users and Developers can disown packages.");
endif;
html_footer(AURWEB_VERSION);

View file

@ -1,91 +0,0 @@
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . '../lib');
include_once("aur.inc.php");
include_once("pkgfuncs.inc.php");
/* Grab the list of package base IDs to be operated on. */
$ids = array();
if (isset($_POST['IDs'])) {
foreach ($_POST['IDs'] as $id => $i) {
$id = intval($id);
if ($id > 0) {
$ids[] = $id;
}
}
}
/* Perform package base actions. */
$ret = false;
$output = "";
if (check_token()) {
if (current_action("do_Flag")) {
list($ret, $output) = pkgbase_flag($ids, $_POST['comments']);
}
if ($ret) {
header('Location: ' . get_pkgbase_uri($pkgbase_name));
exit();
}
}
/* Get default comment. */
$comment = '';
if (isset($_POST['comments'])) {
$comment = $_POST['comments'];
}
html_header(__("Flag Package Out-Of-Date"));
if (has_credential(CRED_PKGBASE_FLAG)): ?>
<div class="box">
<h2><?= __('Flag Package Out-Of-Date') ?>: <?= htmlspecialchars($pkgbase_name) ?></h2>
<p>
<?= __('Use this form to flag the package base %s%s%s and the following packages out-of-date: ',
'<strong>', htmlspecialchars($pkgbase_name), '</strong>'); ?>
</p>
<ul>
<?php foreach(pkgbase_get_pkgnames($base_id) as $pkgname): ?>
<li><?= htmlspecialchars($pkgname) ?></li>
<?php endforeach; ?>
</ul>
<?php if (pkgbase_is_vcs($base_id)): ?>
<p class="error">
This seems to be a VCS package. Please do <strong>not</strong>
flag it out-of-date if the package version in the AUR does not
match the most recent commit. Flagging this package should only
be done if the sources moved or changes in the PKGBUILD are
required because of recent upstream changes.
</p>
<?php endif; ?>
<p>
<?= __('Please do %snot%s use this form to report bugs. Use the package comments instead.',
'<strong>', '</strong>'); ?>
<?= __('Enter details on why the package is out-of-date below, preferably including links to the release announcement or the new release tarball.'); ?>
</p>
<?php if ($output && !$ret): ?>
<ul class="errorlist"><li><?= htmlspecialchars($output) ?></li></ul>
<?php endif; ?>
<form action="<?= get_pkgbase_uri($pkgbase_name); ?>flag/" method="post">
<fieldset>
<input type="hidden" name="IDs[<?= $base_id ?>]" value="1" />
<input type="hidden" name="ID" value="<?= $base_id ?>" />
<input type="hidden" name="token" value="<?= htmlspecialchars($_COOKIE['AURSID']) ?>" />
<p>
<label for="id_comments"><?= __("Comments") ?>:</label>
<textarea name="comments" id="id_comments" rows="5" cols="50"><?= htmlspecialchars($comment) ?></textarea>
</p>
<p><input type="submit" class="button" name="do_Flag" value="<?= __("Flag") ?>" /></p>
</fieldset>
</form>
</div>
<?php
else:
print __("Only registered users can flag packages out-of-date.");
endif;
html_footer(AURWEB_VERSION);

View file

@ -1,16 +0,0 @@
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . '../lib');
include_once("aur.inc.php");
include_once("pkgbasefuncs.inc.php");
if (!isset($base_id)) {
header('Location: /');
exit();
}
html_header(__("Flag Comment"));
$message = pkgbase_get_flag_comment($base_id);
include('flag_comment.php');
html_footer(AURWEB_VERSION);

View file

@ -1,58 +0,0 @@
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . '../lib');
include_once("aur.inc.php");
include_once("pkgfuncs.inc.php");
html_header(__("Package Merging"));
if (has_credential(CRED_PKGBASE_DELETE)): ?>
<div class="box">
<h2><?= __('Merge Package') ?>: <?= htmlspecialchars($pkgbase_name) ?></h2>
<p>
<?= __('Use this form to merge the package base %s%s%s into another package. ',
'<strong>', htmlspecialchars($pkgbase_name), '</strong>'); ?>
<?= __('The following packages will be deleted: '); ?>
</p>
<ul>
<?php foreach(pkgbase_get_pkgnames($base_id) as $pkgname): ?>
<li><?= htmlspecialchars($pkgname) ?></li>
<?php endforeach; ?>
</ul>
<p>
<?= __('Once the package has been merged it cannot be reversed. '); ?>
<?= __('Enter the package name you wish to merge the package into. '); ?>
<?= __('Select the checkbox to confirm action.') ?>
</p>
<form id="merge-form" action="<?= get_pkgbase_uri($pkgbase_name); ?>" method="post">
<fieldset>
<input type="hidden" name="IDs[<?= $base_id ?>]" value="1" />
<input type="hidden" name="ID" value="<?= $base_id ?>" />
<input type="hidden" name="token" value="<?= htmlspecialchars($_COOKIE['AURSID']) ?>" />
<?php if (isset($_GET['via'])): ?>
<input type="hidden" name="via" value="<?= intval($_GET['via']) ?>" />
<?php endif; ?>
<script type="text/javascript" src="/js/typeahead.js"></script>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function() {
const input = document.getElementById('merge_Into');
const form = document.getElementById('merge-form');
const type = "suggest-pkgbase";
typeahead.init(type, input, form, false);
});
</script>
<p><label id="merge-into" for="merge_Into" ><?= __("Merge into:") ?></label>
<input type="text" id="merge_Into" name="merge_Into" value="<?= isset($_GET['into']) ? $_GET['into'] : '' ?>" autocomplete="off"/></p>
<p><label class="confirmation"><input type="checkbox" name="confirm" value="1" />
<?= __("Confirm package merge") ?></label></p>
<p><input type="submit" class="button" name="do_Delete" value="<?= __("Merge") ?>" /></p>
</fieldset>
</form>
</div>
<?php else:
print __("Only Trusted Users and Developers can merge packages.");
endif;
html_footer(AURWEB_VERSION);

View file

@ -1,83 +0,0 @@
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . '../lib');
include_once("aur.inc.php");
include_once("pkgfuncs.inc.php");
if (isset($base_id)) {
if (!has_credential(CRED_PKGREQ_FILE)) {
header('Location: /');
exit();
}
html_header(__("Submit Request"));
include('pkgreq_form.php');
} elseif (isset($pkgreq_id)) {
if (!has_credential(CRED_PKGREQ_CLOSE)) {
header('Location: /');
exit();
}
html_header(__("Close Request"));
$pkgbase_name = pkgreq_get_pkgbase_name($pkgreq_id);
include('pkgreq_close_form.php');
} else {
if (!has_credential(CRED_PKGREQ_LIST)) {
header('Location: /');
exit();
}
/* Sanitize paging variables. */
if (isset($_GET['O'])) {
$_GET['O'] = max(intval($_GET['O']), 0);
} else {
$_GET['O'] = 0;
}
if (isset($_GET["PP"])) {
$_GET["PP"] = bound(intval($_GET["PP"]), 50, 250);
} else {
$_GET["PP"] = 50;
}
$results = pkgreq_list($_GET['O'], $_GET['PP']);
$total = pkgreq_count();
/* Calculate the results to use. */
$first = $_GET['O'] + 1;
/* Calculation of pagination links. */
$per_page = ($_GET['PP'] > 0) ? $_GET['PP'] : 50;
$current = ceil($first / $per_page);
$pages = ceil($total / $per_page);
$templ_pages = array();
if ($current > 1) {
$templ_pages['&laquo; ' . __('First')] = 0;
$templ_pages['&lsaquo; ' . __('Previous')] = ($current - 2) * $per_page;
}
if ($current - 5 > 1)
$templ_pages["..."] = false;
for ($i = max($current - 5, 1); $i <= min($pages, $current + 5); $i++) {
$templ_pages[$i] = ($i - 1) * $per_page;
}
if ($current + 5 < $pages)
$templ_pages["... "] = false;
if ($current < $pages) {
$templ_pages[__('Next') . ' &rsaquo;'] = $current * $per_page;
$templ_pages[__('Last') . ' &raquo;'] = ($pages - 1) * $per_page;
}
$SID = $_COOKIE['AURSID'];
html_header(__("Requests"));
echo '<div id="pkglist-results" class="box">';
$show_headers = true;
include('pkgreq_results.php');
echo '</div>';
}
html_footer(AURWEB_VERSION);

View file

@ -1,87 +0,0 @@
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . '../lib');
include_once('aur.inc.php'); # access AUR common functions
include_once('acctfuncs.inc.php'); # access Account specific functions
if (isset($_COOKIE["AURSID"])) {
header('Location: /');
exit();
}
html_header(__('Register'));
echo '<div class="box">';
echo '<h2>' . __('Register') . '</h2>';
if (in_request("Action") == "NewAccount") {
list($success, $message) = process_account_form(
"new",
"NewAccount",
in_request("U"),
1,
0,
in_request("E"),
in_request("BE"),
in_request("H"),
'',
'',
in_request("R"),
in_request("L"),
in_request("TZ"),
in_request("HP"),
in_request("I"),
in_request("K"),
in_request("PK"),
0,
in_request("CN"),
in_request("UN"),
in_request("ON"),
0,
"",
'',
in_request("captcha_salt"),
in_request("captcha"),
);
print $message;
if (!$success) {
display_account_form("NewAccount",
in_request("U"),
1,
0,
in_request("E"),
in_request("BE"),
in_request("H"),
'',
'',
in_request("R"),
in_request("L"),
in_request("TZ"),
in_request("HP"),
in_request("I"),
in_request("K"),
in_request("PK"),
0,
in_request("CN"),
in_request("UN"),
in_request("ON"),
0,
"",
'',
in_request("captcha_salt"),
in_request("captcha")
);
}
} else {
print '<p>' . __("Use this form to create an account.") . '</p>';
display_account_form("NewAccount", "", "", "", "", "", "", "", "", "", $LANG);
}
echo '</div>';
html_footer(AURWEB_VERSION);
?>

View file

@ -1,17 +0,0 @@
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . '../lib');
include_once("aurjson.class.php");
if ( $_SERVER['REQUEST_METHOD'] != 'GET' ) {
header('HTTP/1.1 405 Method Not Allowed');
exit();
}
if ( isset($_GET['type']) ) {
$rpc_o = new AurJSON();
echo $rpc_o->handle($_GET);
}
else {
echo file_get_contents('../../doc/rpc.html');
}
?>

View file

@ -1,61 +0,0 @@
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . '../lib' . PATH_SEPARATOR . '../lang');
include_once("aur.inc.php");
include_once("pkgfuncs.inc.php");
include_once("feedcreator.class.php");
#detect prefix
$protocol = isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"]=='on' ? "https" : "http";
$host = $_SERVER['HTTP_HOST'];
$feed_key = 'pkg-feed-' . $protocol;
header("Content-Type: application/rss+xml");
$bool = false;
$ret = get_cache_value($feed_key, $bool);
if ($bool) {
echo $ret;
exit();
}
$rss = new RSSCreator20();
$rss->cssStyleSheet = false;
$rss->xslStyleSheet = false;
# Use UTF-8 (fixes FS#10706).
$rss->encoding = "UTF-8";
#All the general RSS setup
$rss->title = "AUR Newest Packages";
$rss->description = "The latest and greatest packages in the AUR";
$rss->link = "${protocol}://{$host}";
$rss->syndicationURL = "{$protocol}://{$host}" . get_uri('/rss/');
$image = new FeedImage();
$image->title = "AUR Newest Packages";
$image->url = "{$protocol}://{$host}/css/archnavbar/aurlogo.png";
$image->link = $rss->link;
$image->description = "AUR Newest Packages Feed";
$rss->image = $image;
#Get the latest packages and add items for them
$packages = latest_pkgs(100);
foreach ($packages as $indx => $row) {
$item = new FeedItem();
$item->title = $row["Name"];
$item->link = "{$protocol}://{$host}" . get_pkg_uri($row["Name"]);
$item->description = $row["Description"];
$item->date = intval($row["SubmittedTS"]);
$item->source = "{$protocol}://{$host}";
$item->author = username_from_id($row["MaintainerUID"]);
$item->guid = $item->link;
$rss->addItem($item);
}
#save it so that useCached() can find it
$feedContent = $rss->createFeed();
set_cache_value($feed_key, $feedContent, 600);
echo $feedContent;
?>

View file

@ -1,50 +0,0 @@
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . '../lib');
include_once("aur.inc.php");
$uid = uid_from_sid($_COOKIE["AURSID"]);
if (isset($_POST["accept"]) && $_POST["accept"]) {
accept_terms($uid, $_POST["rev"]);
header("Location: " . get_uri('/'));
}
$terms = fetch_updated_terms($uid);
if (!$terms) {
header("Location: " . get_uri('/'));
}
html_header('AUR ' . __("Terms of Service"));
?>
<div id="dev-login" class="box">
<h2>AUR <?= __('Terms of Service') ?></h2>
<?php if (isset($_COOKIE["AURSID"])): ?>
<form method="post" action="<?= get_uri('/tos') ?>">
<fieldset>
<p>
<?= __("Logged-in as: %s", '<strong>' . username_from_sid($_COOKIE["AURSID"]) . '</strong>'); ?>
</p>
<p>
<?= __("The following documents have been updated. Please review them carefully:"); ?>
</p>
<ul>
<?php foreach($terms as $row): ?>
<li><a href="<?= htmlspecialchars(sprintf($row["URL"], $row["Revision"]), ENT_QUOTES) ?>"><?= htmlspecialchars($row["Description"]) ?></a> (<?= __('revision %d', $row["Revision"]) ?>)</li>
<?php endforeach; ?>
</ul>
<p>
<?php foreach($terms as $row): ?>
<input type="hidden" name="rev[<?= $row["ID"] ?>]" value="<?= $row["Revision"] ?>" />
<?php endforeach; ?>
<input type="checkbox" name="accept" /> <?= __("I accept the terms and conditions above."); ?>
</p>
<p>
<input type="submit" name="submit" value="<?= __("Continue") ?>" />
</p>
</fieldset>
</form>
<?php endif; ?>
</div>
<?php
html_footer(AURWEB_VERSION);

View file

@ -1,122 +0,0 @@
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . '../lib');
include_once("aur.inc.php");
$title = __("Trusted User");
html_header($title);
# Default votes per page
$pp = 10;
$prev_Len = 75;
if (has_credential(CRED_TU_LIST_VOTES)) {
if (isset($_GET['id'])) {
if (is_numeric($_GET['id'])) {
$row = vote_details($_GET['id']);
if (empty($row)) {
print __("Could not retrieve proposal details.");
} else {
$isrunning = $row['End'] > time() ? 1 : 0;
# List voters of a proposal.
$whovoted = voter_list($row['ID']);
$canvote = 1;
$hasvoted = 0;
$errorvote = "";
if ($isrunning == 0) {
$canvote = 0;
$errorvote = __("Voting is closed for this proposal.");
} else if (!has_credential(CRED_TU_VOTE)) {
$canvote = 0;
$errorvote = __("Only Trusted Users are allowed to vote.");
} else if ($row['User'] == username_from_sid($_COOKIE["AURSID"])) {
$canvote = 0;
$errorvote = __("You cannot vote in an proposal about you.");
}
if (tu_voted($row['ID'], uid_from_sid($_COOKIE["AURSID"]))) {
$canvote = 0;
$hasvoted = 1;
if ($isrunning) {
$errorvote = __("You've already voted for this proposal.");
}
}
if ($canvote == 1) {
if (isset($_POST['doVote']) && check_token()) {
if (isset($_POST['voteYes'])) {
$myvote = "Yes";
} else if (isset($_POST['voteNo'])) {
$myvote = "No";
} else if (isset($_POST['voteAbstain'])) {
$myvote = "Abstain";
}
cast_proposal_vote($row['ID'], uid_from_sid($_COOKIE["AURSID"]), $myvote, $row[$myvote] + 1);
# Can't vote anymore
#
$canvote = 0;
$errorvote = __("You've already voted for this proposal.");
# Update if they voted
if (tu_voted($row['ID'], uid_from_sid($_COOKIE["AURSID"]))) {
$hasvoted = 1;
}
$row = vote_details($_GET['id']);
}
}
include("tu_details.php");
}
} else {
print __("Vote ID not valid.");
}
} else {
$limit = $pp;
if (isset($_GET['off']))
$offset = $_GET['off'];
if (isset($_GET['by']))
$by = $_GET['by'];
else
$by = 'desc';
if (!empty($offset) && is_numeric($offset)) {
if ($offset >= 1) {
$off = $offset;
} else {
$off = 0;
}
} else {
$off = 0;
}
$order = ($by == 'asc') ? 'ASC' : 'DESC';
$lim = ($limit > 0) ? " LIMIT $limit OFFSET $off" : "";
$by_next = ($by == 'desc') ? 'asc' : 'desc';
$result = current_proposal_list($order);
$type = __("Current Votes");
$nextresult = 0;
include("tu_list.php");
$result = past_proposal_list($order, $lim);
$type = __("Past Votes");
$nextresult = proposal_count();
include("tu_list.php");
$result = last_votes_list();
include("tu_last_votes_list.php");
}
}
else {
header('Location: /');
}
html_footer(AURWEB_VERSION);

View file

@ -1,34 +0,0 @@
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . '../lib');
include_once('aur.inc.php');
include_once('pkgbasefuncs.inc.php');
$SID = $_COOKIE['AURSID'];
$pkgbase_name = htmlspecialchars($_GET['N']);
$votes = pkgbase_votes_from_name($pkgbase_name);
html_header(__("Voters"));
if (has_credential(CRED_PKGBASE_LIST_VOTERS)):
?>
<div class="box">
<h2>Votes for <a href="<?= get_pkgbase_uri($pkgbase_name); ?>"><?= $pkgbase_name ?></a></h2>
<div class="boxbody">
<ul>
<?php foreach ($votes as $indx => $row): ?>
<li>
<a href="<?= get_user_uri($row['Username']); ?>"><?= htmlspecialchars($row['Username']) ?></a>
<?php if ($row["VoteTS"] > 0): ?>
(<?= date("Y-m-d H:i", intval($row["VoteTS"])) ?>)
<?php endif; ?>
</li>
<?php endforeach; ?>
</ul>
</div>
</div>
<?php
endif;
html_footer(AURWEB_VERSION);

View file

@ -1,59 +0,0 @@
<?php
include_once("confparser.inc.php");
class DB {
/**
* A database object
*/
private static $dbh = null;
/**
* Return an already existing database object or newly instantiated object
*
* @return \PDO A database connection using PDO
*/
public static function connect() {
if (self::$dbh === null) {
try {
$backend = config_get('database', 'backend');
$host = config_get('database', 'host');
$socket = config_get('database', 'socket');
$port = config_get('database', 'port');
$name = config_get('database', 'name');
$user = config_get('database', 'user');
$password = config_get('database', 'password');
if ($backend == "mysql") {
if ($port != '') {
$dsn = $backend .
':host=' . $host .
';port=' . $port .
';dbname=' . $name;
} else {
$dsn = $backend .
':host=' . $host .
';unix_socket=' . $socket .
';dbname=' . $name;
}
self::$dbh = new PDO($dsn, $user, $password);
self::$dbh->exec("SET NAMES 'utf8' COLLATE 'utf8_general_ci';");
} else if ($backend == "sqlite") {
$dsn = $backend .
":" . $name;
self::$dbh = new PDO($dsn, null, null);
} else {
die("Error - " . $backend . " is not supported by aurweb");
}
} catch (PDOException $e) {
die('Error - Could not connect to AUR database');
}
}
return self::$dbh;
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,774 +0,0 @@
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . '../lib' . PATH_SEPARATOR . '../template');
header('Content-Type: text/html; charset=utf-8');
header('Cache-Control: no-cache, must-revalidate');
header('Expires: Tue, 11 Oct 1988 22:00:00 GMT'); // quite a special day
header('Pragma: no-cache');
header('X-Frame-Options: DENY');
date_default_timezone_set('UTC');
include_once('translator.inc.php');
set_lang();
include_once("DB.class.php");
include_once("routing.inc.php");
include_once("version.inc.php");
include_once("acctfuncs.inc.php");
include_once("cachefuncs.inc.php");
include_once("confparser.inc.php");
include_once("credentials.inc.php");
include_once('timezone.inc.php');
set_tz();
check_sid();
check_tos();
/**
* Check if a visitor is logged in
*
* Query "Sessions" table with supplied cookie. Determine if the cookie is valid
* or not. Unset the cookie if invalid or session timeout reached. Update the
* session timeout if it is still valid.
*
* @global array $_COOKIE User cookie values
*
* @return void
*/
function check_sid() {
global $_COOKIE;
if (isset($_COOKIE["AURSID"])) {
$failed = 0;
$timeout = config_get_int('options', 'login_timeout');
# the visitor is logged in, try and update the session
#
$dbh = DB::connect();
$q = "SELECT LastUpdateTS, " . strval(time()) . " FROM Sessions ";
$q.= "WHERE SessionID = " . $dbh->quote($_COOKIE["AURSID"]);
$result = $dbh->query($q);
$row = $result->fetch(PDO::FETCH_NUM);
if (!$row) {
# Invalid SessionID - hacker alert!
#
$failed = 1;
} else {
$last_update = $row[0];
if ($last_update + $timeout <= $row[1]) {
$failed = 2;
}
}
if ($failed == 1) {
# clear out the hacker's cookie, and send them to a naughty page
# why do you have to be so harsh on these people!?
#
setcookie("AURSID", "", 1, "/", null, !empty($_SERVER['HTTPS']), true);
unset($_COOKIE['AURSID']);
} elseif ($failed == 2) {
# session id timeout was reached and they must login again.
#
delete_session_id($_COOKIE["AURSID"]);
setcookie("AURSID", "", 1, "/", null, !empty($_SERVER['HTTPS']), true);
unset($_COOKIE['AURSID']);
} else {
# still logged in and haven't reached the timeout, go ahead
# and update the idle timestamp
# Only update the timestamp if it is less than the
# current time plus $timeout.
#
# This keeps 'remembered' sessions from being
# overwritten.
if ($last_update < time() + $timeout) {
$q = "UPDATE Sessions SET LastUpdateTS = " . strval(time()) . " ";
$q.= "WHERE SessionID = " . $dbh->quote($_COOKIE["AURSID"]);
$dbh->exec($q);
}
}
}
return;
}
/**
* Redirect user to the Terms of Service agreement if there are updated terms.
*
* @return void
*/
function check_tos() {
if (!isset($_COOKIE["AURSID"])) {
return;
}
$path = $_SERVER['PATH_INFO'];
$route = get_route($path);
if (!$route || $route == "tos.php") {
return;
}
if (count(fetch_updated_terms(uid_from_sid($_COOKIE["AURSID"]))) > 0) {
header('Location: ' . get_uri('/tos'));
exit();
}
}
/**
* Verify the supplied CSRF token matches expected token
*
* @return bool True if the CSRF token is the same as the cookie SID, otherwise false
*/
function check_token() {
if (isset($_POST['token']) && isset($_COOKIE['AURSID'])) {
return ($_POST['token'] == $_COOKIE['AURSID']);
} else {
return false;
}
}
/**
* Verify a user supplied e-mail against RFC 3696 and DNS records
*
* @param string $addy E-mail address being validated in foo@example.com format
*
* @return bool True if e-mail passes validity checks, otherwise false
*/
function valid_email($addy) {
// check against RFC 3696
if (filter_var($addy, FILTER_VALIDATE_EMAIL) === false) {
return false;
}
// check dns for mx, a, aaaa records
list($local, $domain) = explode('@', $addy);
if (!(checkdnsrr($domain, 'MX') || checkdnsrr($domain, 'A') || checkdnsrr($domain, 'AAAA'))) {
return false;
}
return true;
}
/**
* Verify that a given URL is valid and uses the HTTP(s) protocol
*
* @param string $url URL of the home page to be validated
*
* @return bool True if URL passes validity checks, false otherwise
*/
function valid_homepage($url) {
if (filter_var($url, FILTER_VALIDATE_URL) === false) {
return false;
}
$url_components = parse_url($url);
if (!in_array($url_components['scheme'], array('http', 'https'))) {
return false;
}
return true;
}
/**
* Generate a unique session ID
*
* @return string MD5 hash of the concatenated user IP, random number, and current time
*/
function new_sid() {
return md5($_SERVER['REMOTE_ADDR'] . uniqid(mt_rand(), true));
}
/**
* Determine the user's username in the database using a user ID
*
* @param string $id User's ID
*
* @return string Username if it exists, otherwise null
*/
function username_from_id($id) {
$id = intval($id);
$dbh = DB::connect();
$q = "SELECT Username FROM Users WHERE ID = " . $dbh->quote($id);
$result = $dbh->query($q);
if (!$result) {
return null;
}
$row = $result->fetch(PDO::FETCH_NUM);
if ($row) {
return $row[0];
}
}
/**
* Determine the user's username in the database using a session ID
*
* @param string $sid User's session ID
*
* @return string Username of the visitor
*/
function username_from_sid($sid="") {
if (!$sid) {
return "";
}
$dbh = DB::connect();
$q = "SELECT Username ";
$q.= "FROM Users, Sessions ";
$q.= "WHERE Users.ID = Sessions.UsersID ";
$q.= "AND Sessions.SessionID = " . $dbh->quote($sid);
$result = $dbh->query($q);
if (!$result) {
return "";
}
$row = $result->fetch(PDO::FETCH_NUM);
if ($row) {
return $row[0];
}
}
/**
* Format a user name for inclusion in HTML data
*
* @param string $username The user name to format
*
* @return string The generated HTML code for the account link
*/
function html_format_username($username) {
$username_fmt = $username ? htmlspecialchars($username, ENT_QUOTES) : __("None");
if ($username && isset($_COOKIE["AURSID"])) {
$link = '<a href="' . get_uri('/account/') . $username_fmt;
$link .= '" title="' . __('View account information for %s', $username_fmt);
$link .= '">' . $username_fmt . '</a>';
return $link;
} else {
return $username_fmt;
}
}
/**
* Format the maintainer and co-maintainers for inclusion in HTML data
*
* @param string $maintainer The user name of the maintainer
* @param array $comaintainers The list of co-maintainer user names
*
* @return string The generated HTML code for the account links
*/
function html_format_maintainers($maintainer, $comaintainers) {
$code = html_format_username($maintainer);
if (count($comaintainers) > 0) {
$code .= ' (';
foreach ($comaintainers as $comaintainer) {
$code .= html_format_username($comaintainer);
if ($comaintainer !== end($comaintainers)) {
$code .= ', ';
}
}
$code .= ')';
}
return $code;
}
/**
* Format a link in the package actions box
*
* @param string $uri The link target
* @param string $inner The HTML code to use for the link label
*
* @return string The generated HTML code for the action link
*/
function html_action_link($uri, $inner) {
if (isset($_COOKIE["AURSID"])) {
$code = '<a href="' . htmlspecialchars($uri, ENT_QUOTES) . '">';
} else {
$code = '<a href="' . get_uri('/login/', true) . '?referer=';
$code .= urlencode(rtrim(aur_location(), '/') . $uri) . '">';
}
$code .= $inner . '</a>';
return $code;
}
/**
* Format a form in the package actions box
*
* @param string $uri The link target
* @param string $action The action name (passed as HTTP POST parameter)
* @param string $inner The HTML code to use for the link label
*
* @return string The generated HTML code for the action link
*/
function html_action_form($uri, $action, $inner) {
if (isset($_COOKIE["AURSID"])) {
$code = '<form action="' . htmlspecialchars($uri, ENT_QUOTES) . '" ';
$code .= 'method="post">';
$code .= '<input type="hidden" name="token" value="';
$code .= htmlspecialchars($_COOKIE['AURSID'], ENT_QUOTES) . '" />';
$code .= '<input type="submit" class="button text-button" name="';
$code .= htmlspecialchars($action, ENT_QUOTES) . '" ';
$code .= 'value="' . $inner . '" />';
$code .= '</form>';
} else {
$code = '<a href="' . get_uri('/login/', true) . '">';
$code .= $inner . '</a>';
}
return $code;
}
/**
* Determine the user's e-mail address in the database using a session ID
*
* @param string $sid User's session ID
*
* @return string User's e-mail address as given during registration
*/
function email_from_sid($sid="") {
if (!$sid) {
return "";
}
$dbh = DB::connect();
$q = "SELECT Email ";
$q.= "FROM Users, Sessions ";
$q.= "WHERE Users.ID = Sessions.UsersID ";
$q.= "AND Sessions.SessionID = " . $dbh->quote($sid);
$result = $dbh->query($q);
if (!$result) {
return "";
}
$row = $result->fetch(PDO::FETCH_NUM);
if ($row) {
return $row[0];
}
}
/**
* Determine the user's account type in the database using a session ID
*
* @param string $sid User's session ID
*
* @return string Account type of user ("User", "Trusted User", or "Developer")
*/
function account_from_sid($sid="") {
if (!$sid) {
return "";
}
$dbh = DB::connect();
$q = "SELECT AccountType ";
$q.= "FROM Users, AccountTypes, Sessions ";
$q.= "WHERE Users.ID = Sessions.UsersID ";
$q.= "AND AccountTypes.ID = Users.AccountTypeID ";
$q.= "AND Sessions.SessionID = " . $dbh->quote($sid);
$result = $dbh->query($q);
if (!$result) {
return "";
}
$row = $result->fetch(PDO::FETCH_NUM);
if ($row) {
return $row[0];
}
}
/**
* Determine the user's ID in the database using a session ID
*
* @param string $sid User's session ID
*
* @return string|int The user's name, 0 on query failure
*/
function uid_from_sid($sid="") {
if (!$sid) {
return "";
}
$dbh = DB::connect();
$q = "SELECT Users.ID ";
$q.= "FROM Users, Sessions ";
$q.= "WHERE Users.ID = Sessions.UsersID ";
$q.= "AND Sessions.SessionID = " . $dbh->quote($sid);
$result = $dbh->query($q);
if (!$result) {
return 0;
}
$row = $result->fetch(PDO::FETCH_NUM);
if ($row) {
return $row[0];
}
}
/**
* Common AUR header displayed on all pages
*
* @global string $LANG Language selected by the visitor
* @global array $SUPPORTED_LANGS Languages that are supported by the AUR
* @param string $title Name of the AUR page to be displayed on browser
*
* @return void
*/
function html_header($title="", $details=array()) {
global $LANG;
global $SUPPORTED_LANGS;
include('header.php');
return;
}
/**
* Common AUR footer displayed on all pages
*
* @param string $ver The AUR version
*
* @return void
*/
function html_footer($ver="") {
include('footer.php');
return;
}
/**
* Determine if a user has permission to submit a package
*
* @param string $name Name of the package to be submitted
* @param string $sid User's session ID
*
* @return int 0 if the user can't submit, 1 if the user can submit
*/
function can_submit_pkgbase($name="", $sid="") {
if (!$name || !$sid) {return 0;}
$dbh = DB::connect();
$q = "SELECT MaintainerUID ";
$q.= "FROM PackageBases WHERE Name = " . $dbh->quote($name);
$result = $dbh->query($q);
$row = $result->fetch(PDO::FETCH_NUM);
if (!$row[0]) {
return 1;
}
$my_uid = uid_from_sid($sid);
if ($row[0] === NULL || $row[0] == $my_uid) {
return 1;
}
return 0;
}
/**
* Determine if a package can be overwritten by some package base
*
* @param string $name Name of the package to be submitted
* @param int $base_id The ID of the package base
*
* @return bool True if the package can be overwritten, false if not
*/
function can_submit_pkg($name, $base_id) {
$dbh = DB::connect();
$q = "SELECT COUNT(*) FROM Packages WHERE ";
$q.= "Name = " . $dbh->quote($name) . " AND ";
$q.= "PackageBaseID <> " . intval($base_id);
$result = $dbh->query($q);
if (!$result) return false;
return ($result->fetchColumn() == 0);
}
/**
* Recursively delete a directory
*
* @param string $dirname Name of the directory to be removed
*
* @return void
*/
function rm_tree($dirname) {
if (empty($dirname) || !is_dir($dirname)) return;
foreach (scandir($dirname) as $item) {
if ($item != '.' && $item != '..') {
$path = $dirname . '/' . $item;
if (is_file($path) || is_link($path)) {
unlink($path);
}
else {
rm_tree($path);
}
}
}
rmdir($dirname);
return;
}
/**
* Determine the user's ID in the database using a username
*
* @param string $username The username of an account
*
* @return string Return user ID if exists for username, otherwise null
*/
function uid_from_username($username) {
$dbh = DB::connect();
$q = "SELECT ID FROM Users WHERE Username = " . $dbh->quote($username);
$result = $dbh->query($q);
if (!$result) {
return null;
}
$row = $result->fetch(PDO::FETCH_NUM);
if ($row) {
return $row[0];
}
}
/**
* Determine the user's ID in the database using a username or email address
*
* @param string $username The username or email address of an account
*
* @return string Return user ID if exists, otherwise null
*/
function uid_from_loginname($loginname) {
$uid = uid_from_username($loginname);
if (!$uid) {
$uid = uid_from_email($loginname);
}
return $uid;
}
/**
* Determine the user's ID in the database using an e-mail address
*
* @param string $email An e-mail address in foo@example.com format
*
* @return string The user's ID
*/
function uid_from_email($email) {
$dbh = DB::connect();
$q = "SELECT ID FROM Users WHERE Email = " . $dbh->quote($email);
$result = $dbh->query($q);
if (!$result) {
return null;
}
$row = $result->fetch(PDO::FETCH_NUM);
if ($row) {
return $row[0];
}
}
/**
* Generate clean url with edited/added user values
*
* Makes a clean string of variables for use in URLs based on current $_GET and
* list of values to edit/add to that. Any empty variables are discarded.
*
* @example print "http://example.com/test.php?" . mkurl("foo=bar&bar=baz")
*
* @param string $append string of variables and values formatted as in URLs
*
* @return string clean string of variables to append to URL, urlencoded
*/
function mkurl($append) {
$get = $_GET;
$append = explode('&', $append);
$uservars = array();
$out = '';
foreach ($append as $i) {
$ex = explode('=', $i);
$uservars[$ex[0]] = $ex[1];
}
foreach ($uservars as $k => $v) { $get[$k] = $v; }
foreach ($get as $k => $v) {
if ($v !== '') {
$out .= '&amp;' . urlencode($k) . '=' . urlencode($v);
}
}
return substr($out, 5);
}
/**
* Get a package comment
*
* @param int $comment_id The ID of the comment
*
* @return array The user ID and comment OR null, null in case of an error
*/
function comment_by_id($comment_id) {
$dbh = DB::connect();
$q = "SELECT UsersID, Comments FROM PackageComments ";
$q.= "WHERE ID = " . intval($comment_id);
$result = $dbh->query($q);
if (!$result) {
return array(null, null);
}
return $result->fetch(PDO::FETCH_NUM);
}
/**
* Process submitted comments so any links can be followed
*
* @param string $comment Raw user submitted package comment
*
* @return string User comment with links printed in HTML
*/
function parse_comment($comment) {
$url_pattern = '/(\b(?:https?|ftp):\/\/[\w\/\#~:.?+=&%@!\-;,]+?' .
'(?=[.:?\-;,]*(?:[^\w\/\#~:.?+=&%@!\-;,]|$)))/iS';
$matches = preg_split($url_pattern, $comment, -1,
PREG_SPLIT_DELIM_CAPTURE);
$html = '';
for ($i = 0; $i < count($matches); $i++) {
if ($i % 2) {
# convert links
$html .= '<a href="' . htmlspecialchars($matches[$i]) .
'" rel="nofollow">' . htmlspecialchars($matches[$i]) . '</a>';
}
else {
# convert everything else
$html .= nl2br(htmlspecialchars($matches[$i]));
}
}
return $html;
}
/**
* Wrapper for beginning a database transaction
*/
function begin_atomic_commit() {
$dbh = DB::connect();
$dbh->beginTransaction();
}
/**
* Wrapper for committing a database transaction
*/
function end_atomic_commit() {
$dbh = DB::connect();
$dbh->commit();
}
/**
* Merge pkgbase and package options
*
* Merges entries of the first and the second array. If any key appears in both
* arrays and the corresponding value in the second array is either a non-array
* type or a non-empty array, the value from the second array replaces the
* value from the first array. If the value from the second array is an array
* containing a single empty string, the value in the resulting array becomes
* an empty array instead. If the value in the second array is empty, the
* resulting array contains the value from the first array.
*
* @param array $pkgbase_info Options from the pkgbase section
* @param array $section_info Options from the package section
*
* @return array Merged information from both sections
*/
function array_pkgbuild_merge($pkgbase_info, $section_info) {
$pi = $pkgbase_info;
foreach ($section_info as $opt_key => $opt_val) {
if (is_array($opt_val)) {
if ($opt_val == array('')) {
$pi[$opt_key] = array();
} elseif (count($opt_val) > 0) {
$pi[$opt_key] = $opt_val;
}
} else {
$pi[$opt_key] = $opt_val;
}
}
return $pi;
}
/**
* Bound an integer value between two values
*
* @param int $n Integer value to bound
* @param int $min Lower bound
* @param int $max Upper bound
*
* @return int Bounded integer value
*/
function bound($n, $min, $max) {
return min(max($n, $min), $max);
}
/**
* Return the URL of the AUR root
*
* @return string The URL of the AUR root
*/
function aur_location() {
$location = config_get('options', 'aur_location');
if (substr($location, -1) != '/') {
$location .= '/';
}
return $location;
}
/**
* Calculate pagination templates
*
* @return array The array of pagination templates, per page, and offset values
*/
function calculate_pagination($total_comment_count) {
/* Sanitize paging variables. */
if (isset($_GET["O"])) {
$_GET["O"] = max(intval($_GET["O"]), 0);
} else {
$_GET["O"] = 0;
}
$offset = $_GET["O"];
if (isset($_GET["PP"])) {
$_GET["PP"] = bound(intval($_GET["PP"]), 1, 250);
} else {
$_GET["PP"] = 10;
}
$per_page = $_GET["PP"];
// Page offsets start at zero, so page 2 has offset 1, which means that we
// need to add 1 to the offset to get the current page.
$current_page = ceil($offset / $per_page) + 1;
$num_pages = ceil($total_comment_count / $per_page);
$pagination_templs = array();
if ($current_page > 1) {
$previous_page = $current_page - 1;
$previous_offset = ($previous_page - 1) * $per_page;
$pagination_templs['&laquo; ' . __('First')] = 0;
$pagination_templs['&lsaquo; ' . __('Previous')] = $previous_offset;
}
if ($current_page - 5 > 1) {
$pagination_templs["..."] = false;
}
for ($i = max($current_page - 5, 1); $i <= min($num_pages, $current_page + 5); $i++) {
$pagination_templs[$i] = ($i - 1) * $per_page;
}
if ($current_page + 5 < $num_pages)
$pagination_templs["... "] = false;
if ($current_page < $num_pages) {
$pagination_templs[__('Next') . ' &rsaquo;'] = $current_page * $per_page;
$pagination_templs[__('Last') . ' &raquo;'] = ($num_pages - 1) * $per_page;
}
return array($pagination_templs, $per_page, $offset);
}

View file

@ -1,710 +0,0 @@
<?php
include_once("aur.inc.php");
include_once("pkgfuncs.inc.php");
/*
* This class defines a remote interface for fetching data from the AUR using
* JSON formatted elements.
*
* @package rpc
* @subpackage classes
*/
class AurJSON {
private $dbh = false;
private $version = 1;
private static $exposed_methods = array(
'search', 'info', 'multiinfo', 'msearch', 'suggest',
'suggest-pkgbase', 'get-comment-form'
);
private static $exposed_fields = array(
'name', 'name-desc', 'maintainer',
'depends', 'makedepends', 'checkdepends', 'optdepends'
);
private static $exposed_depfields = array(
'depends', 'makedepends', 'checkdepends', 'optdepends'
);
private static $fields_v1 = array(
'Packages.ID', 'Packages.Name',
'PackageBases.ID AS PackageBaseID',
'PackageBases.Name AS PackageBase', 'Version',
'Description', 'URL', 'NumVotes', 'OutOfDateTS AS OutOfDate',
'Users.UserName AS Maintainer',
'SubmittedTS AS FirstSubmitted', 'ModifiedTS AS LastModified',
'Licenses.Name AS License'
);
private static $fields_v2 = array(
'Packages.ID', 'Packages.Name',
'PackageBases.ID AS PackageBaseID',
'PackageBases.Name AS PackageBase', 'Version',
'Description', 'URL', 'NumVotes', 'OutOfDateTS AS OutOfDate',
'Users.UserName AS Maintainer',
'SubmittedTS AS FirstSubmitted', 'ModifiedTS AS LastModified'
);
private static $fields_v4 = array(
'Packages.ID', 'Packages.Name',
'PackageBases.ID AS PackageBaseID',
'PackageBases.Name AS PackageBase', 'Version',
'Description', 'URL', 'NumVotes', 'Popularity',
'OutOfDateTS AS OutOfDate', 'Users.UserName AS Maintainer',
'SubmittedTS AS FirstSubmitted', 'ModifiedTS AS LastModified'
);
private static $numeric_fields = array(
'ID', 'PackageBaseID', 'NumVotes', 'OutOfDate',
'FirstSubmitted', 'LastModified'
);
private static $decimal_fields = array(
'Popularity'
);
/*
* Handles post data, and routes the request.
*
* @param string $post_data The post data to parse and handle.
*
* @return string The JSON formatted response data.
*/
public function handle($http_data) {
/*
* Unset global aur.inc.php Pragma header. We want to allow
* caching of data in proxies, but require validation of data
* (if-none-match) if possible.
*/
header_remove('Pragma');
/*
* Overwrite cache-control header set in aur.inc.php to allow
* caching, but require validation.
*/
header('Cache-Control: public, must-revalidate, max-age=0');
header('Content-Type: application/json, charset=utf-8');
if (isset($http_data['v'])) {
$this->version = intval($http_data['v']);
}
if ($this->version < 1 || $this->version > 6) {
return $this->json_error('Invalid version specified.');
}
if (!isset($http_data['type']) || !isset($http_data['arg'])) {
return $this->json_error('No request type/data specified.');
}
if (!in_array($http_data['type'], self::$exposed_methods)) {
return $this->json_error('Incorrect request type specified.');
}
if (isset($http_data['search_by']) && !isset($http_data['by'])) {
$http_data['by'] = $http_data['search_by'];
}
if (isset($http_data['by']) && !in_array($http_data['by'], self::$exposed_fields)) {
return $this->json_error('Incorrect by field specified.');
}
$this->dbh = DB::connect();
if ($this->check_ratelimit($_SERVER['REMOTE_ADDR'])) {
header("HTTP/1.1 429 Too Many Requests");
return $this->json_error('Rate limit reached');
}
$type = str_replace('-', '_', $http_data['type']);
if ($type == 'info' && $this->version >= 5) {
$type = 'multiinfo';
}
$json = call_user_func(array(&$this, $type), $http_data);
$etag = md5($json);
header("Etag: \"$etag\"");
/*
* Make sure to strip a few things off the
* if-none-match header. Stripping whitespace may not
* be required, but removing the quote on the incoming
* header is required to make the equality test.
*/
$if_none_match = isset($_SERVER['HTTP_IF_NONE_MATCH']) ?
trim($_SERVER['HTTP_IF_NONE_MATCH'], "\t\n\r\" ") : false;
if ($if_none_match && $if_none_match == $etag) {
header('HTTP/1.1 304 Not Modified');
return;
}
if (isset($http_data['callback'])) {
$callback = $http_data['callback'];
if (!preg_match('/^[a-zA-Z0-9()_.]{1,128}$/D', $callback)) {
return $this->json_error('Invalid callback name.');
}
header('content-type: text/javascript');
return '/**/' . $callback . '(' . $json . ')';
} else {
header('content-type: application/json');
return $json;
}
}
/*
* Check if an IP needs to be rate limited.
*
* @param $ip IP of the current request
*
* @return true if IP needs to be rate limited, false otherwise.
*/
private function check_ratelimit($ip) {
$limit = config_get("ratelimit", "request_limit");
if ($limit == 0) {
return false;
}
$this->update_ratelimit($ip);
$status = false;
$value = get_cache_value('ratelimit:' . $ip, $status);
if (!$status) {
$stmt = $this->dbh->prepare("
SELECT Requests FROM ApiRateLimit
WHERE IP = :ip");
$stmt->bindParam(":ip", $ip);
$result = $stmt->execute();
if (!$result) {
return false;
}
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$value = $row['Requests'];
}
return $value > $limit;
}
/*
* Update a rate limit for an IP by increasing it's requests value by one.
*
* @param $ip IP of the current request
*
* @return void
*/
private function update_ratelimit($ip) {
$window_length = config_get("ratelimit", "window_length");
$db_backend = config_get("database", "backend");
$time = time();
$deletion_time = $time - $window_length;
/* Try to use the cache. */
$status = false;
$value = get_cache_value('ratelimit-ws:' . $ip, $status);
if (!$status || ($status && $value < $deletion_time)) {
if (set_cache_value('ratelimit-ws:' . $ip, $time, $window_length) &&
set_cache_value('ratelimit:' . $ip, 1, $window_length)) {
return;
}
} else {
$value = get_cache_value('ratelimit:' . $ip, $status);
if ($status && set_cache_value('ratelimit:' . $ip, $value + 1, $window_length))
return;
}
/* Clean up old windows. */
$stmt = $this->dbh->prepare("
DELETE FROM ApiRateLimit
WHERE WindowStart < :time");
$stmt->bindParam(":time", $deletion_time);
$stmt->execute();
if ($db_backend == "mysql") {
$stmt = $this->dbh->prepare("
INSERT INTO ApiRateLimit
(IP, Requests, WindowStart)
VALUES (:ip, 1, :window_start)
ON DUPLICATE KEY UPDATE Requests=Requests+1");
$stmt->bindParam(":ip", $ip);
$stmt->bindParam(":window_start", $time);
$stmt->execute();
} elseif ($db_backend == "sqlite") {
$stmt = $this->dbh->prepare("
INSERT OR IGNORE INTO ApiRateLimit
(IP, Requests, WindowStart)
VALUES (:ip, 0, :window_start);");
$stmt->bindParam(":ip", $ip);
$stmt->bindParam(":window_start", $time);
$stmt->execute();
$stmt = $this->dbh->prepare("
UPDATE ApiRateLimit
SET Requests = Requests + 1
WHERE IP = :ip");
$stmt->bindParam(":ip", $ip);
$stmt->execute();
} else {
throw new RuntimeException("Unknown database backend");
}
}
/*
* Returns a JSON formatted error string.
*
* @param $msg The error string to return
*
* @return mixed A json formatted error response.
*/
private function json_error($msg) {
header('content-type: application/json');
if ($this->version < 3) {
return $this->json_results('error', 0, $msg, NULL);
} elseif ($this->version >= 3) {
return $this->json_results('error', 0, array(), $msg);
}
}
/*
* Returns a JSON formatted result data.
*
* @param $type The response method type.
* @param $count The number of results to return
* @param $data The result data to return
* @param $error An error message to include in the response
*
* @return mixed A json formatted result response.
*/
private function json_results($type, $count, $data, $error) {
$json_array = array(
'version' => $this->version,
'type' => $type,
'resultcount' => $count,
'results' => $data
);
if ($this->version != 5) {
$json_array['warning'] = 'The use of versions lower than 5 is '
. 'now deprecated and will soon be unsupported. To ensure '
. 'your API client supports the change without issue, it '
. 'should use version 5 and adjust for any changes in the '
. 'API interface. See https://aur.archlinux.org/rpc for '
. 'documentation related to v5.';
}
if ($error) {
$json_array['error'] = $error;
}
return json_encode($json_array);
}
/*
* Get extended package details (for info and multiinfo queries).
*
* @param $pkgid The ID of the package to retrieve details for.
* @param $base_id The ID of the package base to retrieve details for.
*
* @return array An array containing package details.
*/
private function get_extended_fields($pkgid, $base_id) {
$query = "SELECT DependencyTypes.Name AS Type, " .
"PackageDepends.DepName AS Name, " .
"PackageDepends.DepCondition AS Cond " .
"FROM PackageDepends " .
"LEFT JOIN DependencyTypes " .
"ON DependencyTypes.ID = PackageDepends.DepTypeID " .
"WHERE PackageDepends.PackageID = " . $pkgid . " " .
"UNION SELECT RelationTypes.Name AS Type, " .
"PackageRelations.RelName AS Name, " .
"PackageRelations.RelCondition AS Cond " .
"FROM PackageRelations " .
"LEFT JOIN RelationTypes " .
"ON RelationTypes.ID = PackageRelations.RelTypeID " .
"WHERE PackageRelations.PackageID = " . $pkgid . " " .
"UNION SELECT 'groups' AS Type, `Groups`.`Name`, '' AS Cond " .
"FROM `Groups` INNER JOIN PackageGroups " .
"ON PackageGroups.PackageID = " . $pkgid . " " .
"AND PackageGroups.GroupID = `Groups`.ID " .
"UNION SELECT 'license' AS Type, Licenses.Name, '' AS Cond " .
"FROM Licenses INNER JOIN PackageLicenses " .
"ON PackageLicenses.PackageID = " . $pkgid . " " .
"AND PackageLicenses.LicenseID = Licenses.ID";
$ttl = config_get_int('options', 'cache_pkginfo_ttl');
$rows = db_cache_result($query, 'extended-fields:' . $pkgid, PDO::FETCH_ASSOC, $ttl);
$type_map = array(
'depends' => 'Depends',
'makedepends' => 'MakeDepends',
'checkdepends' => 'CheckDepends',
'optdepends' => 'OptDepends',
'conflicts' => 'Conflicts',
'provides' => 'Provides',
'replaces' => 'Replaces',
'groups' => 'Groups',
'license' => 'License',
);
$data = array();
foreach ($rows as $row) {
$type = $type_map[$row['Type']];
$data[$type][] = $row['Name'] . $row['Cond'];
}
if ($this->version >= 5) {
$query = "SELECT Keyword FROM PackageKeywords " .
"WHERE PackageBaseID = " . intval($base_id) . " " .
"ORDER BY Keyword ASC";
$ttl = config_get_int('options', 'cache_pkginfo_ttl');
$rows = db_cache_result($query, 'keywords:' . intval($base_id), PDO::FETCH_NUM, $ttl);
$data['Keywords'] = array_map(function ($x) { return $x[0]; }, $rows);
}
return $data;
}
/*
* Retrieve package information (used in info, multiinfo, search and
* depends requests).
*
* @param $type The request type.
* @param $where_condition An SQL WHERE-condition to filter packages.
*
* @return mixed Returns an array of package matches.
*/
private function process_query($type, $where_condition) {
$max_results = config_get_int('options', 'max_rpc_results');
if ($this->version == 1) {
$fields = implode(',', self::$fields_v1);
$query = "SELECT {$fields} " .
"FROM Packages LEFT JOIN PackageBases " .
"ON PackageBases.ID = Packages.PackageBaseID " .
"LEFT JOIN Users " .
"ON PackageBases.MaintainerUID = Users.ID " .
"LEFT JOIN PackageLicenses " .
"ON PackageLicenses.PackageID = Packages.ID " .
"LEFT JOIN Licenses " .
"ON Licenses.ID = PackageLicenses.LicenseID " .
"WHERE ${where_condition} " .
"AND PackageBases.PackagerUID IS NOT NULL " .
"LIMIT $max_results";
} elseif ($this->version >= 2) {
if ($this->version == 2 || $this->version == 3) {
$fields = implode(',', self::$fields_v2);
} else if ($this->version >= 4 && $this->version <= 6) {
$fields = implode(',', self::$fields_v4);
}
$query = "SELECT {$fields} " .
"FROM Packages LEFT JOIN PackageBases " .
"ON PackageBases.ID = Packages.PackageBaseID " .
"LEFT JOIN Users " .
"ON PackageBases.MaintainerUID = Users.ID " .
"WHERE ${where_condition} " .
"AND PackageBases.PackagerUID IS NOT NULL " .
"LIMIT $max_results";
}
$result = $this->dbh->query($query);
if ($result) {
$resultcount = 0;
$search_data = array();
while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
$resultcount++;
$row['URLPath'] = sprintf(config_get('options', 'snapshot_uri'), urlencode($row['PackageBase']));
if ($this->version < 4) {
$row['CategoryID'] = 1;
}
/*
* Unfortunately, mysql_fetch_assoc() returns
* all fields as strings. We need to coerce
* numeric values into integers to provide
* proper data types in the JSON response.
*/
foreach (self::$numeric_fields as $field) {
if (isset($row[$field])) {
$row[$field] = intval($row[$field]);
}
}
foreach (self::$decimal_fields as $field) {
if (isset($row[$field])) {
$row[$field] = floatval($row[$field]);
}
}
if ($this->version >= 2 && ($type == 'info' || $type == 'multiinfo')) {
$extfields = $this->get_extended_fields($row['ID'], $row['PackageBaseID']);
if ($extfields) {
$row = array_merge($row, $extfields);
}
}
if ($this->version < 3) {
if ($type == 'info') {
$search_data = $row;
break;
} else {
array_push($search_data, $row);
}
} elseif ($this->version >= 3) {
array_push($search_data, $row);
}
}
if ($resultcount === $max_results) {
return $this->json_error('Too many package results.');
}
return $this->json_results($type, $resultcount, $search_data, NULL);
} else {
return $this->json_results($type, 0, array(), NULL);
}
}
/*
* Parse the args to the multiinfo function. We may have a string or an
* array, so do the appropriate thing. Within the elements, both * package
* IDs and package names are valid; sort them into the relevant arrays and
* escape/quote the names.
*
* @param array $args Query parameters.
*
* @return mixed An array containing 'ids' and 'names'.
*/
private function parse_multiinfo_args($args) {
if (!is_array($args)) {
$args = array($args);
}
$id_args = array();
$name_args = array();
foreach ($args as $arg) {
if (!$arg) {
continue;
}
if ($this->version < 5 && is_numeric($arg)) {
$id_args[] = intval($arg);
} else {
$name_args[] = $this->dbh->quote($arg);
}
}
return array('ids' => $id_args, 'names' => $name_args);
}
/*
* Performs a fulltext mysql search of the package database.
*
* @param array $http_data Query parameters.
*
* @return mixed Returns an array of package matches.
*/
private function search($http_data) {
$keyword_string = $http_data['arg'];
if (isset($http_data['by'])) {
$search_by = $http_data['by'];
} else {
$search_by = 'name-desc';
}
if ($search_by === 'name' || $search_by === 'name-desc') {
if (strlen($keyword_string) < 2) {
return $this->json_error('Query arg too small.');
}
if ($this->version >= 6 && $search_by === 'name-desc') {
$where_condition = construct_keyword_search($this->dbh,
$keyword_string, true, false);
} else {
$keyword_string = $this->dbh->quote(
"%" . addcslashes($keyword_string, '%_') . "%");
if ($search_by === 'name') {
$where_condition = "(Packages.Name LIKE $keyword_string)";
} else if ($search_by === 'name-desc') {
$where_condition = "(Packages.Name LIKE $keyword_string ";
$where_condition .= "OR Description LIKE $keyword_string)";
}
}
} else if ($search_by === 'maintainer') {
if (empty($keyword_string)) {
$where_condition = "Users.ID is NULL";
} else {
$keyword_string = $this->dbh->quote($keyword_string);
$where_condition = "Users.Username = $keyword_string ";
}
} else if (in_array($search_by, self::$exposed_depfields)) {
if (empty($keyword_string)) {
return $this->json_error('Query arg is empty.');
} else {
$keyword_string = $this->dbh->quote($keyword_string);
$search_by = $this->dbh->quote($search_by);
$subquery = "SELECT PackageDepends.DepName FROM PackageDepends ";
$subquery .= "LEFT JOIN DependencyTypes ";
$subquery .= "ON PackageDepends.DepTypeID = DependencyTypes.ID ";
$subquery .= "WHERE PackageDepends.PackageID = Packages.ID ";
$subquery .= "AND DependencyTypes.Name = $search_by";
$where_condition = "$keyword_string IN ($subquery)";
}
}
return $this->process_query('search', $where_condition);
}
/*
* Returns the info on a specific package.
*
* @param array $http_data Query parameters.
*
* @return mixed Returns an array of value data containing the package data
*/
private function info($http_data) {
$pqdata = $http_data['arg'];
if ($this->version < 5 && is_numeric($pqdata)) {
$where_condition = "Packages.ID = $pqdata";
} else {
$where_condition = "Packages.Name = " . $this->dbh->quote($pqdata);
}
return $this->process_query('info', $where_condition);
}
/*
* Returns the info on multiple packages.
*
* @param array $http_data Query parameters.
*
* @return mixed Returns an array of results containing the package data
*/
private function multiinfo($http_data) {
$pqdata = $http_data['arg'];
$args = $this->parse_multiinfo_args($pqdata);
$ids = $args['ids'];
$names = $args['names'];
if (!$ids && !$names) {
return $this->json_error('Invalid query arguments.');
}
$where_condition = "";
if ($ids) {
$ids_value = implode(',', $args['ids']);
$where_condition .= "Packages.ID IN ($ids_value) ";
}
if ($ids && $names) {
$where_condition .= "OR ";
}
if ($names) {
/*
* Individual names were quoted in
* parse_multiinfo_args().
*/
$names_value = implode(',', $args['names']);
$where_condition .= "Packages.Name IN ($names_value) ";
}
return $this->process_query('multiinfo', $where_condition);
}
/*
* Returns all the packages for a specific maintainer.
*
* @param array $http_data Query parameters.
*
* @return mixed Returns an array of value data containing the package data
*/
private function msearch($http_data) {
$http_data['by'] = 'maintainer';
return $this->search($http_data);
}
/*
* Get all package names that start with $search.
*
* @param array $http_data Query parameters.
*
* @return string The JSON formatted response data.
*/
private function suggest($http_data) {
$search = $http_data['arg'];
$query = "SELECT Packages.Name FROM Packages ";
$query.= "LEFT JOIN PackageBases ";
$query.= "ON PackageBases.ID = Packages.PackageBaseID ";
$query.= "WHERE Packages.Name LIKE ";
$query.= $this->dbh->quote(addcslashes($search, '%_') . '%');
$query.= " AND PackageBases.PackagerUID IS NOT NULL ";
$query.= "ORDER BY Name ASC LIMIT 20";
$result = $this->dbh->query($query);
$result_array = array();
if ($result) {
$result_array = $result->fetchAll(PDO::FETCH_COLUMN, 0);
}
return json_encode($result_array);
}
/*
* Get all package base names that start with $search.
*
* @param array $http_data Query parameters.
*
* @return string The JSON formatted response data.
*/
private function suggest_pkgbase($http_data) {
$search = $http_data['arg'];
$query = "SELECT Name FROM PackageBases WHERE Name LIKE ";
$query.= $this->dbh->quote(addcslashes($search, '%_') . '%');
$query.= " AND PackageBases.PackagerUID IS NOT NULL ";
$query.= "ORDER BY Name ASC LIMIT 20";
$result = $this->dbh->query($query);
$result_array = array();
if ($result) {
$result_array = $result->fetchAll(PDO::FETCH_COLUMN, 0);
}
return json_encode($result_array);
}
/**
* Get the HTML markup of the comment form.
*
* @param array $http_data Query parameters.
*
* @return string The JSON formatted response data.
*/
private function get_comment_form($http_data) {
if (!isset($http_data['base_id']) || !isset($http_data['pkgbase_name'])) {
$output = array(
'success' => 0,
'error' => __('Package base ID or package base name missing.')
);
return json_encode($output);
}
$comment_id = intval($http_data['arg']);
$base_id = intval($http_data['base_id']);
$pkgbase_name = $http_data['pkgbase_name'];
list($user_id, $comment) = comment_by_id($comment_id);
if (!has_credential(CRED_COMMENT_EDIT, array($user_id))) {
$output = array(
'success' => 0,
'error' => __('You are not allowed to edit this comment.')
);
return json_encode($output);
} elseif (is_null($comment)) {
$output = array(
'success' => 0,
'error' => __('Comment does not exist.')
);
return json_encode($output);
}
ob_start();
include('pkg_comment_form.php');
$html = ob_get_clean();
$output = array(
'success' => 1,
'form' => $html
);
return json_encode($output);
}
}

View file

@ -1,99 +0,0 @@
<?php
# Check if APC extension is loaded, and set cache prefix if it is.
if (config_get('options', 'cache') == 'apc' && !defined('EXTENSION_LOADED_APC')) {
define('EXTENSION_LOADED_APC', extension_loaded('apc'));
define('CACHE_PREFIX', 'aur:');
}
# Check if memcache extension is loaded, and set cache prefix if it is.
if (config_get('options', 'cache') == 'memcache' && !defined('EXTENSION_LOADED_MEMCACHE')) {
define('EXTENSION_LOADED_MEMCACHE', extension_loaded('memcached'));
define('CACHE_PREFIX', 'aur:');
global $memcache;
$memcache = new Memcached();
$mcs = config_get('options', 'memcache_servers');
foreach (explode(',', $mcs) as $elem) {
$telem = trim($elem);
$mcserver = explode(':', $telem);
$memcache->addServer($mcserver[0], intval($mcserver[1]));
}
}
# Set a value in the cache (currently APC) if cache is available for use. If
# not available, this becomes effectively a no-op (return value is
# false). Accepts an optional TTL (defaults to 600 seconds).
function set_cache_value($key, $value, $ttl=600) {
$status = false;
if (defined('EXTENSION_LOADED_APC')) {
$status = apc_store(CACHE_PREFIX.$key, $value, $ttl);
}
if (defined('EXTENSION_LOADED_MEMCACHE')) {
global $memcache;
$status = $memcache->set(CACHE_PREFIX.$key, $value, $ttl);
}
return $status;
}
# Get a value from the cache (currently APC) if cache is available for use. If
# not available, this returns false (optionally sets passed in variable $status
# to false, much like apc_fetch() behaves). This allows for testing the fetch
# result appropriately even in the event that a 'false' value was the value in
# the cache.
function get_cache_value($key, &$status=false) {
if(defined('EXTENSION_LOADED_APC')) {
$ret = apc_fetch(CACHE_PREFIX.$key, $status);
if ($status) {
return $ret;
}
}
if (defined('EXTENSION_LOADED_MEMCACHE')) {
global $memcache;
$ret = $memcache->get(CACHE_PREFIX.$key);
if (!$ret) {
$status = false;
}
else {
$status = true;
}
return $ret;
}
return $status;
}
# Run a simple db query, retrieving and/or caching the value if APC is
# available for use. Accepts an optional TTL value (defaults to 600 seconds).
function db_cache_value($dbq, $key, $ttl=600) {
$dbh = DB::connect();
$status = false;
$value = get_cache_value($key, $status);
if (!$status) {
$result = $dbh->query($dbq);
if (!$result) {
return false;
}
$row = $result->fetch(PDO::FETCH_NUM);
$value = $row[0];
set_cache_value($key, $value, $ttl);
}
return $value;
}
# Run a simple db query, retrieving and/or caching the result set if APC is
# available for use. Accepts an optional TTL value (defaults to 600 seconds).
function db_cache_result($dbq, $key, $fetch_style=PDO::FETCH_NUM, $ttl=600) {
$dbh = DB::connect();
$status = false;
$value = get_cache_value($key, $status);
if (!$status) {
$result = $dbh->query($dbq);
if (!$result) {
return false;
}
$value = $result->fetchAll($fetch_style);
set_cache_value($key, $value, $ttl);
}
return $value;
}
?>

View file

@ -1,59 +0,0 @@
<?php
function config_load() {
global $AUR_CONFIG;
if (!isset($AUR_CONFIG)) {
$path = getenv('AUR_CONFIG');
if (!$path) {
$path = "/etc/aurweb/config";
}
$defaults_path = getenv('AUR_CONFIG_DEFAULTS');
if (!$defaults_path) {
$defaults_path = $path . ".defaults";
}
if (file_exists($defaults_path)) {
$default_config = parse_ini_file($defaults_path, true, INI_SCANNER_RAW);
} else {
$default_config = [];
}
if (file_exists($path)) {
$config = parse_ini_file($path, true, INI_SCANNER_RAW);
} else {
die("aurweb config file not found");
}
$AUR_CONFIG = array_replace_recursive($default_config, $config);
}
}
function config_get($section, $key) {
global $AUR_CONFIG;
config_load();
return isset($AUR_CONFIG[$section][$key])
? $AUR_CONFIG[$section][$key]
: null;
}
function config_get_int($section, $key) {
return intval(config_get($section, $key));
}
function config_get_bool($section, $key) {
$val = strtolower(config_get($section, $key));
return ($val == 'yes' || $val == 'true' || $val == '1');
}
function config_items($section) {
global $AUR_CONFIG;
config_load();
return $AUR_CONFIG[$section];
}
function config_section_exists($key) {
global $AUR_CONFIG;
config_load();
return array_key_exists($key, $AUR_CONFIG);
}

View file

@ -1,91 +0,0 @@
<?php
define("CRED_ACCOUNT_CHANGE_TYPE", 1);
define("CRED_ACCOUNT_EDIT", 2);
define("CRED_ACCOUNT_EDIT_DEV", 3);
define("CRED_ACCOUNT_LAST_LOGIN", 4);
define("CRED_ACCOUNT_SEARCH", 5);
define("CRED_ACCOUNT_LIST_COMMENTS", 28);
define("CRED_COMMENT_DELETE", 6);
define("CRED_COMMENT_UNDELETE", 27);
define("CRED_COMMENT_VIEW_DELETED", 22);
define("CRED_COMMENT_EDIT", 25);
define("CRED_COMMENT_PIN", 26);
define("CRED_PKGBASE_ADOPT", 7);
define("CRED_PKGBASE_SET_KEYWORDS", 8);
define("CRED_PKGBASE_DELETE", 9);
define("CRED_PKGBASE_DISOWN", 10);
define("CRED_PKGBASE_EDIT_COMAINTAINERS", 24);
define("CRED_PKGBASE_FLAG", 11);
define("CRED_PKGBASE_LIST_VOTERS", 12);
define("CRED_PKGBASE_NOTIFY", 13);
define("CRED_PKGBASE_UNFLAG", 15);
define("CRED_PKGBASE_VOTE", 16);
define("CRED_PKGREQ_FILE", 23);
define("CRED_PKGREQ_CLOSE", 17);
define("CRED_PKGREQ_LIST", 18);
define("CRED_TU_ADD_VOTE", 19);
define("CRED_TU_LIST_VOTES", 20);
define("CRED_TU_VOTE", 21);
/**
* Determine if a user has the permission to perform a given action
*
* @param int $credential The type of action to peform
* @param array $approved_users A user whitelist for this query
*
* @return bool Return true if the user has the permission, false if not
*/
function has_credential($credential, $approved_users=array()) {
if (!isset($_COOKIE['AURSID'])) {
return false;
}
$uid = uid_from_sid($_COOKIE['AURSID']);
if (in_array($uid, $approved_users)) {
return true;
}
$atype = account_from_sid($_COOKIE['AURSID']);
switch ($credential) {
case CRED_PKGBASE_FLAG:
case CRED_PKGBASE_NOTIFY:
case CRED_PKGBASE_VOTE:
case CRED_PKGREQ_FILE:
return ($atype == 'User' || $atype == 'Trusted User' ||
$atype == 'Developer' ||
$atype == 'Trusted User & Developer');
case CRED_ACCOUNT_CHANGE_TYPE:
case CRED_ACCOUNT_EDIT:
case CRED_ACCOUNT_LAST_LOGIN:
case CRED_ACCOUNT_LIST_COMMENTS:
case CRED_ACCOUNT_SEARCH:
case CRED_COMMENT_DELETE:
case CRED_COMMENT_UNDELETE:
case CRED_COMMENT_VIEW_DELETED:
case CRED_COMMENT_EDIT:
case CRED_COMMENT_PIN:
case CRED_PKGBASE_ADOPT:
case CRED_PKGBASE_SET_KEYWORDS:
case CRED_PKGBASE_DELETE:
case CRED_PKGBASE_EDIT_COMAINTAINERS:
case CRED_PKGBASE_DISOWN:
case CRED_PKGBASE_LIST_VOTERS:
case CRED_PKGBASE_UNFLAG:
case CRED_PKGREQ_CLOSE:
case CRED_PKGREQ_LIST:
return ($atype == 'Trusted User' || $atype == 'Developer' ||
$atype == 'Trusted User & Developer');
case CRED_TU_ADD_VOTE:
case CRED_TU_LIST_VOTES:
case CRED_TU_VOTE:
return ($atype == 'Trusted User' ||
$atype == 'Trusted User & Developer');
case CRED_ACCOUNT_EDIT_DEV:
return ($atype == 'Developer' ||
$atype == 'Trusted User & Developer');
}
return false;
}

File diff suppressed because it is too large Load diff

View file

@ -1,432 +0,0 @@
<?php
/*
Copyright (c) 2003, 2009 Danilo Segan <danilo@kvota.net>.
Copyright (c) 2005 Nico Kaiser <nico@siriux.net>
This file is part of PHP-gettext.
PHP-gettext is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
PHP-gettext is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with PHP-gettext; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
* Provides a simple gettext replacement that works independently from
* the system's gettext abilities.
* It can read MO files and use them for translating strings.
* The files are passed to gettext_reader as a Stream (see streams.php)
*
* This version has the ability to cache all strings and translations to
* speed up the string lookup.
* While the cache is enabled by default, it can be switched off with the
* second parameter in the constructor (e.g. whenusing very large MO files
* that you don't want to keep in memory)
*/
class gettext_reader {
//public:
var $error = 0; // public variable that holds error code (0 if no error)
//private:
var $BYTEORDER = 0; // 0: low endian, 1: big endian
var $STREAM = NULL;
var $short_circuit = false;
var $enable_cache = false;
var $originals = NULL; // offset of original table
var $translations = NULL; // offset of translation table
var $pluralheader = NULL; // cache header field for plural forms
var $total = 0; // total string count
var $table_originals = NULL; // table for original strings (offsets)
var $table_translations = NULL; // table for translated strings (offsets)
var $cache_translations = NULL; // original -> translation mapping
/* Methods */
/**
* Reads a 32bit Integer from the Stream
*
* @access private
* @return Integer from the Stream
*/
function readint() {
if ($this->BYTEORDER == 0) {
// low endian
$input=unpack('V', $this->STREAM->read(4));
return array_shift($input);
} else {
// big endian
$input=unpack('N', $this->STREAM->read(4));
return array_shift($input);
}
}
function read($bytes) {
return $this->STREAM->read($bytes);
}
/**
* Reads an array of Integers from the Stream
*
* @param int count How many elements should be read
* @return Array of Integers
*/
function readintarray($count) {
if ($this->BYTEORDER == 0) {
// low endian
return unpack('V'.$count, $this->STREAM->read(4 * $count));
} else {
// big endian
return unpack('N'.$count, $this->STREAM->read(4 * $count));
}
}
/**
* Constructor
*
* @param object Reader the StreamReader object
* @param boolean enable_cache Enable or disable caching of strings (default on)
*/
function __construct($Reader, $enable_cache = true) {
// If there isn't a StreamReader, turn on short circuit mode.
if (! $Reader || isset($Reader->error) ) {
$this->short_circuit = true;
return;
}
// Caching can be turned off
$this->enable_cache = $enable_cache;
$MAGIC1 = "\x95\x04\x12\xde";
$MAGIC2 = "\xde\x12\x04\x95";
$this->STREAM = $Reader;
$magic = $this->read(4);
if ($magic == $MAGIC1) {
$this->BYTEORDER = 1;
} elseif ($magic == $MAGIC2) {
$this->BYTEORDER = 0;
} else {
$this->error = 1; // not MO file
return false;
}
// FIXME: Do we care about revision? We should.
$revision = $this->readint();
$this->total = $this->readint();
$this->originals = $this->readint();
$this->translations = $this->readint();
}
/**
* Loads the translation tables from the MO file into the cache
* If caching is enabled, also loads all strings into a cache
* to speed up translation lookups
*
* @access private
*/
function load_tables() {
if (is_array($this->cache_translations) &&
is_array($this->table_originals) &&
is_array($this->table_translations))
return;
/* get original and translations tables */
if (!is_array($this->table_originals)) {
$this->STREAM->seekto($this->originals);
$this->table_originals = $this->readintarray($this->total * 2);
}
if (!is_array($this->table_translations)) {
$this->STREAM->seekto($this->translations);
$this->table_translations = $this->readintarray($this->total * 2);
}
if ($this->enable_cache) {
$this->cache_translations = array ();
/* read all strings in the cache */
for ($i = 0; $i < $this->total; $i++) {
$this->STREAM->seekto($this->table_originals[$i * 2 + 2]);
$original = $this->STREAM->read($this->table_originals[$i * 2 + 1]);
$this->STREAM->seekto($this->table_translations[$i * 2 + 2]);
$translation = $this->STREAM->read($this->table_translations[$i * 2 + 1]);
$this->cache_translations[$original] = $translation;
}
}
}
/**
* Returns a string from the "originals" table
*
* @access private
* @param int num Offset number of original string
* @return string Requested string if found, otherwise ''
*/
function get_original_string($num) {
$length = $this->table_originals[$num * 2 + 1];
$offset = $this->table_originals[$num * 2 + 2];
if (! $length)
return '';
$this->STREAM->seekto($offset);
$data = $this->STREAM->read($length);
return (string)$data;
}
/**
* Returns a string from the "translations" table
*
* @access private
* @param int num Offset number of original string
* @return string Requested string if found, otherwise ''
*/
function get_translation_string($num) {
$length = $this->table_translations[$num * 2 + 1];
$offset = $this->table_translations[$num * 2 + 2];
if (! $length)
return '';
$this->STREAM->seekto($offset);
$data = $this->STREAM->read($length);
return (string)$data;
}
/**
* Binary search for string
*
* @access private
* @param string string
* @param int start (internally used in recursive function)
* @param int end (internally used in recursive function)
* @return int string number (offset in originals table)
*/
function find_string($string, $start = -1, $end = -1) {
if (($start == -1) or ($end == -1)) {
// find_string is called with only one parameter, set start end end
$start = 0;
$end = $this->total;
}
if (abs($start - $end) <= 1) {
// We're done, now we either found the string, or it doesn't exist
$txt = $this->get_original_string($start);
if ($string == $txt)
return $start;
else
return -1;
} else if ($start > $end) {
// start > end -> turn around and start over
return $this->find_string($string, $end, $start);
} else {
// Divide table in two parts
$half = (int)(($start + $end) / 2);
$cmp = strcmp($string, $this->get_original_string($half));
if ($cmp == 0)
// string is exactly in the middle => return it
return $half;
else if ($cmp < 0)
// The string is in the upper half
return $this->find_string($string, $start, $half);
else
// The string is in the lower half
return $this->find_string($string, $half, $end);
}
}
/**
* Translates a string
*
* @access public
* @param string string to be translated
* @return string translated string (or original, if not found)
*/
function translate($string) {
if ($this->short_circuit)
return $string;
$this->load_tables();
if ($this->enable_cache) {
// Caching enabled, get translated string from cache
if (array_key_exists($string, $this->cache_translations))
return $this->cache_translations[$string];
else
return $string;
} else {
// Caching not enabled, try to find string
$num = $this->find_string($string);
if ($num == -1)
return $string;
else
return $this->get_translation_string($num);
}
}
/**
* Sanitize plural form expression for use in PHP eval call.
*
* @access private
* @return string sanitized plural form expression
*/
function sanitize_plural_expression($expr) {
// Get rid of disallowed characters.
$expr = preg_replace('@[^a-zA-Z0-9_:;\(\)\?\|\&=!<>+*/\%-]@', '', $expr);
// Add parenthesis for tertiary '?' operator.
$expr .= ';';
$res = '';
$p = 0;
for ($i = 0; $i < strlen($expr); $i++) {
$ch = $expr[$i];
switch ($ch) {
case '?':
$res .= ' ? (';
$p++;
break;
case ':':
$res .= ') : (';
break;
case ';':
$res .= str_repeat( ')', $p) . ';';
$p = 0;
break;
default:
$res .= $ch;
}
}
return $res;
}
/**
* Parse full PO header and extract only plural forms line.
*
* @access private
* @return string verbatim plural form header field
*/
function extract_plural_forms_header_from_po_header($header) {
if (preg_match("/(^|\n)plural-forms: ([^\n]*)\n/i", $header, $regs))
$expr = $regs[2];
else
$expr = "nplurals=2; plural=n == 1 ? 0 : 1;";
return $expr;
}
/**
* Get possible plural forms from MO header
*
* @access private
* @return string plural form header
*/
function get_plural_forms() {
// lets assume message number 0 is header
// this is true, right?
$this->load_tables();
// cache header field for plural forms
if (! is_string($this->pluralheader)) {
if ($this->enable_cache) {
$header = $this->cache_translations[""];
} else {
$header = $this->get_translation_string(0);
}
$expr = $this->extract_plural_forms_header_from_po_header($header);
$this->pluralheader = $this->sanitize_plural_expression($expr);
}
return $this->pluralheader;
}
/**
* Detects which plural form to take
*
* @access private
* @param n count
* @return int array index of the right plural form
*/
function select_string($n) {
$string = $this->get_plural_forms();
$string = str_replace('nplurals',"\$total",$string);
$string = str_replace("n",$n,$string);
$string = str_replace('plural',"\$plural",$string);
$total = 0;
$plural = 0;
eval("$string");
if ($plural >= $total) $plural = $total - 1;
return $plural;
}
/**
* Plural version of gettext
*
* @access public
* @param string single
* @param string plural
* @param string number
* @return translated plural form
*/
function ngettext($single, $plural, $number) {
if ($this->short_circuit) {
if ($number != 1)
return $plural;
else
return $single;
}
// find out the appropriate form
$select = $this->select_string($number);
// this should contains all strings separated by NULLs
$key = $single . chr(0) . $plural;
if ($this->enable_cache) {
if (! array_key_exists($key, $this->cache_translations)) {
return ($number != 1) ? $plural : $single;
} else {
$result = $this->cache_translations[$key];
$list = explode(chr(0), $result);
return $list[$select];
}
} else {
$num = $this->find_string($key);
if ($num == -1) {
return ($number != 1) ? $plural : $single;
} else {
$result = $this->get_translation_string($num);
$list = explode(chr(0), $result);
return $list[$select];
}
}
}
function pgettext($context, $msgid) {
$key = $context . chr(4) . $msgid;
$ret = $this->translate($key);
if (strpos($ret, "\004") !== false) {
return $msgid;
} else {
return $ret;
}
}
function npgettext($context, $singular, $plural, $number) {
$key = $context . chr(4) . $singular;
$ret = $this->ngettext($key, $plural, $number);
if (strpos($ret, "\004") !== false) {
return $singular;
} else {
return $ret;
}
}
}
?>

File diff suppressed because it is too large Load diff

View file

@ -1,957 +0,0 @@
<?php
include_once("pkgbasefuncs.inc.php");
/**
* Determine if the user can delete a specific package comment
*
* Only the comment submitter, Trusted Users, and Developers can delete
* comments. This function is used for the backend side of comment deletion.
*
* @param string $comment_id The comment ID in the database
*
* @return bool True if the user can delete the comment, otherwise false
*/
function can_delete_comment($comment_id=0) {
$dbh = DB::connect();
$q = "SELECT UsersID FROM PackageComments ";
$q.= "WHERE ID = " . intval($comment_id);
$result = $dbh->query($q);
if (!$result) {
return false;
}
$uid = $result->fetch(PDO::FETCH_COLUMN, 0);
return has_credential(CRED_COMMENT_DELETE, array($uid));
}
/**
* Determine if the user can delete a specific package comment using an array
*
* Only the comment submitter, Trusted Users, and Developers can delete
* comments. This function is used for the frontend side of comment deletion.
*
* @param array $comment All database information relating a specific comment
*
* @return bool True if the user can delete the comment, otherwise false
*/
function can_delete_comment_array($comment) {
return has_credential(CRED_COMMENT_DELETE, array($comment['UsersID']));
}
/**
* Determine if the user can edit a specific package comment
*
* Only the comment submitter, Trusted Users, and Developers can edit
* comments. This function is used for the backend side of comment editing.
*
* @param string $comment_id The comment ID in the database
*
* @return bool True if the user can edit the comment, otherwise false
*/
function can_edit_comment($comment_id=0) {
$dbh = DB::connect();
$q = "SELECT UsersID FROM PackageComments ";
$q.= "WHERE ID = " . intval($comment_id);
$result = $dbh->query($q);
if (!$result) {
return false;
}
$uid = $result->fetch(PDO::FETCH_COLUMN, 0);
return has_credential(CRED_COMMENT_EDIT, array($uid));
}
/**
* Determine if the user can edit a specific package comment using an array
*
* Only the comment submitter, Trusted Users, and Developers can edit
* comments. This function is used for the frontend side of comment editing.
*
* @param array $comment All database information relating a specific comment
*
* @return bool True if the user can edit the comment, otherwise false
*/
function can_edit_comment_array($comment) {
return has_credential(CRED_COMMENT_EDIT, array($comment['UsersID']));
}
/**
* Determine if the user can pin a specific package comment
*
* Only the Package Maintainer, Package Co-maintainers, Trusted Users, and
* Developers can pin comments. This function is used for the backend side of
* comment pinning.
*
* @param string $comment_id The comment ID in the database
*
* @return bool True if the user can pin the comment, otherwise false
*/
function can_pin_comment($comment_id=0) {
$dbh = DB::connect();
$q = "SELECT MaintainerUID FROM PackageBases AS pb ";
$q.= "LEFT JOIN PackageComments AS pc ON pb.ID = pc.PackageBaseID ";
$q.= "WHERE pc.ID = " . intval($comment_id) . " ";
$q.= "UNION ";
$q.= "SELECT pcm.UsersID FROM PackageComaintainers AS pcm ";
$q.= "LEFT JOIN PackageComments AS pc ";
$q.= "ON pcm.PackageBaseID = pc.PackageBaseID ";
$q.= "WHERE pc.ID = " . intval($comment_id);
$result = $dbh->query($q);
if (!$result) {
return false;
}
$uids = $result->fetchAll(PDO::FETCH_COLUMN, 0);
return has_credential(CRED_COMMENT_PIN, $uids);
}
/**
* Determine if the user can edit a specific package comment using an array
*
* Only the Package Maintainer, Package Co-maintainers, Trusted Users, and
* Developers can pin comments. This function is used for the frontend side of
* comment pinning.
*
* @param array $comment All database information relating a specific comment
*
* @return bool True if the user can edit the comment, otherwise false
*/
function can_pin_comment_array($comment) {
return can_pin_comment($comment['ID']);
}
/**
* Check to see if the package name already exists in the database
*
* @param string $name The package name to check
*
* @return string|void Package name if it already exists
*/
function pkg_from_name($name="") {
if (!$name) {return NULL;}
$dbh = DB::connect();
$q = "SELECT ID FROM Packages ";
$q.= "WHERE Name = " . $dbh->quote($name);
$result = $dbh->query($q);
if (!$result) {
return;
}
$row = $result->fetch(PDO::FETCH_NUM);
if ($row) {
return $row[0];
}
}
/**
* Get licenses for a specific package
*
* @param int $pkgid The package to get licenses for
*
* @return array All licenses for the package
*/
function pkg_licenses($pkgid) {
$pkgid = intval($pkgid);
if (!$pkgid) {
return array();
}
$q = "SELECT l.Name FROM Licenses l ";
$q.= "INNER JOIN PackageLicenses pl ON pl.LicenseID = l.ID ";
$q.= "WHERE pl.PackageID = ". $pkgid;
$ttl = config_get_int('options', 'cache_pkginfo_ttl');
$rows = db_cache_result($q, 'licenses:' . $pkgid, PDO::FETCH_NUM, $ttl);
return array_map(function ($x) { return $x[0]; }, $rows);
}
/**
* Get package groups for a specific package
*
* @param int $pkgid The package to get groups for
*
* @return array All package groups for the package
*/
function pkg_groups($pkgid) {
$pkgid = intval($pkgid);
if (!$pkgid) {
return array();
}
$q = "SELECT g.Name FROM `Groups` g ";
$q.= "INNER JOIN PackageGroups pg ON pg.GroupID = g.ID ";
$q.= "WHERE pg.PackageID = ". $pkgid;
$ttl = config_get_int('options', 'cache_pkginfo_ttl');
$rows = db_cache_result($q, 'groups:' . $pkgid, PDO::FETCH_NUM, $ttl);
return array_map(function ($x) { return $x[0]; }, $rows);
}
/**
* Get providers for a specific package
*
* @param string $name The name of the "package" to get providers for
*
* @return array The IDs and names of all providers of the package
*/
function pkg_providers($name) {
$dbh = DB::connect();
$q = "SELECT p.ID, p.Name FROM Packages p ";
$q.= "WHERE p.Name = " . $dbh->quote($name) . " ";
$q.= "UNION ";
$q.= "SELECT p.ID, p.Name FROM Packages p ";
$q.= "LEFT JOIN PackageRelations pr ON pr.PackageID = p.ID ";
$q.= "LEFT JOIN RelationTypes rt ON rt.ID = pr.RelTypeID ";
$q.= "WHERE (rt.Name = 'provides' ";
$q.= "AND pr.RelName = " . $dbh->quote($name) . ")";
$q.= "UNION ";
$q.= "SELECT 0, Name FROM OfficialProviders ";
$q.= "WHERE Provides = " . $dbh->quote($name);
$ttl = config_get_int('options', 'cache_pkginfo_ttl');
return db_cache_result($q, 'providers:' . $name, PDO::FETCH_NUM, $ttl);
}
/**
* Get package dependencies for a specific package
*
* @param int $pkgid The package to get dependencies for
* @param int $limit An upper bound for the number of packages to retrieve
*
* @return array All package dependencies for the package
*/
function pkg_dependencies($pkgid, $limit) {
$pkgid = intval($pkgid);
if (!$pkgid) {
return array();
}
$q = "SELECT pd.DepName, dt.Name, pd.DepDesc, ";
$q.= "pd.DepCondition, pd.DepArch, p.ID ";
$q.= "FROM PackageDepends pd ";
$q.= "LEFT JOIN Packages p ON pd.DepName = p.Name ";
$q.= "LEFT JOIN DependencyTypes dt ON dt.ID = pd.DepTypeID ";
$q.= "WHERE pd.PackageID = ". $pkgid . " ";
$q.= "ORDER BY pd.DepName LIMIT " . intval($limit);
$ttl = config_get_int('options', 'cache_pkginfo_ttl');
return db_cache_result($q, 'dependencies:' . $pkgid, PDO::FETCH_NUM, $ttl);
}
/**
* Get package relations for a specific package
*
* @param int $pkgid The package to get relations for
*
* @return array All package relations for the package
*/
function pkg_relations($pkgid) {
$pkgid = intval($pkgid);
if (!$pkgid) {
return array();
}
$q = "SELECT pr.RelName, rt.Name, pr.RelCondition, pr.RelArch, p.ID FROM PackageRelations pr ";
$q.= "LEFT JOIN Packages p ON pr.RelName = p.Name ";
$q.= "LEFT JOIN RelationTypes rt ON rt.ID = pr.RelTypeID ";
$q.= "WHERE pr.PackageID = ". $pkgid . " ";
$q.= "ORDER BY pr.RelName";
$ttl = config_get_int('options', 'cache_pkginfo_ttl');
return db_cache_result($q, 'relations:' . $pkgid, PDO::FETCH_NUM, $ttl);
}
/**
* Get the HTML code to display a package dependency link annotation
* (dependency type, architecture, ...)
*
* @param string $type The name of the dependency type
* @param string $arch The package dependency architecture
* @param string $desc An optdepends description
*
* @return string The HTML code of the label to display
*/
function pkg_deplink_annotation($type, $arch, $desc=false) {
if ($type == 'depends' && !$arch) {
return '';
}
$link = ' <em>(';
if ($type == 'makedepends') {
$link .= 'make';
} elseif ($type == 'checkdepends') {
$link .= 'check';
} elseif ($type == 'optdepends') {
$link .= 'optional';
}
if ($type != 'depends' && $arch) {
$link .= ', ';
}
if ($arch) {
$link .= htmlspecialchars($arch);
}
$link .= ')';
if ($type == 'optdepends' && $desc) {
$link .= ' &ndash; ' . htmlspecialchars($desc) . ' </em>';
}
$link .= '</em>';
return $link;
}
/**
* Get the HTML code to display a package provider link
*
* @param string $name The name of the provider
* @param bool $official True if the package is in the official repositories
*
* @return string The HTML code of the link to display
*/
function pkg_provider_link($name, $official) {
$link = '<a href="';
if ($official) {
$link .= 'https://www.archlinux.org/packages/?q=' .
urlencode($name);
} else {
$link .= htmlspecialchars(get_pkg_uri($name), ENT_QUOTES);
}
$link .= '" title="' . __('View packages details for') . ' ';
$link .= htmlspecialchars($name) . '">';
$link .= htmlspecialchars($name) . '</a>';
return $link;
}
/**
* Get the HTML code to display a package dependency link
*
* @param string $name The name of the dependency
* @param string $type The name of the dependency type
* @param string $desc The (optional) description of the dependency
* @param string $cond The package dependency condition string
* @param string $arch The package dependency architecture
* @param int $pkg_id The package of the package to display the dependency for
*
* @return string The HTML code of the label to display
*/
function pkg_depend_link($name, $type, $desc, $cond, $arch, $pkg_id) {
/*
* TODO: We currently perform one SQL query per nonexistent package
* dependency. It would be much better if we could annotate dependency
* data with providers so that we already know whether a dependency is
* a "provision name" or a package from the official repositories at
* this point.
*/
$providers = pkg_providers($name);
if (count($providers) == 0) {
$link = '<span class="broken">';
$link .= htmlspecialchars($name);
$link .= '</span>';
$link .= htmlspecialchars($cond) . ' ';
$link .= pkg_deplink_annotation($type, $arch, $desc);
return $link;
}
$link = htmlspecialchars($name);
foreach ($providers as $provider) {
if ($provider[1] == $name) {
$is_official = ($provider[0] == 0);
$name = $provider[1];
$link = pkg_provider_link($name, $is_official);
break;
}
}
$link .= htmlspecialchars($cond) . ' ';
foreach ($providers as $key => $provider) {
if ($provider[1] == $name) {
unset($providers[$key]);
}
}
if (count($providers) > 0) {
$link .= '<span class="virtual-dep">(';
foreach ($providers as $provider) {
$is_official = ($provider[0] == 0);
$name = $provider[1];
$link .= pkg_provider_link($name, $is_official) . ', ';
}
$link = substr($link, 0, -2);
$link .= ')</span>';
}
$link .= pkg_deplink_annotation($type, $arch, $desc);
return $link;
}
/**
* Get the HTML code to display a package requirement link
*
* @param string $name The name of the requirement
* @param string $depends The (literal) name of the dependency of $name
* @param string $type The name of the dependency type
* @param string $arch The package dependency architecture
* @param string $pkgname The name of dependant package
*
* @return string The HTML code of the link to display
*/
function pkg_requiredby_link($name, $depends, $type, $arch, $pkgname) {
$link = '<a href="';
$link .= htmlspecialchars(get_pkg_uri($name), ENT_QUOTES);
$link .= '" title="' . __('View packages details for') .' ' . htmlspecialchars($name) . '">';
$link .= htmlspecialchars($name) . '</a>';
if ($depends != $pkgname) {
$link .= ' <span class="virtual-dep">(';
$link .= __('requires %s', htmlspecialchars($depends));
$link .= ')</span>';
}
return $link . pkg_deplink_annotation($type, $arch);
}
/**
* Get the HTML code to display a package relation
*
* @param string $name The name of the relation
* @param string $cond The package relation condition string
* @param string $arch The package relation architecture
*
* @return string The HTML code of the label to display
*/
function pkg_rel_html($name, $cond, $arch) {
$html = htmlspecialchars($name) . htmlspecialchars($cond);
if ($arch) {
$html .= ' <em>(' . htmlspecialchars($arch) . ')</em>';
}
return $html;
}
/**
* Get the HTML code to display a source link
*
* @param string $url The URL of the source
* @param string $arch The source architecture
* @param string $package The name of the package
*
* @return string The HTML code of the label to display
*/
function pkg_source_link($url, $arch, $package) {
$url = explode('::', $url);
$parsed_url = parse_url($url[0]);
if (isset($parsed_url['scheme']) || isset($url[1])) {
$link = '<a href="' . htmlspecialchars((isset($url[1]) ? $url[1] : $url[0]), ENT_QUOTES) . '">' . htmlspecialchars($url[0]) . '</a>';
} else {
$file_url = sprintf(config_get('options', 'source_file_uri'), htmlspecialchars($url[0]), $package);
$link = '<a href="' . $file_url . '">' . htmlspecialchars($url[0]) . '</a>';
}
if ($arch) {
$link .= ' <em>(' . htmlspecialchars($arch) . ')</em>';
}
return $link;
}
/**
* Determine packages that depend on a package
*
* @param string $name The package name for the dependency search
* @param array $provides A list of virtual provisions of the package
* @param int $limit An upper bound for the number of packages to retrieve
*
* @return array All packages that depend on the specified package name
*/
function pkg_required($name="", $provides, $limit) {
$deps = array();
if ($name != "") {
$dbh = DB::connect();
$name_list = $dbh->quote($name);
foreach ($provides as $p) {
$name_list .= ',' . $dbh->quote($p[0]);
}
$q = "SELECT p.Name, pd.DepName, dt.Name, pd.DepArch ";
$q.= "FROM PackageDepends pd ";
$q.= "LEFT JOIN Packages p ON p.ID = pd.PackageID ";
$q.= "LEFT JOIN DependencyTypes dt ON dt.ID = pd.DepTypeID ";
$q.= "WHERE pd.DepName IN (" . $name_list . ") ";
$q.= "ORDER BY p.Name LIMIT " . intval($limit);
/* Not invalidated by package updates. */
return db_cache_result($q, 'required:' . $name, PDO::FETCH_NUM);
}
return $deps;
}
/**
* Get all package sources for a specific package
*
* @param string $pkgid The package ID to get the sources for
*
* @return array All sources associated with a specific package
*/
function pkg_sources($pkgid) {
$pkgid = intval($pkgid);
if (!$pkgid) {
return array();
}
$q = "SELECT Source, SourceArch FROM PackageSources ";
$q.= "WHERE PackageID = " . $pkgid;
$q.= " ORDER BY Source";
$ttl = config_get_int('options', 'cache_pkginfo_ttl');
return db_cache_result($q, 'required:' . $pkgid, PDO::FETCH_NUM, $ttl);
}
/**
* Get the package details
*
* @param string $id The package ID to get description for
*
* @return array The package's details OR error message
**/
function pkg_get_details($id=0) {
$dbh = DB::connect();
$q = "SELECT Packages.*, PackageBases.ID AS BaseID, ";
$q.= "PackageBases.Name AS BaseName, PackageBases.NumVotes, ";
$q.= "PackageBases.Popularity, PackageBases.OutOfDateTS, ";
$q.= "PackageBases.SubmittedTS, PackageBases.ModifiedTS, ";
$q.= "PackageBases.SubmitterUID, PackageBases.MaintainerUID, ";
$q.= "PackageBases.PackagerUID, PackageBases.FlaggerUID, ";
$q.= "(SELECT COUNT(*) FROM PackageRequests ";
$q.= " WHERE PackageRequests.PackageBaseID = Packages.PackageBaseID ";
$q.= " AND PackageRequests.Status = 0) AS RequestCount ";
$q.= "FROM Packages, PackageBases ";
$q.= "WHERE PackageBases.ID = Packages.PackageBaseID ";
$q.= "AND Packages.ID = " . intval($id);
$result = $dbh->query($q);
$row = array();
if (!$result) {
$row['error'] = __("Error retrieving package details.");
}
else {
$row = $result->fetch(PDO::FETCH_ASSOC);
if (empty($row)) {
$row['error'] = __("Package details could not be found.");
}
}
return $row;
}
/**
* Display the package details page
*
* @param string $id The package ID to get details page for
* @param array $row Package details retrieved by pkg_get_details()
* @param string $SID The session ID of the visitor
*
* @return void
*/
function pkg_display_details($id=0, $row, $SID="") {
$dbh = DB::connect();
if (isset($row['error'])) {
print "<p>" . $row['error'] . "</p>\n";
}
else {
$base_id = pkgbase_from_pkgid($id);
$pkgbase_name = pkgbase_name_from_id($base_id);
include('pkg_details.php');
if ($SID) {
include('pkg_comment_box.php');
}
$include_deleted = has_credential(CRED_COMMENT_VIEW_DELETED);
$limit_pinned = isset($_GET['pinned']) ? 0 : 5;
$pinned = pkgbase_comments($base_id, $limit_pinned, false, true);
if (!empty($pinned)) {
$comment_section = "package";
include('pkg_comments.php');
}
unset($pinned);
$total_comment_count = pkgbase_comments_count($base_id, $include_deleted);
list($pagination_templs, $per_page, $offset) = calculate_pagination($total_comment_count);
$comments = pkgbase_comments($base_id, $per_page, $include_deleted, false, $offset);
if (!empty($comments)) {
$comment_section = "package";
include('pkg_comments.php');
}
}
}
/**
* Output the body of the search results page
*
* @param array $params Search parameters
* @param bool $show_headers True if statistics should be included
* @param string $SID The session ID of the visitor
*
* @return int The total number of packages matching the query
*/
function pkg_search_page($params, $show_headers=true, $SID="") {
$dbh = DB::connect();
/*
* Get commonly used variables.
* TODO: Reduce the number of database queries!
*/
if ($SID)
$myuid = uid_from_sid($SID);
/* Sanitize paging variables. */
if (isset($params['O'])) {
$params['O'] = bound(intval($params['O']), 0, 2500);
} else {
$params['O'] = 0;
}
if (isset($params["PP"])) {
$params["PP"] = bound(intval($params["PP"]), 50, 250);
} else {
$params["PP"] = 50;
}
/*
* FIXME: Pull out DB-related code. All of it! This one's worth a
* choco-chip cookie, one of those nice big soft ones.
*/
/* Build the package search query. */
$q_select = "SELECT ";
if ($SID) {
$q_select .= "PackageNotifications.UserID AS Notify,
PackageVotes.UsersID AS Voted, ";
}
$q_select .= "Users.Username AS Maintainer,
Packages.Name, Packages.Version, Packages.Description,
PackageBases.NumVotes, PackageBases.Popularity, Packages.ID,
Packages.PackageBaseID, PackageBases.OutOfDateTS ";
$q_from = "FROM Packages
LEFT JOIN PackageBases ON (PackageBases.ID = Packages.PackageBaseID)
LEFT JOIN Users ON (PackageBases.MaintainerUID = Users.ID) ";
if ($SID) {
/* This is not needed for the total row count query. */
$q_from_extra = "LEFT JOIN PackageVotes
ON (PackageBases.ID = PackageVotes.PackageBaseID AND PackageVotes.UsersID = $myuid)
LEFT JOIN PackageNotifications
ON (PackageBases.ID = PackageNotifications.PackageBaseID AND PackageNotifications.UserID = $myuid) ";
} else {
$q_from_extra = "";
}
$q_where = 'WHERE PackageBases.PackagerUID IS NOT NULL ';
if (isset($params['K'])) {
if (isset($params["SeB"]) && $params["SeB"] == "m") {
/* Search by maintainer. */
$q_where .= "AND Users.Username = " . $dbh->quote($params['K']) . " ";
}
elseif (isset($params["SeB"]) && $params["SeB"] == "c") {
/* Search by co-maintainer. */
$q_where .= "AND EXISTS (SELECT * FROM PackageComaintainers ";
$q_where .= "INNER JOIN Users ON Users.ID = PackageComaintainers.UsersID ";
$q_where .= "WHERE PackageComaintainers.PackageBaseID = PackageBases.ID ";
$q_where .= "AND Users.Username = " . $dbh->quote($params['K']) . ")";
}
elseif (isset($params["SeB"]) && $params["SeB"] == "M") {
/* Search by maintainer and co-maintainer. */
$q_where .= "AND (Users.Username = " . $dbh->quote($params['K']) . " ";
$q_where .= "OR EXISTS (SELECT * FROM PackageComaintainers ";
$q_where .= "INNER JOIN Users ON Users.ID = PackageComaintainers.UsersID ";
$q_where .= "WHERE PackageComaintainers.PackageBaseID = PackageBases.ID ";
$q_where .= "AND Users.Username = " . $dbh->quote($params['K']) . "))";
}
elseif (isset($params["SeB"]) && $params["SeB"] == "s") {
/* Search by submitter. */
$q_where .= "AND SubmitterUID = " . intval(uid_from_username($params['K'])) . " ";
}
elseif (isset($params["SeB"]) && $params["SeB"] == "n") {
/* Search by name. */
$K = "%" . addcslashes($params['K'], '%_') . "%";
$q_where .= "AND (Packages.Name LIKE " . $dbh->quote($K) . ") ";
}
elseif (isset($params["SeB"]) && $params["SeB"] == "b") {
/* Search by package base name. */
$K = "%" . addcslashes($params['K'], '%_') . "%";
$q_where .= "AND (PackageBases.Name LIKE " . $dbh->quote($K) . ") ";
}
elseif (isset($params["SeB"]) && $params["SeB"] == "k") {
/* Search by name. */
$q_where .= construct_keyword_search($dbh, $params['K'], false, true);
}
elseif (isset($params["SeB"]) && $params["SeB"] == "N") {
/* Search by name (exact match). */
$q_where .= "AND (Packages.Name = " . $dbh->quote($params['K']) . ") ";
}
elseif (isset($params["SeB"]) && $params["SeB"] == "B") {
/* Search by package base name (exact match). */
$q_where .= "AND (PackageBases.Name = " . $dbh->quote($params['K']) . ") ";
}
else {
/* Keyword search (default). */
$q_where .= construct_keyword_search($dbh, $params['K'], true, true);
}
}
if (isset($params["do_Orphans"])) {
$q_where .= "AND MaintainerUID IS NULL ";
}
if (isset($params['outdated'])) {
if ($params['outdated'] == 'on') {
$q_where .= "AND OutOfDateTS IS NOT NULL ";
}
elseif ($params['outdated'] == 'off') {
$q_where .= "AND OutOfDateTS IS NULL ";
}
}
$order = (isset($params["SO"]) && $params["SO"] == 'd') ? 'DESC' : 'ASC';
$q_sort = "ORDER BY ";
$sort_by = isset($params["SB"]) ? $params["SB"] : '';
switch ($sort_by) {
case 'v':
$q_sort .= "NumVotes " . $order . ", ";
break;
case 'p':
$q_sort .= "Popularity " . $order . ", ";
break;
case 'w':
if ($SID) {
$q_sort .= "Voted " . $order . ", ";
}
break;
case 'o':
if ($SID) {
$q_sort .= "Notify " . $order . ", ";
}
break;
case 'm':
$q_sort .= "Maintainer " . $order . ", ";
break;
case 'l':
$q_sort .= "ModifiedTS " . $order . ", ";
break;
case 'a':
/* For compatibility with old search links. */
$q_sort .= "-ModifiedTS " . $order . ", ";
break;
default:
break;
}
$q_sort .= " Packages.Name " . $order . " ";
$q_limit = "LIMIT ".$params["PP"]." OFFSET ".$params["O"];
$q = $q_select . $q_from . $q_from_extra . $q_where . $q_sort . $q_limit;
$q_total = "SELECT COUNT(*) " . $q_from . $q_where;
$result = $dbh->query($q);
$result_t = $dbh->query($q_total);
if ($result_t) {
$row = $result_t->fetch(PDO::FETCH_NUM);
$total = min($row[0], 2500);
} else {
$total = 0;
}
if ($result && $total > 0) {
if (isset($params["SO"]) && $params["SO"] == "d"){
$SO_next = "a";
}
else {
$SO_next = "d";
}
}
/* Calculate the results to use. */
$first = $params['O'] + 1;
/* Calculation of pagination links. */
$per_page = ($params['PP'] > 0) ? $params['PP'] : 50;
$current = ceil($first / $per_page);
$pages = ceil($total / $per_page);
$templ_pages = array();
if ($current > 1) {
$templ_pages['&laquo; ' . __('First')] = 0;
$templ_pages['&lsaquo; ' . __('Previous')] = ($current - 2) * $per_page;
}
if ($current - 5 > 1)
$templ_pages["..."] = false;
for ($i = max($current - 5, 1); $i <= min($pages, $current + 5); $i++) {
$templ_pages[$i] = ($i - 1) * $per_page;
}
if ($current + 5 < $pages)
$templ_pages["... "] = false;
if ($current < $pages) {
$templ_pages[__('Next') . ' &rsaquo;'] = $current * $per_page;
$templ_pages[__('Last') . ' &raquo;'] = ($pages - 1) * $per_page;
}
$searchresults = array();
if ($result) {
while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
$searchresults[] = $row;
}
}
include('pkg_search_results.php');
return $total;
}
/**
* Construct the WHERE part of the sophisticated keyword search
*
* @param handle $dbh Database handle
* @param string $keywords The search term
* @param bool $namedesc Search name and description fields
* @param bool $keyword Search packages with a matching PackageBases.Keyword
*
* @return string WHERE part of the SQL clause
*/
function construct_keyword_search($dbh, $keywords, $namedesc, $keyword=false) {
$count = 0;
$where_part = "";
$q_keywords = "";
$op = "";
foreach (str_getcsv($keywords, ' ') as $term) {
if ($term == "") {
continue;
}
if ($count > 0 && strtolower($term) == "and") {
$op = "AND ";
continue;
}
if ($count > 0 && strtolower($term) == "or") {
$op = "OR ";
continue;
}
if ($count > 0 && strtolower($term) == "not") {
$op .= "NOT ";
continue;
}
$term = "%" . addcslashes($term, '%_') . "%";
$q_keywords .= $op . " (";
$q_keywords .= "Packages.Name LIKE " . $dbh->quote($term) . " ";
if ($namedesc) {
$q_keywords .= "OR Description LIKE " . $dbh->quote($term) . " ";
}
if ($keyword) {
$q_keywords .= "OR EXISTS (SELECT * FROM PackageKeywords WHERE ";
$q_keywords .= "PackageKeywords.PackageBaseID = Packages.PackageBaseID AND ";
$q_keywords .= "PackageKeywords.Keyword LIKE " . $dbh->quote($term) . ")) ";
} else {
$q_keywords .= ") ";
}
$count++;
if ($count >= 20) {
break;
}
$op = "AND ";
}
if (!empty($q_keywords)) {
$where_part = "AND (" . $q_keywords . ") ";
}
return $where_part;
}
/**
* Determine if a POST string has been sent by a visitor
*
* @param string $action String to check has been sent via POST
*
* @return bool True if the POST string was used, otherwise false
*/
function current_action($action) {
return (isset($_POST['action']) && $_POST['action'] == $action) ||
isset($_POST[$action]);
}
/**
* Determine if sent IDs are valid integers
*
* @param array $ids IDs to validate
*
* @return array All sent IDs that are valid integers
*/
function sanitize_ids($ids) {
$new_ids = array();
foreach ($ids as $id) {
$id = intval($id);
if ($id > 0) {
$new_ids[] = $id;
}
}
return $new_ids;
}
/**
* Determine package information for latest package
*
* @param int $numpkgs Number of packages to get information on
*
* @return array $packages Package info for the specified number of recent packages
*/
function latest_pkgs($numpkgs, $orderBy='SubmittedTS') {
$dbh = DB::connect();
$q = "SELECT Packages.*, MaintainerUID, SubmittedTS, ModifiedTS ";
$q.= "FROM Packages LEFT JOIN PackageBases ON ";
$q.= "PackageBases.ID = Packages.PackageBaseID ";
$q.= "ORDER BY " . $orderBy . " DESC ";
$q.= "LIMIT " . intval($numpkgs);
$result = $dbh->query($q);
$packages = array();
if ($result) {
while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
$packages[] = $row;
}
}
return $packages;
}
/**
* Determine package information for latest modified packages
*
* @param int $numpkgs Number of packages to get information on
*
* @return array $packages Package info for the specified number of recently modified packages
*/
function latest_modified_pkgs($numpkgs) {
return latest_pkgs($numpkgs, 'ModifiedTS');
}

View file

@ -1,260 +0,0 @@
<?php
include_once("confparser.inc.php");
include_once("pkgbasefuncs.inc.php");
/**
* Get the number of package requests
*
* @return int The total number of package requests
*/
function pkgreq_count() {
$dbh = DB::connect();
$q = "SELECT COUNT(*) FROM PackageRequests";
return $dbh->query($q)->fetchColumn();
}
/**
* Get a list of all package requests
*
* @param int $offset The index of the first request to return
* @param int $limit The maximum number of requests to return
* @param int $uid Only return packages affecting the given user
* @param int $from Do not return packages older than the given date
*
* @return array List of package requests with details
*/
function pkgreq_list($offset, $limit, $uid=false, $from=false) {
$dbh = DB::connect();
$q = "SELECT PackageRequests.ID, ";
$q.= "PackageRequests.PackageBaseID AS BaseID, ";
$q.= "PackageRequests.PackageBaseName AS Name, ";
$q.= "PackageRequests.MergeBaseName AS MergeInto, ";
$q.= "RequestTypes.Name AS Type, PackageRequests.Comments, ";
$q.= "Users.Username AS User, PackageRequests.RequestTS, ";
$q.= "PackageRequests.Status, PackageRequests.Status = 0 AS Open ";
$q.= "FROM PackageRequests INNER JOIN RequestTypes ON ";
$q.= "RequestTypes.ID = PackageRequests.ReqTypeID ";
$q.= "INNER JOIN Users ON Users.ID = PackageRequests.UsersID ";
if ($uid || $from) {
$q.= "WHERE ";
if ($uid) {
$q.= "(PackageRequests.UsersID = " . intval($uid). " ";
$q.= "OR Users.ID = " . intval($uid) . ") AND ";
}
if ($from) {
$q.= "RequestTS >= " . intval($from). " ";
}
}
$q.= "ORDER BY Open DESC, RequestTS DESC ";
$q.= "LIMIT " . $limit . " OFFSET " . $offset;
return $dbh->query($q)->fetchAll();
}
/**
* Get a list of all open package requests belonging to a certain package base
*
* @param int $baseid The package base ID to retrieve requests for
* @param int $type The type of requests to obtain
*
* @return array List of package request IDs
*/
function pkgreq_by_pkgbase($baseid, $type=false) {
$dbh = DB::connect();
$q = "SELECT PackageRequests.ID ";
$q.= "FROM PackageRequests INNER JOIN RequestTypes ON ";
$q.= "RequestTypes.ID = PackageRequests.ReqTypeID ";
$q.= "WHERE PackageRequests.Status = 0 ";
$q.= "AND PackageRequests.PackageBaseID = " . intval($baseid);
if ($type) {
$q .= " AND RequestTypes.Name = " . $dbh->quote($type);
}
return $dbh->query($q)->fetchAll(PDO::FETCH_COLUMN, 0);
}
/**
* Obtain the package base that belongs to a package request.
*
* @param int $id Package request ID to retrieve the package base for
*
* @return int The name of the corresponding package base
*/
function pkgreq_get_pkgbase_name($id) {
$dbh = DB::connect();
$q = "SELECT PackageBaseName FROM PackageRequests ";
$q.= "WHERE ID = " . intval($id);
$result = $dbh->query($q);
return $result->fetch(PDO::FETCH_COLUMN, 0);
}
/**
* Obtain the email address of the creator of a package request
*
* @param int $id Package request ID to retrieve the creator for
*
* @return int The email address of the creator
*/
function pkgreq_get_creator_email($id) {
$dbh = DB::connect();
$q = "SELECT Email FROM Users INNER JOIN PackageRequests ";
$q.= "ON Users.ID = PackageRequests.UsersID ";
$q.= "WHERE PackageRequests.ID = " . intval($id);
$result = $dbh->query($q);
return $result->fetch(PDO::FETCH_COLUMN, 0);
}
/**
* File a deletion/orphan request against a package base
*
* @param string $ids The package base IDs to file the request against
* @param string $type The type of the request
* @param string $merge_into The target of a merge operation
* @param string $comments The comments to be added to the request
*
* @return array Tuple of success/failure indicator and error message
*/
function pkgreq_file($ids, $type, $merge_into, $comments) {
if (!has_credential(CRED_PKGREQ_FILE)) {
return array(false, __("You must be logged in to file package requests."));
}
/* Ignore merge target for non-merge requests. */
if ($type !== 'merge') {
$merge_into = '';
}
if (!empty($merge_into) && !preg_match("/^[a-z0-9][a-z0-9\.+_-]*$/D", $merge_into)) {
return array(false, __("Invalid name: only lowercase letters are allowed."));
}
if (!empty($merge_into) && !pkgbase_from_name($merge_into)) {
return array(false, __("Cannot find package to merge votes and comments into."));
}
if (empty($comments)) {
return array(false, __("The comment field must not be empty."));
}
$dbh = DB::connect();
$uid = uid_from_sid($_COOKIE["AURSID"]);
/* TODO: Allow for filing multiple requests at once. */
$base_id = intval($ids[0]);
$pkgbase_name = pkgbase_name_from_id($base_id);
if ($merge_into == $pkgbase_name) {
return array(false, __("Cannot merge a package base with itself."));
}
$q = "SELECT ID FROM RequestTypes WHERE Name = " . $dbh->quote($type);
$result = $dbh->query($q);
if ($row = $result->fetch(PDO::FETCH_ASSOC)) {
$type_id = $row['ID'];
} else {
return array(false, __("Invalid request type."));
}
$q = "INSERT INTO PackageRequests ";
$q.= "(ReqTypeID, PackageBaseID, PackageBaseName, MergeBaseName, ";
$q.= "UsersID, Comments, ClosureComment, RequestTS) VALUES (" . $type_id . ", ";
$q.= $base_id . ", " . $dbh->quote($pkgbase_name) . ", ";
$q.= $dbh->quote($merge_into) . ", " . $uid . ", ";
$q.= $dbh->quote($comments) . ", '', " . strval(time()) . ")";
$dbh->exec($q);
$request_id = $dbh->lastInsertId();
/* Send e-mail notifications. */
$params = array('request-open', $uid, $request_id, $type, $base_id);
if ($type === 'merge') {
$params[] = $merge_into;
}
notify($params);
$auto_orphan_age = config_get('options', 'auto_orphan_age');
$auto_delete_age = config_get('options', 'auto_delete_age');
$details = pkgbase_get_details($base_id);
if ($type == 'orphan' && $details['OutOfDateTS'] > 0 &&
time() - $details['OutOfDateTS'] >= $auto_orphan_age &&
$auto_orphan_age > 0) {
/*
* Close package request. NOTE: This needs to happen *before*
* the actual disown operation. Otherwise, the former
* maintainer will not be included in the Cc list of the
* request notification email.
*/
$out_of_date_time = date("Y-m-d", intval($details["OutOfDateTS"]));
pkgreq_close($request_id, "accepted",
"The package base has been flagged out-of-date " .
"since " . $out_of_date_time . ".", true);
$q = "UPDATE PackageBases SET MaintainerUID = NULL ";
$q.= "WHERE ID = " . $base_id;
$dbh->exec($q);
} else if ($type == 'deletion' && $details['MaintainerUID'] == $uid &&
$details['SubmittedTS'] > 0 && $auto_delete_age > 0 &&
time() - $details['SubmittedTS'] <= $auto_delete_age) {
/*
* Close package request. NOTE: This needs to happen *before*
* the actual deletion operation. Otherwise, the former
* maintainer will not be included in the Cc list of the
* request notification email.
*/
pkgreq_close($request_id, "accepted",
"Deletion of a fresh package requested by its " .
"current maintainer.", true);
pkgbase_delete(array($base_id), NULL, NULL, true);
}
return array(true, __("Added request successfully."));
}
/**
* Close a deletion/orphan request
*
* @param int $id The package request to close
* @param string $reason Whether the request was accepted or rejected
* @param string $comments Comments to be added to the notification email
* @param boolean $auto_close (optional) Whether the request is auto-closed
*
* @return array Tuple of success/failure indicator and error message
*/
function pkgreq_close($id, $reason, $comments, $auto_close=false) {
switch ($reason) {
case 'accepted':
$status = 2;
break;
case 'rejected':
$status = 3;
break;
default:
return array(false, __("Invalid reason."));
}
$dbh = DB::connect();
$id = intval($id);
$uid = $auto_close ? 0 : uid_from_sid($_COOKIE["AURSID"]);
if (!$auto_close && !has_credential(CRED_PKGREQ_CLOSE)) {
return array(false, __("Only TUs and developers can close requests."));
}
$q = "UPDATE PackageRequests SET Status = " . intval($status) . ", ";
$q.= "ClosedTS = " . strval(time()) . ", ";
$q.= "ClosedUID = " . ($uid == 0 ? "NULL" : intval($uid)) . ", ";
$q.= "ClosureComment = " . $dbh->quote($comments) . " ";
$q.= "WHERE ID = " . intval($id);
$dbh->exec($q);
/* Send e-mail notifications. */
notify(array('request-close', $uid, $id, $reason));
return array(true, __("Request closed successfully."));
}

View file

@ -1,85 +0,0 @@
<?php
include_once("confparser.inc.php");
$ROUTES = array(
'' => 'home.php',
'/index.php' => 'home.php',
'/packages' => 'packages.php',
'/pkgbase' => 'pkgbase.php',
'/requests' => 'pkgreq.php',
'/register' => 'register.php',
'/account' => 'account.php',
'/accounts' => 'account.php',
'/login' => 'login.php',
'/logout' => 'logout.php',
'/passreset' => 'passreset.php',
'/rpc' => 'rpc.php',
'/rss/modified' => 'modified-rss.php',
'/rss' => 'rss.php',
'/tos' => 'tos.php',
'/tu' => 'tu.php',
'/addvote' => 'addvote.php',
);
$PKG_PATH = '/packages';
$PKGBASE_PATH = '/pkgbase';
$PKGREQ_PATH = '/requests';
$USER_PATH = '/account';
function get_route($path) {
global $ROUTES;
$path = rtrim($path, '/');
if (isset($ROUTES[$path])) {
return $ROUTES[$path];
} else {
return NULL;
}
}
function get_uri($path, $absolute=false) {
if ($absolute) {
return rtrim(aur_location(), '/') . $path;
} else {
return $path;
}
}
function get_pkg_route() {
global $PKG_PATH;
return $PKG_PATH;
}
function get_pkgbase_route() {
global $PKGBASE_PATH;
return $PKGBASE_PATH;
}
function get_pkgreq_route() {
global $PKGREQ_PATH;
return $PKGREQ_PATH;
}
function get_pkg_uri($pkgname, $absolute=false) {
global $PKG_PATH;
$path = $PKG_PATH . '/' . urlencode($pkgname) . '/';
return get_uri($path, $absolute);
}
function get_pkgbase_uri($pkgbase_name, $absolute=false) {
global $PKGBASE_PATH;
$path = $PKGBASE_PATH . '/' . urlencode($pkgbase_name) . '/';
return get_uri($path, $absolute);
}
function get_user_route() {
global $USER_PATH;
return $USER_PATH;
}
function get_user_uri($username, $absolute=false) {
global $USER_PATH;
$path = $USER_PATH . '/' . urlencode($username) . '/';
return get_uri($path, $absolute);
}

View file

@ -1,108 +0,0 @@
<?php
include_once('aur.inc.php');
/**
* Display the most recent 10 packages
*
* @return void
*/
function updates_table() {
$dbh = DB::connect();
$key = 'recent_updates';
if(!($newest_packages = get_cache_value($key))) {
$q = 'SELECT Packages.Name, Version, ModifiedTS ';
$q.= 'FROM Packages INNER JOIN PackageBases ON ';
$q.= 'Packages.PackageBaseID = PackageBases.ID ';
$q.= 'WHERE PackageBases.PackagerUID IS NOT NULL ';
$q.= 'ORDER BY ModifiedTS DESC LIMIT 15';
$result = $dbh->query($q);
$newest_packages = new ArrayObject();
if ($result) {
while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
$newest_packages->append($row);
}
set_cache_value($key, $newest_packages);
}
}
include('stats/updates_table.php');
}
/**
* Display a user's statistics table
*
* @param string $userid The user ID of the person to get package statistics for
*
* @return void
*/
function user_table($userid) {
$base_q = "SELECT COUNT(*) FROM PackageBases ";
$base_q.= "WHERE MaintainerUID = " . $userid . " ";
$base_q.= "AND PackagerUID IS NOT NULL";
$user_pkg_count = db_cache_value($base_q, 'user_pkg_count:' . $userid);
$q = "SELECT COUNT(*) FROM PackageBases ";
$q.= "WHERE OutOfDateTS IS NOT NULL ";
$q.= "AND MaintainerUID = " . $userid . " ";
$q.= "AND PackagerUID IS NOT NULL";
$flagged_outdated = db_cache_value($q, 'user_flagged_outdated:' . $userid);
include('stats/user_table.php');
}
/**
* Display the general package statistics table
*
* @return void
*/
function general_stats_table() {
# AUR statistics
$q = "SELECT COUNT(*) FROM PackageBases WHERE PackagerUID IS NOT NULL";
$pkg_count = db_cache_value($q, 'pkg_count');
$q = "SELECT COUNT(*) FROM PackageBases ";
$q.= "WHERE MaintainerUID IS NULL ";
$q.= "AND PackagerUID IS NOT NULL";
$orphan_count = db_cache_value($q, 'orphan_count');
$q = "SELECT count(*) FROM Users";
$user_count = db_cache_value($q, 'user_count');
$q = "SELECT count(*) FROM Users,AccountTypes WHERE Users.AccountTypeID = AccountTypes.ID AND (AccountTypes.AccountType = 'Trusted User' OR AccountTypes.AccountType = 'Trusted User & Developer')";
$tu_count = db_cache_value($q, 'tu_count');
$targstamp = intval(strtotime("-7 days"));
$yearstamp = intval(strtotime("-1 year"));
$q = "SELECT COUNT(*) FROM PackageBases ";
$q.= "WHERE SubmittedTS >= $targstamp ";
$q.= "AND PackagerUID IS NOT NULL";
$add_count = db_cache_value($q, 'add_count');
/*
* A package whose last modification time differs less than an hour
* from the initial submission time is considered new.
*/
$q = "SELECT COUNT(*) FROM PackageBases ";
$q.= "WHERE ModifiedTS >= $targstamp ";
$q.= "AND ModifiedTS - SubmittedTS >= 3600 ";
$q.= "AND PackagerUID IS NOT NULL";
$update_count = db_cache_value($q, 'update_count');
$q = "SELECT COUNT(*) FROM PackageBases ";
$q.= "WHERE ModifiedTS >= $yearstamp ";
$q.= "AND ModifiedTS - SubmittedTS >= 3600 ";
$q.= "AND PackagerUID IS NOT NULL";
$update_year_count = db_cache_value($q, 'update_year_count');
$q = "SELECT COUNT(*) FROM PackageBases ";
$q.= "WHERE ModifiedTS - SubmittedTS < 3600 ";
$q.= "AND PackagerUID IS NOT NULL";
$never_update_count = db_cache_value($q, 'never_update_count');
include('stats/general_stats_table.php');
}

View file

@ -1,167 +0,0 @@
<?php
/*
Copyright (c) 2003, 2005, 2006, 2009 Danilo Segan <danilo@kvota.net>.
This file is part of PHP-gettext.
PHP-gettext is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
PHP-gettext is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with PHP-gettext; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
// Simple class to wrap file streams, string streams, etc.
// seek is essential, and it should be byte stream
class StreamReader {
// should return a string [FIXME: perhaps return array of bytes?]
function read($bytes) {
return false;
}
// should return new position
function seekto($position) {
return false;
}
// returns current position
function currentpos() {
return false;
}
// returns length of entire stream (limit for seekto()s)
function length() {
return false;
}
};
class StringReader {
var $_pos;
var $_str;
function __construct($str='') {
$this->_str = $str;
$this->_pos = 0;
}
function read($bytes) {
$data = substr($this->_str, $this->_pos, $bytes);
$this->_pos += $bytes;
if (strlen($this->_str)<$this->_pos)
$this->_pos = strlen($this->_str);
return $data;
}
function seekto($pos) {
$this->_pos = $pos;
if (strlen($this->_str)<$this->_pos)
$this->_pos = strlen($this->_str);
return $this->_pos;
}
function currentpos() {
return $this->_pos;
}
function length() {
return strlen($this->_str);
}
};
class FileReader {
var $_pos;
var $_fd;
var $_length;
function __construct($filename) {
if (file_exists($filename)) {
$this->_length=filesize($filename);
$this->_pos = 0;
$this->_fd = fopen($filename,'rb');
if (!$this->_fd) {
$this->error = 3; // Cannot read file, probably permissions
return false;
}
} else {
$this->error = 2; // File doesn't exist
return false;
}
}
function read($bytes) {
if ($bytes) {
fseek($this->_fd, $this->_pos);
// PHP 5.1.1 does not read more than 8192 bytes in one fread()
// the discussions at PHP Bugs suggest it's the intended behaviour
$data = '';
while ($bytes > 0) {
$chunk = fread($this->_fd, $bytes);
$data .= $chunk;
$bytes -= strlen($chunk);
}
$this->_pos = ftell($this->_fd);
return $data;
} else return '';
}
function seekto($pos) {
fseek($this->_fd, $pos);
$this->_pos = ftell($this->_fd);
return $this->_pos;
}
function currentpos() {
return $this->_pos;
}
function length() {
return $this->_length;
}
function close() {
fclose($this->_fd);
}
};
// Preloads entire file in memory first, then creates a StringReader
// over it (it assumes knowledge of StringReader internals)
class CachedFileReader extends StringReader {
function __construct($filename) {
if (file_exists($filename)) {
$length=filesize($filename);
$fd = fopen($filename,'rb');
if (!$fd) {
$this->error = 3; // Cannot read file, probably permissions
return false;
}
$this->_str = fread($fd, $length);
fclose($fd);
} else {
$this->error = 2; // File doesn't exist
return false;
}
}
};
?>

View file

@ -1,63 +0,0 @@
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . '../lib');
/**
* Generate an associative of the PHP timezones and display text.
*
* @return array PHP Timezone => Displayed Description
*/
function generate_timezone_list() {
$php_timezones = DateTimeZone::listIdentifiers(DateTimeZone::ALL);
$offsets = array();
foreach ($php_timezones as $timezone) {
$tz = new DateTimeZone($timezone);
$offset = $tz->getOffset(new DateTime());
$offsets[$timezone] = "(UTC" . ($offset < 0 ? "-" : "+") . gmdate("H:i", abs($offset)) .
") " . $timezone;
}
asort($offsets);
return $offsets;
}
/**
* Set the timezone for the user.
*
* @return null
*/
function set_tz() {
$timezones = generate_timezone_list();
$update_cookie = false;
if (isset($_COOKIE["AURTZ"])) {
$timezone = $_COOKIE["AURTZ"];
} elseif (isset($_COOKIE["AURSID"])) {
$dbh = DB::connect();
$q = "SELECT Timezone FROM Users, Sessions ";
$q .= "WHERE Users.ID = Sessions.UsersID ";
$q .= "AND Sessions.SessionID = ";
$q .= $dbh->quote($_COOKIE["AURSID"]);
$result = $dbh->query($q);
if ($result) {
$timezone = $result->fetchColumn(0);
if (!$timezone) {
unset($timezone);
}
}
$update_cookie = true;
}
if (!isset($timezone) || !array_key_exists($timezone, $timezones)) {
$timezone = config_get("options", "default_timezone");
}
date_default_timezone_set($timezone);
if ($update_cookie) {
$timeout = intval(config_get("options", "persistent_cookie_timeout"));
$cookie_time = time() + $timeout;
setcookie("AURTZ", $timezone, $cookie_time, "/");
}
}

View file

@ -1,139 +0,0 @@
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . '../lib' . PATH_SEPARATOR . '../lang');
# This file provides support for i18n
# usage:
# use the __() function for returning translated strings of
# text. The string can contain escape codes "%s".
#
# examples:
# print __("%s has %s apples.", "Bill", "5");
# print __("This is a %smajor%s problem!", "<strong>", "</strong>");
include_once("confparser.inc.php");
include_once('DB.class.php');
include_once('gettext.php');
include_once('streams.php');
global $streamer, $l10n;
# Languages we have translations for
$SUPPORTED_LANGS = array(
"ar" => "العربية",
"ast" => "Asturianu",
"ca" => "Català",
"cs" => "Český",
"da" => "Dansk",
"de" => "Deutsch",
"en" => "English",
"el" => "Ελληνικά",
"es" => "Español",
"es_419" => "Español (Latinoamérica)",
"fi" => "Suomi",
"fr" => "Français",
"he" => "עברית",
"hr" => "Hrvatski",
"hu" => "Magyar",
"it" => "Italiano",
"ja" => "日本語",
"nb" => "Norsk",
"nl" => "Nederlands",
"pl" => "Polski",
"pt_BR" => "Português (Brasil)",
"pt_PT" => "Português (Portugal)",
"ro" => "Română",
"ru" => "Русский",
"sk" => "Slovenčina",
"sr" => "Srpski",
"tr" => "Türkçe",
"uk" => "Українська",
"zh_CN" => "简体中文",
"zh_TW" => "正體中文"
);
function __() {
global $LANG;
global $l10n;
# Create the translation.
$args = func_get_args();
# First argument is always string to be translated
$tag = array_shift($args);
# Translate using gettext_reader initialized before.
$translated = $l10n->translate($tag);
$translated = htmlspecialchars($translated, ENT_QUOTES);
# Subsequent arguments are strings to be formatted
if (count($args) > 0) {
$translated = vsprintf($translated, $args);
}
return $translated;
}
function _n($msgid1, $msgid2, $n) {
global $l10n;
$translated = sprintf($l10n->ngettext($msgid1, $msgid2, $n), $n);
return htmlspecialchars($translated, ENT_QUOTES);
}
# set up the visitor's language
#
function set_lang() {
global $LANG;
global $SUPPORTED_LANGS;
global $streamer, $l10n;
$update_cookie = 0;
if (isset($_POST['setlang'])) {
# visitor is requesting a language change
#
$LANG = $_POST['setlang'];
$update_cookie = 1;
} elseif (isset($_COOKIE['AURLANG'])) {
# If a cookie is set, use that
#
$LANG = $_COOKIE['AURLANG'];
} elseif (isset($_COOKIE["AURSID"])) {
# No language but a session; use default lang preference
#
$dbh = DB::connect();
$q = "SELECT LangPreference FROM Users, Sessions ";
$q.= "WHERE Users.ID = Sessions.UsersID ";
$q.= "AND Sessions.SessionID = ";
$q.= $dbh->quote($_COOKIE["AURSID"]);
$result = $dbh->query($q);
if ($result) {
$LANG = $result->fetchColumn(0);
if (!$LANG) {
unset($LANG);
}
}
$update_cookie = 1;
}
# Set $LANG to default if nothing is valid.
if (!isset($LANG) || !array_key_exists($LANG, $SUPPORTED_LANGS)) {
$LANG = config_get('options', 'default_lang');
}
if ($update_cookie) {
$timeout = intval(config_get('options', 'persistent_cookie_timeout'));
$cookie_time = time() + $timeout;
setcookie("AURLANG", $LANG, $cookie_time, "/");
}
$localedir = config_get('options', 'localedir');
$streamer = new FileReader($localedir . '/' . $LANG .
'/LC_MESSAGES/aurweb.mo');
$l10n = new gettext_reader($streamer, true);
return;
}

View file

@ -1,2 +0,0 @@
<?php
define("AURWEB_VERSION", "v5.0.0");

View file

@ -1,5 +0,0 @@
This directory is used for machine object files generated by msgfmt(1). Do not
edit any of these files manually. Update the corresponding portable object
files in "po/" instead and run following commands to rebuild all ".mo" files:
make install

View file

@ -1,29 +0,0 @@
<p>
<?= __('You can use this form to permanently delete the AUR account %s.', '<strong>' . htmlspecialchars($username) . '</strong>') ?>
</p>
<p>
<?= __('%sWARNING%s: This action cannot be undone.', '<strong>', '</strong>') ?>
</p>
<form id="edit-profile-form" action="<?= get_user_uri($username) . 'delete/'; ?>" method="post">
<fieldset>
<input type="hidden" name="Action" value="<?= $action ?>" />
<input type="hidden" name="ID" value="<?= $UID ?>" />
<input type="hidden" name="token" value="<?= htmlspecialchars($_COOKIE['AURSID']) ?>" />
</fieldset>
<fieldset>
<p>
<label for="id_passwd"><?= __("Password") ?>:</label>
<input type="password" size="30" name="passwd" id="id_passwd" value="" />
</p>
<p>
<label class="confirmation"><input type="checkbox" name="confirm" value="1" />
<?= __("Confirm deletion") ?></label>
</p>
<p>
<input type="submit" class="button" value="<?= __("Delete") ?>" />
</p>
</fieldset>
</form>

Some files were not shown because too many files have changed in this diff Show more