Compare commits
4 Commits
master
...
BRANCH-0.9
Author | SHA1 | Date | |
---|---|---|---|
|
bc6a3bea7a | ||
|
0074652abf | ||
|
e126518f60 | ||
|
7ff3528665 |
@ -1,10 +0,0 @@
|
||||
.dockerignore
|
||||
.editorconfig
|
||||
.env.testing
|
||||
.git*
|
||||
docker/
|
||||
package.json
|
||||
package-lock.json
|
||||
phpunit.xml
|
||||
webpack.mix.js
|
||||
yarn.lock
|
@ -1,18 +0,0 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 4
|
||||
indent_style = tab
|
||||
insert_final_newline = false
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.{yml,yaml}]
|
||||
indent_size = 2
|
||||
|
||||
[docker-compose.yml]
|
||||
indent_size = 4
|
51
.env.example
51
.env.example
@ -1,51 +0,0 @@
|
||||
APP_NAME=Laravel
|
||||
APP_ENV=production
|
||||
APP_KEY=
|
||||
APP_DEBUG=true
|
||||
APP_URL=http://localhost
|
||||
|
||||
LOG_CHANNEL=stack
|
||||
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=laravel
|
||||
DB_USERNAME=root
|
||||
DB_PASSWORD=
|
||||
|
||||
BROADCAST_DRIVER=log
|
||||
CACHE_DRIVER=file
|
||||
QUEUE_CONNECTION=sync
|
||||
SESSION_DRIVER=file
|
||||
SESSION_LIFETIME=120
|
||||
|
||||
REDIS_HOST=127.0.0.1
|
||||
REDIS_PASSWORD=null
|
||||
REDIS_PORT=6379
|
||||
|
||||
MAIL_DRIVER=smtp
|
||||
MAIL_HOST=smtp.mailtrap.io
|
||||
MAIL_PORT=2525
|
||||
MAIL_USERNAME=null
|
||||
MAIL_PASSWORD=null
|
||||
MAIL_ENCRYPTION=null
|
||||
MAIL_FROM_ADDRESS=null
|
||||
MAIL_FROM_NAME="${APP_NAME}"
|
||||
|
||||
AWS_ACCESS_KEY_ID=
|
||||
AWS_SECRET_ACCESS_KEY=
|
||||
AWS_DEFAULT_REGION=us-east-1
|
||||
AWS_BUCKET=
|
||||
|
||||
PUSHER_APP_ID=
|
||||
PUSHER_APP_KEY=
|
||||
PUSHER_APP_SECRET=
|
||||
PUSHER_APP_CLUSTER=mt1
|
||||
|
||||
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
|
||||
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
|
||||
|
||||
LDAP_HOST=
|
||||
LDAP_BASE_DN=
|
||||
LDAP_USERNAME=
|
||||
LDAP_PASSWORD=
|
51
.env.testing
51
.env.testing
@ -1,51 +0,0 @@
|
||||
APP_NAME=Laravel
|
||||
APP_ENV=dev
|
||||
APP_KEY=base64:KvIecx8zoy6RjcbJM8s98ZKs9IDGUHFVqBRn3Awfmso=
|
||||
APP_DEBUG=true
|
||||
APP_URL=http://localhost
|
||||
|
||||
LOG_CHANNEL=stack
|
||||
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=homestead
|
||||
DB_USERNAME=homestead
|
||||
DB_PASSWORD=secret
|
||||
|
||||
BROADCAST_DRIVER=log
|
||||
CACHE_DRIVER=file
|
||||
QUEUE_CONNECTION=sync
|
||||
SESSION_DRIVER=file
|
||||
SESSION_LIFETIME=120
|
||||
|
||||
REDIS_HOST=127.0.0.1
|
||||
REDIS_PASSWORD=null
|
||||
REDIS_PORT=6379
|
||||
|
||||
MAIL_DRIVER=smtp
|
||||
MAIL_HOST=smtp.mailtrap.io
|
||||
MAIL_PORT=2525
|
||||
MAIL_USERNAME=null
|
||||
MAIL_PASSWORD=null
|
||||
MAIL_ENCRYPTION=null
|
||||
|
||||
AWS_ACCESS_KEY_ID=
|
||||
AWS_SECRET_ACCESS_KEY=
|
||||
AWS_DEFAULT_REGION=us-east-1
|
||||
AWS_BUCKET=
|
||||
|
||||
PUSHER_APP_ID=
|
||||
PUSHER_APP_KEY=
|
||||
PUSHER_APP_SECRET=
|
||||
PUSHER_APP_CLUSTER=mt1
|
||||
|
||||
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
|
||||
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
|
||||
|
||||
LDAP_HOST=test_ldap
|
||||
LDAP_PORT=389
|
||||
LDAP_BASE_DN="dc=Test"
|
||||
LDAP_USERNAME="cn=admin,dc=Test"
|
||||
LDAP_PASSWORD="test"
|
||||
LDAP_CACHE=false
|
5
.gitattributes
vendored
5
.gitattributes
vendored
@ -1,5 +0,0 @@
|
||||
* text=auto
|
||||
*.css linguist-vendored
|
||||
*.scss linguist-vendored
|
||||
*.js linguist-vendored
|
||||
CHANGELOG.md export-ignore
|
13
.github/FUNDING.yml
vendored
13
.github/FUNDING.yml
vendored
@ -1,13 +0,0 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: [leenooks]
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
||||
custom: ['https://www.buymeacoffee.com/dege']
|
38
.github/ISSUE_TEMPLATE/bug_report.md
vendored
38
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -1,38 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem. Also include any logs or backtrace information
|
||||
|
||||
**LDAP Server details (please complete the following information):**
|
||||
- OS: [e.g. iOS]
|
||||
- Server Name [e.g. OpenLDAP, Windows AD,...]
|
||||
- Version [e.g. 22]
|
||||
|
||||
**Smartphone (please complete the following information):**
|
||||
- Device: [e.g. iPhone6]
|
||||
- OS: [e.g. iOS8.1]
|
||||
- Browser [e.g. stock browser, safari]
|
||||
- Version [e.g. 22]
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
19
.gitignore
vendored
19
.gitignore
vendored
@ -1,19 +0,0 @@
|
||||
/node_modules
|
||||
/public/hot
|
||||
/public/storage
|
||||
/storage/*.key
|
||||
/vendor
|
||||
.env
|
||||
.env.backup
|
||||
.phpunit.result.cache
|
||||
Homestead.json
|
||||
Homestead.yaml
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
public/css/app.css
|
||||
public/js/app.js
|
||||
public/js/vendor.js
|
||||
public/js/manifest.js
|
||||
public/fonts/vendor
|
||||
public/images/vendor
|
||||
public/mix-manifest.json
|
@ -1,38 +0,0 @@
|
||||
stages:
|
||||
- test
|
||||
- build
|
||||
- build-manifest
|
||||
|
||||
variables:
|
||||
DOCKER_HOST: tcp://docker:2375
|
||||
VERSION: latest
|
||||
VERSIONARCH: ${VERSION}-${ARCH}
|
||||
|
||||
# This folder is cached between builds
|
||||
# http://docs.gitlab.com/ce/ci/yaml/README.html#cache
|
||||
cache:
|
||||
key: ${CI_COMMIT_REF_SLUG}
|
||||
paths:
|
||||
- public/css/app.css
|
||||
- public/js/app.js
|
||||
- public/js/manifest.js
|
||||
- public/js/vendor.js
|
||||
- public/*/vendor/
|
||||
- node_modules/
|
||||
- vendor/
|
||||
|
||||
image: docker:latest
|
||||
services:
|
||||
- docker:dind
|
||||
|
||||
before_script:
|
||||
- docker info && docker version
|
||||
- echo "$CI_JOB_TOKEN" | docker login -u "$CI_REGISTRY_USER" "$CI_REGISTRY" --password-stdin
|
||||
- if [ -n "$GITHUB_TOKEN" ]; then cat $GITHUB_TOKEN |base64 -d > auth.json; fi
|
||||
|
||||
include:
|
||||
- .gitlab-test.yml
|
||||
- .gitlab-docker-x86_64.yml
|
||||
- .gitlab-docker-armv7l.yml
|
||||
- .gitlab-docker-arm64.yml
|
||||
- .gitlab-docker-manifest.yml
|
@ -1,18 +0,0 @@
|
||||
arm64:build:
|
||||
variables:
|
||||
ARCH: arm64
|
||||
|
||||
stage: build
|
||||
|
||||
script:
|
||||
- if [ -f init ]; then chmod 500 init; fi
|
||||
- echo -n ${CI_COMMIT_SHORT_SHA} > VERSION
|
||||
- rm -rf node_modules database/seeds database/schema database/factories/*
|
||||
- docker build -f docker/Dockerfile -t ${CI_REGISTRY_IMAGE}:${VERSIONARCH} .
|
||||
- docker push ${CI_REGISTRY_IMAGE}:${VERSIONARCH}
|
||||
|
||||
tags:
|
||||
- docker
|
||||
- arm64
|
||||
only:
|
||||
- master
|
@ -1,18 +0,0 @@
|
||||
armv7l:build:
|
||||
variables:
|
||||
ARCH: armv7l
|
||||
|
||||
stage: build
|
||||
|
||||
script:
|
||||
- if [ -f init ]; then chmod 500 init; fi
|
||||
- echo -n ${CI_COMMIT_SHORT_SHA} > VERSION
|
||||
- rm -rf node_modules database/seeds database/schema database/factories/*
|
||||
- docker build -f docker/Dockerfile -t ${CI_REGISTRY_IMAGE}:${VERSIONARCH} .
|
||||
- docker push ${CI_REGISTRY_IMAGE}:${VERSIONARCH}
|
||||
|
||||
tags:
|
||||
- docker
|
||||
- armv7l
|
||||
only:
|
||||
- master
|
@ -1,10 +0,0 @@
|
||||
x86_64:build-manifest:
|
||||
stage: build-manifest
|
||||
script:
|
||||
- docker manifest create ${CI_REGISTRY_IMAGE}:${VERSION} ${CI_REGISTRY_IMAGE}:${VERSION}-x86_64 ${CI_REGISTRY_IMAGE}:${VERSION}-armv7l ${CI_REGISTRY_IMAGE}:${VERSION}-arm64
|
||||
- docker manifest push --purge ${CI_REGISTRY_IMAGE}:${VERSION}
|
||||
tags:
|
||||
- docker
|
||||
- x86_64
|
||||
only:
|
||||
- master
|
@ -1,18 +0,0 @@
|
||||
x86_64:build:
|
||||
variables:
|
||||
ARCH: x86_64
|
||||
|
||||
stage: build
|
||||
|
||||
script:
|
||||
- if [ -f init ]; then chmod 500 init; fi
|
||||
- echo -n ${CI_COMMIT_SHORT_SHA} > VERSION
|
||||
- rm -rf node_modules database/seeds database/schema database/factories/*
|
||||
- docker build -f docker/Dockerfile -t ${CI_REGISTRY_IMAGE}:${VERSIONARCH} .
|
||||
- docker push ${CI_REGISTRY_IMAGE}:${VERSIONARCH}
|
||||
|
||||
tags:
|
||||
- docker
|
||||
- x86_64
|
||||
only:
|
||||
- master
|
@ -1,52 +0,0 @@
|
||||
test:
|
||||
image: ${CI_REGISTRY}/leenooks/php:8.3-fpm-ldap-test
|
||||
|
||||
stage: test
|
||||
|
||||
# NOTE: This service is dependant on project file configuration, which is not there if the cache was deleted
|
||||
# resulting in the testing to fail on the first run.
|
||||
services:
|
||||
- name: osixia/openldap:latest
|
||||
alias: test_ldap
|
||||
command: ["--loglevel","debug"]
|
||||
|
||||
variables:
|
||||
LDAP_SEED_INTERNAL_LDIF_PATH: "${CI_PROJECT_DIR}/tests/server/openldap/data"
|
||||
LDAP_SEED_INTERNAL_SCHEMA_PATH: "${CI_PROJECT_DIR}/tests/server/openldap/schema"
|
||||
LDAP_BASE_DN: "dc=Test"
|
||||
LDAP_DOMAIN: "Test"
|
||||
LDAP_ADMIN_PASSWORD: test
|
||||
#CI_DEBUG_SERVICES: "true"
|
||||
|
||||
tags:
|
||||
- php
|
||||
only:
|
||||
- master
|
||||
|
||||
before_script:
|
||||
- mv .env.testing .env
|
||||
|
||||
# Install npm and dependancies
|
||||
- apk add --no-cache npm
|
||||
- npm i
|
||||
- npm run prod
|
||||
|
||||
# Install Composer and project dependencies.
|
||||
- mkdir -p ${COMPOSER_HOME}
|
||||
- if [ -n "$GITHUB_TOKEN" ]; then cat $GITHUB_TOKEN |base64 -d > ${COMPOSER_HOME}/auth.json; fi
|
||||
- composer install
|
||||
|
||||
# Generate an application key. Re-cache.
|
||||
- php artisan key:generate
|
||||
|
||||
script:
|
||||
# Sleep if we need to, in case we want to jump in and see what is going on during the test
|
||||
- if [ -n "$DEBUG_PAUSE" ]; then echo "Pausing for $DEBUG_PAUSE seconds, so you can jump into the containers"; sleep $DEBUG_PAUSE; fi
|
||||
# run laravel tests
|
||||
- XDEBUG_MODE=coverage php vendor/bin/phpunit --coverage-text --colors=never
|
||||
|
||||
# run frontend tests
|
||||
# if you have any task for testing frontend
|
||||
# set it in your package.json script
|
||||
# comment this out if you don't have a frontend test
|
||||
# npm test
|
37
INSTALL
Normal file
37
INSTALL
Normal file
@ -0,0 +1,37 @@
|
||||
For install instructions in non-English languages, see the files
|
||||
in the "doc" directory.
|
||||
|
||||
* Requirements
|
||||
|
||||
phpLDAPadmin requires the following:
|
||||
a. A web server (Apache, IIS, etc).
|
||||
b. PHP 4.1.0 or newer (with LDAP support)
|
||||
|
||||
* To install
|
||||
|
||||
1. Unpack the archive (if you're reading this, you already did that).
|
||||
2. Put the resulting 'phpldapadmin' directory somewhere in your webroot.
|
||||
3. Copy 'config.php.example' to 'config.php' and edit to taste.
|
||||
4. Then, point your browser to the phpldapadmin directory.
|
||||
|
||||
* For additional help
|
||||
|
||||
See the files in the "doc" directory.
|
||||
Join our mailing list:
|
||||
https://lists.sourceforge.net/lists/listinfo/phpldapadmin-devel
|
||||
|
||||
* Platform specific notes
|
||||
|
||||
* OpenBSD with chroot'ed Apache:
|
||||
|
||||
For jpeg photos to work properly, you must do this:
|
||||
# mkdir /var/www/tmp, and then
|
||||
# chown root:daemon /var/www/tmp
|
||||
# chmod 1755 /var/www/tmp
|
||||
Where tmp is the $jpeg_temp_dir configured in config.php
|
||||
|
||||
* Windows
|
||||
|
||||
For jpeg photos to work properly, be sure to change $jpeg_temp_dir
|
||||
from "/tmp" to "c:\\temp" or similar.
|
||||
|
50
README.md
50
README.md
@ -1,50 +0,0 @@
|
||||
# phpLDAPadmin
|
||||
phpLDAPadmin is a web based LDAP data management tool for system administrators. It is commonly known and referred by many as "PLA".
|
||||
|
||||
PLA is designed to be compliant with LDAP RFCs, enabling it to be used with any LDAP server.
|
||||
If you come across an LDAP server, where PLA exhibits problems, please open an issue with full details of the problem so that we can have it fixed.
|
||||
|
||||
For up to date information on PLA, please head to the [wiki](https://github.com/leenooks/phpLDAPadmin/wiki).
|
||||
|
||||
> **NOTE**: GIT **master** is currently in active development, and as such functionality may be missing, broken or not working as expected.
|
||||
>
|
||||
> If you are after a working version of PLA, please use one of the tagged releases.
|
||||
|
||||
## Demo
|
||||
If you havent seen PLA in action, you can head here to the [demo](https://demo.phpldapadmin.org) site.
|
||||
|
||||
## Running the docker image
|
||||
PLA v2 is available via docker for preview. (PLA v2 is still under heavy development.)
|
||||
|
||||
The container is the same one used for the demo site - but you'll be able to point it to your local LDAP server and see how things work.
|
||||
|
||||
Take a look at the [Docker Container](https://github.com/leenooks/phpLDAPadmin/wiki/Docker-Container) page for more details.
|
||||
|
||||
> Please let me know if you have any troubles with the container image, eg: usage of the container itself, or usage when it is pointing to your LDAP server.
|
||||
>
|
||||
> Open an issue (details below) with enough information for me to be able to recreate the problem. An `LDIF` will be invaluable if it is not handling data correctly.
|
||||
|
||||
## Getting Help
|
||||
The best place to get help with PLA (new and old) is on [Stack Overflow](https://stackoverflow.com/tags/phpldapadmin/info).
|
||||
|
||||
## Found a bug?
|
||||
If you have found a bug, and can provide detailed instructions so that it can be reproduced, please open an [issue](https://github.com/leenooks/phpLDAPadmin/issues) and provide those details.
|
||||
|
||||
Before opening a ticket, please check to see if it hasnt already been reported, and if it has, please provide any additional information that will help it be fixed.
|
||||
|
||||
*TIP*: Issues opened with:
|
||||
|
||||
* details enabling the problem to be reproduced,
|
||||
* including (if appropriate) an LDIF with the data that exhibits the problem,
|
||||
* a patch (or a git pull request) to fix the problem
|
||||
|
||||
will be looked at first :)
|
||||
|
||||
## THANK YOU
|
||||
Over the years, many, many, many people have supported PLA with either their time, their coding or with financial donations.
|
||||
I have tried to send an email to acknowledge each contribution, and if you havent seen anything personally from me, I am sorry, but please know that I do appreciate all the help I get, in whatever form it is provided.
|
||||
|
||||
Again, Thank You.
|
||||
|
||||
## License
|
||||
[LICENSE](LICENSE)
|
167
add_attr.php
Normal file
167
add_attr.php
Normal file
@ -0,0 +1,167 @@
|
||||
<?php
|
||||
// $Header: /cvsroot/phpldapadmin/phpldapadmin/add_attr.php,v 1.13 2005/04/15 11:46:41 wurley Exp $
|
||||
|
||||
/**
|
||||
* Adds an attribute/value pair to an object
|
||||
*
|
||||
* Variables that come in as POST vars:
|
||||
* - dn
|
||||
* - server_id
|
||||
* - attr
|
||||
* - val
|
||||
* - binary
|
||||
*
|
||||
* @package phpLDAPadmin
|
||||
*/
|
||||
/**
|
||||
*/
|
||||
|
||||
require './common.php';
|
||||
require 'templates/template_config.php';
|
||||
|
||||
$server_id = (isset($_POST['server_id']) ? $_POST['server_id'] : '');
|
||||
$ldapserver = new LDAPServer($server_id);
|
||||
|
||||
if( $ldapserver->isReadOnly() )
|
||||
pla_error( $lang['no_updates_in_read_only_mode'] );
|
||||
if( ! $ldapserver->haveAuthInfo())
|
||||
pla_error( $lang['not_enough_login_info'] );
|
||||
|
||||
$attr = $_POST['attr'];
|
||||
$val = isset( $_POST['val'] ) ? $_POST['val'] : false;;
|
||||
$dn = $_POST['dn'] ;
|
||||
$is_binary_val = isset( $_POST['binary'] ) ? true : false;
|
||||
|
||||
$encoded_dn = rawurlencode( $dn );
|
||||
$encoded_attr = rawurlencode( $attr );
|
||||
|
||||
if( ! $is_binary_val && $val == "" ) {
|
||||
pla_error( $lang['left_attr_blank'] );
|
||||
}
|
||||
|
||||
// special case for binary attributes (like jpegPhoto and userCertificate):
|
||||
// we must go read the data from the file and override $val with the binary data
|
||||
// Secondly, we must check if the ";binary" option has to be appended to the name
|
||||
// of the attribute.
|
||||
|
||||
// Check to see if this is a unique Attribute
|
||||
if( $badattr = checkUniqueAttr( $ldapserver, $dn, $attr, array($val) ) ) {
|
||||
$search_href = sprintf('search.php?search=true&form=advanced&server_id=%s&filter=%s=%s',$server_id,$attr,$badattr);
|
||||
pla_error(sprintf( $lang['unique_attr_failed'],$attr,$badattr,$dn,$search_href ) );
|
||||
}
|
||||
|
||||
if( $is_binary_val ) {
|
||||
if( 0 == $_FILES['val']['size'] )
|
||||
pla_error( $lang['file_empty'] );
|
||||
|
||||
if( ! is_uploaded_file( $_FILES['val']['tmp_name'] ) ) {
|
||||
|
||||
if( isset( $_FILES['val']['error'] ) )
|
||||
|
||||
switch($_FILES['val']['error']) {
|
||||
case 0: //no error; possible file attack!
|
||||
pla_error( $lang['invalid_file'] );
|
||||
break;
|
||||
|
||||
case 1: //uploaded file exceeds the upload_max_filesize directive in php.ini
|
||||
pla_error( $lang['uploaded_file_too_big'] );
|
||||
break;
|
||||
|
||||
case 2: //uploaded file exceeds the MAX_FILE_SIZE directive specified in the html form
|
||||
pla_error( $lang['uploaded_file_too_big'] );
|
||||
break;
|
||||
|
||||
case 3: //uploaded file was only partially uploaded
|
||||
pla_error( $lang['uploaded_file_partial'] );
|
||||
break;
|
||||
|
||||
case 4: //no file was uploaded
|
||||
pla_error( $lang['left_attr_blank'] );
|
||||
break;
|
||||
|
||||
default: //a default error, just in case! :)
|
||||
pla_error( $lang['invalid_file'] );
|
||||
break;
|
||||
}
|
||||
|
||||
else
|
||||
pla_error( $lang['invalid_file'] );
|
||||
}
|
||||
|
||||
$file = $_FILES['val']['tmp_name'];
|
||||
$f = fopen( $file, 'r' );
|
||||
$binary_data = fread( $f, filesize( $file ) );
|
||||
fclose( $f );
|
||||
|
||||
$val = $binary_data;
|
||||
|
||||
if( is_binary_option_required( $ldapserver, $attr ) )
|
||||
$attr .= ";binary";
|
||||
}
|
||||
|
||||
// Automagically hash new userPassword attributes according to the
|
||||
// chosen in config.php.
|
||||
if( 0 == strcasecmp( $attr, 'userpassword' ) ) {
|
||||
|
||||
if( isset( $servers[$server_id]['default_hash'] ) &&
|
||||
$servers[$server_id]['default_hash'] != '' ) {
|
||||
|
||||
$enc_type = $servers[$server_id]['default_hash'];
|
||||
$val = password_hash( $val, $enc_type );
|
||||
}
|
||||
}
|
||||
|
||||
elseif( in_array( $attr,array('sambantpassword','sambalmpassword') ) ){
|
||||
$mkntPassword = new MkntPasswdUtil();
|
||||
$mkntPassword->createSambaPasswords( $val );
|
||||
$val = $mkntPassword->valueOf($attr);
|
||||
}
|
||||
|
||||
$new_entry = array( $attr => $val );
|
||||
$result = @ldap_mod_add( $ldapserver->connect(), $dn, $new_entry );
|
||||
|
||||
if( $result )
|
||||
header( "Location: edit.php?server_id=$server_id&dn=$encoded_dn&modified_attrs[]=$encoded_attr" );
|
||||
|
||||
else
|
||||
pla_error( $lang['failed_to_add_attr'],ldap_error($ldapserver->connect()),ldap_errno($ldapserver->connect()) );
|
||||
|
||||
/**
|
||||
* Check if we need to append the ;binary option to the name
|
||||
* of some binary attribute
|
||||
*
|
||||
* @param int $server_id Server ID that the attribute is in.
|
||||
* @param attr $attr Attribute to test to see if it requires ;binary added to it.
|
||||
* @return bool
|
||||
*/
|
||||
|
||||
function is_binary_option_required( $ldapserver, $attr ) {
|
||||
|
||||
// list of the binary attributes which need the ";binary" option
|
||||
$binary_attributes_with_options = array(
|
||||
// Superior: Ldapv3 Syntaxes (1.3.6.1.4.1.1466.115.121.1)
|
||||
'1.3.6.1.4.1.1466.115.121.1.8' => "userCertificate",
|
||||
'1.3.6.1.4.1.1466.115.121.1.8' => "caCertificate",
|
||||
'1.3.6.1.4.1.1466.115.121.1.10' => "crossCertificatePair",
|
||||
'1.3.6.1.4.1.1466.115.121.1.9' => "certificateRevocationList",
|
||||
'1.3.6.1.4.1.1466.115.121.1.9' => "authorityRevocationList",
|
||||
// Superior: Netscape Ldap attributes types (2.16.840.1.113730.3.1)
|
||||
'2.16.840.1.113730.3.1.40' => "userSMIMECertificate"
|
||||
);
|
||||
|
||||
// quick check by attr name (short circuits the schema check if possible)
|
||||
//foreach( $binary_attributes_with_options as $oid => $name )
|
||||
//if( 0 == strcasecmp( $attr, $name ) )
|
||||
//return true;
|
||||
|
||||
$schema_attr = get_schema_attribute( $ldapserver, $attr );
|
||||
if( ! $schema_attr )
|
||||
return false;
|
||||
|
||||
$syntax = $schema_attr->getSyntaxOID();
|
||||
if( isset( $binary_attributes_with_options[ $syntax ] ) )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
?>
|
199
add_attr_form.php
Normal file
199
add_attr_form.php
Normal file
@ -0,0 +1,199 @@
|
||||
<?php
|
||||
// $Header: /cvsroot/phpldapadmin/phpldapadmin/add_attr_form.php,v 1.11 2005/03/05 06:27:06 wurley Exp $
|
||||
|
||||
/**
|
||||
* Displays a form for adding an attribute/value to an LDAP entry.
|
||||
*
|
||||
* Variables that come in as GET vars:
|
||||
* - dn (rawurlencoded)
|
||||
* - server_id
|
||||
*
|
||||
* @package phpLDAPadmin
|
||||
*/
|
||||
/**
|
||||
*/
|
||||
|
||||
require './common.php';
|
||||
|
||||
$server_id = (isset($_GET['server_id']) ? $_GET['server_id'] : '');
|
||||
$ldapserver = new LDAPServer($server_id);
|
||||
|
||||
if( $ldapserver->isReadOnly() )
|
||||
pla_error( $lang['no_updates_in_read_only_mode'] );
|
||||
if( ! $ldapserver->haveAuthInfo())
|
||||
pla_error( $lang['not_enough_login_info'] );
|
||||
|
||||
$dn = $_GET['dn'];
|
||||
$encoded_dn = rawurlencode( $dn );
|
||||
$rdn = get_rdn( $dn );
|
||||
|
||||
$friendly_attrs = process_friendly_attr_table();
|
||||
|
||||
include './header.php'; ?>
|
||||
|
||||
<body>
|
||||
|
||||
<h3 class="title"><?php echo sprintf( $lang['add_new_attribute'], htmlspecialchars( $rdn ) ); ?></b></h3>
|
||||
<h3 class="subtitle"><?php echo $lang['server']; ?>: <b><?php echo $ldapserver->name; ?></b> <?php echo $lang['distinguished_name']; ?>: <b><?php echo htmlspecialchars( ( $dn ) ); ?></b></h3>
|
||||
|
||||
<?php $attrs = get_object_attrs( $ldapserver, $dn );
|
||||
|
||||
$oclasses = get_object_attr( $ldapserver, $dn, 'objectClass' );
|
||||
if( ! is_array( $oclasses ) )
|
||||
$oclasses = array( $oclasses );
|
||||
|
||||
$avail_attrs = array();
|
||||
|
||||
$schema_oclasses = get_schema_objectclasses( $ldapserver, $dn );
|
||||
foreach( $oclasses as $oclass ) {
|
||||
$schema_oclass = get_schema_objectclass( $ldapserver, $oclass, $dn );
|
||||
|
||||
if( $schema_oclass && 0 == strcasecmp( 'objectclass', get_class( $schema_oclass ) ) )
|
||||
$avail_attrs = array_merge( $schema_oclass->getMustAttrNames( $schema_oclasses ),
|
||||
$schema_oclass->getMayAttrNames( $schema_oclasses ),
|
||||
$avail_attrs );
|
||||
}
|
||||
|
||||
$avail_attrs = array_unique( $avail_attrs );
|
||||
$avail_attrs = array_filter( $avail_attrs, "not_an_attr" );
|
||||
sort( $avail_attrs );
|
||||
|
||||
$avail_binary_attrs = array();
|
||||
foreach( $avail_attrs as $i => $attr ) {
|
||||
|
||||
if( is_attr_binary( $ldapserver, $attr ) ) {
|
||||
$avail_binary_attrs[] = $attr;
|
||||
unset( $avail_attrs[ $i ] );
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<br />
|
||||
|
||||
<center>
|
||||
|
||||
<?php echo $lang['add_new_attribute'];
|
||||
|
||||
if( is_array( $avail_attrs ) && count( $avail_attrs ) > 0 ) { ?>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<form action="add_attr.php" method="post">
|
||||
<input type="hidden" name="server_id" value="<?php echo $server_id; ?>" />
|
||||
<input type="hidden" name="dn" value="<?php echo htmlspecialchars($dn); ?>" />
|
||||
|
||||
<select name="attr">
|
||||
|
||||
<?php $attr_select_html = '';
|
||||
usort($avail_attrs,"sortAttrs");
|
||||
foreach( $avail_attrs as $a ) {
|
||||
|
||||
// is there a user-friendly translation available for this attribute?
|
||||
if( isset( $friendly_attrs[ strtolower( $a ) ] ) ) {
|
||||
$attr_display = htmlspecialchars( $friendly_attrs[ strtolower( $a ) ] ) . " (" .
|
||||
htmlspecialchars($a) . ")";
|
||||
|
||||
} else {
|
||||
$attr_display = htmlspecialchars( $a );
|
||||
}
|
||||
|
||||
echo $attr_display;
|
||||
$attr_select_html .= "<option>$attr_display</option>\n";
|
||||
echo "<option value=\"" . htmlspecialchars($a) . "\">$attr_display</option>";
|
||||
} ?>
|
||||
|
||||
</select>
|
||||
|
||||
<input type="text" name="val" size="20" />
|
||||
<input type="submit" name="submit" value="<?php echo $lang['add']; ?>" class="update_dn" />
|
||||
</form>
|
||||
|
||||
<?php } else { ?>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
<small>(<?php echo $lang['no_new_attrs_available']; ?>)</small>
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<?php } ?>
|
||||
|
||||
<?php echo $lang['add_new_binary_attr'];
|
||||
if( count( $avail_binary_attrs ) > 0 ) { ?>
|
||||
|
||||
<!-- Form to add a new BINARY attribute to this entry -->
|
||||
<form action="add_attr.php" method="post" enctype="multipart/form-data">
|
||||
<input type="hidden" name="server_id" value="<?php echo $server_id; ?>" />
|
||||
<input type="hidden" name="dn" value="<?php echo $dn; ?>" />
|
||||
<input type="hidden" name="binary" value="true" />
|
||||
<br />
|
||||
|
||||
<select name="attr">
|
||||
|
||||
<?php $attr_select_html = '';
|
||||
|
||||
usort($avail_binary_attrs,"sortAttrs");
|
||||
|
||||
foreach( $avail_binary_attrs as $a ) {
|
||||
|
||||
// is there a user-friendly translation available for this attribute?
|
||||
if( isset( $friendly_attrs[ strtolower( $a ) ] ) ) {
|
||||
$attr_display = htmlspecialchars( $friendly_attrs[ strtolower( $a ) ] ) . " (" .
|
||||
htmlspecialchars($a) . ")";
|
||||
|
||||
} else {
|
||||
$attr_display = htmlspecialchars( $a );
|
||||
}
|
||||
|
||||
echo $attr_display;
|
||||
$attr_select_html .= "<option>$attr_display</option>\n";
|
||||
echo "<option value=\"" . htmlspecialchars($a) . "\">$attr_display</option>";
|
||||
} ?>
|
||||
|
||||
</select>
|
||||
|
||||
<input type="file" name="val" size="20" />
|
||||
<input type="submit" name="submit" value="<?php echo $lang['add']; ?>" class="update_dn" />
|
||||
|
||||
<?php if( ! ini_get( 'file_uploads' ) )
|
||||
echo "<br><small><b>" . $lang['warning_file_uploads_disabled'] . "</b></small><br>";
|
||||
|
||||
else
|
||||
echo "<br><small><b>" . sprintf( $lang['max_file_size'], ini_get( 'upload_max_filesize' ) ) . "</b></small><br>";
|
||||
?>
|
||||
|
||||
</form>
|
||||
|
||||
<?php } else { ?>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
<small>(<?php echo $lang['no_new_binary_attrs_available']; ?>)</small>
|
||||
|
||||
<?php } ?>
|
||||
|
||||
</center>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Given an attribute $x, this returns true if it is NOT already specified
|
||||
* in the current entry, returns false otherwise.
|
||||
*
|
||||
* @param attr $x
|
||||
* @return bool
|
||||
* @ignore
|
||||
*/
|
||||
function not_an_attr( $x ) {
|
||||
global $attrs;
|
||||
|
||||
//return ! isset( $attrs[ strtolower( $x ) ] );
|
||||
foreach( $attrs as $attr => $values )
|
||||
if( 0 == strcasecmp( $attr, $x ) )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
?>
|
70
add_oclass.php
Normal file
70
add_oclass.php
Normal file
@ -0,0 +1,70 @@
|
||||
<?php
|
||||
// $Header: /cvsroot/phpldapadmin/phpldapadmin/add_oclass.php,v 1.14 2005/03/20 04:43:36 wurley Exp $
|
||||
|
||||
/**
|
||||
* Adds an objectClass to the specified dn.
|
||||
*
|
||||
* Note, this does not do any schema violation checking. That is
|
||||
* performed in add_oclass_form.php.
|
||||
*
|
||||
* Variables that come in as POST vars:
|
||||
* - dn (rawurlencoded)
|
||||
* - server_id
|
||||
* - new_oclass
|
||||
* - new_attrs (array, if any)
|
||||
*
|
||||
* @package phpLDAPadmin
|
||||
*/
|
||||
/**
|
||||
*/
|
||||
|
||||
require './common.php';
|
||||
|
||||
$server_id = (isset($_POST['server_id']) ? $_POST['server_id'] : '');
|
||||
$ldapserver = new LDAPServer($server_id);
|
||||
|
||||
if( $ldapserver->isReadOnly() )
|
||||
pla_error( $lang['no_updates_in_read_only_mode'] );
|
||||
if( ! $ldapserver->haveAuthInfo())
|
||||
pla_error( $lang['not_enough_login_info'] );
|
||||
|
||||
$dn = rawurldecode( $_POST['dn'] );
|
||||
$new_oclass = $_POST['new_oclass'];
|
||||
$new_attrs = $_POST['new_attrs'];
|
||||
|
||||
$encoded_dn = rawurlencode( $dn );
|
||||
|
||||
if( is_attr_read_only( $ldapserver, 'objectClass' ) )
|
||||
pla_error( "ObjectClasses are flagged as read only in the phpLDAPadmin configuration." );
|
||||
|
||||
$new_entry = array();
|
||||
$new_entry['objectClass'] = $new_oclass;
|
||||
|
||||
$new_attrs_entry = array();
|
||||
$new_oclass_entry = array( 'objectClass' => $new_oclass );
|
||||
|
||||
if( is_array( $new_attrs ) && count( $new_attrs ) > 0 )
|
||||
foreach( $new_attrs as $attr => $val ) {
|
||||
|
||||
// Check to see if this is a unique Attribute
|
||||
if( $badattr = checkUniqueAttr( $ldapserver, $dn, $attr, array($val) ) ) {
|
||||
$search_href = sprintf('search.php?search=true&form=advanced&server_id=%s&filter=%s=%s',$server_id,$attr,$badattr);
|
||||
pla_error(sprintf( $lang['unique_attr_failed'],$attr,$badattr,$dn,$search_href ) );
|
||||
}
|
||||
|
||||
$new_entry[ $attr ] = $val;
|
||||
}
|
||||
|
||||
//echo "<pre>";
|
||||
//print_r( $new_entry );
|
||||
//exit;
|
||||
|
||||
$add_res = @ldap_mod_add( $ldapserver->connect(), $dn, $new_entry );
|
||||
|
||||
if( ! $add_res ) {
|
||||
pla_error( $lang['could_not_perform_ldap_mod_add'],ldap_error($ldapserver->connect()),ldap_errno($ldapserver->connect()) );
|
||||
|
||||
} else {
|
||||
header( "Location: edit.php?server_id=$server_id&dn=$encoded_dn&modified_attrs[]=objectclass" );
|
||||
}
|
||||
?>
|
132
add_oclass_form.php
Normal file
132
add_oclass_form.php
Normal file
@ -0,0 +1,132 @@
|
||||
<?php
|
||||
// $Header: /cvsroot/phpldapadmin/phpldapadmin/add_oclass_form.php,v 1.18 2005/03/12 14:03:36 wurley Exp $
|
||||
|
||||
/**
|
||||
* This page may simply add the objectClass and take you back to the edit page,
|
||||
* but, in one condition it may prompt the user for input. That condition is this:
|
||||
*
|
||||
* If the user has requested to add an objectClass that requires a set of
|
||||
* attributes with 1 or more not defined by the object. In that case, we will
|
||||
* present a form for the user to add those attributes to the object.
|
||||
*
|
||||
* Variables that come in as REQUEST vars:
|
||||
* - dn (rawurlencoded)
|
||||
* - server_id
|
||||
* - new_oclass
|
||||
*
|
||||
* @package phpLDAPadmin
|
||||
*/
|
||||
/**
|
||||
*/
|
||||
require './common.php';
|
||||
|
||||
$server_id = (isset($_REQUEST['server_id']) ? $_REQUEST['server_id'] : '');
|
||||
$ldapserver = new LDAPServer($server_id);
|
||||
|
||||
if( $ldapserver->isReadOnly() )
|
||||
pla_error( $lang['no_updates_in_read_only_mode'] );
|
||||
if( ! $ldapserver->haveAuthInfo())
|
||||
pla_error( $lang['not_enough_login_info'] );
|
||||
|
||||
$new_oclass = $_REQUEST['new_oclass'];
|
||||
$dn = rawurldecode( $_REQUEST['dn'] );
|
||||
$encoded_dn = rawurlencode( $dn );
|
||||
|
||||
/* Ensure that the object has defined all MUST attrs for this objectClass.
|
||||
* If it hasn't, present a form to have the user enter values for all the
|
||||
* newly required attrs. */
|
||||
|
||||
$entry = get_object_attrs( $ldapserver, $dn, true );
|
||||
|
||||
$current_attrs = array();
|
||||
foreach( $entry as $attr => $junk )
|
||||
$current_attrs[] = strtolower($attr);
|
||||
|
||||
// grab the required attributes for the new objectClass
|
||||
$oclass = get_schema_objectclass( $ldapserver, $new_oclass );
|
||||
if( $oclass )
|
||||
$must_attrs = $oclass->getMustAttrs();
|
||||
|
||||
else
|
||||
$must_attrs = array();
|
||||
|
||||
// We don't want any of the attr meta-data, just the string
|
||||
//foreach( $must_attrs as $i => $attr )
|
||||
//$must_attrs[$i] = $attr->getName();
|
||||
|
||||
// build a list of the attributes that this new objectClass requires,
|
||||
// but that the object does not currently contain
|
||||
$needed_attrs = array();
|
||||
foreach( $must_attrs as $attr ) {
|
||||
$attr = get_schema_attribute( $ldapserver, $attr->getName() );
|
||||
|
||||
//echo "<pre>"; var_dump( $attr ); echo "</pre>";
|
||||
|
||||
// First, check if one of this attr's aliases is already an attribute of this entry
|
||||
foreach( $attr->getAliases() as $alias_attr_name )
|
||||
if( in_array( strtolower( $alias_attr_name ), $current_attrs ) )
|
||||
|
||||
// Skip this attribute since it's already in the entry
|
||||
continue;
|
||||
|
||||
if( in_array( strtolower($attr->getName()), $current_attrs ) )
|
||||
continue;
|
||||
|
||||
// We made it this far, so the attribute needs to be added to this entry in order
|
||||
// to add this objectClass
|
||||
$needed_attrs[] = $attr;
|
||||
}
|
||||
|
||||
if( count( $needed_attrs ) > 0 ) {
|
||||
include './header.php'; ?>
|
||||
<body>
|
||||
|
||||
<h3 class="title"><?php echo $lang['new_required_attrs']; ?></h3>
|
||||
<h3 class="subtitle"><?php echo $lang['requires_to_add'] . ' ' . count($needed_attrs) .
|
||||
' ' . $lang['new_attributes']; ?></h3>
|
||||
|
||||
<small>
|
||||
|
||||
<?php echo $lang['new_required_attrs_instructions'];
|
||||
echo ' ' . count( $needed_attrs ) . ' ' . $lang['new_attributes'] . ' ';
|
||||
echo $lang['that_this_oclass_requires']; ?>
|
||||
|
||||
</small>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<form action="add_oclass.php" method="post">
|
||||
<input type="hidden" name="new_oclass" value="<?php echo htmlspecialchars( $new_oclass ); ?>" />
|
||||
<input type="hidden" name="dn" value="<?php echo $encoded_dn; ?>" />
|
||||
<input type="hidden" name="server_id" value="<?php echo $server_id; ?>" />
|
||||
|
||||
<table class="edit_dn" cellspacing="0">
|
||||
<tr><th colspan="2"><?php echo $lang['new_required_attrs']; ?></th></tr>
|
||||
|
||||
<?php foreach( $needed_attrs as $count => $attr ) { ?>
|
||||
|
||||
<tr><td class="attr"><b><?php echo htmlspecialchars($attr->getName()); ?></b></td></tr>
|
||||
<tr><td class="val"><input type="text" name="new_attrs[<?php echo htmlspecialchars($attr->getName()); ?>]" value="" size="40" /></tr>
|
||||
<?php } ?>
|
||||
|
||||
</table>
|
||||
<br />
|
||||
<br />
|
||||
<center><input type="submit" value="<?php echo $lang['add_oclass_and_attrs']; ?>" /></center>
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<?php } else {
|
||||
|
||||
$add_res = @ldap_mod_add( $ldapserver->connect(), $dn, array( 'objectClass' => $new_oclass ) );
|
||||
if( ! $add_res )
|
||||
pla_error( "Could not perform ldap_mod_add operation.",
|
||||
ldap_error( $ldapserver->connect() ),ldap_errno( $ldapserver->connect() ) );
|
||||
else
|
||||
header( "Location: edit.php?server_id=$server_id&dn=$encoded_dn&modified_attrs[]=objectClass" );
|
||||
|
||||
}
|
||||
?>
|
75
add_value.php
Normal file
75
add_value.php
Normal file
@ -0,0 +1,75 @@
|
||||
<?php
|
||||
// $Header: /cvsroot/phpldapadmin/phpldapadmin/add_value.php,v 1.17 2005/03/12 10:42:27 wurley Exp $
|
||||
|
||||
/**
|
||||
* Adds a value to an attribute for a given dn.
|
||||
*
|
||||
* Variables that come in as POST vars:
|
||||
* - dn (rawurlencoded)
|
||||
* - attr (rawurlencoded) the attribute to which we are adding a value
|
||||
* - server_id
|
||||
* - new_value (form element)
|
||||
* - binary
|
||||
*
|
||||
* On success, redirect to the edit_dn page. On failure, echo an error.
|
||||
*
|
||||
* @package phpLDAPadmin
|
||||
*/
|
||||
/**
|
||||
*/
|
||||
|
||||
require './common.php';
|
||||
|
||||
$server_id = (isset($_POST['server_id']) ? $_POST['server_id'] : '');
|
||||
$ldapserver = new LDAPServer($server_id);
|
||||
|
||||
if( $ldapserver->isReadOnly() )
|
||||
pla_error( $lang['no_updates_in_read_only_mode'] );
|
||||
if( ! $ldapserver->haveAuthInfo())
|
||||
pla_error( $lang['not_enough_login_info'] );
|
||||
|
||||
$attr = $_POST['attr'];
|
||||
$new_value = $_POST['new_value'];
|
||||
$dn = rawurldecode( $_POST['dn'] );
|
||||
$is_binary_val = isset( $_POST['binary'] ) ? true : false;
|
||||
|
||||
$encoded_dn = rawurlencode( $dn );
|
||||
$encoded_attr = rawurlencode( $attr );
|
||||
|
||||
if( is_attr_read_only( $ldapserver, $attr ) )
|
||||
pla_error(sprintf($lang['attr_is_read_only'],htmlspecialchars( $attr )));
|
||||
|
||||
// special case for binary attributes:
|
||||
// we must go read the data from the file.
|
||||
if( $is_binary_val ) {
|
||||
$file = $_FILES['new_value']['tmp_name'];
|
||||
|
||||
$f = fopen( $file, 'r' );
|
||||
$binary_value = fread( $f, filesize( $file ) );
|
||||
fclose( $f );
|
||||
|
||||
$new_value = $binary_value;
|
||||
}
|
||||
|
||||
$new_entry = array( $attr => $new_value );
|
||||
|
||||
// Check to see if this is a unique Attribute
|
||||
if( $badattr = checkUniqueAttr( $ldapserver, $dn, $attr, $new_entry ) ) {
|
||||
$search_href = sprintf('search.php?search=true&form=advanced&server_id=%s&filter=%s=%s',$server_id,$attr,$badattr);
|
||||
pla_error(sprintf( $lang['unique_attr_failed'],$attr,$badattr,$dn,$search_href ) );
|
||||
}
|
||||
|
||||
// Call the custom callback for each attribute modification
|
||||
// and verify that it should be modified.
|
||||
if( run_hook ( 'pre_attr_add', array ( 'server_id' => $server_id, 'dn' => $dn, 'attr_name' => $attr,
|
||||
'new_value' => $new_entry ) ) ) {
|
||||
|
||||
$add_result = @ldap_mod_add( $ldapserver->connect(), $dn, $new_entry );
|
||||
|
||||
if( ! $add_result )
|
||||
pla_error( $lang['could_not_perform_ldap_mod_add'], ldap_error( $ldapserver->connect() ), ldap_errno( $ldapserver->connect() ) );
|
||||
}
|
||||
|
||||
header( "Location: edit.php?server_id=$server_id&dn=$encoded_dn&modified_attrs[]=$encoded_attr" );
|
||||
|
||||
?>
|
213
add_value_form.php
Normal file
213
add_value_form.php
Normal file
@ -0,0 +1,213 @@
|
||||
<?php
|
||||
// $Header: /cvsroot/phpldapadmin/phpldapadmin/add_value_form.php,v 1.29 2005/03/12 14:03:36 wurley Exp $
|
||||
|
||||
/**
|
||||
* Displays a form to allow the user to enter a new value to add
|
||||
* to the existing list of values for a multi-valued attribute.
|
||||
*
|
||||
* Variables that come in as GET vars:
|
||||
* - dn (rawurlencoded)
|
||||
* - attr (rawurlencoded) the attribute to which we are adding a value
|
||||
* - server_id
|
||||
*
|
||||
* @package phpLDAPadmin
|
||||
*/
|
||||
/**
|
||||
*/
|
||||
|
||||
require './common.php';
|
||||
|
||||
$server_id = (isset($_GET['server_id']) ? $_GET['server_id'] : '');
|
||||
$ldapserver = new LDAPServer($server_id);
|
||||
|
||||
if( $ldapserver->isReadOnly() )
|
||||
pla_error( $lang['no_updates_in_read_only_mode'] );
|
||||
if( ! $ldapserver->haveAuthInfo())
|
||||
pla_error( $lang['not_enough_login_info'] );
|
||||
|
||||
$attr = $_GET['attr'];
|
||||
$dn = isset( $_GET['dn'] ) ? $_GET['dn'] : null;
|
||||
$encoded_dn = rawurlencode( $dn );
|
||||
$encoded_attr = rawurlencode( $attr );
|
||||
|
||||
if( null != $dn ) {
|
||||
$rdn = get_rdn( $dn );
|
||||
|
||||
} else {
|
||||
$rdn = null;
|
||||
}
|
||||
|
||||
$current_values = get_object_attr( $ldapserver, $dn, $attr );
|
||||
$num_current_values = ( is_array($current_values) ? count($current_values) : 0 );
|
||||
$is_object_class = ( 0 == strcasecmp( $attr, 'objectClass' ) ) ? true : false;
|
||||
$is_jpeg_photo = is_jpeg_photo( $ldapserver, $attr ); //( 0 == strcasecmp( $attr, 'jpegPhoto' ) ) ? true : false;
|
||||
|
||||
if( $is_object_class ) {
|
||||
// fetch all available objectClasses and remove those from the list that are already defined in the entry
|
||||
$schema_oclasses = get_schema_objectclasses( $ldapserver );
|
||||
|
||||
foreach( $current_values as $oclass )
|
||||
unset( $schema_oclasses[ strtolower( $oclass ) ] );
|
||||
|
||||
} else {
|
||||
$schema_attr = get_schema_attribute( $ldapserver, $attr );
|
||||
}
|
||||
|
||||
include './header.php'; ?>
|
||||
|
||||
<body>
|
||||
|
||||
<h3 class="title">
|
||||
<?php echo $lang['add_new']; ?>
|
||||
<b><?php echo htmlspecialchars($attr); ?></b>
|
||||
<?php echo $lang['value_to']; ?>
|
||||
<b><?php echo htmlspecialchars($rdn); ?></b></h3>
|
||||
|
||||
<h3 class="subtitle">
|
||||
<?php echo $lang['server']; ?>:
|
||||
<b><?php echo $ldapserver->name; ?></b>
|
||||
<?php echo $lang['distinguished_name']; ?>: <b><?php echo htmlspecialchars( $dn ); ?></b></h3>
|
||||
|
||||
<?php echo $lang['current_list_of']; ?> <b><?php echo $num_current_values; ?></b>
|
||||
<?php echo $lang['values_for_attribute']; ?> <b><?php echo htmlspecialchars($attr); ?></b>:
|
||||
|
||||
<?php if ($num_current_values) { ?>
|
||||
<?php if( $is_jpeg_photo ) { ?>
|
||||
|
||||
<table><tr><td>
|
||||
<?php draw_jpeg_photos( $ldapserver, $dn, $attr, false ); ?>
|
||||
</td></tr></table>
|
||||
|
||||
<!-- Temporary warning until we find a way to add jpegPhoto values without an INAPROPRIATE_MATCHING error -->
|
||||
<p><small>
|
||||
<?php echo $lang['inappropriate_matching_note']; ?>
|
||||
</small></p>
|
||||
<!-- End of temporary warning -->
|
||||
|
||||
<?php } else if( is_attr_binary( $ldapserver, $attr ) ) { ?>
|
||||
<ul>
|
||||
|
||||
<?php if( is_array( $vals ) ) {
|
||||
|
||||
for( $i=1; $i<=count($vals); $i++ ) {
|
||||
|
||||
$href = sprintf('download_binary_attr.php?server_id=%s&dn=%s&attr=%s&value_num=%s',
|
||||
$server_id,$encoded_dn,$attr,$i-1); ?>
|
||||
|
||||
<li><a href="<?php echo $href; ?>"><img src="images/save.png" /> <?php echo $lang['download_value'] . ' ' . $i; ?>)</a></li>
|
||||
<?php }
|
||||
|
||||
} else {
|
||||
$href = sprintf('download_binary_attr.php?server_id=%s&dn=%s&attr=%s',$server_id,$encoded_dn,$attr); ?>
|
||||
<li><a href="<?php echo $href; ?>"><img src="images/save.png" /> <?php echo $lang['download_value']; ?></a></li>
|
||||
<?php } ?>
|
||||
|
||||
</ul>
|
||||
<!-- Temporary warning until we find a way to add jpegPhoto values without an INAPROPRIATE_MATCHING error -->
|
||||
<p><small>
|
||||
<?php echo $lang['inappropriate_matching_note']; ?>
|
||||
</small></p>
|
||||
<!-- End of temporary warning -->
|
||||
|
||||
<?php } else { ?>
|
||||
|
||||
<ul class="current_values">
|
||||
|
||||
<?php if( is_array( $current_values ) ) /*$num_current_values > 1 )*/ {
|
||||
|
||||
foreach( $current_values as $val ) { ?>
|
||||
<li><nobr><?php echo htmlspecialchars(($val)); ?></nobr></li>
|
||||
<?php } ?>
|
||||
|
||||
<?php } else { ?>
|
||||
<li><nobr><?php echo htmlspecialchars(($current_values)); ?></nobr></li>
|
||||
<?php } ?>
|
||||
|
||||
</ul>
|
||||
|
||||
<?php } ?>
|
||||
<?php } else { ?>
|
||||
<br />
|
||||
<br />
|
||||
<?php } ?>
|
||||
|
||||
<?php echo $lang['enter_value_to_add']; ?>
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<?php if( $is_object_class ) { ?>
|
||||
|
||||
<form action="add_oclass_form.php" method="post" class="new_value">
|
||||
<input type="hidden" name="server_id" value="<?php echo $server_id; ?>" />
|
||||
<input type="hidden" name="dn" value="<?php echo $encoded_dn; ?>" />
|
||||
<select name="new_oclass">
|
||||
|
||||
<?php foreach( $schema_oclasses as $name => $oclass ) {
|
||||
|
||||
// exclude any structural ones, as they'll only generate an LDAP_OBJECT_CLASS_VIOLATION
|
||||
if ($oclass->type == "structural") continue; ?>
|
||||
|
||||
<option value="<?php echo $oclass->getName(); ?>"><?php echo $oclass->getName(); ?></option>
|
||||
|
||||
<?php } ?>
|
||||
|
||||
</select>
|
||||
<input type="submit" value="<?php echo $lang['add_new_objectclass']; ?>" />
|
||||
|
||||
<br />
|
||||
<?php if( show_hints() ) { ?>
|
||||
<small>
|
||||
<br />
|
||||
<img src="images/light.png" /><span class="hint"><?php echo $lang['new_required_attrs_note']; ?></span>
|
||||
</small>
|
||||
<?php }
|
||||
|
||||
} else { ?>
|
||||
|
||||
<form action="add_value.php" method="post" class="new_value" name="new_value_form"<?php
|
||||
if( is_attr_binary( $ldapserver, $attr ) ) echo "enctype=\"multipart/form-data\""; ?>>
|
||||
|
||||
<input type="hidden" name="server_id" value="<?php echo $server_id; ?>" />
|
||||
<input type="hidden" name="dn" value="<?php echo $encoded_dn; ?>" />
|
||||
<input type="hidden" name="attr" value="<?php echo $encoded_attr; ?>" />
|
||||
|
||||
<?php if( is_attr_binary( $ldapserver, $attr ) ) { ?>
|
||||
<input type="file" name="new_value" />
|
||||
<input type="hidden" name="binary" value="true" />
|
||||
|
||||
<?php } else {
|
||||
if( is_multi_line_attr( $attr, $server_id ) ) { ?>
|
||||
|
||||
<textarea name="new_value" rows="3" cols="30"></textarea>
|
||||
|
||||
<?php } else { ?>
|
||||
<input type="text" <?php if( $schema_attr->getMaxLength() ) echo "maxlength=\"" . $schema_attr->getMaxLength() . "\" "; ?>name="new_value" size="40" value="" />
|
||||
|
||||
<?php // draw the "browse" button next to this input box if this attr houses DNs:
|
||||
if( is_dn_attr( $ldapserver, $attr ) )
|
||||
draw_chooser_link( "new_value_form.new_value", false ); ?>
|
||||
|
||||
<?php }
|
||||
} ?>
|
||||
|
||||
<input type="submit" name="submit" value="<?php echo $lang['add_new_value']; ?>" />
|
||||
<br />
|
||||
|
||||
<?php if( $schema_attr->getDescription() ) { ?>
|
||||
<small><b><?php echo $lang['desc']; ?>:</b> <?php echo $schema_attr->getDescription(); ?></small><br />
|
||||
<?php } ?>
|
||||
|
||||
<?php if( $schema_attr->getType() ) { ?>
|
||||
<small><b><?php echo $lang['syntax']; ?>:</b> <?php echo $schema_attr->getType(); ?></small><br />
|
||||
<?php } ?>
|
||||
|
||||
<?php if( $schema_attr->getMaxLength() ) { ?>
|
||||
<small><b><?php echo $lang['maximum_length']; ?>:</b> <?php echo number_format( $schema_attr->getMaxLength() ); ?> <?php echo $lang['characters']; ?></small><br />
|
||||
<?php } ?>
|
||||
|
||||
</form>
|
||||
|
||||
<?php } ?>
|
||||
|
||||
</body>
|
||||
</html>
|
3
app/.gitignore
vendored
3
app/.gitignore
vendored
@ -1,3 +0,0 @@
|
||||
q*
|
||||
!public/
|
||||
!.gitignore
|
@ -1,996 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\LDAP;
|
||||
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
use App\Classes\LDAP\Schema\AttributeType;
|
||||
|
||||
/**
|
||||
* Represents an attribute of an LDAP Object
|
||||
*/
|
||||
class Attribute implements \Countable, \ArrayAccess
|
||||
{
|
||||
// Attribute Name
|
||||
protected string $name;
|
||||
|
||||
protected ?AttributeType $schema = NULL;
|
||||
|
||||
/*
|
||||
# Source of this attribute definition
|
||||
protected $source;
|
||||
*/
|
||||
|
||||
// Current and Old Values
|
||||
protected Collection $values;
|
||||
|
||||
// Is this attribute an internal attribute
|
||||
protected bool $is_internal = FALSE;
|
||||
|
||||
// Is this attribute the RDN?
|
||||
protected bool $is_rdn = FALSE;
|
||||
|
||||
// Objectclasses that require this attribute
|
||||
protected Collection $required_by;
|
||||
|
||||
// MIN/MAX number of values
|
||||
protected int $min_values_count = 0;
|
||||
protected int $max_values_count = 0;
|
||||
|
||||
// RFC3866 Language Tags
|
||||
protected Collection $lang_tags;
|
||||
|
||||
// The old values for this attribute - helps with isDirty() to determine if there is an update pending
|
||||
protected Collection $oldValues;
|
||||
|
||||
/*
|
||||
# Has the attribute been modified
|
||||
protected $modified = false;
|
||||
# Is the attribute being deleted because of an object class removal
|
||||
protected $forcedelete = false;
|
||||
# Is the attribute visible
|
||||
protected $visible = false;
|
||||
protected $forcehide = false;
|
||||
# Is the attribute modifiable
|
||||
protected $readonly = false;
|
||||
# LDAP attribute type MUST/MAY
|
||||
protected $ldaptype = null;
|
||||
# Attribute property type (eg password, select, multiselect)
|
||||
protected $type = '';
|
||||
# Attribute value to keep unique
|
||||
protected $unique = false;
|
||||
|
||||
# Display parameters
|
||||
protected $display = '';
|
||||
protected $icon = '';
|
||||
protected $hint = '';
|
||||
# Helper details
|
||||
protected $helper = array();
|
||||
protected $helpervalue = array();
|
||||
# Onchange details
|
||||
protected $onchange = array();
|
||||
# Show spacer after this attribute is rendered
|
||||
protected $spacer = false;
|
||||
protected $verify = false;
|
||||
|
||||
# Component size
|
||||
protected $size = 0;
|
||||
# Value max length
|
||||
protected $maxlength = 0;
|
||||
# Text Area sizings
|
||||
protected $cols = 0;
|
||||
protected $rows = 0;
|
||||
|
||||
# Public for sorting
|
||||
public $page = 1;
|
||||
public $order = 255;
|
||||
public $ordersort = 255;
|
||||
|
||||
# Schema Aliases for this attribute (stored in lowercase)
|
||||
protected $aliases = array();
|
||||
|
||||
# Configuration for automatically generated values
|
||||
protected $autovalue = array();
|
||||
protected $postvalue = array();
|
||||
*/
|
||||
|
||||
public function __construct(string $name,array $values)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->values = collect($values);
|
||||
$this->lang_tags = collect();
|
||||
$this->required_by = collect();
|
||||
$this->oldValues = collect($values);
|
||||
|
||||
// No need to load our schema for internal attributes
|
||||
if (! $this->is_internal)
|
||||
$this->schema = (new Server)->schema('attributetypes',$name);
|
||||
|
||||
/*
|
||||
# Should this attribute be hidden
|
||||
if ($server->isAttrHidden($this->name))
|
||||
$this->forcehide = true;
|
||||
|
||||
# Should this attribute value be read only
|
||||
if ($server->isAttrReadOnly($this->name))
|
||||
$this->readonly = true;
|
||||
|
||||
# Should this attribute value be unique
|
||||
if ($server->isAttrUnique($this->name))
|
||||
$this->unique = true;
|
||||
*/
|
||||
}
|
||||
|
||||
public function __get(string $key): mixed
|
||||
{
|
||||
return match ($key) {
|
||||
// List all the attributes
|
||||
'attributes' => $this->attributes(),
|
||||
// Can this attribute have more values
|
||||
'can_addvalues' => $this->schema && (! $this->schema->is_single_value) && ((! $this->max_values_count) || ($this->values->count() < $this->max_values_count)),
|
||||
// Schema attribute description
|
||||
'description' => $this->schema ? $this->schema->{$key} : NULL,
|
||||
// Attribute hints
|
||||
'hints' => $this->hints(),
|
||||
// Can this attribute be edited
|
||||
'is_editable' => $this->schema ? $this->schema->{$key} : NULL,
|
||||
// Is this an internal attribute
|
||||
'is_internal' => isset($this->{$key}) && $this->{$key},
|
||||
// Is this attribute the RDN
|
||||
'is_rdn' => $this->is_rdn,
|
||||
// We prefer the name as per the schema if it exists
|
||||
'name' => $this->schema ? $this->schema->{$key} : $this->{$key},
|
||||
// Attribute name in lower case
|
||||
'name_lc' => strtolower($this->name),
|
||||
// Old Values
|
||||
'old_values' => $this->oldValues,
|
||||
// Attribute values
|
||||
'values' => $this->values,
|
||||
|
||||
default => throw new \Exception('Unknown key:' . $key),
|
||||
};
|
||||
}
|
||||
|
||||
public function __set(string $key,mixed $values): void
|
||||
{
|
||||
switch ($key) {
|
||||
case 'value':
|
||||
$this->values = collect($values);
|
||||
break;
|
||||
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function addValue(string $value): void
|
||||
{
|
||||
$this->values->push($value);
|
||||
}
|
||||
|
||||
public function count(): int
|
||||
{
|
||||
return $this->values->count();
|
||||
}
|
||||
|
||||
public function offsetExists(mixed $offset): bool
|
||||
{
|
||||
return ! is_null($this->values->get($offset));
|
||||
}
|
||||
|
||||
public function offsetGet(mixed $offset): mixed
|
||||
{
|
||||
return $this->values->get($offset);
|
||||
}
|
||||
|
||||
public function offsetSet(mixed $offset, mixed $value): void
|
||||
{
|
||||
// We cannot set new values using array syntax
|
||||
}
|
||||
|
||||
public function offsetUnset(mixed $offset): void
|
||||
{
|
||||
// We cannot clear values using array syntax
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the hints about this attribute, ie: RDN, Required, etc
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function hints(): array
|
||||
{
|
||||
$result = collect();
|
||||
|
||||
// Is this Attribute an RDN
|
||||
if ($this->is_rdn)
|
||||
$result->put(__('rdn'),__('This attribute is required for the RDN'));
|
||||
|
||||
// If this attribute name is an alias for the schema attribute name
|
||||
// @todo
|
||||
|
||||
// objectClasses requiring this attribute
|
||||
// eg: $result->put('required','Required by objectClasses: a,b');
|
||||
if ($this->required_by->count())
|
||||
$result->put(__('required'),sprintf('%s: %s',__('Required Attribute by ObjectClass(es)'),$this->required_by->join(',')));
|
||||
|
||||
// This attribute has language tags
|
||||
if ($this->lang_tags->count())
|
||||
$result->put(__('language tags'),sprintf('%s: %d',__('This Attribute has Language Tags'),$this->lang_tags->count()));
|
||||
|
||||
return $result->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if this attribute has changes
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isDirty(): bool
|
||||
{
|
||||
if ($this->oldValues->count() !== $this->values->count())
|
||||
return TRUE;
|
||||
|
||||
return $this->values->diff($this->oldValues)->count() !== 0;
|
||||
}
|
||||
|
||||
public function oldValues(array $array): void
|
||||
{
|
||||
$this->oldValues = collect($array);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the attribute value
|
||||
*
|
||||
* @param bool $edit
|
||||
* @param bool $old
|
||||
* @param bool $new
|
||||
* @return View
|
||||
*/
|
||||
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE): View
|
||||
{
|
||||
return view('components.attribute')
|
||||
->with('o',$this)
|
||||
->with('edit',$edit)
|
||||
->with('old',$old)
|
||||
->with('new',$new);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the objectclasses that require this attribute
|
||||
*
|
||||
* @param Collection $oc
|
||||
* @return Collection
|
||||
*/
|
||||
public function required_by(Collection $oc): Collection
|
||||
{
|
||||
return $this->required_by = ($this->schema
|
||||
? $oc->intersect($this->schema->required_by_object_classes)
|
||||
: collect());
|
||||
}
|
||||
|
||||
/**
|
||||
* If this attribute has RFC3866 Language Tags, this will enable those values to be captured
|
||||
*
|
||||
* @param string $tag
|
||||
* @param array $value
|
||||
* @return void
|
||||
*/
|
||||
public function setLangTag(string $tag,array $value): void
|
||||
{
|
||||
$this->lang_tags->put($tag,$value);
|
||||
}
|
||||
|
||||
public function setRDN(): void
|
||||
{
|
||||
$this->is_rdn = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the attribute.
|
||||
*
|
||||
* @param boolean $lower - Return the attribute in normal or lower case (default lower)
|
||||
* @param boolean $real - Return the real attribute name (with ;binary, or just the name)
|
||||
* @return string Attribute name
|
||||
*
|
||||
public function getName($lower=true,$real=false) {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs,$this->name);
|
||||
|
||||
if ($real)
|
||||
return $lower ? strtolower($this->name) : $this->name;
|
||||
else
|
||||
return $lower ? strtolower($this->real_attr_name()) : $this->real_attr_name();
|
||||
}
|
||||
|
||||
public function getValues() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->values);
|
||||
|
||||
return $this->values;
|
||||
}
|
||||
|
||||
public function getOldValues() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->oldvalues);
|
||||
|
||||
return $this->oldvalues;
|
||||
}
|
||||
|
||||
public function getValueCount() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs,$this->values);
|
||||
|
||||
return count($this->values);
|
||||
}
|
||||
|
||||
public function getSource() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->source);
|
||||
|
||||
return $this->source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Autovalue is called after the attribute is initialised, and thus the values from the ldap server will be set.
|
||||
*
|
||||
public function autoValue($new_val) {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs);
|
||||
|
||||
if ($this->values)
|
||||
return;
|
||||
|
||||
$this->values = $new_val;
|
||||
}
|
||||
|
||||
public function initValue($new_val) {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs);
|
||||
|
||||
if ($this->values || $this->oldvalues) {
|
||||
debug_dump(array('new_val'=>$new_val,'this'=>$this));
|
||||
debug_dump_backtrace('new and/or old values are set',1);
|
||||
}
|
||||
|
||||
$this->values = $new_val;
|
||||
}
|
||||
|
||||
public function clearValue() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs);
|
||||
|
||||
$this->values = array();
|
||||
}
|
||||
|
||||
public function setOldValue($val) {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs);
|
||||
|
||||
$this->oldvalues = $val;
|
||||
}
|
||||
|
||||
public function setValue($new_val) {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs);
|
||||
|
||||
if ($this->values) {
|
||||
if ($this->values == $new_val)
|
||||
return;
|
||||
|
||||
if ($this->oldvalues) {
|
||||
debug_dump($this);
|
||||
debug_dump_backtrace('old values are set',1);
|
||||
} else
|
||||
$this->oldvalues = $this->values;
|
||||
}
|
||||
|
||||
if ($new_val == $this->values)
|
||||
return;
|
||||
|
||||
$this->values = $new_val;
|
||||
$this->justModified();
|
||||
}
|
||||
|
||||
public function addValue($new_val,$i=-1) {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs);
|
||||
|
||||
if ($i < 0)
|
||||
$i = $this->getValueCount();
|
||||
|
||||
$old_val = $this->getValue($i);
|
||||
if (is_null($old_val) || ($old_val != $new_val))
|
||||
$this->justModified();
|
||||
|
||||
$this->values[$i] = $new_val;
|
||||
}
|
||||
|
||||
public function delValue($i=-1) {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs);
|
||||
|
||||
if ($i < 0)
|
||||
$this->setValue(array());
|
||||
|
||||
if (! $this->hasBeenModified())
|
||||
$this->oldvalues = $this->values;
|
||||
|
||||
if (isset($this->values[$i])) {
|
||||
unset($this->values[$i]);
|
||||
$this->values = array_values($this->values);
|
||||
$this->justModified();
|
||||
}
|
||||
}
|
||||
|
||||
public function justModified() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs);
|
||||
|
||||
$this->modified = true;
|
||||
}
|
||||
|
||||
public function hasBeenModified() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->modified);
|
||||
|
||||
return $this->modified;
|
||||
}
|
||||
|
||||
public function isForceDelete() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->forcedelete);
|
||||
|
||||
return $this->forcedelete;
|
||||
}
|
||||
|
||||
public function setForceDelete() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs);
|
||||
|
||||
$this->forcedelete = true;
|
||||
$this->oldvalues = $this->values;
|
||||
$this->values = array();
|
||||
$this->justModified();
|
||||
}
|
||||
|
||||
public function isRequired() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs);
|
||||
|
||||
if ($this->getMinValueCount() > 0)
|
||||
return true;
|
||||
elseif ($this->ldaptype == 'must')
|
||||
return true;
|
||||
elseif ($this->isRDN())
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
public function isMay() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs);
|
||||
|
||||
if (($this->ldaptype == 'may') && ! $this->isRequired())
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
public function setType($type) {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs);
|
||||
|
||||
$this->type = strtolower($type);
|
||||
}
|
||||
|
||||
public function getType() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->type);
|
||||
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
public function setLDAPtype($type) {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs);
|
||||
|
||||
$this->ldaptype = strtolower($type);
|
||||
}
|
||||
|
||||
public function getLDAPtype() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->ldaptype);
|
||||
|
||||
return $this->ldaptype;
|
||||
}
|
||||
|
||||
public function setProperties($properties) {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs);
|
||||
|
||||
foreach ($properties as $index => $value) {
|
||||
if ($index == 'maxvalnb') {
|
||||
$this->setMaxValueCount($value);
|
||||
continue;
|
||||
|
||||
} elseif ($index == 'minvalnb') {
|
||||
$this->setMinValueCount($value);
|
||||
continue;
|
||||
|
||||
} elseif ($index == 'maxlength') {
|
||||
$this->setMinValueCount($value);
|
||||
continue;
|
||||
|
||||
} elseif ($index == 'hidden') {
|
||||
$this->visible = $value;
|
||||
continue;
|
||||
|
||||
} elseif (in_array($index,array('cols','rows'))) {
|
||||
# @todo To be implemented
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isset($this->$index))
|
||||
$this->$index = $value;
|
||||
else {
|
||||
debug_dump($this);
|
||||
debug_dump_backtrace(sprintf('Unknown property (%s) with value (%s) for (%s)',$index,$value,$this->getName()),1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function setRequired() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs);
|
||||
|
||||
if ($this->getMinValueCount() <= 0)
|
||||
$this->setMinValueCount(1);
|
||||
}
|
||||
|
||||
public function setOptional() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs);
|
||||
|
||||
$this->setMinValueCount(0);
|
||||
}
|
||||
|
||||
public function isReadOnly() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->readonly);
|
||||
|
||||
return $this->readonly;
|
||||
}
|
||||
|
||||
public function setReadOnly() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs);
|
||||
|
||||
$this->readonly = true;
|
||||
}
|
||||
|
||||
public function isMultiple() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function isVisible() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs);
|
||||
|
||||
return $this->visible && (! $this->forcehide);
|
||||
}
|
||||
|
||||
public function hide() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs);
|
||||
|
||||
$this->visible = false;
|
||||
}
|
||||
|
||||
public function show() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs);
|
||||
|
||||
$this->visible = true;
|
||||
}
|
||||
|
||||
public function haveFriendlyName() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs);
|
||||
|
||||
return $_SESSION[APPCONFIG]->haveFriendlyName($this);
|
||||
}
|
||||
|
||||
public function getFriendlyName() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->display);
|
||||
|
||||
if ($this->display)
|
||||
return $this->display;
|
||||
else
|
||||
return $_SESSION[APPCONFIG]->getFriendlyName($this);
|
||||
}
|
||||
|
||||
public function setDescription($description) {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs);
|
||||
|
||||
$this->description = $description;
|
||||
}
|
||||
|
||||
public function getDescription() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->description);
|
||||
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
public function setIcon($icon) {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs);
|
||||
|
||||
$this->icon = $icon;
|
||||
}
|
||||
|
||||
public function getIcon() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->icon);
|
||||
|
||||
return $this->icon ? sprintf('%s/%s',IMGDIR,$this->icon) : '';
|
||||
}
|
||||
|
||||
public function getHint() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->hint);
|
||||
|
||||
return $this->hint;
|
||||
}
|
||||
|
||||
public function setHint($hint) {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs);
|
||||
|
||||
$this->hint = $hint;
|
||||
}
|
||||
|
||||
public function getMaxLength() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->maxlength);
|
||||
|
||||
return $this->maxlength;
|
||||
}
|
||||
|
||||
public function setMaxLength($maxlength) {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs);
|
||||
|
||||
$this->maxlength = $maxlength;
|
||||
}
|
||||
|
||||
public function getSize() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->size);
|
||||
|
||||
return $this->size;
|
||||
}
|
||||
|
||||
public function setSize($size) {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs);
|
||||
|
||||
$this->size = $size;
|
||||
}
|
||||
|
||||
public function getSpacer() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->spacer);
|
||||
|
||||
return $this->spacer;
|
||||
}
|
||||
|
||||
public function getPage() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->page);
|
||||
|
||||
return $this->page;
|
||||
}
|
||||
public function setPage($page) {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs);
|
||||
|
||||
$this->page = $page;
|
||||
}
|
||||
|
||||
public function getOnChange() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->onchange);
|
||||
|
||||
return $this->onchange;
|
||||
}
|
||||
|
||||
public function getHelper() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->helper);
|
||||
|
||||
return $this->helper;
|
||||
}
|
||||
|
||||
public function getHelperValue() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->helpervalue);
|
||||
|
||||
return $this->helpervalue;
|
||||
}
|
||||
|
||||
public function getVerify() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->verify);
|
||||
|
||||
return $this->verify;
|
||||
}
|
||||
|
||||
/**
|
||||
* Capture all the LDAP details we are interested in
|
||||
*
|
||||
* @param sattr Schema Attribute
|
||||
*
|
||||
private function setLDAPdetails($sattr) {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs);
|
||||
|
||||
# By default, set this as a MAY attribute, later processing should make it a MUST attribute if it is.
|
||||
if (! $this->ldaptype)
|
||||
$this->ldaptype = 'may';
|
||||
|
||||
# Store our Aliases
|
||||
foreach ($sattr->getAliases() as $alias)
|
||||
array_push($this->aliases,strtolower($alias));
|
||||
|
||||
if ($sattr->getIsSingleValue())
|
||||
$this->setMaxValueCount(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of aliases for this Attribute (as defined by the schema)
|
||||
* This list will be lowercase.
|
||||
*
|
||||
public function getAliases() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->aliases);
|
||||
|
||||
return $this->aliases;
|
||||
}
|
||||
|
||||
public function getAutoValue() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->autovalue);
|
||||
|
||||
return $this->autovalue;
|
||||
}
|
||||
|
||||
public function getPostValue() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->postvalue);
|
||||
|
||||
return $this->postvalue;
|
||||
}
|
||||
|
||||
public function setPostValue($postvalue) {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs);
|
||||
|
||||
$this->postvalue = $postvalue;
|
||||
}
|
||||
|
||||
public function setXML($values) {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs);
|
||||
|
||||
# Mostly all the time, this should be an array
|
||||
if (is_array($values))
|
||||
foreach ($values as $index => $value)
|
||||
switch ($index) {
|
||||
# Helpers should be accompanied with a <post> attribute.
|
||||
case 'helper':
|
||||
if (! isset($values['post']) && ! $_SESSION[APPCONFIG]->getValue('appearance','hide_template_warning'))
|
||||
system_message(array(
|
||||
'title'=>sprintf('%s [<i>%s</i>]',_('Missing [post] setting in XML file'),$index),
|
||||
'body'=>_('[helper] needs an accompanying [post] action.'),
|
||||
'type'=>'warn'));
|
||||
|
||||
if (isset($value['value']) && ! is_array($value['value']) && preg_match('/^=php\.(\w+)\((.*)\)$/',$value['value'],$matches)) {
|
||||
$this->helpervalue['function'] = $matches[1];
|
||||
$this->helpervalue['args'] = $matches[2];
|
||||
|
||||
unset ($value['value']);
|
||||
}
|
||||
|
||||
foreach ($value as $i => $detail) {
|
||||
if (! in_array($i,array('default','display','id','value'))) {
|
||||
if (! $_SESSION[APPCONFIG]->getValue('appearance','hide_template_warning'))
|
||||
system_message(array(
|
||||
'title'=>sprintf('%s [<i>%s</i>]',_('Unknown XML setting'),$i),
|
||||
'body'=>sprintf('%s <small>[%s]</small>',_('Unknown XML type setting for helper will be ignored.'),$detail),
|
||||
'type'=>'warn'));
|
||||
|
||||
unset($value[$i]);
|
||||
}
|
||||
}
|
||||
|
||||
$this->$index = $value;
|
||||
|
||||
break;
|
||||
|
||||
case 'hidden': $value ? $this->visible = false : $this->visible = true;
|
||||
break;
|
||||
|
||||
case 'spacer': $value ? $this->$index = true : $this->$index = false;
|
||||
break;
|
||||
|
||||
# Essentially, we ignore type, it is used to select an Attribute type in the Factory. But we'll generated a warning if there is an unknown type.
|
||||
case 'type':
|
||||
if (! in_array($value,array('password','multiselect','select','textarea')) && ! $_SESSION[APPCONFIG]->getValue('appearance','hide_template_warning'))
|
||||
system_message(array(
|
||||
'title'=>sprintf('%s [<i>%s</i>]',_('Unknown XML setting'),$index),
|
||||
'body'=>sprintf('%s <small>[%s]</small>',_('Unknown XML type setting will be ignored.'),$value),
|
||||
'type'=>'warn'));
|
||||
|
||||
break;
|
||||
|
||||
case 'post':
|
||||
if (preg_match('/^=php\.(\w+)\((.*)\)$/',$value,$matches)) {
|
||||
$this->postvalue['function'] = $matches[1];
|
||||
$this->postvalue['args'] = $matches[2];
|
||||
|
||||
} else
|
||||
if (! $_SESSION[APPCONFIG]->getValue('appearance','hide_template_warning'))
|
||||
system_message(array(
|
||||
'title'=>sprintf('%s [<i>%s</i>]',_('Unknown XML setting'),$index),
|
||||
'body'=>sprintf('%s <small>[%s]</small>',_('Unknown XML type setting will be ignored.'),$value),
|
||||
'type'=>'warn'));
|
||||
|
||||
case 'value':
|
||||
if (is_array($value))
|
||||
foreach ($value as $x => $y) {
|
||||
if (! $this->haveMoreValues()) {
|
||||
system_message(array(
|
||||
'title'=>_('Automatically removed attribute values from template'),
|
||||
'body'=>sprintf('%s <small>[%s]</small>',_('Template defines more values than can be accepted by attribute.'),$this->getName(true)),
|
||||
'type'=>'warn'));
|
||||
|
||||
$this->clearValue();
|
||||
|
||||
break;
|
||||
|
||||
} else
|
||||
$this->addValue($x,$y);
|
||||
}
|
||||
|
||||
else
|
||||
# Check to see if the value is auto generated.
|
||||
if (preg_match('/^=php\.(\w+)\((.*)\)$/',$value,$matches)) {
|
||||
$this->autovalue['function'] = $matches[1];
|
||||
$this->autovalue['args'] = $matches[2];
|
||||
|
||||
# We'll add a hint too
|
||||
if (! $this->hint)
|
||||
$this->hint = _('Automatically determined');
|
||||
|
||||
} else
|
||||
$this->addValue($value);
|
||||
|
||||
break;
|
||||
|
||||
# Queries
|
||||
case 'ordersort':
|
||||
|
||||
# Creation/Editing Templates
|
||||
case 'cols':
|
||||
case 'default':
|
||||
case 'display':
|
||||
case 'hint':
|
||||
case 'icon':
|
||||
case 'maxlength':
|
||||
case 'onchange':
|
||||
case 'order':
|
||||
case 'page':
|
||||
case 'readonly':
|
||||
case 'rows':
|
||||
case 'size':
|
||||
case 'values':
|
||||
case 'verify': $this->$index = $value;
|
||||
break;
|
||||
|
||||
case 'max':
|
||||
if ($this->getMaxValueCount() == -1)
|
||||
$this->setMaxValueCount($value);
|
||||
|
||||
default:
|
||||
if (! $_SESSION[APPCONFIG]->getValue('appearance','hide_template_warning'))
|
||||
system_message(array(
|
||||
'title'=>sprintf('%s [<i>%s</i>]',_('Unknown XML setting'),$index),
|
||||
'body'=>sprintf('%s <small>[%s]</small>',_('Unknown attribute setting will be ignored.'),serialize($value)),
|
||||
'type'=>'warn'));
|
||||
}
|
||||
|
||||
elseif (is_string($values) && (strlen($values) > 0))
|
||||
$this->values = array($values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the values removed in an attribute.
|
||||
*
|
||||
public function getRemovedValues() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs);
|
||||
|
||||
return array_diff($this->getOldValues(),$this->getValues());
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the values removed in an attribute.
|
||||
*
|
||||
public function getAddedValues() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs);
|
||||
|
||||
return array_diff($this->getValues(),$this->getOldValues());
|
||||
}
|
||||
|
||||
/**
|
||||
* Prunes off anything after the ";" in an attr name. This is useful for
|
||||
* attributes that may have ";binary" appended to their names. With
|
||||
* real_attr_name(), you can more easily fetch these attributes' schema
|
||||
* with their "real" attribute name.
|
||||
*
|
||||
* @param string $attr_name The name of the attribute to examine.
|
||||
* @return string
|
||||
*
|
||||
private function real_attr_name() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->name);
|
||||
|
||||
return preg_replace('/;.*$/U','',$this->name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this attribute need supporting JS
|
||||
*
|
||||
public function needJS($type=null) {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs);
|
||||
|
||||
if (is_null($type)) {
|
||||
foreach (array('focus','blur','validate') as $type)
|
||||
if ($this->needJS($type))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
||||
} elseif ($type == 'focus') {
|
||||
# We dont have any focus javascript routines.
|
||||
return false;
|
||||
|
||||
} elseif ($type == 'blur') {
|
||||
if ($this->onchange || $this->isRequired())
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
|
||||
} elseif ($type == 'validate') {
|
||||
if ($this->isRequired())
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
|
||||
} else
|
||||
debug_dump_backtrace(sprintf('Unknown JS request %s',$type),1);
|
||||
}
|
||||
*/
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\LDAP\Attribute;
|
||||
|
||||
use App\Classes\LDAP\Attribute;
|
||||
|
||||
/**
|
||||
* Represents an attribute whose values are binary
|
||||
*/
|
||||
class Binary extends Attribute
|
||||
{
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\LDAP\Attribute\Binary;
|
||||
|
||||
use Illuminate\Contracts\View\View;
|
||||
|
||||
use App\Classes\LDAP\Attribute\Binary;
|
||||
use App\Traits\MD5Updates;
|
||||
|
||||
/**
|
||||
* Represents an JpegPhoto Attribute
|
||||
*/
|
||||
final class JpegPhoto extends Binary
|
||||
{
|
||||
use MD5Updates;
|
||||
|
||||
public function __construct(string $name,array $values)
|
||||
{
|
||||
parent::__construct($name,$values);
|
||||
|
||||
$this->internal = FALSE;
|
||||
}
|
||||
|
||||
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE): View
|
||||
{
|
||||
return view('components.attribute.binary.jpegphoto')
|
||||
->with('o',$this)
|
||||
->with('edit',$edit)
|
||||
->with('old',$old)
|
||||
->with('new',$new)
|
||||
->with('f',new \finfo);
|
||||
}
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\LDAP\Attribute;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
use App\Classes\LDAP\Attribute;
|
||||
|
||||
/**
|
||||
* This factory is used to return LDAP attributes as an object
|
||||
*
|
||||
* If there is no specific Attribute defined, then the default Attribute::class is return
|
||||
*/
|
||||
class Factory
|
||||
{
|
||||
private const LOGKEY = 'LAf';
|
||||
|
||||
/**
|
||||
* Map of attributes to appropriate class
|
||||
*/
|
||||
public const map = [
|
||||
'createtimestamp' => Internal\Timestamp::class,
|
||||
'creatorsname' => Internal\DN::class,
|
||||
'contextcsn' => Internal\CSN::class,
|
||||
'entrycsn' => Internal\CSN::class,
|
||||
'entrydn' => Internal\DN::class,
|
||||
'entryuuid' => Internal\UUID::class,
|
||||
'gidnumber' => GidNumber::class,
|
||||
'hassubordinates' => Internal\HasSubordinates::class,
|
||||
'jpegphoto' => Binary\JpegPhoto::class,
|
||||
'modifytimestamp' => Internal\Timestamp::class,
|
||||
'modifiersname' => Internal\DN::class,
|
||||
'objectclass' => ObjectClass::class,
|
||||
'structuralobjectclass' => Internal\StructuralObjectClass::class,
|
||||
'subschemasubentry' => Internal\SubschemaSubentry::class,
|
||||
'supportedcontrol' => Schema\OID::class,
|
||||
'supportedextension' => Schema\OID::class,
|
||||
'supportedfeatures' => Schema\OID::class,
|
||||
'supportedsaslmechanisms' => Schema\Mechanisms::class,
|
||||
'userpassword' => Password::class,
|
||||
];
|
||||
|
||||
/**
|
||||
* Create the new Object for an attribute
|
||||
*
|
||||
* @param string $attribute
|
||||
* @param array $values
|
||||
* @return Attribute
|
||||
*/
|
||||
public static function create(string $attribute,array $values): Attribute
|
||||
{
|
||||
$class = Arr::get(self::map,strtolower($attribute),Attribute::class);
|
||||
Log::debug(sprintf('%s:Creating LDAP Attribute [%s] as [%s]',static::LOGKEY,$attribute,$class));
|
||||
|
||||
return new $class($attribute,$values);
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\LDAP\Attribute;
|
||||
|
||||
use App\Classes\LDAP\Attribute;
|
||||
|
||||
/**
|
||||
* Represents an GidNumber Attribute
|
||||
*/
|
||||
final class GidNumber extends Attribute
|
||||
{
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\LDAP\Attribute;
|
||||
|
||||
use Illuminate\Contracts\View\View;
|
||||
|
||||
use App\Classes\LDAP\Attribute;
|
||||
|
||||
/**
|
||||
* Represents an attribute whose values are internal
|
||||
*/
|
||||
abstract class Internal extends Attribute
|
||||
{
|
||||
protected bool $is_internal = TRUE;
|
||||
|
||||
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE): View
|
||||
{
|
||||
// @note Internal attributes cannot be edited
|
||||
return view('components.attribute.internal')
|
||||
->with('o',$this);
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\LDAP\Attribute\Internal;
|
||||
|
||||
use App\Classes\LDAP\Attribute\Internal;
|
||||
|
||||
/**
|
||||
* Represents an CSN Attribute
|
||||
*/
|
||||
final class CSN extends Internal
|
||||
{
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\LDAP\Attribute\Internal;
|
||||
|
||||
use App\Classes\LDAP\Attribute\Internal;
|
||||
|
||||
/**
|
||||
* Represents an DN Attribute
|
||||
*/
|
||||
final class DN extends Internal
|
||||
{
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\LDAP\Attribute\Internal;
|
||||
|
||||
use App\Classes\LDAP\Attribute\Internal;
|
||||
|
||||
/**
|
||||
* Represents an HasSubordinates Attribute
|
||||
*/
|
||||
final class HasSubordinates extends Internal
|
||||
{
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\LDAP\Attribute\Internal;
|
||||
|
||||
use App\Classes\LDAP\Attribute\Internal;
|
||||
|
||||
/**
|
||||
* Represents an StructuralObjectClass Attribute
|
||||
*/
|
||||
final class StructuralObjectClass extends Internal
|
||||
{
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\LDAP\Attribute\Internal;
|
||||
|
||||
use App\Classes\LDAP\Attribute\Internal;
|
||||
|
||||
/**
|
||||
* Represents an SubschemaSubentry Attribute
|
||||
*/
|
||||
final class SubschemaSubentry extends Internal
|
||||
{
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\LDAP\Attribute\Internal;
|
||||
|
||||
use Illuminate\Contracts\View\View;
|
||||
|
||||
use App\Classes\LDAP\Attribute\Internal;
|
||||
|
||||
/**
|
||||
* Represents an attribute whose values are timestamps
|
||||
*/
|
||||
final class Timestamp extends Internal
|
||||
{
|
||||
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE): View
|
||||
{
|
||||
// @note Internal attributes cannot be edited
|
||||
return view('components.attribute.internal.timestamp')
|
||||
->with('o',$this);
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\LDAP\Attribute\Internal;
|
||||
|
||||
use App\Classes\LDAP\Attribute\Internal;
|
||||
|
||||
/**
|
||||
* Represents an UUID Attribute
|
||||
*/
|
||||
final class UUID extends Internal
|
||||
{
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\LDAP\Attribute;
|
||||
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
use App\Classes\LDAP\{Attribute,Server};
|
||||
|
||||
/**
|
||||
* Represents an ObjectClass Attribute
|
||||
*/
|
||||
final class ObjectClass extends Attribute
|
||||
{
|
||||
// Which of the values is the structural object class
|
||||
protected Collection $structural;
|
||||
|
||||
public function __construct(string $name,array $values)
|
||||
{
|
||||
parent::__construct($name,$values);
|
||||
|
||||
$this->structural = collect();
|
||||
|
||||
// Determine which of the values is the structural objectclass
|
||||
foreach ($values as $oc) {
|
||||
if ((new Server)->schema('objectclasses',$oc)->isStructural())
|
||||
$this->structural->push($oc);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Is a specific value the structural objectclass
|
||||
*
|
||||
* @param string $value
|
||||
* @return bool
|
||||
*/
|
||||
public function isStructural(string $value): bool
|
||||
{
|
||||
return $this->structural->search($value) !== FALSE;
|
||||
}
|
||||
|
||||
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE): View
|
||||
{
|
||||
return view('components.attribute.objectclass')
|
||||
->with('o',$this)
|
||||
->with('edit',$edit)
|
||||
->with('old',$old)
|
||||
->with('new',$new);
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\LDAP\Attribute;
|
||||
|
||||
use Illuminate\Contracts\View\View;
|
||||
|
||||
use App\Classes\LDAP\Attribute;
|
||||
use App\Traits\MD5Updates;
|
||||
|
||||
/**
|
||||
* Represents an attribute whose values are passwords
|
||||
*/
|
||||
final class Password extends Attribute
|
||||
{
|
||||
use MD5Updates;
|
||||
|
||||
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE): View
|
||||
{
|
||||
return view('components.attribute.password')
|
||||
->with('o',$this)
|
||||
->with('edit',$edit)
|
||||
->with('old',$old)
|
||||
->with('new',$new);
|
||||
}
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\LDAP\Attribute;
|
||||
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
use App\Classes\LDAP\Attribute;
|
||||
|
||||
/**
|
||||
* Represents an attribute whose values are schema related
|
||||
*/
|
||||
abstract class Schema extends Attribute
|
||||
{
|
||||
protected bool $internal = TRUE;
|
||||
|
||||
protected static function _get(string $filename,string $string,string $key): ?string
|
||||
{
|
||||
$array = Cache::remember($filename,86400,function() use ($filename) {
|
||||
try {
|
||||
$f = fopen($filename,'r');
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
$result = collect();
|
||||
|
||||
while (! feof($f)) {
|
||||
$line = trim(fgets($f));
|
||||
|
||||
if (! $line OR preg_match('/^#/',$line))
|
||||
continue;
|
||||
|
||||
$fields = explode(':',$line);
|
||||
|
||||
$result->put($x=Arr::get($fields,0),[
|
||||
'title'=>Arr::get($fields,1,$x),
|
||||
'ref'=>Arr::get($fields,2),
|
||||
'desc'=>Arr::get($fields,3,__('No description available, can you help with one?')),
|
||||
]);
|
||||
}
|
||||
fclose($f);
|
||||
|
||||
return $result;
|
||||
});
|
||||
|
||||
return Arr::get(($array ? $array->get($string) : []),$key);
|
||||
}
|
||||
|
||||
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE): View
|
||||
{
|
||||
// @note Schema attributes cannot be edited
|
||||
return view('components.attribute.internal')
|
||||
->with('o',$this);
|
||||
}
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\LDAP\Attribute\Schema;
|
||||
|
||||
use Illuminate\Contracts\View\View;
|
||||
|
||||
use App\Classes\LDAP\Attribute\Schema;
|
||||
|
||||
/**
|
||||
* Represents a Mechanisms Attribute
|
||||
*/
|
||||
final class Mechanisms extends Schema
|
||||
{
|
||||
/**
|
||||
* Given an SASL Mechanism name, returns a verbose description of the Mechanism.
|
||||
* This function parses ldap_supported_saslmechanisms.txt and looks up the specified
|
||||
* Mechanism, and returns the verbose message defined in that file.
|
||||
*
|
||||
* <code>
|
||||
* "SCRAM-SHA-1" => array:3 [▼
|
||||
* "title" => "Salted Challenge Response Authentication Mechanism (SCRAM) SHA1"
|
||||
* "ref" => "RFC 5802"
|
||||
* "desc" => "This specification describes a family of authentication mechanisms called the Salted Challenge Response Authentication Mechanism (SCRAM) which addresses the req ▶"
|
||||
* ]
|
||||
* </code>
|
||||
*
|
||||
* @param string $string The SASL Mechanism (ie, "SCRAM-SHA-1") of interest.
|
||||
* @param string $key The title|ref|desc to return
|
||||
* @return string|NULL
|
||||
*/
|
||||
public static function get(string $string,string $key): ?string
|
||||
{
|
||||
return parent::_get(config_path('ldap_supported_saslmechanisms.txt'),$string,$key);
|
||||
}
|
||||
|
||||
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE): View
|
||||
{
|
||||
// @note Schema attributes cannot be edited
|
||||
return view('components.attribute.schema.mechanisms')
|
||||
->with('o',$this);
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\LDAP\Attribute\Schema;
|
||||
|
||||
use Illuminate\Contracts\View\View;
|
||||
|
||||
use App\Classes\LDAP\Attribute\Schema;
|
||||
|
||||
/**
|
||||
* Represents an OID Attribute
|
||||
*/
|
||||
final class OID extends Schema
|
||||
{
|
||||
/**
|
||||
* Given an LDAP OID number, returns a verbose description of the OID.
|
||||
* This function parses ldap_supported_oids.txt and looks up the specified
|
||||
* OID, and returns the verbose message defined in that file.
|
||||
*
|
||||
* <code>
|
||||
* "1.3.6.1.4.1.4203.1.5.1" => array:3 [
|
||||
* [title] => All Operational Attribute
|
||||
* [ref] => RFC 3673
|
||||
* [desc] => An LDAP extension which clients may use to request the return of all operational attributes.
|
||||
* ]
|
||||
* </code>
|
||||
*
|
||||
* @param string $string The OID number (ie, "1.3.6.1.4.1.4203.1.5.1") of the OID of interest.
|
||||
* @param string $key The title|ref|desc to return
|
||||
* @return string|null
|
||||
* @testedby TranslateOidTest::testRootDSE()
|
||||
*/
|
||||
public static function get(string $string,string $key): ?string
|
||||
{
|
||||
return parent::_get(config_path('ldap_supported_oids.txt'),$string,$key);
|
||||
}
|
||||
|
||||
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE): View
|
||||
{
|
||||
// @note Schema attributes cannot be edited
|
||||
return view('components.attribute.schema.oid')
|
||||
->with('o',$this);
|
||||
}
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\LDAP;
|
||||
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use LdapRecord\Query\Collection;
|
||||
|
||||
/**
|
||||
* Export Class
|
||||
*
|
||||
* This abstract classes provides all the common methods and variables for the
|
||||
* export classes.
|
||||
*/
|
||||
abstract class Export
|
||||
{
|
||||
// Line Break
|
||||
protected string $br = "\r\n";
|
||||
|
||||
// Item(s) being Exported
|
||||
protected Collection $items;
|
||||
|
||||
// Type of export
|
||||
protected const type = 'Unknown';
|
||||
|
||||
public function __construct(Collection $items)
|
||||
{
|
||||
$this->items = $items;
|
||||
}
|
||||
|
||||
abstract public function __toString(): string;
|
||||
|
||||
protected function header()
|
||||
{
|
||||
$output = '';
|
||||
|
||||
$output .= sprintf('# %s %s',__(static::type.' for'),($x=$this->items->first())).$this->br;
|
||||
$output .= sprintf('# %s: %s (%s)',
|
||||
__('Server'),
|
||||
$x->getConnection()->getConfiguration()->get('name'),
|
||||
$x->getConnection()->getLdapConnection()->getHost()).$this->br;
|
||||
//$output .= sprintf('# %s: %s',__('Search Scope'),$this->scope).$this->br;
|
||||
//$output .= sprintf('# %s: %s',__('Search Filter'),$this->entry->dn).$this->br;
|
||||
$output .= sprintf('# %s: %s',__('Total Entries'),$this->items->count()).$this->br;
|
||||
$output .= '#'.$this->br;
|
||||
$output .= sprintf('# %s %s (%s) on %s',__('Generated by'),config('app.name'),config('app.url'),date('F j, Y g:i a')).$this->br;
|
||||
$output .= sprintf('# %s %s',__('Exported by'),Auth::user() ?: 'Anonymous').$this->br;
|
||||
$output .= sprintf('# %s: %s',__('Version'),config('app.version')).$this->br;
|
||||
|
||||
$output .= $this->br;
|
||||
|
||||
return $output;
|
||||
}
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\LDAP\Export;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
use App\Classes\LDAP\Export;
|
||||
|
||||
/**
|
||||
* Export from LDAP using an LDIF format
|
||||
*/
|
||||
class LDIF extends Export
|
||||
{
|
||||
// The maximum length of the ldif line
|
||||
private int $line_length = 76;
|
||||
protected const type = 'LDIF Export';
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
$result = parent::header();
|
||||
$result .= 'version: 1';
|
||||
$result .= $this->br;
|
||||
|
||||
$c = 1;
|
||||
foreach ($this->items as $o) {
|
||||
if ($c > 1)
|
||||
$result .= $this->br;
|
||||
|
||||
$title = (string)$o;
|
||||
if (strlen($title) > $this->line_length)
|
||||
$title = Str::of($title)->limit($this->line_length-3-5,'...'.substr($title,-5));
|
||||
|
||||
$result .= sprintf('# %s %s: %s',__('Entry'),$c++,$title).$this->br;
|
||||
|
||||
// Display DN
|
||||
$result .= $this->multiLineDisplay(
|
||||
Str::isAscii($o)
|
||||
? sprintf('dn: %s',$o)
|
||||
: sprintf('dn:: %s',base64_encode($o))
|
||||
,$this->br);
|
||||
|
||||
// Display Attributes
|
||||
foreach ($o->getObjects() as $ao) {
|
||||
foreach ($ao->values as $value) {
|
||||
$result .= $this->multiLineDisplay(
|
||||
Str::isAscii($value)
|
||||
? sprintf('%s: %s',$ao->name,$value)
|
||||
: sprintf('%s:: %s',$ao->name,base64_encode($value))
|
||||
,$this->br);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to wrap LDIF lines
|
||||
*
|
||||
* @param string $str The line to be wrapped if needed.
|
||||
*/
|
||||
private function multiLineDisplay(string $str,string $br): string
|
||||
{
|
||||
$length_string = strlen($str);
|
||||
$length_max = $this->line_length;
|
||||
|
||||
$output = '';
|
||||
while ($length_string > $length_max) {
|
||||
$output .= substr($str,0,$length_max).$br;
|
||||
$str = ' '.substr($str,$length_max);
|
||||
$length_string = strlen($str);
|
||||
}
|
||||
|
||||
$output .= $str.$br;
|
||||
|
||||
return $output;
|
||||
}
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\LDAP;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
use App\Exceptions\Import\GeneralException;
|
||||
use App\Exceptions\Import\ObjectExistsException;
|
||||
use App\Ldap\Entry;
|
||||
|
||||
/**
|
||||
* Import Class
|
||||
*
|
||||
* This abstract classes provides all the common methods and variables for the
|
||||
* import classes.
|
||||
*/
|
||||
abstract class Import
|
||||
{
|
||||
// Valid LDIF commands
|
||||
protected const LDAP_IMPORT_ADD = 1;
|
||||
protected const LDAP_IMPORT_DELETE = 2;
|
||||
protected const LDAP_IMPORT_MODRDN = 3;
|
||||
protected const LDAP_IMPORT_MODDN = 4;
|
||||
protected const LDAP_IMPORT_MODIFY = 5;
|
||||
|
||||
protected const LDAP_ACTIONS = [
|
||||
'add' => self::LDAP_IMPORT_ADD,
|
||||
'delete' => self::LDAP_IMPORT_DELETE,
|
||||
'modrdn' => self::LDAP_IMPORT_MODRDN,
|
||||
'moddn' => self::LDAP_IMPORT_MODDN,
|
||||
'modify' => self::LDAP_IMPORT_MODIFY,
|
||||
];
|
||||
|
||||
// The import data to process
|
||||
protected string $input;
|
||||
// The attributes the server knows about
|
||||
protected Collection $server_attributes;
|
||||
|
||||
public function __construct(string $input) {
|
||||
$this->input = $input;
|
||||
$this->server_attributes = config('server')->schema('attributetypes');
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to commit an entry and return the result.
|
||||
*
|
||||
* @param Entry $o
|
||||
* @param int $action
|
||||
* @return Collection
|
||||
* @throws GeneralException
|
||||
* @throws ObjectExistsException
|
||||
*/
|
||||
final protected function commit(Entry $o,int $action): Collection
|
||||
{
|
||||
switch ($action) {
|
||||
case static::LDAP_IMPORT_ADD:
|
||||
try {
|
||||
$o->save();
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return collect([
|
||||
'dn'=>$o->getDN(),
|
||||
'result'=>sprintf('%d: %s (%s)',
|
||||
($x=$e->getDetailedError())->getErrorCode(),
|
||||
$x->getErrorMessage(),
|
||||
$x->getDiagnosticMessage(),
|
||||
)
|
||||
]);
|
||||
}
|
||||
|
||||
return collect(['dn'=>$o->getDN(),'result'=>__('Created')]);
|
||||
|
||||
default:
|
||||
throw new GeneralException('Unhandled action during commit: '.$action);
|
||||
}
|
||||
}
|
||||
|
||||
abstract public function process(): Collection;
|
||||
}
|
@ -1,233 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\LDAP\Import;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Nette\NotImplementedException;
|
||||
|
||||
use App\Classes\LDAP\Import;
|
||||
use App\Exceptions\Import\{GeneralException,VersionException};
|
||||
use App\Ldap\Entry;
|
||||
|
||||
/**
|
||||
* Import LDIF to LDAP using an LDIF format
|
||||
*
|
||||
* The LDIF spec is described by RFC2849
|
||||
* http://www.ietf.org/rfc/rfc2849.txt
|
||||
*/
|
||||
class LDIF extends Import
|
||||
{
|
||||
private const LOGKEY = 'ILF';
|
||||
|
||||
public function process(): Collection
|
||||
{
|
||||
$c = 0;
|
||||
$action = NULL;
|
||||
$attribute = NULL;
|
||||
$base64encoded = FALSE;
|
||||
$o = NULL;
|
||||
$value = '';
|
||||
$version = NULL;
|
||||
$result = collect();
|
||||
|
||||
// @todo When renaming DNs, the hotlink should point to the new entry on success, or the old entry on failure.
|
||||
foreach (preg_split('/(\r?\n|\r)/',$this->input) as $line) {
|
||||
$c++;
|
||||
Log::debug(sprintf('%s: LDIF Line [%s]',self::LOGKEY,$line));
|
||||
$line = trim($line);
|
||||
|
||||
// If the line starts with a comment, ignore it
|
||||
if (preg_match('/^#/',$line))
|
||||
continue;
|
||||
|
||||
// If we have a blank line, then that completes this command
|
||||
if (! $line) {
|
||||
if (! is_null($o)) {
|
||||
// Add the last attribute;
|
||||
$o->addAttribute($attribute,$base64encoded ? base64_decode($value) : $value);
|
||||
|
||||
Log::debug(sprintf('%s: Committing Entry [%s]',self::LOGKEY,$o->getDN()));
|
||||
|
||||
// Commit
|
||||
$result->push($this->commit($o,$action));
|
||||
$result->last()->put('line',$c);
|
||||
|
||||
$o = NULL;
|
||||
$action = NULL;
|
||||
$base64encoded = FALSE;
|
||||
$attribute = NULL;
|
||||
$value = '';
|
||||
|
||||
// Else its a blank line
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$m = [];
|
||||
preg_match('/^([a-zA-Z0-9;-]+)(:+)\s+(.*)$/',$line,$m);
|
||||
|
||||
switch ($x=Arr::get($m,1)) {
|
||||
case 'changetype':
|
||||
if ($m[2] !== ':')
|
||||
throw new GeneralException(sprintf('ChangeType cannot be base64 encoded set at [%d]. (line %d)',$version,$c));
|
||||
|
||||
switch ($m[3]) {
|
||||
// if (preg_match('/^changetype:[ ]*(delete|add|modrdn|moddn|modify)/i',$lines[0])) {
|
||||
default:
|
||||
throw new NotImplementedException(sprintf('Unknown change type [%s]? (line %d)',$m[3],$c));
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'version':
|
||||
if (! is_null($version))
|
||||
throw new VersionException(sprintf('Version has already been set at [%d]. (line %d)',$version,$c));
|
||||
|
||||
if ($m[2] !== ':')
|
||||
throw new VersionException(sprintf('Version cannot be base64 encoded set at [%d]. (line %d)',$version,$c));
|
||||
|
||||
$version = (int)$m[3];
|
||||
break;
|
||||
|
||||
// Treat it as an attribute
|
||||
default:
|
||||
// If $m is NULL, then this is the 2nd (or more) line of a base64 encoded value
|
||||
if (! $m) {
|
||||
$value .= $line;
|
||||
Log::debug(sprintf('%s: Attribute [%s] adding [%s] (%d)',self::LOGKEY,$attribute,$line,$c));
|
||||
|
||||
// add to last attr value
|
||||
continue 2;
|
||||
}
|
||||
|
||||
// We are ready to create the entry or add the attribute
|
||||
if ($attribute) {
|
||||
if ($attribute === 'dn') {
|
||||
if (! is_null($o))
|
||||
throw new GeneralException(sprintf('Previous Entry not complete? (line %d)',$c));
|
||||
|
||||
$dn = $base64encoded ? base64_decode($value) : $value;
|
||||
Log::debug(sprintf('%s: Creating new entry:',self::LOGKEY,$dn));
|
||||
//$o = Entry::find($dn);
|
||||
|
||||
// If it doesnt exist, we'll create it
|
||||
//if (! $o) {
|
||||
$o = new Entry;
|
||||
$o->setDn($dn);
|
||||
//}
|
||||
|
||||
$action = self::LDAP_IMPORT_ADD;
|
||||
|
||||
} else {
|
||||
Log::debug(sprintf('%s: Adding Attribute [%s] value [%s] (%d)',self::LOGKEY,$attribute,$value,$c));
|
||||
|
||||
if ($value)
|
||||
$o->addAttribute($attribute,$base64encoded ? base64_decode($value) : $value);
|
||||
else
|
||||
throw new GeneralException(sprintf('Attribute has no value [%s] (line %d)',$attribute,$c));
|
||||
}
|
||||
}
|
||||
|
||||
// Start of a new attribute
|
||||
$base64encoded = ($m[2] === '::');
|
||||
// @todo Need to parse attributes with ';' options
|
||||
$attribute = $m[1];
|
||||
$value = $m[3];
|
||||
|
||||
Log::debug(sprintf('%s: New Attribute [%s] with [%s] (%d)',self::LOGKEY,$attribute,$value,$c));
|
||||
}
|
||||
|
||||
if ($version !== 1)
|
||||
throw new VersionException('LDIF import cannot handle version: '.($version ?: __('NOT DEFINED')));
|
||||
}
|
||||
|
||||
// We may still have a pending action
|
||||
if ($action) {
|
||||
// Add the last attribute;
|
||||
$o->addAttribute($attribute,$base64encoded ? base64_decode($value) : $value);
|
||||
|
||||
Log::debug(sprintf('%s: Committing Entry [%s]',self::LOGKEY,$o->getDN()));
|
||||
|
||||
// Commit
|
||||
$result->push($this->commit($o,$action));
|
||||
$result->last()->put('line',$c);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function readEntry() {
|
||||
static $haveVersion = false;
|
||||
|
||||
if ($lines = $this->nextLines()) {
|
||||
|
||||
$server = $this->getServer();
|
||||
|
||||
# The first line should be the DN
|
||||
if (preg_match('/^dn:/',$lines[0])) {
|
||||
list($text,$dn) = $this->getAttrValue(array_shift($lines));
|
||||
|
||||
# The second line should be our changetype
|
||||
if (preg_match('/^changetype:[ ]*(delete|add|modrdn|moddn|modify)/i',$lines[0])) {
|
||||
$attrvalue = $this->getAttrValue($lines[0]);
|
||||
$changetype = $attrvalue[1];
|
||||
array_shift($lines);
|
||||
|
||||
} else
|
||||
$changetype = 'add';
|
||||
|
||||
$this->template = new Template($this->server_id,null,null,$changetype);
|
||||
|
||||
switch ($changetype) {
|
||||
case 'add':
|
||||
$rdn = get_rdn($dn);
|
||||
$container = $server->getContainer($dn);
|
||||
|
||||
$this->template->setContainer($container);
|
||||
$this->template->accept();
|
||||
|
||||
$this->getAddDetails($lines);
|
||||
$this->template->setRDNAttributes($rdn);
|
||||
|
||||
return $this->template;
|
||||
|
||||
break;
|
||||
|
||||
case 'modify':
|
||||
if (! $server->dnExists($dn))
|
||||
return $this->error(sprintf('%s %s',_('DN does not exist'),$dn),$lines);
|
||||
|
||||
$this->template->setDN($dn);
|
||||
$this->template->accept(false,true);
|
||||
|
||||
return $this->getModifyDetails($lines);
|
||||
|
||||
break;
|
||||
|
||||
case 'moddn':
|
||||
case 'modrdn':
|
||||
if (! $server->dnExists($dn))
|
||||
return $this->error(sprintf('%s %s',_('DN does not exist'),$dn),$lines);
|
||||
|
||||
$this->template->setDN($dn);
|
||||
$this->template->accept();
|
||||
|
||||
return $this->getModRDNAttributes($lines);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
if (! $server->dnExists($dn))
|
||||
return $this->error(_('Unkown change type'),$lines);
|
||||
}
|
||||
|
||||
} else
|
||||
return $this->error(_('A valid dn line is required'),$lines);
|
||||
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
}
|
@ -1,598 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\LDAP\Schema;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Represents an LDAP AttributeType
|
||||
*
|
||||
* @package phpLDAPadmin
|
||||
* @subpackage Schema
|
||||
*/
|
||||
final class AttributeType extends Base {
|
||||
// The attribute from which this attribute inherits (if any)
|
||||
private ?string $sup_attribute = NULL;
|
||||
|
||||
// Array of AttributeTypes which inherit from this one
|
||||
private Collection $children;
|
||||
|
||||
// The equality rule used
|
||||
private ?string $equality = NULL;
|
||||
|
||||
// The ordering of the attributeType
|
||||
private ?string $ordering = NULL;
|
||||
|
||||
// Supports substring matching?
|
||||
private ?string $sub_str_rule = NULL;
|
||||
|
||||
// The full syntax string, ie 1.2.3.4{16}
|
||||
private ?string $syntax = NULL;
|
||||
private ?string $syntax_oid = NULL;
|
||||
|
||||
// boolean: is single valued only?
|
||||
private bool $is_single_value = FALSE;
|
||||
|
||||
// boolean: is collective?
|
||||
private bool $is_collective = FALSE;
|
||||
|
||||
// boolean: can use modify?
|
||||
private bool $is_no_user_modification = FALSE;
|
||||
|
||||
// The usage string set by the LDAP schema
|
||||
private ?string $usage = NULL;
|
||||
|
||||
// An array of alias attribute names, strings
|
||||
private Collection $aliases;
|
||||
|
||||
// The max number of characters this attribute can be
|
||||
private ?int $max_length = NULL;
|
||||
|
||||
// A string description of the syntax type (taken from the LDAPSyntaxes)
|
||||
/**
|
||||
* @deprecated - reference syntaxes directly if possible
|
||||
* @var string
|
||||
*/
|
||||
private ?string $type = NULL;
|
||||
|
||||
// An array of objectClasses which use this attributeType (must be set by caller)
|
||||
private Collection $used_in_object_classes;
|
||||
|
||||
// A list of object class names that require this attribute type.
|
||||
private Collection $required_by_object_classes;
|
||||
|
||||
// This attribute has been forced a MAY attribute by the configuration.
|
||||
private bool $forced_as_may = FALSE;
|
||||
|
||||
/**
|
||||
* Creates a new AttributeType object from a raw LDAP AttributeType string.
|
||||
*
|
||||
* eg: ( 2.5.4.0 NAME 'objectClass' DESC 'RFC4512: object classes of the entity' EQUALITY objectIdentifierMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )
|
||||
*/
|
||||
public function __construct(string $line) {
|
||||
Log::debug(sprintf('Parsing AttributeType [%s]',$line));
|
||||
|
||||
parent::__construct($line);
|
||||
|
||||
$strings = preg_split('/[\s,]+/',$line,-1,PREG_SPLIT_DELIM_CAPTURE);
|
||||
|
||||
// Init
|
||||
$this->children = collect();
|
||||
$this->aliases = collect();
|
||||
$this->used_in_object_classes = collect();
|
||||
$this->required_by_object_classes = collect();
|
||||
|
||||
for ($i=0; $i < count($strings); $i++) {
|
||||
switch ($strings[$i]) {
|
||||
case '(':
|
||||
case ')':
|
||||
break;
|
||||
|
||||
case 'NAME':
|
||||
// @note Some schema's return a (' instead of a ( '
|
||||
if ($strings[$i+1] != '(' && ! preg_match('/^\(/',$strings[$i+1])) {
|
||||
do {
|
||||
$this->name .= (strlen($this->name) ? ' ' : '').$strings[++$i];
|
||||
|
||||
} while (! preg_match("/\'$/s",$strings[$i]));
|
||||
|
||||
// This attribute has no aliases
|
||||
//$this->aliases = collect();
|
||||
|
||||
} else {
|
||||
$i++;
|
||||
|
||||
do {
|
||||
// In case we came here becaues of a ('
|
||||
if (preg_match('/^\(/',$strings[$i]))
|
||||
$strings[$i] = preg_replace('/^\(/','',$strings[$i]);
|
||||
else
|
||||
$i++;
|
||||
|
||||
$this->name .= (strlen($this->name) ? ' ' : '').$strings[++$i];
|
||||
|
||||
} while (! preg_match("/\'$/s",$strings[$i]));
|
||||
|
||||
// Add alias names for this attribute
|
||||
while ($strings[++$i] != ')') {
|
||||
$alias = $strings[$i];
|
||||
$alias = preg_replace("/^\'(.*)\'$/",'$1',$alias);
|
||||
$this->addAlias($alias);
|
||||
}
|
||||
}
|
||||
|
||||
$this->name = preg_replace("/^\'(.*)\'$/",'$1',$this->name);
|
||||
|
||||
Log::debug(sprintf('- Case NAME returned (%s)',$this->name),['aliases'=>$this->aliases]);
|
||||
break;
|
||||
|
||||
case 'DESC':
|
||||
do {
|
||||
$this->description .= (strlen($this->description) ? ' ' : '').$strings[++$i];
|
||||
|
||||
} while (! preg_match("/\'$/s",$strings[$i]));
|
||||
|
||||
$this->description = preg_replace("/^\'(.*)\'$/",'$1',$this->description);
|
||||
|
||||
Log::debug(sprintf('- Case DESC returned (%s)',$this->description));
|
||||
break;
|
||||
|
||||
case 'OBSOLETE':
|
||||
$this->is_obsolete = TRUE;
|
||||
|
||||
Log::debug(sprintf('- Case OBSOLETE returned (%s)',$this->is_obsolete));
|
||||
break;
|
||||
|
||||
case 'SUP':
|
||||
$i++;
|
||||
$this->sup_attribute = preg_replace("/^\'(.*)\'$/",'$1',$strings[$i]);
|
||||
|
||||
Log::debug(sprintf('- Case SUP returned (%s)',$this->sup_attribute));
|
||||
break;
|
||||
|
||||
case 'EQUALITY':
|
||||
$this->equality = $strings[++$i];
|
||||
|
||||
Log::debug(sprintf('- Case EQUALITY returned (%s)',$this->equality));
|
||||
break;
|
||||
|
||||
case 'ORDERING':
|
||||
$this->ordering = $strings[++$i];
|
||||
|
||||
Log::debug(sprintf('- Case ORDERING returned (%s)',$this->ordering));
|
||||
break;
|
||||
|
||||
case 'SUBSTR':
|
||||
$this->sub_str_rule = $strings[++$i];
|
||||
|
||||
Log::debug(sprintf('- Case SUBSTR returned (%s)',$this->sub_str_rule));
|
||||
break;
|
||||
|
||||
case 'SYNTAX':
|
||||
$this->syntax = $strings[++$i];
|
||||
$this->syntax_oid = preg_replace('/{\d+}$/','',$this->syntax);
|
||||
Log::debug(sprintf('/ Evaluating SYNTAX returned (%s) [%s]',$this->syntax,$this->syntax_oid));
|
||||
|
||||
// Does this SYNTAX string specify a max length (ie, 1.2.3.4{16})
|
||||
$m = [];
|
||||
if (preg_match('/{(\d+)}$/',$this->syntax,$m))
|
||||
$this->max_length = $m[1];
|
||||
else
|
||||
$this->max_length = NULL;
|
||||
|
||||
if ($i < count($strings) - 1 && $strings[$i+1] == '{')
|
||||
do {
|
||||
$this->name .= ' '.$strings[++$i];
|
||||
} while ($strings[$i] != '}');
|
||||
|
||||
$this->syntax = preg_replace("/^\'(.*)\'$/",'$1',$this->syntax);
|
||||
$this->syntax_oid = preg_replace("/^\'(.*)\'$/",'$1',$this->syntax_oid);
|
||||
|
||||
Log::debug(sprintf('- Case SYNTAX returned (%s) [%s] {%d}',$this->syntax,$this->syntax_oid,$this->max_length));
|
||||
break;
|
||||
|
||||
case 'SINGLE-VALUE':
|
||||
$this->is_single_value = TRUE;
|
||||
|
||||
Log::debug(sprintf('- Case SINGLE-VALUE returned (%s)',$this->is_single_value));
|
||||
break;
|
||||
|
||||
case 'COLLECTIVE':
|
||||
$this->is_collective = TRUE;
|
||||
|
||||
Log::debug(sprintf('- Case COLLECTIVE returned (%s)',$this->is_collective));
|
||||
break;
|
||||
|
||||
case 'NO-USER-MODIFICATION':
|
||||
$this->is_no_user_modification = TRUE;
|
||||
|
||||
Log::debug(sprintf('- Case NO-USER-MODIFICATION returned (%s)',$this->is_no_user_modification));
|
||||
break;
|
||||
|
||||
case 'USAGE':
|
||||
$this->usage = $strings[++$i];
|
||||
|
||||
Log::debug(sprintf('- Case USAGE returned (%s)',$this->usage));
|
||||
break;
|
||||
|
||||
// @note currently not captured
|
||||
case 'X-ORDERED':
|
||||
Log::error(sprintf('- Case X-ORDERED returned (%s)',$strings[++$i]));
|
||||
break;
|
||||
|
||||
// @note currently not captured
|
||||
case 'X-ORIGIN':
|
||||
$value = '';
|
||||
|
||||
do {
|
||||
$value .= (strlen($value) ? ' ' : '').$strings[++$i];
|
||||
|
||||
} while (! preg_match("/\'$/s",$strings[$i]));
|
||||
|
||||
Log::error(sprintf('- Case X-ORIGIN returned (%s)',$value));
|
||||
break;
|
||||
|
||||
default:
|
||||
if (preg_match('/[\d\.]+/i',$strings[$i]) && ($i === 1)) {
|
||||
$this->oid = $strings[$i];
|
||||
Log::debug(sprintf('- Case default returned (%s)',$this->oid));
|
||||
|
||||
} elseif ($strings[$i])
|
||||
Log::alert(sprintf('! Case default discovered a value NOT parsed (%s)',$strings[$i]),['line'=>$line]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function __clone()
|
||||
{
|
||||
// When we clone, we need to break the reference too
|
||||
$this->aliases = clone $this->aliases;
|
||||
}
|
||||
|
||||
public function __get(string $key): mixed
|
||||
{
|
||||
switch ($key) {
|
||||
case 'aliases': return $this->aliases;
|
||||
case 'children': return $this->children;
|
||||
case 'forced_as_may': return $this->forced_as_may;
|
||||
case 'is_collective': return $this->is_collective;
|
||||
case 'is_editable': return ! $this->is_no_user_modification;
|
||||
case 'is_no_user_modification': return $this->is_no_user_modification;
|
||||
case 'is_single_value': return $this->is_single_value;
|
||||
case 'equality': return $this->equality;
|
||||
case 'max_length': return $this->max_length;
|
||||
case 'ordering': return $this->ordering;
|
||||
case 'required_by_object_classes': return $this->required_by_object_classes;
|
||||
case 'sub_str_rule': return $this->sub_str_rule;
|
||||
case 'sup_attribute': return $this->sup_attribute;
|
||||
case 'syntax': return $this->syntax;
|
||||
case 'syntax_oid': return $this->syntax_oid;
|
||||
case 'type': return $this->type;
|
||||
case 'usage': return $this->usage;
|
||||
case 'used_in_object_classes': return $this->used_in_object_classes;
|
||||
case 'validation': return Arr::get(config('ldap.validation'),$this->name_lc);
|
||||
|
||||
default: return parent::__get($key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an attribute name to the alias array.
|
||||
*
|
||||
* @param string $alias The name of a new attribute to add to this attribute's list of aliases.
|
||||
*/
|
||||
public function addAlias(string $alias): void
|
||||
{
|
||||
$this->aliases->push($alias);
|
||||
}
|
||||
|
||||
/**
|
||||
* Children of this attribute type that inherit from this one
|
||||
*
|
||||
* @param string $child
|
||||
* @return void
|
||||
*/
|
||||
public function addChild(string $child): void
|
||||
{
|
||||
$this->children->push($child);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an objectClass name to this attribute's list of "required by" objectClasses,
|
||||
* that is the list of objectClasses which must have this attribute.
|
||||
*
|
||||
* @param string $name The name of the objectClass to add.
|
||||
*/
|
||||
public function addRequiredByObjectClass(string $name): void
|
||||
{
|
||||
if ($this->required_by_object_classes->search($name) === FALSE)
|
||||
$this->required_by_object_classes->push($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an objectClass name to this attribute's list of "used in" objectClasses,
|
||||
* that is the list of objectClasses which provide this attribute.
|
||||
*
|
||||
* @param string $name The name of the objectClass to add.
|
||||
*/
|
||||
public function addUsedInObjectClass(string $name): void
|
||||
{
|
||||
if ($this->used_in_object_classes->search($name) === FALSE)
|
||||
$this->used_in_object_classes->push($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the names of attributes that are an alias for this attribute (if any).
|
||||
*
|
||||
* @return Collection An array of names of attributes which alias this attribute or
|
||||
* an empty array if no attribute aliases this object.
|
||||
* @deprecated use class->aliases
|
||||
*/
|
||||
public function getAliases(): Collection
|
||||
{
|
||||
return $this->aliases;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this attribute's equality string
|
||||
*
|
||||
* @return string
|
||||
* @deprecated use $this->equality
|
||||
*/
|
||||
public function getEquality()
|
||||
{
|
||||
return $this->equality;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether this attribute is collective.
|
||||
*
|
||||
* @return boolean Returns TRUE if this attribute is collective and FALSE otherwise.
|
||||
* @deprecated use $this->is_collective
|
||||
*/
|
||||
public function getIsCollective(): bool
|
||||
{
|
||||
return $this->is_collective;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether this attribute is not modifiable by users.
|
||||
*
|
||||
* @return boolean Returns TRUE if this attribute is not modifiable by users.
|
||||
* @deprecated use $this->is_no_user_modification
|
||||
*/
|
||||
public function getIsNoUserModification(): bool
|
||||
{
|
||||
return $this->is_no_user_modification;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether this attribute is single-valued. If this attribute only supports single values, TRUE
|
||||
* is returned. If this attribute supports multiple values, FALSE is returned.
|
||||
*
|
||||
* @return boolean Returns TRUE if this attribute is single-valued or FALSE otherwise.
|
||||
* @deprecated use class->is_single_value
|
||||
*/
|
||||
public function getIsSingleValue(): bool
|
||||
{
|
||||
return $this->is_single_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this attribute's the maximum length. If no maximum is defined by the LDAP server, NULL is returned.
|
||||
*
|
||||
* @return int The maximum length (in characters) of this attribute or NULL if no maximum is specified.
|
||||
* @deprecated use $this->max_length;
|
||||
*/
|
||||
public function getMaxLength()
|
||||
{
|
||||
return $this->max_length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this attribute's ordering specification.
|
||||
*
|
||||
* @return string
|
||||
* @deprecated use $this->ordering
|
||||
*/
|
||||
public function getOrdering(): string
|
||||
{
|
||||
return $this->ordering;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of "required by" objectClasses, that is the list of objectClasses
|
||||
* which provide must have attribute.
|
||||
*
|
||||
* @return array An array of names of objectclasses (strings) which provide this attribute
|
||||
*/
|
||||
public function getRequiredByObjectClasses() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->required_by_object_classes);
|
||||
|
||||
return $this->required_by_object_classes;
|
||||
}
|
||||
/**
|
||||
* Gets this attribute's substring matching specification
|
||||
*
|
||||
* @return string
|
||||
* @deprecated use $this->sub_str_rule;
|
||||
*/
|
||||
public function getSubstr() {
|
||||
return $this->sub_str_rule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this attribute's parent attribute (if any). If this attribute does not
|
||||
* inherit from another attribute, NULL is returned.
|
||||
*
|
||||
* @return string
|
||||
* @deprecated use $class->sup_attribute directly
|
||||
*/
|
||||
public function getSupAttribute() {
|
||||
return $this->sup_attribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this attribute's syntax OID. Differs from getSyntaxString() in that this
|
||||
* function only returns the actual OID with any length specification removed.
|
||||
* Ie, if the syntax string is "1.2.3.4{16}", this function only retruns
|
||||
* "1.2.3.4".
|
||||
*
|
||||
* @return string The syntax OID string.
|
||||
* @deprecated use $this->syntax_oid;
|
||||
*/
|
||||
public function getSyntaxOID()
|
||||
{
|
||||
return $this->syntax_oid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this attribute's raw syntax string (ie: "1.2.3.4{16}").
|
||||
*
|
||||
* @return string The raw syntax string
|
||||
*/
|
||||
public function getSyntaxString() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->syntax);
|
||||
|
||||
return $this->syntax;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this attribute's type
|
||||
*
|
||||
* @return string The attribute's type.
|
||||
* @deprecated use $this->type;
|
||||
*/
|
||||
public function getType()
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this attribute's usage string as defined by the LDAP server
|
||||
*
|
||||
* @return string
|
||||
* @deprecated use $this->usage
|
||||
*/
|
||||
public function getUsage()
|
||||
{
|
||||
return $this->usage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of "used in" objectClasses, that is the list of objectClasses
|
||||
* which provide this attribute.
|
||||
*
|
||||
* @return Collection An array of names of objectclasses (strings) which provide this attribute
|
||||
* @deprecated use $this->used_in_object_classes
|
||||
*/
|
||||
public function getUsedInObjectClasses(): Collection
|
||||
{
|
||||
return $this->used_in_object_classes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the specified attribute is an alias for this one (based on this attribute's alias list).
|
||||
*
|
||||
* @param string $attr_name The name of the attribute to check.
|
||||
* @return boolean TRUE if the specified attribute is an alias for this one, or FALSE otherwise.
|
||||
*/
|
||||
public function isAliasFor($attr_name) {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs);
|
||||
|
||||
foreach ($this->aliases as $alias_attr_name)
|
||||
if (strcasecmp($alias_attr_name,$attr_name) == 0)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @deprecated use $this->forced_as_may
|
||||
*/
|
||||
public function isForceMay(): bool
|
||||
{
|
||||
return $this->forced_as_may;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an attribute name from this attribute's alias array.
|
||||
*
|
||||
* @param string $alias The name of the attribute to remove.
|
||||
*/
|
||||
public function removeAlias(string $alias): void
|
||||
{
|
||||
if (($x=$this->aliases->search($alias)) !== FALSE)
|
||||
$this->aliases->forget($x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a list of object classes, determine if this is a required attribute
|
||||
*
|
||||
* @param Collection $oc List of objectclasses to compare.
|
||||
* @return Collection
|
||||
*/
|
||||
public function required_by(Collection $oc): Collection
|
||||
{
|
||||
return $oc->diff($this->required_by_object_classes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this attribute's list of aliases.
|
||||
*
|
||||
* @param Collection $aliases The array of alias names (strings)
|
||||
* @deprecated use $this->aliases =
|
||||
*/
|
||||
public function setAliases(Collection $aliases): void
|
||||
{
|
||||
$this->aliases = $aliases;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will mark this attribute as a forced MAY attribute
|
||||
*/
|
||||
public function setForceMay() {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs);
|
||||
|
||||
$this->forced_as_may = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether this attribute is single-valued.
|
||||
*
|
||||
* @param boolean $is
|
||||
*/
|
||||
public function setIsSingleValue(bool $is): void
|
||||
{
|
||||
$this->is_single_value = $is;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this attribute's SUP attribute (ie, the attribute from which this attribute inherits).
|
||||
*
|
||||
* @param string $attr The name of the new parent (SUP) attribute
|
||||
*/
|
||||
public function setSupAttribute(string $attr): void
|
||||
{
|
||||
$this->sup_attribute = trim($attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this attribute's type.
|
||||
*
|
||||
* @param string $type The new type.
|
||||
*/
|
||||
public function setType($type) {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs);
|
||||
|
||||
$this->type = $type;
|
||||
}
|
||||
}
|
@ -1,120 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\LDAP\Schema;
|
||||
|
||||
use App\Exceptions\InvalidUsage;
|
||||
|
||||
/**
|
||||
* Generic parent class for all schema items.
|
||||
*
|
||||
* A schema item is an ObjectClass, an AttributeBype, a MatchingRule, or a Syntax.
|
||||
* All schema items have at least two things in common: An OID and a Description.
|
||||
*/
|
||||
abstract class Base {
|
||||
// Record the LDAP String
|
||||
private string $line;
|
||||
|
||||
// The schema item's name.
|
||||
protected ?string $name = NULL;
|
||||
|
||||
// The OID of this schema item.
|
||||
protected string $oid;
|
||||
|
||||
# The description of this schema item.
|
||||
protected ?string $description = NULL;
|
||||
|
||||
// Boolean value indicating whether this objectClass is obsolete
|
||||
private bool $is_obsolete = FALSE;
|
||||
|
||||
public function __construct(string $line)
|
||||
{
|
||||
$this->line = $line;
|
||||
}
|
||||
|
||||
public function __get(string $key): mixed
|
||||
{
|
||||
switch ($key) {
|
||||
case 'description': return $this->description;
|
||||
case 'is_obsolete': return $this->is_obsolete;
|
||||
case 'line': return $this->line;
|
||||
case 'name': return $this->name;
|
||||
case 'name_lc': return strtolower($this->name);
|
||||
case 'oid': return $this->oid;
|
||||
|
||||
default:
|
||||
throw new InvalidUsage('Unknown key:'.$key);
|
||||
}
|
||||
}
|
||||
|
||||
public function __isset(string $key): bool
|
||||
{
|
||||
return isset($this->{$key});
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @deprecated replace with $class->description
|
||||
*/
|
||||
public function getDescription(): string
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether this item is flagged as obsolete by the LDAP server.
|
||||
*
|
||||
* @deprecated replace with $this->is_obsolete
|
||||
*/
|
||||
public function getIsObsolete(): bool
|
||||
{
|
||||
return $this->is_obsolete;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the objects name.
|
||||
*
|
||||
* @param boolean $lower Return the name in lower case (default)
|
||||
* @return string The name
|
||||
* @deprecated use object->name
|
||||
*/
|
||||
public function getName(bool $lower=TRUE): string
|
||||
{
|
||||
return $lower ? strtolower($this->name) : $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the objects name.
|
||||
*
|
||||
* @return string The name
|
||||
* @deprecated use object->oid
|
||||
*/
|
||||
public function getOID(): string
|
||||
{
|
||||
return $this->oid;
|
||||
}
|
||||
|
||||
public function setDescription(string $desc): void
|
||||
{
|
||||
$this->description = $desc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this attribute's name.
|
||||
*
|
||||
* @param string $name The new name to give this attribute.
|
||||
*/
|
||||
public function setName($name): void
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
public function setOID(string $oid): void
|
||||
{
|
||||
$this->oid = $oid;
|
||||
}
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\LDAP\Schema;
|
||||
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Represents an LDAP Syntax
|
||||
*
|
||||
* @package phpLDAPadmin
|
||||
* @subpackage Schema
|
||||
*/
|
||||
final class LDAPSyntax extends Base {
|
||||
// Is human readable?
|
||||
private ?bool $is_not_human_readable = NULL;
|
||||
|
||||
// Binary transfer required?
|
||||
private ?bool $binary_transfer_required = NULL;
|
||||
|
||||
/**
|
||||
* Creates a new Syntax object from a raw LDAP syntax string.
|
||||
*/
|
||||
public function __construct(string $line) {
|
||||
Log::debug(sprintf('Parsing LDAPSyntax [%s]',$line));
|
||||
|
||||
parent::__construct($line);
|
||||
|
||||
$strings = preg_split('/[\s,]+/',$line,-1,PREG_SPLIT_DELIM_CAPTURE);
|
||||
|
||||
for ($i=0; $i<count($strings); $i++) {
|
||||
switch($strings[$i]) {
|
||||
case '(':
|
||||
case ')':
|
||||
break;
|
||||
|
||||
case 'DESC':
|
||||
do {
|
||||
$this->description .= (strlen($this->description) ? ' ' : '').$strings[++$i];
|
||||
|
||||
} while (! preg_match("/\'$/s",$strings[$i]));
|
||||
|
||||
$this->description = preg_replace("/^\'(.*)\'$/",'$1',$this->description);
|
||||
|
||||
Log::debug(sprintf('- Case DESC returned (%s)',$this->description));
|
||||
break;
|
||||
|
||||
case 'X-BINARY-TRANSFER-REQUIRED':
|
||||
$this->binary_transfer_required = (str_replace("'",'',$strings[++$i]) === 'TRUE');
|
||||
|
||||
Log::debug(sprintf('- Case X-BINARY-TRANSFER-REQUIRED returned (%s)',$this->binary_transfer_required));
|
||||
break;
|
||||
|
||||
case 'X-NOT-HUMAN-READABLE':
|
||||
$this->is_not_human_readable = (str_replace("'",'',$strings[++$i]) === 'TRUE');
|
||||
|
||||
Log::debug(sprintf('- Case X-NOT-HUMAN-READABLE returned (%s)',$this->is_not_human_readable));
|
||||
break;
|
||||
|
||||
default:
|
||||
if (preg_match('/[\d\.]+/i',$strings[$i]) && ($i === 1)) {
|
||||
$this->oid = $strings[$i];
|
||||
Log::debug(sprintf('- Case default returned (%s)',$this->oid));
|
||||
|
||||
} elseif ($strings[$i])
|
||||
Log::alert(sprintf('! Case default discovered a value NOT parsed (%s)',$strings[$i]),['line'=>$line]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function __get(string $key): mixed
|
||||
{
|
||||
switch ($key) {
|
||||
case 'binary_transfer_required': return $this->binary_transfer_required;
|
||||
case 'is_not_human_readable': return $this->is_not_human_readable;
|
||||
|
||||
default: return parent::__get($key);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,142 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\LDAP\Schema;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Represents an LDAP MatchingRule
|
||||
*
|
||||
* @package phpLDAPadmin
|
||||
* @subpackage Schema
|
||||
*/
|
||||
final class MatchingRule extends Base {
|
||||
// This rule's syntax OID
|
||||
private ?string $syntax = NULL;
|
||||
|
||||
// An array of attribute names who use this MatchingRule
|
||||
private Collection $used_by_attrs;
|
||||
|
||||
/**
|
||||
* Creates a new MatchingRule object from a raw LDAP MatchingRule string.
|
||||
*/
|
||||
function __construct(string $line) {
|
||||
Log::debug(sprintf('Parsing MatchingRule [%s]',$line));
|
||||
|
||||
parent::__construct($line);
|
||||
|
||||
$strings = preg_split('/[\s,]+/',$line,-1,PREG_SPLIT_DELIM_CAPTURE);
|
||||
|
||||
// Init
|
||||
$this->used_by_attrs = collect();
|
||||
|
||||
for ($i=0; $i<count($strings); $i++) {
|
||||
switch ($strings[$i]) {
|
||||
case '(':
|
||||
case ')':
|
||||
break;
|
||||
|
||||
case 'NAME':
|
||||
if ($strings[$i+1] != '(') {
|
||||
do {
|
||||
$this->name .= (strlen($this->name) ? ' ' : '').$strings[++$i];
|
||||
|
||||
} while (! preg_match("/\'$/s",$strings[$i]));
|
||||
|
||||
} else {
|
||||
$i++;
|
||||
|
||||
do {
|
||||
$this->name .= (strlen($this->name) ? ' ' : '').$strings[++$i];
|
||||
|
||||
} while (! preg_match("/\'$/s",$strings[$i]));
|
||||
|
||||
do {
|
||||
$i++;
|
||||
|
||||
} while (! preg_match('/\)+\)?/',$strings[$i]));
|
||||
}
|
||||
|
||||
$this->name = preg_replace("/^\'/",'',$this->name);
|
||||
$this->name = preg_replace("/\'$/",'',$this->name);
|
||||
|
||||
Log::debug(sprintf(sprintf('- Case NAME returned (%s)',$this->name)));
|
||||
break;
|
||||
|
||||
case 'DESC':
|
||||
do {
|
||||
$this->description .= (strlen($this->description) ? ' ' : '').$strings[++$i];
|
||||
|
||||
} while (! preg_match("/\'$/s",$strings[$i]));
|
||||
|
||||
$this->description = preg_replace("/^\'(.*)\'$/",'$1',$this->description);
|
||||
|
||||
Log::debug(sprintf('- Case DESC returned (%s)',$this->description));
|
||||
break;
|
||||
|
||||
case 'OBSOLETE':
|
||||
$this->is_obsolete = TRUE;
|
||||
|
||||
Log::debug(sprintf('- Case OBSOLETE returned (%s)',$this->is_obsolete));
|
||||
break;
|
||||
|
||||
case 'SYNTAX':
|
||||
$this->syntax = $strings[++$i];
|
||||
|
||||
Log::debug(sprintf('- Case SYNTAX returned (%s)',$this->syntax));
|
||||
break;
|
||||
|
||||
default:
|
||||
if (preg_match('/[\d\.]+/i',$strings[$i]) && ($i === 1)) {
|
||||
$this->oid = $strings[$i];
|
||||
Log::debug(sprintf('- Case default returned (%s)',$this->oid));
|
||||
|
||||
} elseif ($strings[$i])
|
||||
Log::alert(sprintf('! Case default discovered a value NOT parsed (%s)',$strings[$i]),['line'=>$line]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function __get(string $key): mixed
|
||||
{
|
||||
switch ($key) {
|
||||
case 'syntax': return $this->syntax;
|
||||
case 'used_by_attrs': return $this->used_by_attrs;
|
||||
|
||||
default: return parent::__get($key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an attribute name to the list of attributes who use this MatchingRule
|
||||
*/
|
||||
public function addUsedByAttr(string $name): void
|
||||
{
|
||||
$name = trim($name);
|
||||
|
||||
if ($this->used_by_attrs->search($name) === FALSE)
|
||||
$this->used_by_attrs->push($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an array of attribute names (strings) which use this MatchingRule
|
||||
*
|
||||
* @return array The array of attribute names (strings).
|
||||
* @deprecated use $this->used_by_attrs
|
||||
*/
|
||||
public function getUsedByAttrs()
|
||||
{
|
||||
return $this->used_by_attrs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the list of used_by_attrs to the array specified by $attrs;
|
||||
*
|
||||
* @param Collection $attrs The array of attribute names (strings) which use this MatchingRule
|
||||
*/
|
||||
public function setUsedByAttrs(Collection $attrs): void
|
||||
{
|
||||
$this->used_by_attrs = $attrs;
|
||||
}
|
||||
}
|
@ -1,99 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\LDAP\Schema;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Represents an LDAP schema matchingRuleUse entry
|
||||
*
|
||||
* @package phpLDAPadmin
|
||||
* @subpackage Schema
|
||||
*/
|
||||
final class MatchingRuleUse extends Base {
|
||||
// An array of attribute names who use this MatchingRule
|
||||
private Collection $used_by_attrs;
|
||||
|
||||
function __construct(string $line) {
|
||||
Log::debug(sprintf('Parsing MatchingRuleUse [%s]',$line));
|
||||
|
||||
parent::__construct($line);
|
||||
|
||||
$strings = preg_split('/[\s,]+/',$line,-1,PREG_SPLIT_DELIM_CAPTURE);
|
||||
|
||||
// Init
|
||||
$this->used_by_attrs = collect();
|
||||
|
||||
for ($i=0; $i<count($strings); $i++) {
|
||||
switch ($strings[$i]) {
|
||||
case '(':
|
||||
case ')':
|
||||
break;
|
||||
|
||||
case 'NAME':
|
||||
if ($strings[$i+1] != '(') {
|
||||
do {
|
||||
$this->name .= (strlen($this->name) ? ' ' : '').$strings[++$i];
|
||||
|
||||
} while (! preg_match("/\'$/s",$strings[$i]));
|
||||
|
||||
} else {
|
||||
$i++;
|
||||
|
||||
do {
|
||||
$this->name .= (strlen($this->name) ? ' ' : '').$strings[++$i];
|
||||
|
||||
} while (! preg_match("/\'$/s",$strings[$i]));
|
||||
|
||||
do {
|
||||
$i++;
|
||||
|
||||
} while (! preg_match('/\)+\)?/',$strings[$i]));
|
||||
}
|
||||
|
||||
$this->name = preg_replace("/^\'(.*)\'$/",'$1',$this->name);
|
||||
|
||||
Log::debug(sprintf(sprintf('- Case NAME returned (%s)',$this->name)));
|
||||
break;
|
||||
|
||||
case 'APPLIES':
|
||||
if ($strings[$i+1] != '(') {
|
||||
// Has a single attribute name
|
||||
$this->used_by_attrs = collect($strings[++$i]);
|
||||
|
||||
} else {
|
||||
// Has multiple attribute names
|
||||
while ($strings[++$i] != ')') {
|
||||
$new_attr = $strings[++$i];
|
||||
$new_attr = preg_replace("/^\'(.*)\'$/",'$1',$new_attr);
|
||||
|
||||
$this->used_by_attrs->push($new_attr);
|
||||
}
|
||||
}
|
||||
|
||||
Log::debug(sprintf('- Case APPLIES returned (%s)',$this->used_by_attrs->join(',')));
|
||||
break;
|
||||
|
||||
default:
|
||||
if (preg_match('/[\d\.]+/i',$strings[$i]) && ($i === 1)) {
|
||||
$this->oid = $strings[$i];
|
||||
Log::debug(sprintf('- Case default returned (%s)',$this->oid));
|
||||
|
||||
} elseif ($strings[$i])
|
||||
Log::alert(sprintf('! Case default discovered a value NOT parsed (%s)',$strings[$i]),['line'=>$line]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an array of attribute names (strings) which use this MatchingRuleUse object.
|
||||
*
|
||||
* @return array The array of attribute names (strings).
|
||||
* @deprecated use $this->used_by_attrs
|
||||
*/
|
||||
public function getUsedByAttrs()
|
||||
{
|
||||
return $this->used_by_attrs;
|
||||
}
|
||||
}
|
@ -1,540 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\LDAP\Schema;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
use App\Classes\LDAP\Server;
|
||||
use App\Exceptions\InvalidUsage;
|
||||
use App\Ldap\Entry;
|
||||
|
||||
/**
|
||||
* Represents an LDAP Schema objectClass
|
||||
*
|
||||
* @package phpLDAPadmin
|
||||
* @subpackage Schema
|
||||
*/
|
||||
final class ObjectClass extends Base {
|
||||
// The server ID that this objectclass belongs to.
|
||||
private Server $server;
|
||||
|
||||
// Array of objectClass names from which this objectClass inherits
|
||||
private Collection $sup_classes;
|
||||
|
||||
// One of STRUCTURAL, ABSTRACT, or AUXILIARY
|
||||
private int $type;
|
||||
|
||||
// Arrays of attribute names that this objectClass requires
|
||||
private Collection $must_attrs;
|
||||
|
||||
// Arrays of attribute names that this objectClass allows, but does not require
|
||||
private Collection $may_attrs;
|
||||
|
||||
// Arrays of attribute names that this objectClass has been forced to MAY attrs, due to configuration
|
||||
private Collection $may_force;
|
||||
|
||||
// Array of objectClasses which inherit from this one
|
||||
private Collection $child_objectclasses;
|
||||
|
||||
private bool $is_obsolete;
|
||||
|
||||
/* ObjectClass Types */
|
||||
private const OC_STRUCTURAL = 0x01;
|
||||
private const OC_ABSTRACT = 0x02;
|
||||
private const OC_AUXILIARY = 0x03;
|
||||
|
||||
/**
|
||||
* Creates a new ObjectClass object given a raw LDAP objectClass string.
|
||||
*
|
||||
* eg: ( 2.5.6.0 NAME 'top' DESC 'top of the superclass chain' ABSTRACT MUST objectClass )
|
||||
*/
|
||||
public function __construct(string $line,Server $server)
|
||||
{
|
||||
parent::__construct($line);
|
||||
|
||||
Log::debug(sprintf('Parsing ObjectClass [%s]',$line));
|
||||
|
||||
$strings = preg_split('/[\s,]+/',$line,-1,PREG_SPLIT_DELIM_CAPTURE);
|
||||
|
||||
// Init
|
||||
$this->server = $server;
|
||||
$this->may_attrs = collect();
|
||||
$this->may_force = collect();
|
||||
$this->must_attrs = collect();
|
||||
$this->sup_classes = collect();
|
||||
$this->child_objectclasses = collect();
|
||||
|
||||
for ($i=0; $i < count($strings); $i++) {
|
||||
switch ($strings[$i]) {
|
||||
case '(':
|
||||
case ')':
|
||||
break;
|
||||
|
||||
case 'NAME':
|
||||
if ($strings[$i+1] != '(') {
|
||||
do {
|
||||
$this->name .= (strlen($this->name) ? ' ' : '').$strings[++$i];
|
||||
|
||||
} while (! preg_match('/\'$/s',$strings[$i]));
|
||||
|
||||
} else {
|
||||
$i++;
|
||||
|
||||
do {
|
||||
$this->name .= (strlen($this->name) ? ' ' : '').$strings[++$i];
|
||||
|
||||
} while (! preg_match('/\'$/s',$strings[$i]));
|
||||
|
||||
do {
|
||||
$i++;
|
||||
} while (! preg_match('/\)+\)?/',$strings[$i]));
|
||||
}
|
||||
|
||||
$this->name = preg_replace("/^\'(.*)\'$/",'$1',$this->name);
|
||||
|
||||
Log::debug(sprintf(sprintf('- Case NAME returned (%s)',$this->name)));
|
||||
break;
|
||||
|
||||
case 'DESC':
|
||||
do {
|
||||
$this->description .= (strlen($this->description) ? ' ' : '').$strings[++$i];
|
||||
|
||||
} while (! preg_match('/\'$/s',$strings[$i]));
|
||||
|
||||
$this->description = preg_replace("/^\'(.*)\'$/",'$1',$this->description);
|
||||
|
||||
Log::debug(sprintf('- Case DESC returned (%s)',$this->description));
|
||||
break;
|
||||
|
||||
case 'OBSOLETE':
|
||||
$this->is_obsolete = TRUE;
|
||||
|
||||
Log::debug(sprintf('- Case OBSOLETE returned (%s)',$this->is_obsolete));
|
||||
break;
|
||||
|
||||
case 'SUP':
|
||||
if ($strings[$i+1] != '(') {
|
||||
$this->sup_classes->push(preg_replace("/'/",'',$strings[++$i]));
|
||||
|
||||
} else {
|
||||
$i++;
|
||||
|
||||
do {
|
||||
$i++;
|
||||
|
||||
if ($strings[$i] != '$')
|
||||
$this->sup_classes->push(preg_replace("/'/",'',$strings[$i]));
|
||||
|
||||
} while (! preg_match('/\)+\)?/',$strings[$i+1]));
|
||||
}
|
||||
|
||||
Log::debug(sprintf('- Case SUP returned (%s)',$this->sup_classes->join(',')));
|
||||
break;
|
||||
|
||||
case 'ABSTRACT':
|
||||
$this->type = self::OC_ABSTRACT;
|
||||
|
||||
Log::debug(sprintf('- Case ABSTRACT returned (%s)',$this->type));
|
||||
break;
|
||||
|
||||
case 'STRUCTURAL':
|
||||
$this->type = self::OC_STRUCTURAL;
|
||||
|
||||
Log::debug(sprintf('- Case STRUCTURAL returned (%s)',$this->type));
|
||||
break;
|
||||
|
||||
case 'AUXILIARY':
|
||||
$this->type = self::OC_AUXILIARY;
|
||||
|
||||
Log::debug(sprintf('- Case AUXILIARY returned (%s)',$this->type));
|
||||
break;
|
||||
|
||||
case 'MUST':
|
||||
$attrs = collect();
|
||||
|
||||
$i = $this->parseList(++$i,$strings,$attrs);
|
||||
|
||||
Log::debug(sprintf('= parseList returned %d (%s)',$i,$attrs->join(',')));
|
||||
|
||||
foreach ($attrs as $string) {
|
||||
$attr = new ObjectClassAttribute($string,$this->name);
|
||||
|
||||
if ($server->isForceMay($attr->getName())) {
|
||||
$this->may_force->push($attr);
|
||||
$this->may_attrs->push($attr);
|
||||
|
||||
} else
|
||||
$this->must_attrs->push($attr);
|
||||
}
|
||||
|
||||
Log::debug(sprintf('- Case MUST returned (%s) (%s)',$this->must_attrs->join(','),$this->may_force->join(',')));
|
||||
break;
|
||||
|
||||
case 'MAY':
|
||||
$attrs = collect();
|
||||
|
||||
$i = $this->parseList(++$i,$strings,$attrs);
|
||||
|
||||
Log::debug(sprintf('parseList returned %d (%s)',$i,$attrs->join(',')));
|
||||
|
||||
foreach ($attrs as $string) {
|
||||
$attr = new ObjectClassAttribute($string,$this->name);
|
||||
$this->may_attrs->push($attr);
|
||||
}
|
||||
|
||||
Log::debug(sprintf('- Case MAY returned (%s)',$this->may_attrs->join(',')));
|
||||
break;
|
||||
|
||||
default:
|
||||
if (preg_match('/[\d\.]+/i',$strings[$i]) && ($i === 1)) {
|
||||
$this->oid = $strings[$i];
|
||||
Log::debug(sprintf('- Case default returned (%s)',$this->oid));
|
||||
|
||||
} elseif ($strings[$i])
|
||||
Log::alert(sprintf('! Case default discovered a value NOT parsed (%s)',$strings[$i]),['line'=>$line]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function __get(string $key): mixed
|
||||
{
|
||||
switch ($key) {
|
||||
case 'attributes':
|
||||
return $this->getAllAttrs();
|
||||
|
||||
case 'sup':
|
||||
return $this->sup_classes;
|
||||
|
||||
case 'type_name':
|
||||
switch ($this->type) {
|
||||
case self::OC_STRUCTURAL: return 'Structural';
|
||||
case self::OC_ABSTRACT: return 'Abstract';
|
||||
case self::OC_AUXILIARY: return 'Auxiliary';
|
||||
default:
|
||||
throw new InvalidUsage('Unknown ObjectClass Type: '.$this->type);
|
||||
}
|
||||
|
||||
default: return parent::__get($key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of attributes that this objectClass provides
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getAllAttrs(): Collection
|
||||
{
|
||||
return $this->getMustAttrs()->merge($this->getMayAttrs());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an objectClass to the list of objectClasses that inherit
|
||||
* from this objectClass.
|
||||
*
|
||||
* @param String $name The name of the objectClass to add
|
||||
*/
|
||||
public function addChildObjectClass(string $name): void
|
||||
{
|
||||
if ($this->child_objectclasses->search($name) === FALSE) {
|
||||
$this->child_objectclasses->push($name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the array of objectClass names which inherit from this objectClass.
|
||||
*
|
||||
* @return Collection Names of objectClasses which inherit from this objectClass.
|
||||
* @deprecated use $this->child_objectclasses
|
||||
*/
|
||||
public function getChildObjectClasses(): Collection
|
||||
{
|
||||
return $this->child_objectclasses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Behaves identically to addMustAttrs, but it operates on the MAY
|
||||
* attributes of this objectClass.
|
||||
*
|
||||
* @param array $attr An array of attribute names (strings) to add.
|
||||
*/
|
||||
private function addMayAttrs(array $attr): void
|
||||
{
|
||||
if (! is_array($attr) || ! count($attr))
|
||||
return;
|
||||
|
||||
$this->may_attrs = $this->may_attrs->merge($attr)->unique();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified array of attributes to this objectClass' list of
|
||||
* MUST attributes. The resulting array of must attributes will contain
|
||||
* unique members.
|
||||
*
|
||||
* @param array $attr An array of attribute names (strings) to add.
|
||||
*/
|
||||
private function addMustAttrs(array $attr): void
|
||||
{
|
||||
if (! is_array($attr) || ! count($attr))
|
||||
return;
|
||||
|
||||
$this->must_attrs = $this->must_attrs->merge($attr)->unique();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
* @deprecated use $this->may_force
|
||||
*/
|
||||
public function getForceMayAttrs(): Collection
|
||||
{
|
||||
return $this->may_force;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an array of AttributeType objects that entries of this ObjectClass may define.
|
||||
* This differs from getMayAttrNames in that it returns an array of AttributeType objects
|
||||
*
|
||||
* @param bool $parents Also get the may attrs of our parents.
|
||||
* @return Collection The array of allowed AttributeType objects.
|
||||
*
|
||||
* @throws InvalidUsage
|
||||
* @see getMustAttrNames
|
||||
* @see getMustAttrs
|
||||
* @see getMayAttrNames
|
||||
* @see AttributeType
|
||||
*/
|
||||
public function getMayAttrs(bool $parents=FALSE): Collection
|
||||
{
|
||||
// If we dont need our parents, then we'll just return ours.
|
||||
if (! $parents)
|
||||
return $this->may_attrs->sortBy(function($item) { return strtolower($item->name.$item->source); });
|
||||
|
||||
$attrs = $this->may_attrs;
|
||||
|
||||
foreach ($this->getParents() as $object_class) {
|
||||
$sc = $this->server->schema('objectclasses',$object_class);
|
||||
$attrs = $attrs->merge($sc->getMayAttrs($parents));
|
||||
}
|
||||
|
||||
// Remove any duplicates
|
||||
$attrs = $attrs->unique(function($item) { return $item->name; });
|
||||
|
||||
// Return a sorted list
|
||||
return $attrs->sortBy(function($item) { return strtolower($item->name.$item->source); });
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an array of attribute names (strings) that entries of this ObjectClass must define.
|
||||
* This differs from getMayAttrs in that it returns an array of strings rather than
|
||||
* array of AttributeType objects
|
||||
*
|
||||
* @param bool $parents An array of ObjectClass objects to use when traversing
|
||||
* the inheritance tree. This presents some what of a bootstrapping problem
|
||||
* as we must fetch all objectClasses to determine through inheritance which
|
||||
* attributes this objectClass provides.
|
||||
* @return Collection The array of allowed attribute names (strings).
|
||||
*
|
||||
* @throws InvalidUsage
|
||||
* @see getMustAttrs
|
||||
* @see getMayAttrs
|
||||
* @see getMustAttrNames
|
||||
*/
|
||||
public function getMayAttrNames(bool $parents=FALSE): Collection
|
||||
{
|
||||
return $this->getMayAttrs($parents)->ppluck('name');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an array of AttributeType objects that entries of this ObjectClass must define.
|
||||
* This differs from getMustAttrNames in that it returns an array of AttributeType objects
|
||||
*
|
||||
* @param bool $parents Also get the must attrs of our parents.
|
||||
* @return Collection The array of required AttributeType objects.
|
||||
*
|
||||
* @throws InvalidUsage
|
||||
* @see getMustAttrNames
|
||||
* @see getMayAttrs
|
||||
* @see getMayAttrNames
|
||||
*/
|
||||
public function getMustAttrs(bool $parents=FALSE): Collection
|
||||
{
|
||||
// If we dont need our parents, then we'll just return ours.
|
||||
if (! $parents)
|
||||
return $this->must_attrs->sortBy(function($item) { return strtolower($item->name.$item->source); });
|
||||
|
||||
$attrs = $this->must_attrs;
|
||||
|
||||
foreach ($this->getParents() as $object_class) {
|
||||
$sc = $this->server->schema('objectclasses',$object_class);
|
||||
$attrs = $attrs->merge($sc->getMustAttrs($parents));
|
||||
}
|
||||
|
||||
// Remove any duplicates
|
||||
$attrs = $attrs->unique(function($item) { return $item->name; });
|
||||
|
||||
// Return a sorted list
|
||||
return $attrs->sortBy(function($item) { return strtolower($item->name.$item->source); });
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an array of attribute names (strings) that entries of this ObjectClass must define.
|
||||
* This differs from getMustAttrs in that it returns an array of strings rather than
|
||||
* array of AttributeType objects
|
||||
*
|
||||
* @param bool $parents An array of ObjectClass objects to use when traversing
|
||||
* the inheritance tree. This presents some what of a bootstrapping problem
|
||||
* as we must fetch all objectClasses to determine through inheritance which
|
||||
* attributes this objectClass provides.
|
||||
* @return Collection The array of allowed attribute names (strings).
|
||||
*
|
||||
* @throws InvalidUsage
|
||||
* @see getMustAttrs
|
||||
* @see getMayAttrs
|
||||
* @see getMayAttrNames
|
||||
*/
|
||||
public function getMustAttrNames(bool $parents=FALSE): Collection
|
||||
{
|
||||
return $this->getMustAttrs($parents)->ppluck('name');
|
||||
}
|
||||
|
||||
/**
|
||||
* This will return all our parent ObjectClass Objects
|
||||
*/
|
||||
public function getParents(): Collection
|
||||
{
|
||||
// If the only class is 'top', then we have no more parents
|
||||
if (($this->sup_classes->count() === 1) && (strtolower($this->sup_classes->first()) === 'top'))
|
||||
return collect();
|
||||
|
||||
$result = collect();
|
||||
|
||||
foreach ($this->sup_classes as $object_class) {
|
||||
$result->push($object_class);
|
||||
|
||||
$oc = $this->server->schema('objectclasses',$object_class);
|
||||
|
||||
if ($oc)
|
||||
$result = $result->merge($oc->getParents());
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the objectClass names from which this objectClass inherits.
|
||||
*
|
||||
* @return Collection An array of objectClass names (strings)
|
||||
* @deprecated use $this->sup_classes;
|
||||
*/
|
||||
public function getSupClasses(): Collection
|
||||
{
|
||||
return $this->sup_classes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of this objectClass: STRUCTURAL, ABSTRACT, or AUXILIARY.
|
||||
*
|
||||
* @deprecated use $this->type_name
|
||||
*/
|
||||
public function getType()
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if an array is listed in the may_force attrs
|
||||
*/
|
||||
public function isForceMay(string $attr): bool
|
||||
{
|
||||
return $this->may_force->ppluck('name')->contains($attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if this objectClass is related to $oclass
|
||||
*
|
||||
* @param array $oclass ObjectClasses that this attribute may be related to
|
||||
* @return bool
|
||||
* @throws InvalidUsage
|
||||
*/
|
||||
public function isRelated(array $oclass): bool
|
||||
{
|
||||
// If I am in the array, we'll just return false
|
||||
if (in_array_ignore_case($this->name,$oclass))
|
||||
return FALSE;
|
||||
|
||||
foreach ($oclass as $object_class) {
|
||||
$oc = $this->server->schema('objectclasses',$object_class);
|
||||
|
||||
if ($oc->isStructural() && in_array_ignore_case($this->name,$oc->getParents()))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
public function isStructural(): bool
|
||||
{
|
||||
return $this->type === self::OC_STRUCTURAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse an LDAP schema list
|
||||
*
|
||||
* A list starts with a ( followed by a list of attributes separated by $ terminated by )
|
||||
* The first token can therefore be a ( or a (NAME or a (NAME)
|
||||
* The last token can therefore be a ) or NAME)
|
||||
* The last token may be terminated by more than one bracket
|
||||
*/
|
||||
private function parseList(int $i,array $strings,Collection &$attrs): int
|
||||
{
|
||||
$string = $strings[$i];
|
||||
|
||||
if (! preg_match('/^\(/',$string)) {
|
||||
// A bareword only - can be terminated by a ) if the last item
|
||||
if (preg_match('/\)+$/',$string))
|
||||
$string = preg_replace('/\)+$/','',$string);
|
||||
|
||||
$attrs->push($string);
|
||||
|
||||
} elseif (preg_match('/^\(.*\)$/',$string)) {
|
||||
$string = preg_replace('/^\(/','',$string);
|
||||
$string = preg_replace('/\)+$/','',$string);
|
||||
|
||||
$attrs->push($string);
|
||||
|
||||
} else {
|
||||
// Handle the opening cases first
|
||||
if ($string === '(') {
|
||||
$i++;
|
||||
|
||||
} elseif (preg_match('/^\(./',$string)) {
|
||||
$string = preg_replace('/^\(/','',$string);
|
||||
$attrs->push($string);
|
||||
$i++;
|
||||
}
|
||||
|
||||
// Token is either a name, a $ or a ')'
|
||||
// NAME can be terminated by one or more ')'
|
||||
while (! preg_match('/\)+$/',$strings[$i])) {
|
||||
$string = $strings[$i];
|
||||
|
||||
if ($string === '$') {
|
||||
$i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (preg_match('/\)$/',$string))
|
||||
$string = preg_replace('/\)+$/','',$string);
|
||||
else
|
||||
$i++;
|
||||
|
||||
$attrs->push($string);
|
||||
}
|
||||
}
|
||||
|
||||
$attrs = $attrs->sort();
|
||||
|
||||
return $i;
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\LDAP\Schema;
|
||||
|
||||
/**
|
||||
* A simple class for representing AttributeTypes used only by the ObjectClass class.
|
||||
*
|
||||
* Users should never instantiate this class. It represents an attribute internal to
|
||||
* an ObjectClass. If PHP supported inner-classes and variable permissions, this would
|
||||
* be interior to class ObjectClass and flagged private. The reason this class is used
|
||||
* and not the "real" class AttributeType is because this class supports the notion of
|
||||
* a "source" objectClass, meaning that it keeps track of which objectClass originally
|
||||
* specified it. This class is therefore used by the class ObjectClass to determine
|
||||
* inheritance.
|
||||
*/
|
||||
final class ObjectClassAttribute extends Base {
|
||||
// This Attribute's root.
|
||||
private string $source;
|
||||
|
||||
/**
|
||||
* Creates a new ObjectClassAttribute with specified name and source objectClass.
|
||||
*
|
||||
* @param string $name the name of the new attribute.
|
||||
* @param string $source the name of the ObjectClass which specifies this attribute.
|
||||
*/
|
||||
public function __construct($name,$source)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->source = $source;
|
||||
}
|
||||
|
||||
public function __get(string $key): mixed
|
||||
{
|
||||
switch ($key) {
|
||||
case 'source':
|
||||
return $this->source;
|
||||
|
||||
default: return parent::__get($key);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,551 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\LDAP;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Exception;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
use Illuminate\Support\Facades\Cookie;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use LdapRecord\LdapRecordException;
|
||||
use LdapRecord\Models\Model;
|
||||
use LdapRecord\Query\Collection as LDAPCollection;
|
||||
use LdapRecord\Query\ObjectNotFoundException;
|
||||
|
||||
use App\Classes\LDAP\Schema\{AttributeType,Base,LDAPSyntax,MatchingRule,MatchingRuleUse,ObjectClass};
|
||||
use App\Exceptions\InvalidUsage;
|
||||
use App\Ldap\Entry;
|
||||
|
||||
final class Server
|
||||
{
|
||||
// This servers schema objectclasses
|
||||
private Collection $attributetypes;
|
||||
private Collection $ldapsyntaxes;
|
||||
private Collection $matchingrules;
|
||||
private Collection $matchingruleuse;
|
||||
private Collection $objectclasses;
|
||||
|
||||
// Valid items that can be fetched
|
||||
public const schema_types = [
|
||||
'objectclasses',
|
||||
'attributetypes',
|
||||
'ldapsyntaxes',
|
||||
'matchingrules',
|
||||
];
|
||||
|
||||
public function __get(string $key): mixed
|
||||
{
|
||||
switch ($key) {
|
||||
case 'attributetypes': return $this->attributetypes;
|
||||
case 'ldapsyntaxes': return $this->ldapsyntaxes;
|
||||
case 'matchingrules': return $this->matchingrules;
|
||||
case 'objectclasses': return $this->objectclasses;
|
||||
|
||||
default:
|
||||
throw new Exception('Unknown key:'.$key);
|
||||
}
|
||||
}
|
||||
|
||||
/* STATIC METHODS */
|
||||
|
||||
/**
|
||||
* Gets the root DN of the specified LDAPServer, or throws an exception if it
|
||||
* can't find it.
|
||||
*
|
||||
* @param null $connection Return a collection of baseDNs
|
||||
* @param bool $objects Return a collection of Entry Models
|
||||
* @return Collection
|
||||
* @throws ObjectNotFoundException
|
||||
* @testedin GetBaseDNTest::testBaseDNExists();
|
||||
* @todo Need to allow for the scenario if the baseDN is not readable by ACLs
|
||||
*/
|
||||
public static function baseDNs($connection=NULL,bool $objects=TRUE): Collection
|
||||
{
|
||||
$cachetime = Carbon::now()->addSeconds(Config::get('ldap.cache.time'));
|
||||
|
||||
try {
|
||||
$base = self::rootDSE($connection,$cachetime);
|
||||
|
||||
/**
|
||||
* LDAP Error Codes:
|
||||
* https://ldap.com/ldap-result-code-reference/
|
||||
* + success 0
|
||||
* + operationsError 1
|
||||
* + protocolError 2
|
||||
* + timeLimitExceeded 3
|
||||
* + sizeLimitExceeded 4
|
||||
* + compareFalse 5
|
||||
* + compareTrue 6
|
||||
* + authMethodNotSupported 7
|
||||
* + strongerAuthRequired 8
|
||||
* + referral 10
|
||||
* + adminLimitExceeded 11
|
||||
* + unavailableCriticalExtension 12
|
||||
* + confidentialityRequired 13
|
||||
* + saslBindInProgress 14
|
||||
* + noSuchAttribute 16
|
||||
* + undefinedAttributeType 17
|
||||
* + inappropriateMatching 18
|
||||
* + constraintViolation 19
|
||||
* + attributeOrValueExists 20
|
||||
* + invalidAttributeSyntax 21
|
||||
* + noSuchObject 32
|
||||
* + aliasProblem 33
|
||||
* + invalidDNSyntax 34
|
||||
* + isLeaf 35
|
||||
* + aliasDereferencingProblem 36
|
||||
* + inappropriateAuthentication 48
|
||||
* + invalidCredentials 49
|
||||
* + insufficientAccessRights 50
|
||||
* + busy 51
|
||||
* + unavailable 52
|
||||
* + unwillingToPerform 53
|
||||
* + loopDetect 54
|
||||
* + sortControlMissing 60
|
||||
* + offsetRangeError 61
|
||||
* + namingViolation 64
|
||||
* + objectClassViolation 65
|
||||
* + notAllowedOnNonLeaf 66
|
||||
* + notAllowedOnRDN 67
|
||||
* + entryAlreadyExists 68
|
||||
* + objectClassModsProhibited 69
|
||||
* + resultsTooLarge 70
|
||||
* + affectsMultipleDSAs 71
|
||||
* + virtualListViewError or controlError 76
|
||||
* + other 80
|
||||
* + serverDown 81
|
||||
* + localError 82
|
||||
* + encodingError 83
|
||||
* + decodingError 84
|
||||
* + timeout 85
|
||||
* + authUnknown 86
|
||||
* + filterError 87
|
||||
* + userCanceled 88
|
||||
* + paramError 89
|
||||
* + noMemory 90
|
||||
* + connectError 91
|
||||
* + notSupported 92
|
||||
* + controlNotFound 93
|
||||
* + noResultsReturned 94
|
||||
* + moreResultsToReturn 95
|
||||
* + clientLoop 96
|
||||
* + referralLimitExceeded 97
|
||||
* + invalidResponse 100
|
||||
* + ambiguousResponse 101
|
||||
* + tlsNotSupported 112
|
||||
* + intermediateResponse 113
|
||||
* + unknownType 114
|
||||
* + canceled 118
|
||||
* + noSuchOperation 119
|
||||
* + tooLate 120
|
||||
* + cannotCancel 121
|
||||
* + assertionFailed 122
|
||||
* + authorizationDenied 123
|
||||
* + e-syncRefreshRequired 4096
|
||||
* + noOperation 16654
|
||||
*
|
||||
* LDAP Tag Codes:
|
||||
* + A client bind operation 97
|
||||
* + The entry for which you were searching 100
|
||||
* + The result from a search operation 101
|
||||
* + The result from a modify operation 103
|
||||
* + The result from an add operation 105
|
||||
* + The result from a delete operation 107
|
||||
* + The result from a modify DN operation 109
|
||||
* + The result from a compare operation 111
|
||||
* + A search reference when the entry you perform your search on holds a referral to the entry you require.
|
||||
* + Search references are expressed in terms of a referral.
|
||||
* 115
|
||||
* + A result from an extended operation 120
|
||||
*/
|
||||
// If we cannot get to our LDAP server we'll head straight to the error page
|
||||
} catch (LdapRecordException $e) {
|
||||
switch ($e->getDetailedError()->getErrorCode()) {
|
||||
case 49:
|
||||
// Since we failed authentication, we should delete our auth cookie
|
||||
if (Cookie::has('password_encrypt')) {
|
||||
Log::alert('Clearing user credentials and logging out');
|
||||
|
||||
Cookie::queue(Cookie::forget('password_encrypt'));
|
||||
Cookie::queue(Cookie::forget('username_encrypt'));
|
||||
|
||||
Session::invalidate();
|
||||
}
|
||||
|
||||
abort(401,$e->getDetailedError()->getErrorMessage());
|
||||
|
||||
default:
|
||||
abort(597,$e->getDetailedError()->getErrorMessage());
|
||||
}
|
||||
}
|
||||
|
||||
if (! $objects)
|
||||
return collect($base->namingcontexts);
|
||||
|
||||
/**
|
||||
* @note While we are caching our baseDNs, it seems if we have more than 1,
|
||||
* our caching doesnt generate a hit on a subsequent call to this function (before the cache expires).
|
||||
* IE: If we have 5 baseDNs, it takes 5 calls to this function to case them all.
|
||||
* @todo Possibly a bug wtih ldaprecord, so need to investigate
|
||||
*/
|
||||
$result = collect();
|
||||
foreach ($base->namingcontexts as $dn) {
|
||||
$result->push((new Entry)->cache($cachetime)->findOrFail($dn));
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the rootDSE for the server, that gives us server information
|
||||
*
|
||||
* @param null $connection
|
||||
* @return Entry|null
|
||||
* @throws ObjectNotFoundException
|
||||
* @testedin TranslateOidTest::testRootDSE();
|
||||
*/
|
||||
public static function rootDSE($connection=NULL,Carbon $cachetime=NULL): ?Model
|
||||
{
|
||||
$e = new Entry;
|
||||
|
||||
return Entry::on($connection ?? $e->getConnectionName())
|
||||
->cache($cachetime)
|
||||
->in(NULL)
|
||||
->read()
|
||||
->select(['+'])
|
||||
->whereHas('objectclass')
|
||||
->firstOrFail();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Schema DN
|
||||
*
|
||||
* @param $connection
|
||||
* @return string
|
||||
* @throws ObjectNotFoundException
|
||||
*/
|
||||
public static function schemaDN($connection=NULL): string
|
||||
{
|
||||
$cachetime = Carbon::now()->addSeconds(Config::get('ldap.cache.time'));
|
||||
|
||||
return collect(self::rootDSE($connection,$cachetime)->subschemasubentry)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the server for a DN and return its children and if those children have children.
|
||||
*
|
||||
* @param string $dn
|
||||
* @return LDAPCollection|NULL
|
||||
*/
|
||||
public function children(string $dn): ?LDAPCollection
|
||||
{
|
||||
return ($x=(new Entry)
|
||||
->query()
|
||||
->cache(Carbon::now()->addSeconds(Config::get('ldap.cache.time')))
|
||||
->select(['*','hassubordinates'])
|
||||
->setDn($dn)
|
||||
->list()
|
||||
->get()) ? $x : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a DN from the server
|
||||
*
|
||||
* @param string $dn
|
||||
* @param array $attrs
|
||||
* @return Entry|null
|
||||
*/
|
||||
public function fetch(string $dn,array $attrs=['*','+']): ?Entry
|
||||
{
|
||||
return ($x=(new Entry)
|
||||
->query()
|
||||
->cache(Carbon::now()->addSeconds(Config::get('ldap.cache.time')))
|
||||
->select($attrs)
|
||||
->find($dn)) ? $x : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function determines if the specified attribute is contained in the force_may list
|
||||
* as configured in config.php.
|
||||
*
|
||||
* @return boolean True if the specified attribute is configured to be force as a may attribute
|
||||
*/
|
||||
public function isForceMay($attr_name): bool
|
||||
{
|
||||
return in_array($attr_name,config('pla.force_may',[]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this server support RFC3666 language tags
|
||||
* OID: 1.3.6.1.4.1.4203.1.5.4
|
||||
*
|
||||
* @return bool
|
||||
* @throws ObjectNotFoundException
|
||||
*/
|
||||
public function isLanguageTags(): bool
|
||||
{
|
||||
return in_array('1.3.6.1.4.1.4203.1.5.4',$this->rootDSE()->supportedfeatures);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the server's schema
|
||||
*
|
||||
* @param string $item Schema Item to Fetch
|
||||
* @param string|null $key
|
||||
* @return Collection|Base|NULL
|
||||
* @throws InvalidUsage
|
||||
*/
|
||||
public function schema(string $item,string $key=NULL): Collection|Base|NULL
|
||||
{
|
||||
// Ensure our item to fetch is lower case
|
||||
$item = strtolower($item);
|
||||
if ($key)
|
||||
$key = strtolower($key);
|
||||
|
||||
// This error message is not localized as only developers should ever see it
|
||||
if (! in_array($item,self::schema_types))
|
||||
throw new InvalidUsage('Invalid request to fetch schema: '.$item);
|
||||
|
||||
$result = Cache::remember('schema'.$item,config('ldap.cache.time'),function() use ($item) {
|
||||
// First pass if we have already retrieved the schema item
|
||||
switch ($item) {
|
||||
case 'attributetypes':
|
||||
if (isset($this->attributetypes))
|
||||
return $this->attributetypes;
|
||||
else
|
||||
$this->attributetypes = collect();
|
||||
|
||||
break;
|
||||
|
||||
case 'ldapsyntaxes':
|
||||
if (isset($this->ldapsyntaxes))
|
||||
return $this->ldapsyntaxes;
|
||||
else
|
||||
$this->ldapsyntaxes = collect();
|
||||
|
||||
break;
|
||||
|
||||
case 'matchingrules':
|
||||
if (isset($this->matchingrules))
|
||||
return $this->matchingrules;
|
||||
else
|
||||
$this->matchingrules = collect();
|
||||
|
||||
break;
|
||||
|
||||
/*
|
||||
case 'matchingruleuse':
|
||||
if (isset($this->matchingruleuse))
|
||||
return is_null($key) ? $this->matchingruleuse : $this->matchingruleuse->get($key);
|
||||
else
|
||||
$this->matchingruleuse = collect();
|
||||
|
||||
break;
|
||||
*/
|
||||
|
||||
case 'objectclasses':
|
||||
if (isset($this->objectclasses))
|
||||
return $this->objectclasses;
|
||||
else
|
||||
$this->objectclasses = collect();
|
||||
|
||||
break;
|
||||
|
||||
// Shouldnt get here
|
||||
default:
|
||||
throw new InvalidUsage('Invalid request to fetch schema: '.$item);
|
||||
}
|
||||
|
||||
// Try to get the schema DN from the specified entry.
|
||||
$schema_dn = $this->schemaDN();
|
||||
$schema = $this->fetch($schema_dn);
|
||||
|
||||
switch ($item) {
|
||||
case 'attributetypes':
|
||||
Log::debug('Attribute Types');
|
||||
// build the array of attribueTypes
|
||||
//$syntaxes = $this->SchemaSyntaxes($dn);
|
||||
|
||||
foreach ($schema->{$item} as $line) {
|
||||
if (is_null($line) || ! strlen($line))
|
||||
continue;
|
||||
|
||||
$o = new AttributeType($line);
|
||||
$this->attributetypes->put($o->name_lc,$o);
|
||||
|
||||
/*
|
||||
if (isset($syntaxes[$attr->getSyntaxOID()])) {
|
||||
$syntax = $syntaxes[$attr->getSyntaxOID()];
|
||||
$attr->setType($syntax->getDescription());
|
||||
}
|
||||
$this->attributetypes[$attr->getName()] = $attr;
|
||||
*/
|
||||
|
||||
/**
|
||||
* bug 856832: create an entry in the $attrs_oid array too. This
|
||||
* will be a ref to the $attrs entry for maintenance and performance
|
||||
* reasons
|
||||
*/
|
||||
//$attrs_oid[$attr->getOID()] = &$attrs[$attr->getName()];
|
||||
}
|
||||
|
||||
// go back and add data from aliased attributeTypes
|
||||
foreach ($this->attributetypes as $o) {
|
||||
/* foreach of the attribute's aliases, create a new entry in the attrs array
|
||||
* with its name set to the alias name, and all other data copied.*/
|
||||
|
||||
if ($o->aliases->count()) {
|
||||
Log::debug(sprintf('\ Attribute [%s] has the following aliases [%s]',$o->name,$o->aliases->join(',')));
|
||||
|
||||
foreach ($o->aliases as $alias) {
|
||||
$new_attr = clone $o;
|
||||
$new_attr->setName($alias);
|
||||
$new_attr->addAlias($o->name);
|
||||
$new_attr->removeAlias($alias);
|
||||
|
||||
$this->attributetypes->put(strtolower($alias),$new_attr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now go through and reference the parent/child relationships
|
||||
foreach ($this->attributetypes as $o)
|
||||
if ($o->sup_attribute) {
|
||||
$parent = strtolower($o->sup_attribute);
|
||||
|
||||
if ($this->attributetypes->has($parent) !== FALSE)
|
||||
$this->attributetypes[$parent]->addChild($o->name);
|
||||
}
|
||||
|
||||
// go through any children and add details if the child doesnt have them (ie, cn inherits name)
|
||||
// @todo This doesnt traverse children properly, so children of children may not get the settings they should
|
||||
foreach ($this->attributetypes as $parent) {
|
||||
foreach ($parent->children as $child) {
|
||||
$child = strtolower($child);
|
||||
|
||||
/* only overwrite the child's SINGLE-VALUE property if the parent has it set, and the child doesnt
|
||||
* (note: All LDAP attributes default to multi-value if not explicitly set SINGLE-VALUE) */
|
||||
if (! is_null($parent->is_single_value) && is_null($this->attributetypes[$child]->is_single_value))
|
||||
$this->attributetypes[$child]->setIsSingleValue($parent->is_single_value);
|
||||
}
|
||||
}
|
||||
|
||||
// Add the used in and required_by values.
|
||||
foreach ($this->schema('objectclasses') as $object_class) {
|
||||
$must_attrs = $object_class->getMustAttrNames();
|
||||
$may_attrs = $object_class->getMayAttrNames();
|
||||
$oclass_attrs = $must_attrs->merge($may_attrs)->unique();
|
||||
|
||||
// Add Used In.
|
||||
foreach ($oclass_attrs as $attr_name)
|
||||
if ($this->attributetypes->has(strtolower($attr_name)))
|
||||
$this->attributetypes[strtolower($attr_name)]->addUsedInObjectClass($object_class->name);
|
||||
|
||||
// Add Required By.
|
||||
foreach ($must_attrs as $attr_name)
|
||||
if ($this->attributetypes->has(strtolower($attr_name)))
|
||||
$this->attributetypes[strtolower($attr_name)]->addRequiredByObjectClass($object_class->name);
|
||||
|
||||
// Force May
|
||||
foreach ($object_class->getForceMayAttrs() as $attr_name)
|
||||
if ($this->attributetypes->has(strtolower($attr_name->name)))
|
||||
$this->attributetypes[strtolower($attr_name->name)]->setForceMay();
|
||||
}
|
||||
|
||||
return $this->attributetypes;
|
||||
|
||||
case 'ldapsyntaxes':
|
||||
Log::debug('LDAP Syntaxes');
|
||||
|
||||
foreach ($schema->{$item} as $line) {
|
||||
if (is_null($line) || ! strlen($line))
|
||||
continue;
|
||||
|
||||
$o = new LDAPSyntax($line);
|
||||
$this->ldapsyntaxes->put(strtolower($o->oid),$o);
|
||||
}
|
||||
|
||||
return $this->ldapsyntaxes;
|
||||
|
||||
case 'matchingrules':
|
||||
Log::debug('Matching Rules');
|
||||
$this->matchingruleuse = collect();
|
||||
|
||||
foreach ($schema->{$item} as $line) {
|
||||
if (is_null($line) || ! strlen($line))
|
||||
continue;
|
||||
|
||||
$o = new MatchingRule($line);
|
||||
$this->matchingrules->put($o->name_lc,$o);
|
||||
}
|
||||
|
||||
/*
|
||||
* For each MatchingRuleUse entry, add the attributes who use it to the
|
||||
* MatchingRule in the $rules array.
|
||||
*/
|
||||
if ($schema->matchingruleuse) {
|
||||
foreach ($schema->matchingruleuse as $line) {
|
||||
if (is_null($line) || ! strlen($line))
|
||||
continue;
|
||||
|
||||
$o = new MatchingRuleUse($line);
|
||||
$this->matchingruleuse->put($o->name_lc,$o);
|
||||
|
||||
if ($this->matchingrules->has($o->name_lc) !== FALSE)
|
||||
$this->matchingrules[$o->name_lc]->setUsedByAttrs($o->getUsedByAttrs());
|
||||
}
|
||||
|
||||
} else {
|
||||
/* No MatchingRuleUse entry in the subschema, so brute-forcing
|
||||
* the reverse-map for the "$rule->getUsedByAttrs()" data.*/
|
||||
foreach ($this->schema('attributetypes') as $attr) {
|
||||
$rule_key = strtolower($attr->getEquality());
|
||||
|
||||
if ($this->matchingrules->has($rule_key) !== FALSE)
|
||||
$this->matchingrules[$rule_key]->addUsedByAttr($attr->name);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->matchingrules;
|
||||
|
||||
case 'objectclasses':
|
||||
Log::debug('Object Classes');
|
||||
|
||||
foreach ($schema->{$item} as $line) {
|
||||
if (is_null($line) || ! strlen($line))
|
||||
continue;
|
||||
|
||||
$o = new ObjectClass($line,$this);
|
||||
$this->objectclasses->put($o->name_lc,$o);
|
||||
}
|
||||
|
||||
// Now go through and reference the parent/child relationships
|
||||
foreach ($this->objectclasses as $o)
|
||||
foreach ($o->getSupClasses() as $parent) {
|
||||
$parent = strtolower($parent);
|
||||
if ($this->objectclasses->has($parent) !== FALSE)
|
||||
$this->objectclasses[$parent]->addChildObjectClass($o->name);
|
||||
}
|
||||
|
||||
return $this->objectclasses;
|
||||
}
|
||||
});
|
||||
|
||||
return is_null($key) ? $result : $result->get($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an OID, return the ldapsyntax for the OID
|
||||
*
|
||||
* @param string $oid
|
||||
* @return LDAPSyntax|null
|
||||
* @throws InvalidUsage
|
||||
*/
|
||||
public function schemaSyntaxName(string $oid): ?LDAPSyntax
|
||||
{
|
||||
return $this->schema('ldapsyntaxes',$oid);
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console;
|
||||
|
||||
use Illuminate\Console\Scheduling\Schedule;
|
||||
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||
|
||||
class Kernel extends ConsoleKernel
|
||||
{
|
||||
/**
|
||||
* The Artisan commands provided by your application.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $commands = [
|
||||
//
|
||||
];
|
||||
|
||||
/**
|
||||
* Define the application's command schedule.
|
||||
*
|
||||
* @param \Illuminate\Console\Scheduling\Schedule $schedule
|
||||
* @return void
|
||||
*/
|
||||
protected function schedule(Schedule $schedule)
|
||||
{
|
||||
// $schedule->command('inspire')->hourly();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the commands for the application.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function commands()
|
||||
{
|
||||
$this->load(__DIR__.'/Commands');
|
||||
|
||||
require base_path('routes/console.php');
|
||||
}
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Exceptions;
|
||||
|
||||
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
|
||||
use Throwable;
|
||||
|
||||
class Handler extends ExceptionHandler
|
||||
{
|
||||
/**
|
||||
* A list of exception types with their corresponding custom log levels.
|
||||
*
|
||||
* @var array<class-string<\Throwable>, \Psr\Log\LogLevel::*>
|
||||
*/
|
||||
protected $levels = [
|
||||
//
|
||||
];
|
||||
|
||||
/**
|
||||
* A list of the exception types that are not reported.
|
||||
*
|
||||
* @var array<int, class-string<\Throwable>>
|
||||
*/
|
||||
protected $dontReport = [
|
||||
//
|
||||
];
|
||||
|
||||
/**
|
||||
* A list of the inputs that are never flashed to the session on validation exceptions.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $dontFlash = [
|
||||
'current_password',
|
||||
'password',
|
||||
'password_confirmation',
|
||||
];
|
||||
|
||||
/**
|
||||
* Register the exception handling callbacks for the application.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
$this->reportable(function (Throwable $e) {
|
||||
//
|
||||
});
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Exceptions\Import;
|
||||
|
||||
use Exception;
|
||||
|
||||
class AttributeException extends Exception {}
|
@ -1,7 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Exceptions\Import;
|
||||
|
||||
use Exception;
|
||||
|
||||
class GeneralException extends Exception {}
|
@ -1,7 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Exceptions\Import;
|
||||
|
||||
use Exception;
|
||||
|
||||
class ObjectExistsException extends Exception {}
|
@ -1,7 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Exceptions\Import;
|
||||
|
||||
use Exception;
|
||||
|
||||
class VersionException extends Exception {}
|
@ -1,10 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Exceptions;
|
||||
|
||||
use Exception;
|
||||
|
||||
class InvalidUsage extends Exception
|
||||
{
|
||||
//
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
use App\Classes\LDAP\Server;
|
||||
|
||||
class APIController extends Controller
|
||||
{
|
||||
/**
|
||||
* Get the LDAP server BASE DNs
|
||||
*
|
||||
* @return Collection
|
||||
* @throws LdapRecord\Query\ObjectNotFoundException
|
||||
*/
|
||||
public function bases(): Collection
|
||||
{
|
||||
$base = Server::baseDNs() ?: collect();
|
||||
|
||||
return $base->transform(function($item) {
|
||||
return [
|
||||
'title'=>$item->getRdn(),
|
||||
'item'=>$item->getDNSecure(),
|
||||
'lazy'=>TRUE,
|
||||
'icon'=>'fa-fw fas fa-sitemap',
|
||||
'tooltip'=>$item->getDn(),
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @return Collection
|
||||
*/
|
||||
public function children(Request $request): Collection
|
||||
{
|
||||
$levels = $request->query('depth',1);
|
||||
$dn = Crypt::decryptString($request->query('key'));
|
||||
Log::debug(sprintf('%s: Query [%s] - Levels [%d]',__METHOD__,$dn,$levels));
|
||||
|
||||
return (config('server'))
|
||||
->children($dn)
|
||||
->transform(function($item) {
|
||||
return [
|
||||
'title'=>$item->getRdn(),
|
||||
'item'=>$item->getDNSecure(),
|
||||
'icon'=>$item->icon(),
|
||||
'lazy'=>Arr::get($item->getAttribute('hassubordinates'),0) == 'TRUE',
|
||||
'tooltip'=>$item->getDn(),
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
public function schema_view(Request $request)
|
||||
{
|
||||
$server = new Server;
|
||||
|
||||
switch($request->type) {
|
||||
case 'objectclasses':
|
||||
return view('fragment.schema.objectclasses')
|
||||
->with('objectclasses',$server->schema('objectclasses')->sortBy(function($item) { return strtolower($item->name); }));
|
||||
|
||||
case 'attributetypes':
|
||||
return view('fragment.schema.attributetypes')
|
||||
->with('server',$server)
|
||||
->with('attributetypes',$server->schema('attributetypes')->sortBy(function($item) { return strtolower($item->name); }));
|
||||
|
||||
case 'ldapsyntaxes':
|
||||
return view('fragment.schema.ldapsyntaxes')
|
||||
->with('ldapsyntaxes',$server->schema('ldapsyntaxes')->sortBy(function($item) { return strtolower($item->description); }));
|
||||
|
||||
case 'matchingrules':
|
||||
return view('fragment.schema.matchingrules')
|
||||
->with('matchingrules',$server->schema('matchingrules')->sortBy(function($item) { return strtolower($item->name); }));
|
||||
|
||||
default:
|
||||
abort(404);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,104 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use Illuminate\Foundation\Auth\AuthenticatesUsers;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Cookie;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Providers\RouteServiceProvider;
|
||||
|
||||
class LoginController extends Controller
|
||||
{
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Login Controller
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This controller handles authenticating users for the application and
|
||||
| redirecting them to your home screen. The controller uses a trait
|
||||
| to conveniently provide its functionality to your applications.
|
||||
|
|
||||
*/
|
||||
|
||||
use AuthenticatesUsers;
|
||||
|
||||
/**
|
||||
* Where to redirect users after login.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $redirectTo = RouteServiceProvider::HOME;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('guest')->except('logout');
|
||||
}
|
||||
|
||||
protected function credentials(Request $request): array
|
||||
{
|
||||
return [
|
||||
login_attr_name() => $request->get(login_attr_name()),
|
||||
'password' => $request->get('password'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* We need to delete our encrypted username/password cookies
|
||||
*
|
||||
* @note The rest of this function is the same as a normal laravel logout as in AuthenticatesUsers::class
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Contracts\Foundation\Application|JsonResponse|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|mixed
|
||||
*/
|
||||
public function logout(Request $request)
|
||||
{
|
||||
// Delete our LDAP authentication cookies
|
||||
Cookie::queue(Cookie::forget('username_encrypt'));
|
||||
Cookie::queue(Cookie::forget('password_encrypt'));
|
||||
|
||||
$this->guard()->logout();
|
||||
|
||||
$request->session()->invalidate();
|
||||
|
||||
$request->session()->regenerateToken();
|
||||
|
||||
if ($response = $this->loggedOut($request)) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
return $request->wantsJson()
|
||||
? new JsonResponse([], 204)
|
||||
: redirect('/');
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Show our themed login page
|
||||
*/
|
||||
public function showLoginForm()
|
||||
{
|
||||
$login_note = '';
|
||||
|
||||
if (file_exists('login_note.txt'))
|
||||
$login_note = file_get_contents('login_note.txt');
|
||||
|
||||
return view('architect::auth.login')->with('login_note',$login_note);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the login username to be used by the controller.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function username()
|
||||
{
|
||||
return login_attr_name();
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||
use Illuminate\Routing\Controller as BaseController;
|
||||
|
||||
class Controller extends BaseController
|
||||
{
|
||||
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
|
||||
}
|
@ -1,309 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Redirect;
|
||||
use LdapRecord\Exceptions\InsufficientAccessException;
|
||||
use LdapRecord\LdapRecordException;
|
||||
use LdapRecord\Query\ObjectNotFoundException;
|
||||
|
||||
use App\Classes\LDAP\{Attribute,Server};
|
||||
use App\Classes\LDAP\Import\LDIF as LDIFImport;
|
||||
use App\Classes\LDAP\Export\LDIF as LDIFExport;
|
||||
use App\Exceptions\Import\{GeneralException,VersionException};
|
||||
use App\Exceptions\InvalidUsage;
|
||||
use App\Http\Requests\{EntryRequest,ImportRequest};
|
||||
use App\Ldap\Entry;
|
||||
use App\View\Components\AttributeType;
|
||||
use Nette\NotImplementedException;
|
||||
|
||||
class HomeController extends Controller
|
||||
{
|
||||
private function bases()
|
||||
{
|
||||
$base = Server::baseDNs() ?: collect();
|
||||
|
||||
return $base->transform(function($item) {
|
||||
return [
|
||||
'title'=>$item->getRdn(),
|
||||
'item'=>$item->getDNSecure(),
|
||||
'lazy'=>TRUE,
|
||||
'icon'=>'fa-fw fas fa-sitemap',
|
||||
'tooltip'=>$item->getDn(),
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Debug Page
|
||||
*
|
||||
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function debug()
|
||||
{
|
||||
return view('debug');
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a specific DN
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function dn_frame(Request $request)
|
||||
{
|
||||
$dn = Crypt::decryptString($request->post('key'));
|
||||
|
||||
$page_actions = collect(['edit'=>TRUE,'copy'=>TRUE]);
|
||||
|
||||
return view('frames.dn')
|
||||
->with('o',config('server')->fetch($dn))
|
||||
->with('dn',$dn)
|
||||
->with('page_actions',$page_actions);
|
||||
}
|
||||
|
||||
public function entry_export(Request $request,string $id)
|
||||
{
|
||||
$dn = Crypt::decryptString($id);
|
||||
|
||||
$result = (new Entry)
|
||||
->query()
|
||||
//->cache(Carbon::now()->addSeconds(Config::get('ldap.cache.time')))
|
||||
//->select(['*'])
|
||||
->setDn($dn)
|
||||
->recursive()
|
||||
->get();
|
||||
|
||||
return view('fragment.export')
|
||||
->with('result',new LDIFExport($result));
|
||||
}
|
||||
|
||||
public function entry_newattr(string $id)
|
||||
{
|
||||
$x = new AttributeType(new Attribute($id,[]),TRUE);
|
||||
return $x->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a confirmation to update a DN
|
||||
*
|
||||
* @param EntryRequest $request
|
||||
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Foundation\Application|\Illuminate\Http\RedirectResponse
|
||||
* @throws ObjectNotFoundException
|
||||
*/
|
||||
public function entry_pending_update(EntryRequest $request)
|
||||
{
|
||||
$dn = Crypt::decryptString($request->dn);
|
||||
|
||||
$o = config('server')->fetch($dn);
|
||||
|
||||
foreach ($request->except(['_token','dn']) as $key => $value)
|
||||
$o->{$key} = array_filter($value);
|
||||
|
||||
if (! $o->getDirty())
|
||||
return back()
|
||||
->withInput()
|
||||
->with('note',__('No attributes changed'));
|
||||
|
||||
return view('update')
|
||||
->with('bases',$this->bases())
|
||||
->with('dn',$dn)
|
||||
->with('o',$o);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a DN entry
|
||||
*
|
||||
* @param EntryRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws ObjectNotFoundException
|
||||
*/
|
||||
public function entry_update(EntryRequest $request)
|
||||
{
|
||||
$dn = Crypt::decryptString($request->dn);
|
||||
|
||||
$o = config('server')->fetch($dn);
|
||||
|
||||
foreach ($request->except(['_token','dn']) as $key => $value)
|
||||
$o->{$key} = array_filter($value);
|
||||
|
||||
if (! $dirty=$o->getDirty())
|
||||
return back()
|
||||
->withInput()
|
||||
->with('note',__('No attributes changed'));
|
||||
|
||||
try {
|
||||
$o->update($request->except(['_token','dn']));
|
||||
|
||||
} catch (InsufficientAccessException $e) {
|
||||
$request->flash();
|
||||
|
||||
switch ($x=$e->getDetailedError()->getErrorCode()) {
|
||||
case 50:
|
||||
return Redirect::to('/')
|
||||
->withInput()
|
||||
->withErrors(sprintf('%s: %s (%s)',__('LDAP Server Error Code'),$x,__($e->getDetailedError()->getErrorMessage())));
|
||||
|
||||
default:
|
||||
abort(599,$e->getDetailedError()->getErrorMessage());
|
||||
}
|
||||
|
||||
} catch (LdapRecordException $e) {
|
||||
$request->flash();
|
||||
|
||||
switch ($x=$e->getDetailedError()->getErrorCode()) {
|
||||
case 8:
|
||||
return Redirect::to('/')
|
||||
->withInput()
|
||||
->withErrors(sprintf('%s: %s (%s)',__('LDAP Server Error Code'),$x,__($e->getDetailedError()->getErrorMessage())));
|
||||
|
||||
default:
|
||||
abort(599,$e->getDetailedError()->getErrorMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return Redirect::to('/')
|
||||
->withInput()
|
||||
->with('success',__('Entry updated'))
|
||||
->with('updated',$dirty);
|
||||
}
|
||||
|
||||
/**
|
||||
* Application home page
|
||||
*/
|
||||
public function home()
|
||||
{
|
||||
if (old('dn'))
|
||||
return view('frame')
|
||||
->with('subframe','dn')
|
||||
->with('bases',$this->bases())
|
||||
->with('o',config('server')->fetch($dn=Crypt::decryptString(old('dn'))))
|
||||
->with('dn',$dn);
|
||||
|
||||
elseif (old('frame'))
|
||||
return view('frame')
|
||||
->with('subframe',old('frame'))
|
||||
->with('bases',$this->bases());
|
||||
|
||||
else
|
||||
return view('home')
|
||||
->with('bases',$this->bases())
|
||||
->with('server',config('ldap.connections.default.name'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the incoming LDIF file or LDIF text
|
||||
*
|
||||
* @param ImportRequest $request
|
||||
* @param string $type
|
||||
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Foundation\Application
|
||||
* @throws GeneralException
|
||||
* @throws VersionException
|
||||
*/
|
||||
public function import(ImportRequest $request,string $type)
|
||||
{
|
||||
switch ($type) {
|
||||
case 'ldif':
|
||||
$import = new LDIFImport($x=($request->text ?: $request->file->get()));
|
||||
break;
|
||||
|
||||
default:
|
||||
abort(404,'Unknown import type: '.$type);
|
||||
}
|
||||
|
||||
try {
|
||||
$result = $import->process();
|
||||
|
||||
} catch (NotImplementedException $e) {
|
||||
abort(555,$e->getMessage());
|
||||
|
||||
} catch (\Exception $e) {
|
||||
abort(598,$e->getMessage());
|
||||
}
|
||||
|
||||
return view('frame')
|
||||
->with('subframe','import_result')
|
||||
->with('bases',$this->bases())
|
||||
->with('result',$result)
|
||||
->with('ldif',htmlspecialchars($x));
|
||||
}
|
||||
|
||||
public function import_frame()
|
||||
{
|
||||
return view('frames.import');
|
||||
}
|
||||
|
||||
/**
|
||||
* LDAP Server INFO
|
||||
*
|
||||
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function info()
|
||||
{
|
||||
return view('frames.info')
|
||||
->with('s',config('server'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the Schema Viewer
|
||||
*
|
||||
* @note Our route will validate that types are valid.
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
|
||||
* @throws InvalidUsage
|
||||
*/
|
||||
public function schema_frame(Request $request)
|
||||
{
|
||||
$s = config('server');
|
||||
|
||||
// If an invalid key, we'll 404
|
||||
if ($request->type && $request->key && ($s->schema($request->type)->has($request->key) === FALSE))
|
||||
abort(404);
|
||||
|
||||
return view('frames.schema')
|
||||
->with('type',$request->type)
|
||||
->with('key',$request->key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the attributes
|
||||
*
|
||||
* @param Collection $attrs
|
||||
* @return Collection
|
||||
*/
|
||||
private function sortAttrs(Collection $attrs): Collection
|
||||
{
|
||||
return $attrs->sortKeys();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the image for the logged in user or anonymous
|
||||
*
|
||||
* @param Request $request
|
||||
* @return mixed
|
||||
*/
|
||||
public function user_image(Request $request)
|
||||
{
|
||||
$image = NULL;
|
||||
$content = NULL;
|
||||
|
||||
if (Auth::check()) {
|
||||
$image = Arr::get(Auth::user()->getAttribute('jpegphoto'),0);
|
||||
$content = 'image/jpeg';
|
||||
}
|
||||
|
||||
if (! $image) {
|
||||
$image = File::get('../resources/images/user-secret-solid.svg');
|
||||
$content = 'image/svg+xml';
|
||||
}
|
||||
|
||||
return response($image)
|
||||
->header('Content-Type',$content);
|
||||
}
|
||||
}
|
@ -1,82 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http;
|
||||
|
||||
use Illuminate\Foundation\Http\Kernel as HttpKernel;
|
||||
|
||||
use App\Http\Middleware\{ApplicationSession,CheckUpdate,SwapinAuthUser};
|
||||
|
||||
class Kernel extends HttpKernel
|
||||
{
|
||||
/**
|
||||
* The application's global HTTP middleware stack.
|
||||
*
|
||||
* These middleware are run during every request to your application.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $middleware = [
|
||||
// \App\Http\Middleware\TrustHosts::class,
|
||||
\App\Http\Middleware\TrustProxies::class,
|
||||
\Illuminate\Http\Middleware\HandleCors::class,
|
||||
\App\Http\Middleware\CheckForMaintenanceMode::class,
|
||||
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
|
||||
\App\Http\Middleware\TrimStrings::class,
|
||||
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
|
||||
];
|
||||
|
||||
/**
|
||||
* The application's route middleware groups.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $middlewareGroups = [
|
||||
'web' => [
|
||||
\App\Http\Middleware\EncryptCookies::class,
|
||||
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
|
||||
\Illuminate\Session\Middleware\StartSession::class,
|
||||
ApplicationSession::class,
|
||||
SwapinAuthUser::class,
|
||||
\Illuminate\Session\Middleware\AuthenticateSession::class,
|
||||
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
|
||||
\App\Http\Middleware\VerifyCsrfToken::class,
|
||||
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||
\Laravel\Passport\Http\Middleware\CreateFreshApiToken::class,
|
||||
CheckUpdate::class,
|
||||
],
|
||||
|
||||
'api' => [
|
||||
'throttle:60,1',
|
||||
\App\Http\Middleware\EncryptCookies::class,
|
||||
SwapinAuthUser::class,
|
||||
ApplicationSession::class,
|
||||
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* The application's route middleware.
|
||||
*
|
||||
* These middleware may be assigned to groups or used individually.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $middlewareAliases = [
|
||||
'auth' => \App\Http\Middleware\Authenticate::class,
|
||||
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
|
||||
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
|
||||
'can' => \Illuminate\Auth\Middleware\Authorize::class,
|
||||
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
|
||||
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
|
||||
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
|
||||
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
|
||||
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
|
||||
|
||||
'localize' => \Mcamara\LaravelLocalization\Middleware\LaravelLocalizationRoutes::class,
|
||||
'localizationRedirect' => \Mcamara\LaravelLocalization\Middleware\LaravelLocalizationRedirectFilter::class,
|
||||
'localeSessionRedirect' => \Mcamara\LaravelLocalization\Middleware\LocaleSessionRedirect::class,
|
||||
'localeCookieRedirect' => \Mcamara\LaravelLocalization\Middleware\LocaleCookieRedirect::class,
|
||||
'localeViewPath' => \Mcamara\LaravelLocalization\Middleware\LaravelLocalizationViewPath::class
|
||||
];
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Classes\LDAP\Server;
|
||||
use App\Ldap\User;
|
||||
use Closure;
|
||||
|
||||
/**
|
||||
* This sets up our application session with any required values, ultimately for cache optimisation reasons
|
||||
*/
|
||||
class ApplicationSession
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request,Closure $next)
|
||||
{
|
||||
\Config::set('server',new Server);
|
||||
|
||||
view()->share('user', auth()->user() ?: new User);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Illuminate\Auth\Middleware\Authenticate as Middleware;
|
||||
|
||||
class Authenticate extends Middleware
|
||||
{
|
||||
/**
|
||||
* Get the path the user should be redirected to when they are not authenticated.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return string|null
|
||||
*/
|
||||
protected function redirectTo($request)
|
||||
{
|
||||
if (! $request->expectsJson()) {
|
||||
return route('login');
|
||||
}
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode as Middleware;
|
||||
|
||||
class CheckForMaintenanceMode extends Middleware
|
||||
{
|
||||
/**
|
||||
* The URIs that should be reachable while maintenance mode is enabled.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $except = [
|
||||
//
|
||||
];
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use GuzzleHttp\Client;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class CheckUpdate
|
||||
{
|
||||
private const UPDATE_SERVER = 'https://version.phpldapadmin.org';
|
||||
private const UPDATE_TIME = 60*60*6;
|
||||
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
\Config::set('update_available',Cache::get('upstream_version'));
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle tasks after the response has been sent to the browser.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function terminate()
|
||||
{
|
||||
Cache::remember('upstream_version',self::UPDATE_TIME,function() {
|
||||
// CURL call to URL to see if there is a new version
|
||||
Log::debug(sprintf('CU_:Checking for updates for [%s]',config('app.version')));
|
||||
|
||||
$client = new Client;
|
||||
|
||||
try {
|
||||
|
||||
$response = $client->request('POST',sprintf('%s/%s',self::UPDATE_SERVER,strtolower(config('app.version'))));
|
||||
|
||||
if ($response->getStatusCode() === 200) {
|
||||
$result = json_decode($response->getBody());
|
||||
|
||||
Log::debug(sprintf('CU_:- Update server returned...'),['update'=>$result]);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::debug(sprintf('CU_:- Exception connecting to update server'),['e'=>get_class($e)]);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
});
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Illuminate\Cookie\Middleware\EncryptCookies as Middleware;
|
||||
|
||||
class EncryptCookies extends Middleware
|
||||
{
|
||||
/**
|
||||
* The names of the cookies that should not be encrypted.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $except = [
|
||||
//
|
||||
];
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Providers\RouteServiceProvider;
|
||||
use Closure;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class RedirectIfAuthenticated
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param string|null $guard
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next, $guard = null)
|
||||
{
|
||||
if (Auth::guard($guard)->check()) {
|
||||
return redirect(RouteServiceProvider::HOME);
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
use Illuminate\Support\Facades\Cookie;
|
||||
// use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
// use Illuminate\Support\Facades\Session;
|
||||
use LdapRecord\Container;
|
||||
|
||||
use App\Ldap\Connection;
|
||||
|
||||
class SwapinAuthUser
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
|
||||
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
$key = config('ldap.default');
|
||||
|
||||
/*
|
||||
// Rebuild our connection with the authenticated user.
|
||||
if (Session::has('username_encrypt') && Session::has('password_encrypt')) {
|
||||
Config::set('ldap.connections.'.$key.'.username',Crypt::decryptString(Session::get('username_encrypt')));
|
||||
Config::set('ldap.connections.'.$key.'.password',Crypt::decryptString(Session::get('password_encrypt')));
|
||||
|
||||
} else
|
||||
*/
|
||||
|
||||
if (Cookie::has('username_encrypt') && Cookie::has('password_encrypt')) {
|
||||
Config::set('ldap.connections.'.$key.'.username',Cookie::get('username_encrypt'));
|
||||
Config::set('ldap.connections.'.$key.'.password',Cookie::get('password_encrypt'));
|
||||
|
||||
Log::debug('Swapping out configured LDAP credentials with the user\'s cookie.');
|
||||
}
|
||||
|
||||
// We need to override our Connection object so that we can store and retrieve the logged in user and swap out the credentials to use them.
|
||||
Container::getInstance()->addConnection(new Connection(config('ldap.connections.'.$key)),$key);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Illuminate\Foundation\Http\Middleware\TrimStrings as Middleware;
|
||||
|
||||
class TrimStrings extends Middleware
|
||||
{
|
||||
/**
|
||||
* The names of the attributes that should not be trimmed.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $except = [
|
||||
'password',
|
||||
'password_confirmation',
|
||||
];
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Illuminate\Http\Middleware\TrustHosts as Middleware;
|
||||
|
||||
class TrustHosts extends Middleware
|
||||
{
|
||||
/**
|
||||
* Get the host patterns that should be trusted.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function hosts()
|
||||
{
|
||||
return [
|
||||
$this->allSubdomainsOfApplicationUrl(),
|
||||
];
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Illuminate\Http\Middleware\TrustProxies as Middleware;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class TrustProxies extends Middleware
|
||||
{
|
||||
/**
|
||||
* The trusted proxies for this application.
|
||||
*
|
||||
* @var array<int, string>|string|null
|
||||
*/
|
||||
protected $proxies;
|
||||
|
||||
/**
|
||||
* The headers that should be used to detect proxies.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $headers =
|
||||
Request::HEADER_X_FORWARDED_FOR |
|
||||
Request::HEADER_X_FORWARDED_HOST |
|
||||
Request::HEADER_X_FORWARDED_PORT |
|
||||
Request::HEADER_X_FORWARDED_PROTO |
|
||||
Request::HEADER_X_FORWARDED_AWS_ELB;
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
|
||||
|
||||
class VerifyCsrfToken extends Middleware
|
||||
{
|
||||
/**
|
||||
* The URIs that should be excluded from CSRF verification.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $except = [
|
||||
//
|
||||
];
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class EntryRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return config('server')
|
||||
->schema('attributetypes')
|
||||
->intersectByKeys($this->request)
|
||||
->transform(function($item) { return $item->validation; })
|
||||
->filter()
|
||||
->flatMap(function($item) { return $item; })
|
||||
->toArray();
|
||||
}
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class ImportRequest extends FormRequest
|
||||
{
|
||||
public function authorize()
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'frame' => 'required|string|in:import',
|
||||
'file' => 'nullable|extensions:ldif|required_without:text',
|
||||
'text'=> 'nullable|prohibits:file|string|min:16',
|
||||
];
|
||||
}
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Ldap;
|
||||
|
||||
use LdapRecord\Connection as ConnectionBase;
|
||||
use LdapRecord\LdapInterface;
|
||||
|
||||
class Connection extends ConnectionBase
|
||||
{
|
||||
|
||||
public function __construct($config = [], LdapInterface $ldap = null)
|
||||
{
|
||||
parent::__construct($config,$ldap);
|
||||
|
||||
// We need to override this so that we use our own Guard, that stores the users credentials in the session
|
||||
$this->authGuardResolver = function () {
|
||||
return new Guard($this->ldap, $this->configuration);
|
||||
};
|
||||
}
|
||||
}
|
@ -1,423 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Ldap;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use LdapRecord\Support\Arr;
|
||||
use LdapRecord\Models\Model;
|
||||
use LdapRecord\Query\Model\Builder;
|
||||
|
||||
use App\Classes\LDAP\Attribute;
|
||||
use App\Classes\LDAP\Attribute\Factory;
|
||||
use App\Classes\LDAP\Export\LDIF;
|
||||
use App\Exceptions\Import\AttributeException;
|
||||
|
||||
class Entry extends Model
|
||||
{
|
||||
private Collection $objects;
|
||||
private bool $noObjectAttributes = FALSE;
|
||||
|
||||
/* OVERRIDES */
|
||||
|
||||
public function __construct(array $attributes = [])
|
||||
{
|
||||
$this->objects = collect();
|
||||
|
||||
parent::__construct($attributes);
|
||||
}
|
||||
|
||||
public function discardChanges(): static
|
||||
{
|
||||
parent::discardChanges();
|
||||
|
||||
// If we are discharging changes, we need to reset our $objects;
|
||||
$this->objects = $this->getAttributesAsObjects($this->attributes);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function overrides getAttributes to use our collection of Attribute objects instead of the models attributes.
|
||||
*
|
||||
* @return array
|
||||
* @note $this->attributes may not be updated with changes
|
||||
*/
|
||||
public function getAttributes(): array
|
||||
{
|
||||
return $this->objects->map(function($item) { return $item->values->toArray(); })->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the new and old values for a given key are equivalent.
|
||||
*/
|
||||
protected function originalIsEquivalent(string $key): bool
|
||||
{
|
||||
$key = $this->normalizeAttributeKey($key);
|
||||
|
||||
if ((! array_key_exists($key, $this->original)) && (! $this->objects->has($key))) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
$current = $this->attributes[$key];
|
||||
$original = $this->objects->get($key)->values;
|
||||
|
||||
if ($current === $original) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return ! $this->getObject($key)->isDirty();
|
||||
}
|
||||
|
||||
public static function query(bool $noattrs=false): Builder
|
||||
{
|
||||
$o = new static;
|
||||
|
||||
if ($noattrs)
|
||||
$o->noObjectAttributes();
|
||||
|
||||
return $o->newQuery();
|
||||
}
|
||||
|
||||
/**
|
||||
* As attribute values are updated, or new ones created, we need to mirror that
|
||||
* into our $objects
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return $this
|
||||
*/
|
||||
public function setAttribute(string $key, mixed $value): static
|
||||
{
|
||||
parent::setAttribute($key,$value);
|
||||
|
||||
$key = $this->normalizeAttributeKey($key);
|
||||
|
||||
if ((! $this->objects->get($key)) && $value) {
|
||||
$o = new Attribute($key,[]);
|
||||
$o->value = $value;
|
||||
|
||||
$this->objects->put($key,$o);
|
||||
|
||||
} elseif ($this->objects->get($key)) {
|
||||
$this->objects->get($key)->value = $this->attributes[$key];
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* We'll shadow $this->attributes to $this->objects - a collection of Attribute objects
|
||||
*
|
||||
* Using the objects, it'll make it easier to work with attribute values
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return $this
|
||||
*/
|
||||
public function setRawAttributes(array $attributes = []): static
|
||||
{
|
||||
parent::setRawAttributes($attributes);
|
||||
|
||||
// We only set our objects on DN entries (otherwise we might get into a recursion loop if this is the schema DN)
|
||||
if ($this->dn && (! in_array($this->dn,Arr::get($this->attributes,'subschemasubentry',[])))) {
|
||||
$this->objects = $this->getAttributesAsObjects($this->attributes);
|
||||
|
||||
} else {
|
||||
$this->objects = collect();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/* ATTRIBUTES */
|
||||
|
||||
/**
|
||||
* Return a key to use for sorting
|
||||
*
|
||||
* @todo This should be the DN in reverse order
|
||||
* @return string
|
||||
*/
|
||||
public function getSortKeyAttribute(): string
|
||||
{
|
||||
return $this->getDn();
|
||||
}
|
||||
|
||||
/* METHODS */
|
||||
|
||||
public function addAttribute(string $key,mixed $value): void
|
||||
{
|
||||
$key = $this->normalizeAttributeKey($key);
|
||||
|
||||
if (config('server')->schema('attributetypes')->has($key) === FALSE)
|
||||
throw new AttributeException('Schema doesnt have attribute [%s]',$key);
|
||||
|
||||
if ($x=$this->objects->get($key)) {
|
||||
$x->addValue($value);
|
||||
|
||||
} else {
|
||||
$this->objects->put($key,Attribute\Factory::create($key,Arr::wrap($value)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert all our attribute values into an array of Objects
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return Collection
|
||||
*/
|
||||
protected function getAttributesAsObjects(array $attributes): Collection
|
||||
{
|
||||
$result = collect();
|
||||
|
||||
foreach ($attributes as $attribute => $value) {
|
||||
// If the attribute name has language tags
|
||||
$matches = [];
|
||||
if (preg_match('/^([a-zA-Z]+)(;([a-zA-Z-;]+))+/',$attribute,$matches)) {
|
||||
$attribute = $matches[1];
|
||||
|
||||
// If the attribute doesnt exist we'll create it
|
||||
$o = Arr::get($result,$attribute,Factory::create($attribute,[]));
|
||||
$o->setLangTag($matches[3],$value);
|
||||
|
||||
} else {
|
||||
$o = Factory::create($attribute,$value);
|
||||
}
|
||||
|
||||
if (! $result->has($attribute)) {
|
||||
// Set the rdn flag
|
||||
if (preg_match('/^'.$attribute.'=/i',$this->dn))
|
||||
$o->setRDN();
|
||||
|
||||
// Set required flag
|
||||
$o->required_by(collect($this->getAttribute('objectclass')));
|
||||
|
||||
// Store our original value to know if this attribute has changed
|
||||
if ($x=Arr::get($this->original,$attribute))
|
||||
$o->oldValues($x);
|
||||
|
||||
$result->put($attribute,$o);
|
||||
}
|
||||
}
|
||||
|
||||
$sort = collect(config('ldap.attr_display_order',[]))->transform(function($item) { return strtolower($item); });
|
||||
|
||||
// Order the attributes
|
||||
$result = $result->sortBy([function(Attribute $a,Attribute $b) use ($sort): int {
|
||||
if ($a === $b)
|
||||
return 0;
|
||||
|
||||
// Check if $a/$b are in the configuration to be sorted first, if so get it's key
|
||||
$a_key = $sort->search($a->name_lc);
|
||||
$b_key = $sort->search($b->name_lc);
|
||||
|
||||
// If the keys were not in the sort list, set the key to be the count of elements (ie: so it is last to be sorted)
|
||||
if ($a_key === FALSE)
|
||||
$a_key = $sort->count()+1;
|
||||
|
||||
if ($b_key === FALSE)
|
||||
$b_key = $sort->count()+1;
|
||||
|
||||
// Case where neither $a, nor $b are in ldap.attr_display_order, $a_key = $b_key = one greater than num elements.
|
||||
// So we sort them alphabetically
|
||||
if ($a_key === $b_key)
|
||||
return strcasecmp($a->name,$b->name);
|
||||
|
||||
// Case where at least one attribute or its friendly name is in $attrs_display_order
|
||||
// return -1 if $a before $b in $attrs_display_order
|
||||
return ($a_key < $b_key) ? -1 : 1;
|
||||
} ]);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of available attributes - as per the objectClass entry of the record
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getAvailableAttributes(): Collection
|
||||
{
|
||||
$result = collect();
|
||||
|
||||
foreach ($this->objectclass as $oc)
|
||||
$result = $result->merge(config('server')->schema('objectclasses',$oc)->attributes);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a secure version of the DN
|
||||
* @return string
|
||||
*/
|
||||
public function getDNSecure(): string
|
||||
{
|
||||
return Crypt::encryptString($this->getDn());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of LDAP internal attributes
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getInternalAttributes(): Collection
|
||||
{
|
||||
return $this->objects->filter(function($item) {
|
||||
return $item->is_internal;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an attribute as an object
|
||||
*
|
||||
* @param string $key
|
||||
* @return Attribute|null
|
||||
*/
|
||||
public function getObject(string $key): Attribute|null
|
||||
{
|
||||
return $this->objects->get($this->normalizeAttributeKey($key));
|
||||
}
|
||||
|
||||
public function getObjects(): Collection
|
||||
{
|
||||
// In case we havent built our objects yet (because they werent available while determining the schema DN)
|
||||
if ((! $this->objects->count()) && $this->attributes)
|
||||
$this->objects = $this->getAttributesAsObjects($this->attributes);
|
||||
|
||||
return $this->objects;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of attributes without any values
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getMissingAttributes(): Collection
|
||||
{
|
||||
return $this->getAvailableAttributes()->diff($this->getVisibleAttributes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return this list of user attributes
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getVisibleAttributes(): Collection
|
||||
{
|
||||
return $this->objects->filter(function($item) {
|
||||
return ! $item->is_internal;
|
||||
});
|
||||
}
|
||||
|
||||
public function hasAttribute(int|string $key): bool
|
||||
{
|
||||
return $this->objects->has($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Export this record
|
||||
*
|
||||
* @param string $method
|
||||
* @param string $scope
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function export(string $method,string $scope): string
|
||||
{
|
||||
// @todo To implement
|
||||
switch ($scope) {
|
||||
case 'base':
|
||||
case 'one':
|
||||
case 'sub':
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new \Exception('Export scope unknown:'.$scope);
|
||||
}
|
||||
|
||||
switch ($method) {
|
||||
case 'ldif':
|
||||
return new LDIF(collect($this));
|
||||
|
||||
default:
|
||||
throw new \Exception('Export method not implemented:'.$method);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an icon for a DN based on objectClass
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function icon(): string
|
||||
{
|
||||
$objectclasses = array_map('strtolower',$this->objectclass);
|
||||
|
||||
// Return icon based upon objectClass value
|
||||
if (in_array('person',$objectclasses) ||
|
||||
in_array('organizationalperson',$objectclasses) ||
|
||||
in_array('inetorgperson',$objectclasses) ||
|
||||
in_array('account',$objectclasses) ||
|
||||
in_array('posixaccount',$objectclasses))
|
||||
|
||||
return 'fas fa-user';
|
||||
|
||||
elseif (in_array('organization',$objectclasses))
|
||||
return 'fas fa-university';
|
||||
|
||||
elseif (in_array('organizationalunit',$objectclasses))
|
||||
return 'fas fa-object-group';
|
||||
|
||||
elseif (in_array('posixgroup',$objectclasses) ||
|
||||
in_array('groupofnames',$objectclasses) ||
|
||||
in_array('groupofuniquenames',$objectclasses) ||
|
||||
in_array('group',$objectclasses))
|
||||
|
||||
return 'fas fa-users';
|
||||
|
||||
elseif (in_array('dcobject',$objectclasses) ||
|
||||
in_array('domainrelatedobject',$objectclasses) ||
|
||||
in_array('domain',$objectclasses) ||
|
||||
in_array('builtindomain',$objectclasses))
|
||||
|
||||
return 'fas fa-network-wired';
|
||||
|
||||
elseif (in_array('alias',$objectclasses))
|
||||
return 'fas fa-theater-masks';
|
||||
|
||||
elseif (in_array('country',$objectclasses))
|
||||
return sprintf('flag %s',strtolower(Arr::get($this->c,0)));
|
||||
|
||||
elseif (in_array('device',$objectclasses))
|
||||
return 'fas fa-mobile-alt';
|
||||
|
||||
elseif (in_array('document',$objectclasses))
|
||||
return 'fas fa-file-alt';
|
||||
|
||||
elseif (in_array('iphost',$objectclasses))
|
||||
return 'fas fa-wifi';
|
||||
|
||||
elseif (in_array('room',$objectclasses))
|
||||
return 'fas fa-door-open';
|
||||
|
||||
elseif (in_array('server',$objectclasses))
|
||||
return 'fas fa-server';
|
||||
|
||||
elseif (in_array('openldaprootdse',$objectclasses))
|
||||
return 'fas fa-info';
|
||||
|
||||
// Default
|
||||
return 'fa-fw fas fa-cog';
|
||||
}
|
||||
|
||||
/**
|
||||
* Dont convert our $this->attributes to $this->objects when creating a new Entry::class
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function noObjectAttributes(): static
|
||||
{
|
||||
$this->noObjectAttributes = TRUE;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Ldap;
|
||||
|
||||
use Illuminate\Support\Facades\Cookie;
|
||||
// use Illuminate\Support\Facades\Crypt;
|
||||
use LdapRecord\Auth\Guard as GuardBase;
|
||||
|
||||
class Guard extends GuardBase
|
||||
{
|
||||
public function attempt(string $username, string $password, bool $stayBound = false): bool
|
||||
{
|
||||
if ($result = parent::attempt($username,$password,$stayBound)) {
|
||||
/*
|
||||
* We can either use our session or cookies to store this. If using session, then Http/Kernel needs to be
|
||||
* updated to start a session for API calls.
|
||||
// We need to store our password so that we can swap in the user in during SwapinAuthUser::class middleware
|
||||
request()->session()->put('username_encrypt',Crypt::encryptString($username));
|
||||
request()->session()->put('password_encrypt',Crypt::encryptString($password));
|
||||
*/
|
||||
|
||||
// For our API calls, we store the cookie - which our cookies are already encrypted
|
||||
Cookie::queue('username_encrypt',$username);
|
||||
Cookie::queue('password_encrypt',$password);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Ldap;
|
||||
|
||||
use Illuminate\Contracts\Support\Arrayable;
|
||||
use Illuminate\Support\Str;
|
||||
use LdapRecord\Laravel\Events\Auth\DiscoveredWithCredentials;
|
||||
use LdapRecord\Laravel\LdapUserRepository as LdapUserRepositoryBase;
|
||||
use LdapRecord\Models\Model;
|
||||
|
||||
use App\Classes\LDAP\Server;
|
||||
|
||||
class LdapUserRepository extends LdapUserRepositoryBase
|
||||
{
|
||||
/**
|
||||
* Retrieve a user by the given credentials.
|
||||
*
|
||||
* @param array $credentials
|
||||
*
|
||||
* @return Model|null
|
||||
* @throws \LdapRecord\Query\ObjectNotFoundException
|
||||
*/
|
||||
public function findByCredentials(array $credentials = []): ?Model
|
||||
{
|
||||
if (empty($credentials)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// For DN based logins
|
||||
if (! empty($credentials['dn']))
|
||||
return $this->query()->find($credentials['dn']);
|
||||
|
||||
// Look for a user using all our baseDNs
|
||||
foreach (Server::baseDNs() as $base) {
|
||||
$query = $this->query()->setBaseDn($base);
|
||||
|
||||
foreach ($credentials as $key => $value) {
|
||||
if (Str::contains($key, $this->bypassCredentialKeys)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_array($value) || $value instanceof Arrayable) {
|
||||
$query->whereIn($key, $value);
|
||||
} else {
|
||||
$query->where($key, $value);
|
||||
}
|
||||
}
|
||||
|
||||
if (! is_null($user = $query->first())) {
|
||||
event(new DiscoveredWithCredentials($user));
|
||||
|
||||
return $user;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a user by their object GUID.
|
||||
*
|
||||
* @param string $guid
|
||||
*
|
||||
* @return Model|null
|
||||
* @throws \LdapRecord\Query\ObjectNotFoundException
|
||||
*/
|
||||
public function findByGuid($guid): ?Model
|
||||
{
|
||||
// Look for a user using all our baseDNs
|
||||
foreach (Server::baseDNs() as $base) {
|
||||
$user = $this->query()->setBaseDn($base)->findByGuid($guid);
|
||||
|
||||
if ($user)
|
||||
return $user;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Ldap\Rules;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model as Eloquent;
|
||||
use LdapRecord\Laravel\Auth\Rule;
|
||||
use LdapRecord\Models\Model as LdapRecord;
|
||||
|
||||
/**
|
||||
* User must have this objectClass to login
|
||||
*
|
||||
* This is overridden by LDAP_LOGIN_OBJECTCLASS
|
||||
* @see User::$objectClasses
|
||||
*/
|
||||
class LoginObjectclassRule implements Rule
|
||||
{
|
||||
public function passes(LdapRecord $user, Eloquent $model = null): bool
|
||||
{
|
||||
if ($x=config('ldap.login.objectclass')) {
|
||||
return count(array_intersect($user->objectclass,$x));
|
||||
|
||||
// Otherwise allow the user to login
|
||||
} else {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Ldap;
|
||||
|
||||
use Laravel\Passport\HasApiTokens;
|
||||
use LdapRecord\Models\OpenLDAP\User as Model;
|
||||
|
||||
use App\Ldap\Rules\LoginObjectclassRule;
|
||||
|
||||
class User extends Model
|
||||
{
|
||||
use HasApiTokens;
|
||||
|
||||
/**
|
||||
* The object classes of the LDAP model.
|
||||
*
|
||||
* @note We set this to an empty array so that any objectclass can login
|
||||
* @see LoginObjectclassRule::class
|
||||
*/
|
||||
public static array $objectClasses = [
|
||||
];
|
||||
|
||||
/* METHODS */
|
||||
|
||||
public function getDn(): string
|
||||
{
|
||||
return $this->exists ? parent::getDn() : 'Anonymous';
|
||||
}
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use LdapRecord\Configuration\DomainConfiguration;
|
||||
use LdapRecord\Laravel\LdapRecord;
|
||||
|
||||
use App\Ldap\LdapUserRepository;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Register any application services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
// Add a new option available to be set in the configuration:
|
||||
DomainConfiguration::extend('name', $default = null);
|
||||
|
||||
// Use our LdapUserRepository to support multiple baseDN querying
|
||||
LdapRecord::locateUsersUsing(LdapUserRepository::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstrap any application services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
$this->loadViewsFrom(__DIR__.'/../../resources/themes/architect/views/','architect');
|
||||
|
||||
// Enable pluck on collections to work on private values
|
||||
Collection::macro('ppluck', function ($attr) {
|
||||
return $this->map(function (object $item) use ($attr) {
|
||||
return $item->{$attr};
|
||||
})->values();
|
||||
});
|
||||
}
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
|
||||
|
||||
class AuthServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* The model to policy mappings for the application.
|
||||
*
|
||||
* @var array<class-string, class-string>
|
||||
*/
|
||||
protected $policies = [
|
||||
// 'App\Models\Model' => 'App\Policies\ModelPolicy',
|
||||
];
|
||||
|
||||
/**
|
||||
* Register any authentication / authorization services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Support\Facades\Broadcast;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class BroadcastServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Bootstrap any application services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
Broadcast::routes();
|
||||
|
||||
require base_path('routes/channels.php');
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Auth\Events\Registered;
|
||||
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
|
||||
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
|
||||
class EventServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* The event listener mappings for the application.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $listen = [];
|
||||
|
||||
/**
|
||||
* Register any events for your application.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
//
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Cache\RateLimiting\Limit;
|
||||
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\RateLimiter;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
class RouteServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* The path to the "home" route for your application.
|
||||
*
|
||||
* Typically, users are redirected here after authentication.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public const HOME = '/';
|
||||
|
||||
/**
|
||||
* Define your route model bindings, pattern filters, and other route configuration.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
$this->configureRateLimiting();
|
||||
|
||||
$this->routes(function () {
|
||||
Route::middleware('api')
|
||||
->prefix('api')
|
||||
->group(base_path('routes/api.php'));
|
||||
|
||||
Route::middleware('web')
|
||||
->group(base_path('routes/web.php'));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the rate limiters for the application.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function configureRateLimiting()
|
||||
{
|
||||
RateLimiter::for('api', function (Request $request) {
|
||||
return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
|
||||
});
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Determine if a value has changed by comparing its MD5 value
|
||||
*/
|
||||
namespace App\Traits;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
trait MD5Updates
|
||||
{
|
||||
public function isDirty(): bool
|
||||
{
|
||||
if (! parent::isDirty())
|
||||
return TRUE;
|
||||
|
||||
foreach ($this->values->diff($this->oldValues) as $key => $value)
|
||||
if (md5(Arr::get($this->oldValues,$key)) !== $value)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\View\Components;
|
||||
|
||||
use Illuminate\View\Component;
|
||||
|
||||
use App\Classes\LDAP\Attribute as LDAPAttribute;
|
||||
|
||||
class Attribute extends Component
|
||||
{
|
||||
public LDAPAttribute $o;
|
||||
public bool $edit;
|
||||
public bool $new;
|
||||
public bool $old;
|
||||
|
||||
/**
|
||||
* Create a new component instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(LDAPAttribute $o,bool $edit,bool $old=FALSE,bool $new=FALSE)
|
||||
{
|
||||
$this->o = $o;
|
||||
$this->edit = $edit;
|
||||
$this->old = $old;
|
||||
$this->new = $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the view / contents that represent the component.
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\View|\Closure|string
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
return $this->o->render($this->edit,$this->old,$this->new);
|
||||
}
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\View\Components;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\View\Component;
|
||||
|
||||
use App\Classes\LDAP\Attribute as LDAPAttribute;
|
||||
|
||||
class AttributeType extends Component
|
||||
{
|
||||
public LDAPAttribute $o;
|
||||
public bool $new;
|
||||
|
||||
/**
|
||||
* Create a new component instance.
|
||||
*/
|
||||
public function __construct(LDAPAttribute $o,bool $new=FALSE)
|
||||
{
|
||||
$this->o = $o;
|
||||
$this->new = $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the view / contents that represent the component.
|
||||
*/
|
||||
public function render(): View|Closure|string
|
||||
{
|
||||
return view('components.attribute-type')
|
||||
->with('o',$this->o)
|
||||
->with('new',$this->new);
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
function login_attr_description(): string
|
||||
{
|
||||
return Arr::get(config('ldap.login.attr'),login_attr_name());
|
||||
}
|
||||
|
||||
function login_attr_name(): string
|
||||
{
|
||||
return key(config('ldap.login.attr'));
|
||||
}
|
53
artisan
53
artisan
@ -1,53 +0,0 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
define('LARAVEL_START', microtime(true));
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Register The Auto Loader
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Composer provides a convenient, automatically generated class loader
|
||||
| for our application. We just need to utilize it! We'll require it
|
||||
| into the script here so that we do not have to worry about the
|
||||
| loading of any of our classes manually. It's great to relax.
|
||||
|
|
||||
*/
|
||||
|
||||
require __DIR__.'/vendor/autoload.php';
|
||||
|
||||
$app = require_once __DIR__.'/bootstrap/app.php';
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Run The Artisan Application
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When we run the console application, the current CLI command will be
|
||||
| executed in this console and the response sent back to a terminal
|
||||
| or another output device for the developers. Here goes nothing!
|
||||
|
|
||||
*/
|
||||
|
||||
$kernel = $app->make(Illuminate\Contracts\Console\Kernel::class);
|
||||
|
||||
$status = $kernel->handle(
|
||||
$input = new Symfony\Component\Console\Input\ArgvInput,
|
||||
new Symfony\Component\Console\Output\ConsoleOutput
|
||||
);
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Shutdown The Application
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Once Artisan has finished running, we will fire off the shutdown events
|
||||
| so that any final work may be done by the application before we shut
|
||||
| down the process. This is the last thing to happen to the request.
|
||||
|
|
||||
*/
|
||||
|
||||
$kernel->terminate($input, $status);
|
||||
|
||||
exit($status);
|
@ -1,4 +1,6 @@
|
||||
<?php
|
||||
// $Header: /cvsroot/phpldapadmin/phpldapadmin/blowfish.php,v 1.3 2005/02/25 13:44:05 wurley Exp $
|
||||
|
||||
/**
|
||||
* The Cipher_blowfish:: class implements the Cipher interface enryption data
|
||||
* using the Blowfish algorithm.
|
||||
@ -11,7 +13,7 @@
|
||||
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
|
||||
*
|
||||
* @author Mike Cochrane <mike@graftonhall.co.nz>
|
||||
* @version $Revision$
|
||||
* @version $Revision: 1.3 $
|
||||
* @since Horde 2.2
|
||||
* @package horde.cipher
|
||||
*/
|
||||
@ -24,7 +26,7 @@
|
||||
class Horde_Cipher_blowfish {
|
||||
|
||||
/* Pi Array */
|
||||
public $p = array(
|
||||
var $p = array(
|
||||
0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344,
|
||||
0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89,
|
||||
0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C,
|
||||
@ -32,7 +34,7 @@ class Horde_Cipher_blowfish {
|
||||
0x9216D5D9, 0x8979FB1B);
|
||||
|
||||
/* S Boxes */
|
||||
public $s1 = array(
|
||||
var $s1 = array(
|
||||
0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7,
|
||||
0xB8E1AFED, 0x6A267E96, 0xBA7C9045, 0xF12C7F99,
|
||||
0x24A19947, 0xB3916CF7, 0x0801F2E2, 0x858EFC16,
|
||||
@ -97,7 +99,7 @@ class Horde_Cipher_blowfish {
|
||||
0x08BA6FB5, 0x571BE91F, 0xF296EC6B, 0x2A0DD915,
|
||||
0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664,
|
||||
0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A);
|
||||
public $s2 = array(
|
||||
var $s2 = array(
|
||||
0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623,
|
||||
0xAD6EA6B0, 0x49A7DF7D, 0x9CEE60B8, 0x8FEDB266,
|
||||
0xECAA8C71, 0x699A17FF, 0x5664526C, 0xC2B19EE1,
|
||||
@ -162,7 +164,7 @@ class Horde_Cipher_blowfish {
|
||||
0xDB73DBD3, 0x105588CD, 0x675FDA79, 0xE3674340,
|
||||
0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20,
|
||||
0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, 0xDB83ADF7);
|
||||
public $s3 = array(
|
||||
var $s3 = array(
|
||||
0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934,
|
||||
0x411520F7, 0x7602D4F7, 0xBCF46B2E, 0xD4A20068,
|
||||
0xD4082471, 0x3320F46A, 0x43B7D4B7, 0x500061AF,
|
||||
@ -227,7 +229,7 @@ class Horde_Cipher_blowfish {
|
||||
0x1E50EF5E, 0xB161E6F8, 0xA28514D9, 0x6C51133C,
|
||||
0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, 0xDDC6C837,
|
||||
0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0);
|
||||
public $s4 = array(
|
||||
var $s4 = array(
|
||||
0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B,
|
||||
0x5CB0679E, 0x4FA33742, 0xD3822740, 0x99BC9BBE,
|
||||
0xD5118E9D, 0xBF0F7315, 0xD62D1C7E, 0xC700C47B,
|
||||
@ -294,7 +296,7 @@ class Horde_Cipher_blowfish {
|
||||
0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6);
|
||||
|
||||
/* The number of rounds to do */
|
||||
public $_rounds = 16;
|
||||
var $_rounds = 16;
|
||||
|
||||
/* Constructor */
|
||||
function Cipher_blowfish($params = null)
|
||||
@ -435,14 +437,7 @@ class Horde_Cipher_blowfish {
|
||||
$this->setKey($key);
|
||||
}
|
||||
|
||||
$unpack = unpack('N*', $block);
|
||||
|
||||
if (! is_array($unpack))
|
||||
error(
|
||||
sprintf('BLOWFISH: decryptBock()<br>We expected unpack to produce an array, but instead it produced [%s]. This function was entered with (%s,%s). If you think that this is a bug, then please tell the PLA developers how you got here. You are using PLA [%s,%s]',
|
||||
serialize($unpack),$block,$key,app_version(),phpversion()),'error','index.php');
|
||||
|
||||
list($L, $R) = array_values($unpack);
|
||||
list($L, $R) = array_values(unpack('N*', $block));
|
||||
|
||||
$L ^= $this->p[17];
|
||||
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[16];
|
@ -1,55 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Create The Application
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The first thing we will do is create a new Laravel application instance
|
||||
| which serves as the "glue" for all the components of Laravel, and is
|
||||
| the IoC container for the system binding all of the various parts.
|
||||
|
|
||||
*/
|
||||
|
||||
$app = new Illuminate\Foundation\Application(
|
||||
$_ENV['APP_BASE_PATH'] ?? dirname(__DIR__)
|
||||
);
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Bind Important Interfaces
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Next, we need to bind some important interfaces into the container so
|
||||
| we will be able to resolve them when needed. The kernels serve the
|
||||
| incoming requests to this application from both the web and CLI.
|
||||
|
|
||||
*/
|
||||
|
||||
$app->singleton(
|
||||
Illuminate\Contracts\Http\Kernel::class,
|
||||
App\Http\Kernel::class
|
||||
);
|
||||
|
||||
$app->singleton(
|
||||
Illuminate\Contracts\Console\Kernel::class,
|
||||
App\Console\Kernel::class
|
||||
);
|
||||
|
||||
$app->singleton(
|
||||
Illuminate\Contracts\Debug\ExceptionHandler::class,
|
||||
App\Exceptions\Handler::class
|
||||
);
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Return The Application
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This script returns the application instance. The instance is given to
|
||||
| the calling script so we can separate the building of the instances
|
||||
| from the actual running of the application and sending responses.
|
||||
|
|
||||
*/
|
||||
|
||||
return $app;
|
2
bootstrap/cache/.gitignore
vendored
2
bootstrap/cache/.gitignore
vendored
@ -1,2 +0,0 @@
|
||||
*
|
||||
!.gitignore
|
86
check_lang_files.php
Normal file
86
check_lang_files.php
Normal file
@ -0,0 +1,86 @@
|
||||
<?php
|
||||
// $Header: /cvsroot/phpldapadmin/phpldapadmin/check_lang_files.php,v 1.11 2005/02/25 13:44:05 wurley Exp $
|
||||
|
||||
/**
|
||||
* Test script to check that $lang variables in each language file.
|
||||
* @package phpLDAPadmin
|
||||
*/
|
||||
/**
|
||||
*/
|
||||
|
||||
echo "<html><head><title>phpldapadmin - check of translation</title></head><body>";
|
||||
$CHECKLANG=$_REQUEST['CHECKLANG'];
|
||||
|
||||
include realpath( './lang/en.php' );
|
||||
$english_lang = $lang;
|
||||
unset( $lang );
|
||||
$lang_dir = realpath( './lang/recoded' );
|
||||
$dir = opendir( $lang_dir );
|
||||
|
||||
// First, detect any unused strings from the english language:
|
||||
echo "<h1>Checking English language file for unused strings</h1>\n";
|
||||
echo "<ol>\n";
|
||||
$unused_keys = false;
|
||||
|
||||
// special case keys that do not occur hard-coded but are dynamically generated
|
||||
$ignore_keys['equals'] = 1;
|
||||
$ignore_keys['starts with'] = 1;
|
||||
$ignore_keys['ends with'] = 1;
|
||||
$ignore_keys['sounds like'] = 1;
|
||||
$ignore_keys['contains'] = 1;
|
||||
foreach( $english_lang as $key => $string ) {
|
||||
if( isset( $ignore_keys[$key] ) )
|
||||
continue;
|
||||
$grep_cmd = "grep -r \"lang\[['\\\"]$key\" *.php templates/";
|
||||
$used = `$grep_cmd`;
|
||||
if( ! $used ) {
|
||||
$unused_keys = true;
|
||||
echo "<li>Unused English key: <tt>$key</tt> <br /> (<small><tt>" . htmlspecialchars( $grep_cmd ) . "</tt></small>)</li>\n";
|
||||
flush();
|
||||
}
|
||||
}
|
||||
if( false === $unused_keys )
|
||||
echo "No unused English strings.";
|
||||
echo "</ol>\n";
|
||||
|
||||
echo "<h1>Incomplete or Erroneous Language Files</h1>\n\n";
|
||||
if ($CHECKLANG)
|
||||
printf("<h1>Checking language files %s</h1>\n\n",$CHECKLANG);
|
||||
echo "<h1><A HREF='?'>check all languages</A></h1>\n";
|
||||
flush();
|
||||
while( ( $file = readdir( $dir ) ) !== false ) {
|
||||
// skip the devel languages, english, and auto
|
||||
if( $file == "zz.php" || $file == "zzz.php" || $file == "auto.php" || $file == "en.php" )
|
||||
continue;
|
||||
// Sanity check. Is this really a PHP file?
|
||||
if( ! preg_match( "/\.php$/", $file ) )
|
||||
continue;
|
||||
unset( $lang );
|
||||
$lang = array();
|
||||
include realpath( $lang_dir.'/'.$file );
|
||||
$has_errors = false;
|
||||
if ($CHECKLANG=="" || $file===$CHECKLANG ){
|
||||
echo "<h2><A HREF='?CHECKLANG=$file'>$file</A></h2>\n";
|
||||
echo "<ol>\n";
|
||||
foreach( $english_lang as $key => $string )
|
||||
if( ! isset( $lang[ $key ] ) ) {
|
||||
$has_errors = true;
|
||||
echo "<li>missing entry: <tt>$key</tt></li>\n";
|
||||
}
|
||||
foreach( $lang as $key => $string )
|
||||
if( ! isset( $english_lang[ $key ] ) ){
|
||||
$has_errors = true;
|
||||
echo "<li>extra entry: <tt>$key</tt></li>\n";
|
||||
}
|
||||
if( ! $has_errors )
|
||||
echo "(No errors)\n";
|
||||
}
|
||||
echo "</ol>\n";
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
echo "</body></html>";
|
||||
|
||||
?>
|
47
collapse.php
Normal file
47
collapse.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
// $Header: /cvsroot/phpldapadmin/phpldapadmin/collapse.php,v 1.12 2005/02/25 13:44:05 wurley Exp $
|
||||
|
||||
/**
|
||||
* This script alters the session variable 'tree', collapsing it
|
||||
* at the dn specified in the query string.
|
||||
*
|
||||
* Variables that come in as GET vars:
|
||||
* - dn (rawurlencoded)
|
||||
* - server_id
|
||||
*
|
||||
* Note: this script is equal and opposite to expand.php
|
||||
* @package phpLDAPadmin
|
||||
*/
|
||||
/**
|
||||
*/
|
||||
|
||||
require './common.php';
|
||||
|
||||
$server_id = (isset($_GET['server_id']) ? $_GET['server_id'] : '');
|
||||
//$ldapserver = new LDAPServer($server_id);
|
||||
|
||||
//if( ! $ldapserver->haveAuthInfo())
|
||||
// pla_error( $lang['not_enough_login_info'] );
|
||||
|
||||
$dn = $_GET['dn'];
|
||||
$encoded_dn = rawurlencode( $dn );
|
||||
|
||||
initialize_session_tree();
|
||||
|
||||
if( array_key_exists( $dn, $_SESSION['tree'][$server_id] ) )
|
||||
unset( $_SESSION['tree'][$server_id][$dn] );
|
||||
|
||||
// This is for Opera. By putting "random junk" in the query string, it thinks
|
||||
// that it does not have a cached version of the page, and will thus
|
||||
// fetch the page rather than display the cached version
|
||||
$time = gettimeofday();
|
||||
$random_junk = md5( strtotime( 'now' ) . $time['usec'] );
|
||||
|
||||
// If cookies were disabled, build the url parameter for the session id.
|
||||
// It will be append to the url to be redirect
|
||||
$id_session_param = "";
|
||||
if (SID != "")
|
||||
$id_session_param = "&".session_name()."=".session_id();
|
||||
|
||||
header( "Location:tree.php?foo=$random_junk#{$server_id}_{$encoded_dn}$id_session_param" );
|
||||
?>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user