housekeep: remove PHP implementation
removal of the PHP codebase Signed-off-by: moson-mo <mo-son@mailbox.org>
|
@ -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
|
@ -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/"
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
3
INSTALL
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
-------------
|
-------------
|
||||||
|
|
1
TESTING
|
@ -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:
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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`
|
||||||
|
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
exec pgrep memcached
|
|
|
@ -1,2 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
exec printf "" >>/dev/tcp/127.0.0.1/9000
|
|
|
@ -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';"
|
||||||
|
|
|
@ -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 "$@"
|
|
|
@ -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 "$@"
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
exec /usr/bin/memcached -u memcached -m 64 -c 1024 -l 0.0.0.0
|
|
|
@ -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
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
set -eou pipefail
|
|
||||||
|
|
||||||
exec php-fpm --fpm-config /etc/php/php-fpm.conf --nodaemonize
|
|
16
po/Makefile
|
@ -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
|
||||||
|
|
|
@ -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}",
|
||||||
]
|
]
|
||||||
|
|
|
@ -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);
|
|
|
@ -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);
|
|
|
@ -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);
|
|
||||||
|
|
||||||
?>
|
|
|
@ -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);
|
|
|
@ -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);
|
|
|
@ -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);
|
|
Before Width: | Height: | Size: 5.2 KiB |
|
@ -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; }
|
|
Before Width: | Height: | Size: 5.9 KiB |
|
@ -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;
|
|
||||||
}
|
|
|
@ -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; }
|
|
|
@ -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&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&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);
|
|
|
@ -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.
|
|
||||||
----
|
|
|
@ -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 |
|
@ -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 |
Before Width: | Height: | Size: 723 B |
Before Width: | Height: | Size: 575 B |
|
@ -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 |
|
@ -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 |
|
@ -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 |
|
@ -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 |
|
@ -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 |
|
@ -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 |
|
@ -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 |
|
@ -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 |
|
@ -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 |
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -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);
|
|
||||||
});
|
|
|
@ -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);
|
|
||||||
});
|
|
|
@ -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();
|
|
||||||
});
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}());
|
|
|
@ -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);
|
|
|
@ -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");
|
|
|
@ -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;
|
|
||||||
?>
|
|
|
@ -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);
|
|
|
@ -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);
|
|
|
@ -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);
|
|
|
@ -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);
|
|
|
@ -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);
|
|
|
@ -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);
|
|
|
@ -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);
|
|
|
@ -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);
|
|
|
@ -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['« ' . __('First')] = 0;
|
|
||||||
$templ_pages['‹ ' . __('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') . ' ›'] = $current * $per_page;
|
|
||||||
$templ_pages[__('Last') . ' »'] = ($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);
|
|
|
@ -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);
|
|
||||||
|
|
||||||
?>
|
|
|
@ -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');
|
|
||||||
}
|
|
||||||
?>
|
|
|
@ -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;
|
|
||||||
?>
|
|
|
@ -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);
|
|
122
web/html/tu.php
|
@ -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);
|
|
|
@ -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);
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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 .= '&' . 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['« ' . __('First')] = 0;
|
|
||||||
$pagination_templs['‹ ' . __('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') . ' ›'] = $current_page * $per_page;
|
|
||||||
$pagination_templs[__('Last') . ' »'] = ($num_pages - 1) * $per_page;
|
|
||||||
}
|
|
||||||
|
|
||||||
return array($pagination_templs, $per_page, $offset);
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
|
@ -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 .= ' – ' . 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['« ' . __('First')] = 0;
|
|
||||||
$templ_pages['‹ ' . __('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') . ' ›'] = $current * $per_page;
|
|
||||||
$templ_pages[__('Last') . ' »'] = ($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');
|
|
||||||
}
|
|
|
@ -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."));
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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');
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
?>
|
|
|
@ -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, "/");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
<?php
|
|
||||||
define("AURWEB_VERSION", "v5.0.0");
|
|
|
@ -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
|
|
|
@ -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>
|
|