I would like to set "joomla_remember_me..." cookie from my custom script depending on condition. I would probably need to execute public function onUserAfterLogin from the file \plugins\authentication\cookie\cookie.php with the argument "remember me" set, but I cannot figure out how.
Here's the cookie.php file for the reference:
/**
* Joomla Authentication plugin
*
* #since 3.2
* #note Code based on http://jaspan.com/improved_persistent_login_cookie_best_practice
* and http://fishbowl.pastiche.org/2004/01/19/persistent_login_cookie_best_practice/
*/
class PlgAuthenticationCookie extends JPlugin
{
/**
* Application object
*
* #var JApplicationCms
* #since 3.2
*/
protected $app;
/**
* Database object
*
* #var JDatabaseDriver
* #since 3.2
*/
protected $db;
/**
* Reports the privacy related capabilities for this plugin to site administrators.
*
* #return array
*
* #since 3.9.0
*/
public function onPrivacyCollectAdminCapabilities()
{
$this->loadLanguage();
return array(
JText::_('PLG_AUTHENTICATION_COOKIE') => array(
JText::_('PLG_AUTH_COOKIE_PRIVACY_CAPABILITY_COOKIE'),
)
);
}
/**
* This method should handle any authentication and report back to the subject
*
* #param array $credentials Array holding the user credentials
* #param array $options Array of extra options
* #param object &$response Authentication response object
*
* #return boolean
*
* #since 3.2
*/
public function onUserAuthenticate($credentials, $options, &$response)
{
// No remember me for admin
if ($this->app->isClient('administrator'))
{
return false;
}
// Get cookie
$cookieName = 'joomla_remember_me_' . JUserHelper::getShortHashedUserAgent();
$cookieValue = $this->app->input->cookie->get($cookieName);
// Try with old cookieName (pre 3.6.0) if not found
if (!$cookieValue)
{
$cookieName = JUserHelper::getShortHashedUserAgent();
$cookieValue = $this->app->input->cookie->get($cookieName);
}
if (!$cookieValue)
{
return false;
}
$cookieArray = explode('.', $cookieValue);
// Check for valid cookie value
if (count($cookieArray) !== 2)
{
// Destroy the cookie in the browser.
$this->app->input->cookie->set($cookieName, '', 1, $this->app->get('cookie_path', '/'), $this->app->get('cookie_domain', ''));
JLog::add('Invalid cookie detected.', JLog::WARNING, 'error');
return false;
}
$response->type = 'Cookie';
// Filter series since we're going to use it in the query
$filter = new JFilterInput;
$series = $filter->clean($cookieArray[1], 'ALNUM');
// Remove expired tokens
$query = $this->db->getQuery(true)
->delete('#__user_keys')
->where($this->db->quoteName('time') . ' < ' . $this->db->quote(time()));
try
{
$this->db->setQuery($query)->execute();
}
catch (RuntimeException $e)
{
// We aren't concerned with errors from this query, carry on
}
// Find the matching record if it exists.
$query = $this->db->getQuery(true)
->select($this->db->quoteName(array('user_id', 'token', 'series', 'time')))
->from($this->db->quoteName('#__user_keys'))
->where($this->db->quoteName('series') . ' = ' . $this->db->quote($series))
->where($this->db->quoteName('uastring') . ' = ' . $this->db->quote($cookieName))
->order($this->db->quoteName('time') . ' DESC');
try
{
$results = $this->db->setQuery($query)->loadObjectList();
}
catch (RuntimeException $e)
{
$response->status = JAuthentication::STATUS_FAILURE;
return false;
}
if (count($results) !== 1)
{
// Destroy the cookie in the browser.
$this->app->input->cookie->set($cookieName, '', 1, $this->app->get('cookie_path', '/'), $this->app->get('cookie_domain', ''));
$response->status = JAuthentication::STATUS_FAILURE;
return false;
}
// We have a user with one cookie with a valid series and a corresponding record in the database.
if (!JUserHelper::verifyPassword($cookieArray[0], $results[0]->token))
{
/*
* This is a real attack!
* Either the series was guessed correctly or a cookie was stolen and used twice (once by attacker and once by victim).
* Delete all tokens for this user!
*/
$query = $this->db->getQuery(true)
->delete('#__user_keys')
->where($this->db->quoteName('user_id') . ' = ' . $this->db->quote($results[0]->user_id));
try
{
$this->db->setQuery($query)->execute();
}
catch (RuntimeException $e)
{
// Log an alert for the site admin
JLog::add(
sprintf('Failed to delete cookie token for user %s with the following error: %s', $results[0]->user_id, $e->getMessage()),
JLog::WARNING,
'security'
);
}
// Destroy the cookie in the browser.
$this->app->input->cookie->set($cookieName, '', 1, $this->app->get('cookie_path', '/'), $this->app->get('cookie_domain', ''));
// Issue warning by email to user and/or admin?
JLog::add(JText::sprintf('PLG_AUTH_COOKIE_ERROR_LOG_LOGIN_FAILED', $results[0]->user_id), JLog::WARNING, 'security');
$response->status = JAuthentication::STATUS_FAILURE;
return false;
}
// Make sure there really is a user with this name and get the data for the session.
$query = $this->db->getQuery(true)
->select($this->db->quoteName(array('id', 'username', 'password')))
->from($this->db->quoteName('#__users'))
->where($this->db->quoteName('username') . ' = ' . $this->db->quote($results[0]->user_id))
->where($this->db->quoteName('requireReset') . ' = 0');
try
{
$result = $this->db->setQuery($query)->loadObject();
}
catch (RuntimeException $e)
{
$response->status = JAuthentication::STATUS_FAILURE;
return false;
}
if ($result)
{
// Bring this in line with the rest of the system
$user = JUser::getInstance($result->id);
// Set response data.
$response->username = $result->username;
$response->email = $user->email;
$response->fullname = $user->name;
$response->password = $result->password;
$response->language = $user->getParam('language');
// Set response status.
$response->status = JAuthentication::STATUS_SUCCESS;
$response->error_message = '';
}
else
{
$response->status = JAuthentication::STATUS_FAILURE;
$response->error_message = JText::_('JGLOBAL_AUTH_NO_USER');
}
}
/**
* We set the authentication cookie only after login is successfullly finished.
* We set a new cookie either for a user with no cookies or one
* where the user used a cookie to authenticate.
*
* #param array $options Array holding options
*
* #return boolean True on success
*
* #since 3.2
*/
public function onUserAfterLogin($options)
{
// No remember me for admin
if ($this->app->isClient('administrator'))
{
return false;
}
if (isset($options['responseType']) && $options['responseType'] === 'Cookie')
{
// Logged in using a cookie
$cookieName = 'joomla_remember_me_' . JUserHelper::getShortHashedUserAgent();
// We need the old data to get the existing series
$cookieValue = $this->app->input->cookie->get($cookieName);
// Try with old cookieName (pre 3.6.0) if not found
if (!$cookieValue)
{
$oldCookieName = JUserHelper::getShortHashedUserAgent();
$cookieValue = $this->app->input->cookie->get($oldCookieName);
// Destroy the old cookie in the browser
$this->app->input->cookie->set($oldCookieName, '', 1, $this->app->get('cookie_path', '/'), $this->app->get('cookie_domain', ''));
}
$cookieArray = explode('.', $cookieValue);
// Filter series since we're going to use it in the query
$filter = new JFilterInput;
$series = $filter->clean($cookieArray[1], 'ALNUM');
}
elseif (!empty($options['remember']))
{
// Remember checkbox is set
$cookieName = 'joomla_remember_me_' . JUserHelper::getShortHashedUserAgent();
// Create a unique series which will be used over the lifespan of the cookie
$unique = false;
$errorCount = 0;
do
{
$series = JUserHelper::genRandomPassword(20);
$query = $this->db->getQuery(true)
->select($this->db->quoteName('series'))
->from($this->db->quoteName('#__user_keys'))
->where($this->db->quoteName('series') . ' = ' . $this->db->quote($series));
try
{
$results = $this->db->setQuery($query)->loadResult();
if ($results === null)
{
$unique = true;
}
}
catch (RuntimeException $e)
{
$errorCount++;
// We'll let this query fail up to 5 times before giving up, there's probably a bigger issue at this point
if ($errorCount === 5)
{
return false;
}
}
}
while ($unique === false);
}
else
{
return false;
}
// Get the parameter values
$lifetime = $this->params->get('cookie_lifetime', 60) * 24 * 60 * 60;
$length = $this->params->get('key_length', 16);
// Generate new cookie
$token = JUserHelper::genRandomPassword($length);
$cookieValue = $token . '.' . $series;
// Overwrite existing cookie with new value
$this->app->input->cookie->set(
$cookieName,
$cookieValue,
time() + $lifetime,
$this->app->get('cookie_path', '/'),
$this->app->get('cookie_domain', ''),
$this->app->isHttpsForced(),
true
);
$query = $this->db->getQuery(true);
if (!empty($options['remember']))
{
// Create new record
$query
->insert($this->db->quoteName('#__user_keys'))
->set($this->db->quoteName('user_id') . ' = ' . $this->db->quote($options['user']->username))
->set($this->db->quoteName('series') . ' = ' . $this->db->quote($series))
->set($this->db->quoteName('uastring') . ' = ' . $this->db->quote($cookieName))
->set($this->db->quoteName('time') . ' = ' . (time() + $lifetime));
}
else
{
// Update existing record with new token
$query
->update($this->db->quoteName('#__user_keys'))
->where($this->db->quoteName('user_id') . ' = ' . $this->db->quote($options['user']->username))
->where($this->db->quoteName('series') . ' = ' . $this->db->quote($series))
->where($this->db->quoteName('uastring') . ' = ' . $this->db->quote($cookieName));
}
$hashedToken = JUserHelper::hashPassword($token);
$query->set($this->db->quoteName('token') . ' = ' . $this->db->quote($hashedToken));
try
{
$this->db->setQuery($query)->execute();
}
catch (RuntimeException $e)
{
return false;
}
return true;
}
/**
* This is where we delete any authentication cookie when a user logs out
*
* #param array $options Array holding options (length, timeToExpiration)
*
* #return boolean True on success
*
* #since 3.2
*/
public function onUserAfterLogout($options)
{
// No remember me for admin
if ($this->app->isClient('administrator'))
{
return false;
}
$cookieName = 'joomla_remember_me_' . JUserHelper::getShortHashedUserAgent();
$cookieValue = $this->app->input->cookie->get($cookieName);
// There are no cookies to delete.
if (!$cookieValue)
{
return true;
}
$cookieArray = explode('.', $cookieValue);
// Filter series since we're going to use it in the query
$filter = new JFilterInput;
$series = $filter->clean($cookieArray[1], 'ALNUM');
// Remove the record from the database
$query = $this->db->getQuery(true)
->delete('#__user_keys')
->where($this->db->quoteName('series') . ' = ' . $this->db->quote($series));
try
{
$this->db->setQuery($query)->execute();
}
catch (RuntimeException $e)
{
// We aren't concerned with errors from this query, carry on
}
// Destroy the cookie
$this->app->input->cookie->set($cookieName, '', 1, $this->app->get('cookie_path', '/'), $this->app->get('cookie_domain', ''));
return true;
}
}
Thanks in advance :)
It's a very complex process and I think you would be better off cloning this plugin to a new name, adding your condition to the function, unpublish the current plugin and publish your new one instead. You will also have to watch for any changes to the original plugin in case a security issue is found.
Related
Just integrated Google Recaptcha. I am using this form as a POST to a secure checkout for a secure transaction site ( API ).
My challenge is, I have the form action =
"action="https://securepayments.cardconnect.com/hpp/payment/"
And event if I use :
if (isset($_POST['submit'])) {
to validate the :: recaptcha :: it still just goes straight to the form action URL without verifying the recaptcha.
Here is more code:
$secret = '-- XX --';
$response = $_POST['g-recaptcha-response'];
$remoteip = $_SERVER['REMOTE_ADDR'];
$url = file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=$secret&response=$response&remoteip=$remoteip");
$res = json_decode($unpass, TRUE);
$result = json_decode($url, TRUE);
if ($result['success'] == 1) {
echo $_POST['name'];
echo $_POST['companyname'];
}
else { echo 'you are a robot'; }
}
The form action URL passes POST / hidden variables to connect via MID/Password to authenticate itself with the API. I can't figure out how to integrate a solution to use recaptcha and then do the form action. Any help would be awesome!
function isValid()
{
try {
$url = 'https://www.google.com/recaptcha/api/siteverify';
$data = ['secret' => 'secret',
'response' => $_POST['g-recaptcha-response'],
'remoteip' => $_SERVER['REMOTE_ADDR']];
$options = [
'http' => [
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'POST',
'content' => http_build_query($data)
]
];
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
return json_decode($result)->success;
}
catch (Exception $e) {
return null;
}
}
if($_POST && isValid())
{
//do stuff
}
Why you don't use the Recaptcha Library?
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
class Recaptcha
{
/*
* This is a PHP library that handles calling reCAPTCHA.
* - Documentation and latest version
* http://recaptcha.net/plugins/php/
* - Get a reCAPTCHA API Key
* https://www.google.com/recaptcha/admin/create
* - Discussion group
* http://groups.google.com/group/recaptcha
*
* Copyright (c) 2007 reCAPTCHA -- http://recaptcha.net
* AUTHORS:
* Mike Crawford
* Ben Maurer
*
* CONTRIBUTION:
* Codeigniter version - 23.08.2012 by Christer Nordbø, Norway.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*
* UPDATE HISTORY:
* 28.08.2013 - Made recaptcha_check_answer() function bit simpler on default
* fields as html is generated by recaptcha_get_html() function.
* Updated by - Puneet Kalra (https://github.com/puneetkay)
*/
/**
* The reCAPTCHA server URL's
*/
const RECAPTCHA_API_SERVER = "http://www.google.com/recaptcha/api";
const RECAPTCHA_API_SECURE_SERVER = "https://www.google.com/recaptcha/api";
const RECAPTCHA_VERIFY_SERVER = "www.google.com";
protected $is_valid;
protected $error;
//Remember to obtain the Public and Private key # https://www.google.com/recaptcha/admin/create
protected $public_key = "YOUR PUBLIC KEY";
protected $privkey = "YOUR PRIVATE KEY";
protected $options = array();
function __construct()
{
log_message('debug', "RECAPTCHA Class Initialized.");
$this->_ci =& get_instance();
//Load the CI Config file for recaptcha
$this->_ci->load->config('recaptcha');
//load in the values from the config file.
$this->public_key = $this->_ci->config->item('public_key');
$this->privkey = $this->_ci->config->item('private_key');
$this->options = $this->_ci->config->item('recaptcha_options');
//Lets do some basic error handling to see if the configuration is A-OK.
$temp_error_msg = '';
if ($this->public_key === 'YOUR PUBLIC KEY') {
$temp_error_msg .= 'You need to set your public key in the config file <br />';
}
if ($this->privkey === 'YOUR PRIVATE KEY') {
$temp_error_msg .= 'You need to set your private key in the config file <br />';
}
if ($temp_error_msg != '') {
show_error($temp_error_msg);
}
}
/**
* Encodes the given data into a query string format
* #param $data - array of string elements to be encoded
* #return string - encoded request
*/
function recaptcha_qsencode($data)
{
$req = "";
foreach ($data as $key => $value)
$req .= $key . '=' . urlencode(stripslashes($value)) . '&';
// Cut the last '&'
$req = substr($req, 0, strlen($req) - 1);
return $req;
}
/**
* Submits an HTTP POST to a reCAPTCHA server
* #param string $host
* #param string $path
* #param array $data
* #param int port
* #return array response
*/
function recaptcha_http_post($host, $path, $data, $port = 80)
{
$req = $this->recaptcha_qsencode($data);
$http_request = "POST $path HTTP/1.0\r\n";
$http_request .= "Host: $host\r\n";
$http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n";
$http_request .= "Content-Length: " . strlen($req) . "\r\n";
$http_request .= "User-Agent: reCAPTCHA/PHP\r\n";
$http_request .= "\r\n";
$http_request .= $req;
$response = '';
if (false == ($fs = #fsockopen($host, $port, $errno, $errstr, 10))) {
die ('Could not open socket');
}
fwrite($fs, $http_request);
while (!feof($fs))
$response .= fgets($fs, 1160); // One TCP-IP packet
fclose($fs);
$response = explode("\r\n\r\n", $response, 2);
return $response;
}
function recaptcha_get_html($error = null, $use_ssl = false)
{
if ($this->public_key == null || $this->public_key == '') {
die ("To use reCAPTCHA you must get an API key from <a href='https://www.google.com/recaptcha/admin/create'>https://www.google.com/recaptcha/admin/create</a>");
}
if ($use_ssl) {
$server = self::RECAPTCHA_API_SECURE_SERVER;
} else {
$server = self::RECAPTCHA_API_SERVER;
}
$errorpart = "";
if ($error) {
$errorpart = "&error=" . $error;
}
$options = "";
foreach ($this->options as $key => $value) {
$options .= $key . ':"' . $value . '", ';
}
return '<script type="text/javascript"> var RecaptchaOptions = { ' . $options . ' }; </script>
<script type="text/javascript" src="' . $server . '/challenge?k=' . $this->public_key . $errorpart . '"></script>
<noscript>
<iframe src="' . $server . '/noscript?k=' . $this->public_key . $errorpart . '" height="300" width="500" frameborder="0"></iframe><br/>
<textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
<input type="hidden" name="recaptcha_response_field" value="manual_challenge"/>
</noscript>';
}
/**
* Calls an HTTP POST function to verify if the user's guess was correct
* #param string $remoteip
* #param string $challenge
* #param string $response
* #param array $extra_params an array of extra variables to post to the server
* #return ReCaptchaResponse
*/
function recaptcha_check_answer($remoteip = null, $challenge = null, $response = null, $extra_params = array())
{
if ($this->privkey == null || $this->privkey == '') {
die ("To use reCAPTCHA you must get an API key from <a href='https://www.google.com/recaptcha/admin/create'>https://www.google.com/recaptcha/admin/create</a>");
}
$remoteip = ($remoteip == null) ? $_SERVER['REMOTE_ADDR'] : $remoteip;
$challenge = ($challenge == null) ? $this->_ci->input->post('recaptcha_challenge_field') : $challenge;
$response = ($response == null) ? $this->_ci->input->post('recaptcha_response_field') : $response;
if ($remoteip == null || $remoteip == '') {
die ("For security reasons, you must pass the remote ip to reCAPTCHA");
}
//discard spam submissions
if ($challenge == null || strlen($challenge) == 0 || $response == null || strlen($response) == 0) {
$this->is_valid = false;
$this->error = 'incorrect-captcha-sol';
}
$response = $this->recaptcha_http_post(self::RECAPTCHA_VERIFY_SERVER, "/recaptcha/api/verify",
array(
'privatekey' => $this->privkey,
'remoteip' => $remoteip,
'challenge' => $challenge,
'response' => $response
) + $extra_params
);
$answers = explode("\n", $response [1]);
if (trim($answers [0]) == 'true') {
$this->is_valid = true;
} else {
$this->is_valid = false;
$this->error = $answers [1];
}
}
/**
* gets a URL where the user can sign up for reCAPTCHA. If your application
* has a configuration page where you enter a key, you should provide a link
* using this function.
* #param string $domain The domain where the page is hosted
* #param string $appname The name of your application
*/
function recaptcha_get_signup_url($domain = null, $appname = 'Codeigniter')
{
return "https://www.google.com/recaptcha/admin/create?" . $this->recaptcha_qsencode(array('domains' => $domain, 'app' => $appname));
}
function recaptcha_aes_pad($val)
{
$block_size = 16;
$numpad = $block_size - (strlen($val) % $block_size);
return str_pad($val, strlen($val) + $numpad, chr($numpad));
}
/* Mailhide related code */
function recaptcha_aes_encrypt($val, $ky)
{
if (!function_exists("mcrypt_encrypt")) {
die ("To use reCAPTCHA Mailhide, you need to have the mcrypt php module installed.");
}
$mode = MCRYPT_MODE_CBC;
$enc = MCRYPT_RIJNDAEL_128;
$val = $this->recaptcha_aes_pad($val);
return mcrypt_encrypt($enc, $ky, $val, $mode, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
}
function recaptcha_mailhide_urlbase64($x)
{
return strtr(base64_encode($x), '+/', '-_');
}
/* gets the reCAPTCHA Mailhide url for a given email, public key and private key */
function recaptcha_mailhide_url($email)
{
if ($this->public_key == '' || $this->public_key == null || $this->privkey == "" || $this->privkey == null) {
die ("To use reCAPTCHA Mailhide, you have to sign up for a public and private key, " .
"you can do so at <a href='http://www.google.com/recaptcha/mailhide/apikey'>http://www.google.com/recaptcha/mailhide/apikey</a>");
}
$ky = pack('H*', $this->privkey);
$cryptmail = $this->recaptcha_aes_encrypt($email, $ky);
return "http://www.google.com/recaptcha/mailhide/d?k=" . $this->public_key . "&c=" . $this->recaptcha_mailhide_urlbase64($cryptmail);
}
/**
* gets the parts of the email to expose to the user.
* eg, given johndoe#example,com return ["john", "example.com"].
* the email is then displayed as john...#example.com
*/
function recaptcha_mailhide_email_parts($email)
{
$arr = preg_split("/#/", $email);
if (strlen($arr[0]) <= 4) {
$arr[0] = substr($arr[0], 0, 1);
} else if (strlen($arr[0]) <= 6) {
$arr[0] = substr($arr[0], 0, 3);
} else {
$arr[0] = substr($arr[0], 0, 4);
}
return $arr;
}
/**
* Gets html to display an email address given a public an private key.
* to get a key, go to:
*
* http://www.google.com/recaptcha/mailhide/apikey
*/
function recaptcha_mailhide_html($email)
{
$emailparts = $this->recaptcha_mailhide_email_parts($email);
$url = $this->recaptcha_mailhide_url($this->public_key, $this->privkey, $email);
return htmlentities($emailparts[0]) . "<a href='" . htmlentities($url) .
"' onclick=\"window.open('" . htmlentities($url) . "', '', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=300'); return false;\" title=\"Reveal this e-mail address\">...</a>#" . htmlentities($emailparts [1]);
}
function checkIfIsValid()
{
if ($this->getIsValid()) {
return $this->getIsValid();
} else {
return array($this->getIsValid(), $this->getError());
}
}
function getIsValid()
{
return $this->is_valid;
}
function getError()
{
return $this->error;
}
}
Use it:
$this->load->library('recaptcha');
$this->recaptcha->recaptcha_check_answer();
if (!$this->recaptcha->getIsValid()) {
$this->session->set_flashdata('error', 'Código Captcha incorrecto');
redirect(base_url() . 'add');
}
unset($post['recaptcha_challenge_field']);
unset($post['recaptcha_response_field']);
I have a class loader like this :
function __autoload($classname){
require_once CLASSES_DIR . "/" . $classname . ".class.php";
}
and it correctly sets the URL of any classes.
The problem is that when an instance of a class is tried to be created in the index.php (line 13):
$pdo = PDOWrapper::instance();
The browser shows a page like this:
validateDriver($driver)) { throw new Exception('DATABASE WRAPPER::error, the database you wish to connect to is not supported by your install of PHP.'); } if (isset($this->pdo_master)) { error_log('DATABASE WRAPPER::warning, attempting to config master after connection exists'); } $this->config_master = array( 'driver' => $driver, 'host' => $host, 'name' => $name, 'user' => $user, 'password' => $password, 'port' => $port ); } /** * method configSlave * - configure a connection to a slave (can be called multiple times) * * #param host - the host name of the db to connect to * #param name - the database name * #param user - the user name * #param password - the users password * #param port (optional) - the port to connect using, default to 3306 * #param driver - the dsn prefix */ public function configSlave($host, $name, $user, $password, $port=null, $driver='mysql') { if (!$this->validateDriver($driver)) { throw new Exception('DATABASE WRAPPER::error, the database you wish to connect to is not supported by your install of PHP.'); } if (isset($this->pdo_slave)) { error_log('DATABASE WRAPPER::warning, attempting to config slave after connection exists'); } if (!isset($this->config_slaves)) { $this->config_slaves = array(); } $this->config_slaves[] = array( 'driver' => $driver, 'host' => $host, 'name' => $name, 'user' => $user, 'password' => $password, 'port' => $port ); } /** * method createConnection. * - create a PDO connection using the credentials provided * * #param driver - the dsn prefix * #param host - the host name of the db to connect to * #param name - the database name * #param user - the user name * #param password - the users password * #param port (optional) - the port to connect using, default to 3306 * #return PDO object with a connection to the database specified */ protected function createConnection($driver, $host, $name, $user, $password, $port=null) { die( var_dump(PDO::getAvailableDrivers())); if (!$this->validateDriver($driver)) { throw new Exception('DATABASE WRAPPER::error, the database you wish to connect to is not supported by your install of PHP.'); } // attempt to create pdo object and connect to the database try { //#TODO the following drivers are NOT supported yet: odbc, ibm, informix, 4D // build the connection string from static constants based on the selected PDO Driver. if ($driver == "sqlite" || $driver == "sqlite2") { $connection_string = $driver.':'.$host; } elseif ($driver == "sqlsrv") { $connection_string = "sqlsrv:Server=".$host.";Database=".$name; } elseif ($driver == "firebird" || $driver == "oci") { $connection_string = $driver.":dbname=".$name; } else { $connection_string = $driver.':host='.$host.';dbname='.$name; } // add the port if one was specified if (!empty($port)) { $connection_string .= "port=$port"; } // initialize the PDO object $new_connection = new PDO($connection_string, $user, $password, array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8")); // set the error mode $new_connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // return the new connection return $new_connection; } // handle any exceptions by catching them and returning false catch (PDOException $e) { if (self::$LOG_ERRORS == true) { error_log('DATABASE WRAPPER::'.print_r($e, true)); } $this->pdo_exception = $e; return false; } catch(Exception $e) { if (self::$LOG_ERRORS == true) { error_log('DATABASE WRAPPER::'.print_r($e, true)); } $this->pdo_exception = $e; return false; } } /** * method getMaster. * - grab the PDO connection to the master DB */ protected function getMaster() { // if we have not been configured, use hard coded values if (!isset($this->config_master)) { $this->config_master = array( 'driver' => self::DB_DSN_PREFIX_MASTER, 'host' => self::DB_HOST_MASTER, 'name' => self::DB_NAME_MASTER, 'user' => self::DB_USER_MASTER, 'password' => self::DB_PASSWORD_MASTER, 'port' => self::DB_PORT_MASTER ); } // if we have not created the master db connection yet, create it now if (!isset($this->pdo_master)) { $this->pdo_master = $this->createConnection( $this->config_master['driver'], $this->config_master['host'], $this->config_master['name'], $this->config_master['user'], $this->config_master['password'], $this->config_master['port'] ); } return $this->pdo_master; } /** * method getSlave. * - grab the PDO connection to the slave DB, create it if not there */ protected function getSlave() { // if we have not created a slave db connection, create it now if (!isset($this->pdo_slave)) { // if no slaves were configured, use hardcoded values if (!isset($this->config_slaves)) { $i = 1; while (defined('self::SLAVE' . $i . '_HOST') && constant('self::SLAVE' . $i . '_HOST')) { $this->config_slaves[] = array( 'driver' => constant('self::SLAVE' . $i . '_DSN_PREFIX'), 'host' => constant('self::SLAVE' . $i . '_HOST'), 'name' => constant('self::SLAVE' . $i . '_NAME'), 'user' => constant('self::SLAVE' . $i . '_USER'), 'password' => constant('self::SLAVE' . $i . '_PASSWORD'), 'port' => constant('self::SLAVE' . $i . '_PORT'), ); $i++; } } // if no slaves are configured, use the master connection if (empty($this->config_slaves)) { $this->pdo_slave = $this->getMaster(); } // if we have slaves, randomly choose one to use for this request and connect else { $random_slave = $this->config_slaves[array_rand($this->config_slaves)]; $this->pdo_slave = $this->createConnection( $random_slave['driver'], $random_slave['host'], $random_slave['name'], $random_slave['user'], $random_slave['password'], $random_slave['port'] ); } } return $this->pdo_slave; } /** * method select. * - retrieve information from the database, as an array * * #param string $table - the name of the db table we are retreiving the rows from * #param array $params - associative array representing the WHERE clause filters * #param int $limit (optional) - the amount of rows to return * #param int $start (optional) - the row to start on, indexed by zero * #param array $order_by (optional) - an array with order by clause * #param bool $use_master (optional) - use the master db for this read * #return mixed - associate representing the fetched table row, false on failure */ public function select($table, $params = null, $limit = null, $start = null, $order_by=null, $use_master = false) { // building query string $sql_str = "SELECT * FROM $table"; // append WHERE if necessary $sql_str .= ( count($params)>0 ? ' WHERE ' : '' ); $add_and = false; // add each clause using parameter array if (empty($params)) { $params = array(); } foreach ($params as $key=>$val) { // only add AND after the first clause item has been appended if ($add_and) { $sql_str .= ' AND '; } else { $add_and = true; } // append clause item $sql_str .= "$key = :$key"; } // add the order by clause if we have one if (!empty($order_by)) { $sql_str .= ' ORDER BY'; $add_comma = false; foreach ($order_by as $column => $order) { if ($add_comma) { $sql_str .= ', '; } else { $add_comma = true; } $sql_str .= " $column $order"; } } // now we attempt to retrieve the row using the sql string try { // decide which database we are selecting from $pdo_connection = $use_master ? $this->getMaster() : $this->getSlave(); $pdoDriver = $pdo_connection->getAttribute(PDO::ATTR_DRIVER_NAME); //#TODO MS SQL Server & Oracle handle LIMITs differently, for now its disabled but we should address it later. $disableLimit = array("sqlsrv", "mssql", "oci"); // add the limit clause if we have one if (!is_null($limit) && !in_array($pdoDriver, $disableLimit)) { $sql_str .= ' LIMIT '.(!is_null($start) ? "$start, ": '')."$limit"; } $pstmt = $pdo_connection->prepare($sql_str); // bind each parameter in the array foreach ($params as $key=>$val) { $pstmt->bindValue(':'.$key, $val); } $pstmt->execute(); // now return the results, depending on if we want all or first row only if ( !is_null($limit) && $limit == 1 ) { return $pstmt->fetch(PDO::FETCH_ASSOC); } else { return $pstmt->fetchAll(PDO::FETCH_ASSOC); } } catch(PDOException $e) { if (self::$LOG_ERRORS == true) { error_log('DATABASE WRAPPER::'.print_r($e, true)); } $this->pdo_exception = $e; return false; } catch(Exception $e) { if (self::$LOG_ERRORS == true) { error_log('DATABASE WRAPPER::'.print_r($e, true)); } $this->pdo_exception = $e; return false; } } /** * method selectMaster. * - retrieve information from the master database, as an array * * #param table - the name of the db table we are retreiving the rows from * #param params - associative array representing the WHERE clause filters * #param int $limit (optional) - the amount of rows to return * #param int $start (optional) - the row to start on, indexed by zero * #param array $order_by (optional) - an array with order by clause * #return mixed - associate representing the fetched table row, false on failure */ public function selectMaster($table, $params = array(), $limit = null, $start = null, $order_by=null) { return $this->select($table, $params, $limit, $start, $order_by, true); } /** * method selectFirst. * - retrieve the first row returned from a select statement * * #param table - the name of the db table we are retreiving the rows from * #param params - associative array representing the WHERE clause filters * #param array $order_by (optional) - an array with order by clause * #return mixed - associate representing the fetched table row, false on failure */ public function selectFirst($table, $params = array(), $order_by=null) { return $this->select($table, $params, 1, null, $order_by); } /** * method selectFirstMaster. * - retrieve the first row returned from a select statement using the master database * * #param table - the name of the db table we are retreiving the rows from * #param params - associative array representing the WHERE clause filters * #param array $order_by (optional) - an array with order by clause * #return mixed - associate representing the fetched table row, false on failure */ public function selectFirstMaster($table, $params = array(), $order_by=null) { return $this->select($table, $params, 1, null, $order_by, true); } /** * method delete. * - deletes rows from a table based on the parameters * * #param table - the name of the db table we are deleting the rows from * #param params - associative array representing the WHERE clause filters * #return bool - associate representing the fetched table row, false on failure */ public function delete($table, $params = array()) { // building query string $sql_str = "DELETE FROM $table"; // append WHERE if necessary $sql_str .= ( count($params)>0 ? ' WHERE ' : '' ); $add_and = false; // add each clause using parameter array foreach ($params as $key=>$val) { // only add AND after the first clause item has been appended if ($add_and) { $sql_str .= ' AND '; } else { $add_and = true; } // append clause item $sql_str .= "$key = :$key"; } // now we attempt to retrieve the row using the sql string try { $pstmt = $this->getMaster()->prepare($sql_str); // bind each parameter in the array foreach ($params as $key=>$val) { $pstmt->bindValue(':'.$key, $val); } // execute the delete query $successful_delete = $pstmt->execute(); // if we were successful, return the amount of rows updated, otherwise return false return ($successful_delete == true) ? $pstmt->rowCount() : false; } catch(PDOException $e) { if (self::$LOG_ERRORS == true) { error_log('DATABASE WRAPPER::'.print_r($e, true)); } $this->pdo_exception = $e; return false; } catch(Exception $e) { if (self::$LOG_ERRORS == true) { error_log('DATABASE WRAPPER::'.print_r($e, true)); } $this->pdo_exception = $e; return false; } } /** * method update. * - updates a row to the specified table * * #param string $table - the name of the db table we are adding row to * #param array $params - associative array representing the columns and their respective values to update * #param array $wheres (Optional) - the where clause of the query * #param bool $timestamp_this (Optional) - if true we set date_created and date_modified values to now * #return int|bool - the amount of rows updated, false on failure */ public function update($table, $params, $wheres=array(), $timestamp_this=null) { if (is_null($timestamp_this)) { $timestamp_this = self::$TIMESTAMP_WRITES; } // build the set part of the update query by // adding each parameter into the set query string $add_comma = false; $set_string = ''; foreach ($params as $key=>$val) { // only add comma after the first parameter has been appended if ($add_comma) { $set_string .= ', '; } else { $add_comma = true; } // now append the parameter $set_string .= "$key=:param_$key"; } // add the timestamp columns if neccessary if ($timestamp_this === true) { $set_string .= ($add_comma ? ', ' : '') . 'date_modified='.time(); } // lets add our where clause if we have one $where_string = ''; if (!empty($wheres)) { // load each key value pair, and implode them with an AND $where_array = array(); foreach($wheres as $key => $val) { $where_array[] = "$key=:where_$key"; } // build the final where string $where_string = 'WHERE '.implode(' AND ', $where_array); } // build final update string $sql_str = "UPDATE $table SET $set_string $where_string"; // now we attempt to write this row into the database try { $pstmt = $this->getMaster()->prepare($sql_str); // bind each parameter in the array foreach ($params as $key=>$val) { $pstmt->bindValue(':param_'.$key, $val); } // bind each where item in the array foreach ($wheres as $key=>$val) { $pstmt->bindValue(':where_'.$key, $val); } // execute the update query $successful_update = $pstmt->execute(); // if we were successful, return the amount of rows updated, otherwise return false return ($successful_update == true) ? $pstmt->rowCount() : false; } catch(PDOException $e) { if (self::$LOG_ERRORS == true) { error_log('DATABASE WRAPPER::'.print_r($e, true)); } $this->pdo_exception = $e; return false; } catch(Exception $e) { if (self::$LOG_ERRORS == true) { error_log('DATABASE WRAPPER::'.print_r($e, true)); } $this->pdo_exception = $e; return false; } } /** * method insert. * - adds a row to the specified table * * #param string $table - the name of the db table we are adding row to * #param array $params - associative array representing the columns and their respective values * #param bool $timestamp_this (Optional), if true we set date_created and date_modified values to now * #return mixed - new primary key of inserted table, false on failure */ public function insert($table, $params = array(), $timestamp_this = null) { if (is_null($timestamp_this)) { $timestamp_this = self::$TIMESTAMP_WRITES; } // first we build the sql query string $columns_str = '('; $values_str = 'VALUES ('; $add_comma = false; // add each parameter into the query string foreach ($params as $key=>$val) { // only add comma after the first parameter has been appended if ($add_comma) { $columns_str .= ', '; $values_str .= ', '; } else { $add_comma = true; } // now append the parameter $columns_str .= "$key"; $values_str .= ":$key"; } // add the timestamp columns if neccessary if ($timestamp_this === true) { $columns_str .= ($add_comma ? ', ' : '') . 'date_created, date_modified'; $values_str .= ($add_comma ? ', ' : '') . 'UNIX_TIMESTAMP(), UNIX_TIMESTAMP()'; } // close the builder strings $columns_str .= ') '; $values_str .= ')'; // build final insert string $sql_str = "INSERT INTO $table $columns_str $values_str"; // now we attempt to write this row into the database try { $pstmt = $this->getMaster()->prepare($sql_str); // bind each parameter in the array foreach ($params as $key=>$val) { $pstmt->bindValue(':'.$key, $val); } $pstmt->execute(); $newID = $this->getMaster()->lastInsertId(); // return the new id return $newID; } catch(PDOException $e) { if (self::$LOG_ERRORS == true) { error_log('DATABASE WRAPPER::'.print_r($e, true)); } $this->pdo_exception = $e; return false; } catch(Exception $e) { if (self::$LOG_ERRORS == true) { error_log('DATABASE WRAPPER::'.print_r($e, true)); print_r($e); } $this->pdo_exception = $e; return false; } } /** * method insertMultiple. * - adds multiple rows to a table with a single query * * #param string $table - the name of the db table we are adding row to * #param array $columns - contains the column names * #param bool $timestamp_these (Optional), if true we set date_created and date_modified values to NOW() for each row * #return mixed - new primary key of inserted table, false on failure */ public function insertMultiple($table, $columns = array(), $rows = array(), $timestamp_these = null) { if (is_null($timestamp_these)) { $timestamp_these = self::$TIMESTAMP_WRITES; } // generate the columns portion of the insert statment // adding the timestamp fields if needs be if ($timestamp_these) { $columns[] = 'date_created'; $columns[] = 'date_modified'; } $columns_str = '(' . implode(',', $columns) . ') '; // generate the values portions of the string $values_str = 'VALUES '; $add_comma = false; foreach ($rows as $row_index => $row_values) { // only add comma after the first row has been added if ($add_comma) { $values_str .= ', '; } else { $add_comma = true; } // here we will create the values string for a single row $values_str .= '('; $add_comma_forvalue = false; foreach ($row_values as $value_index => $value) { if ($add_comma_forvalue) { $values_str .= ', '; } else { $add_comma_forvalue = true; } // generate the bind variable name based on the row and column index $values_str .= ':'.$row_index.'_'.$value_index; } // append timestamps if necessary if ($timestamp_these) { $values_str .= ($add_comma_forvalue ? ', ' : '') . time().', '.time(); } $values_str .= ')'; } // build final insert string $sql_str = "INSERT INTO $table $columns_str $values_str"; // now we attempt to write this multi inster query to the database using a transaction try { $this->getMaster()->beginTransaction(); $pstmt = $this->getMaster()->prepare($sql_str); // traverse the 2d array of rows and values to bind all parameters foreach ($rows as $row_index => $row_values) { foreach ($row_values as $value_index => $value) { $pstmt->bindValue(':'.$row_index.'_'.$value_index, $value); } } // now lets execute the statement, commit the transaction and return $pstmt->execute(); $this->getMaster()->commit(); return true; } catch(PDOException $e) { if (self::$LOG_ERRORS == true) { error_log('DATABASE WRAPPER::'.print_r($e, true)); } $this->pdo_exception = $e; $this->getMaster()->rollback(); return false; } catch(Exception $e) { if (self::$LOG_ERRORS == true) { error_log('DATABASE WRAPPER::'.print_r($e, true)); } $this->pdo_exception = $e; $this->getMaster()->rollback(); return false; } } /** * method execute. * - executes a query that modifies the database * * #param string $query - the SQL query we are executing * #param bool $use_master (Optional) - whether or not to use the master connection * #return mixed - the affected rows, false on failure */ public function execute($query, $params=array()) { try { // use the master connection $pdo_connection = $this->getMaster(); // prepare the statement $pstmt = $pdo_connection->prepare($query); // bind each parameter in the array foreach ((array)$params as $key=>$val) { $pstmt->bindValue($key, $val); } // execute the query $result = $pstmt->execute(); // only if return value is false did this query fail return ($result == true) ? $pstmt->rowCount() : false; } catch(PDOException $e) { if (self::$LOG_ERRORS == true) { error_log('DATABASE WRAPPER::'.print_r($e, true)); } $this->pdo_exception = $e; return false; } catch(Exception $e) { if (self::$LOG_ERRORS == true) { error_log('DATABASE WRAPPER::'.print_r($e, true)); } $this->pdo_exception = $e; return false; } } /** * method query. * - returns data from a free form select query * * #param string $query - the SQL query we are executing * #param array $params - a list of bind parameters * #param bool $use_master (Optional) - whether or not to use the master connection * #return mixed - the affected rows, false on failure */ public function query($query, $params=array(), $use_master=false) { try { // decide which database we are selecting from $pdo_connection = $use_master ? $this->getMaster() : $this->getSlave(); $pstmt = $pdo_connection->prepare($query); // bind each parameter in the array foreach ((array)$params as $key=>$val) { $pstmt->bindValue($key, $val); } // execute the query $pstmt->execute(); // now return the results return $pstmt->fetchAll(PDO::FETCH_ASSOC); } catch(PDOException $e) { if (self::$LOG_ERRORS == true) { error_log('DATABASE WRAPPER::'.print_r($e, true)); } $this->pdo_exception = $e; return false; } catch(Exception $e) { if (self::$LOG_ERRORS == true) { error_log('DATABASE WRAPPER::'.print_r($e, true)); } $this->pdo_exception = $e; return false; } } /** * method queryFirst. * - returns the first record from a free form select query * * #param string $query - the SQL query we are executing * #param array $params - a list of bind parameters * #param bool $use_master (Optional) - whether or not to use the master connection * #return mixed - the affected rows, false on failure */ public function queryFirst($query, $params=array(), $use_master=false) { $result = $this->query($query, $params, $use_master); if (empty($result)) { return false; } else { return $result[0]; } } /** * method getErrorMessage. * - returns the last error message caught */ public function getErrorMessage() { if ($this->pdo_exception) return $this->pdo_exception->getMessage(); else return 'Database temporarily unavailable'; } /** * method getError. * - returns the actual PDO exception */ public function getPDOException() { return $this->pdo_exception; } /** * Validate the database in question is supported by your installation of PHP. * #param string $driver The DSN prefix * #return boolean true, the database is supported; false, the database is not supported. */ private function validateDriver($driver) { if (!in_array($driver, PDO::getAvailableDrivers())) { return false; } else { return true; } } /** * Destructor. * - release the PDO db connections */ function __destruct() { unset($this->pdo_master); unset($this->pdo_slave); } }
Notice: Undefined index: language in C:\xampp\htdocs_\config.php on
line 133
Notice: Undefined variable: condo_name in
C:\xampp\htdocs_\language\fr.php on line 319
Notice: Undefined variable: condo_name in
C:\xampp\htdocs_\language\fr.php on line 320
Notice: Undefined variable: condo_name in
C:\xampp\htdocs_\language\fr.php on line 321
Notice: Undefined variable: claim_name in
C:\xampp\htdocs_\language\fr.php on line 327
Notice: Undefined variable: claim_name in
C:\xampp\htdocs_\language\fr.php on line 328
Notice: Undefined variable: tender in
C:\xampp\htdocs_\language\fr.php on line 329
Notice: Undefined variable: condo_name in
C:\xampp\htdocs_\language\fr.php on line 332
Notice: Undefined variable: condo_name in
C:\xampp\htdocs_\language\fr.php on line 333
Notice: Undefined variable: condo_name in
C:\xampp\htdocs_\language\fr.php on line 361
Fatal error: Class 'PDOWrapper' not found in
C:\xampp\htdocs_\index.php on line 13 etc. and a fatal error:
Fatal error: Class 'PDOWrapper' not found in C:\xampp\htdocs_\index.php on line 13.
So it seems strange that it can show some PDOWrapper code content and a fatal error to find it.
I don't know why the class is not found, and the browser shows the content of the class, you can see the write, throw new Exception . . .Etc.
For some odd reason im unable to retrieve group memebers from domain users or any group for that batter.
Base DN is set to dc=domain,dc=com Ive hits block here. When I use the test tool im able to authenticate [NOTICE] Authentication successfull for "rpimentel#domain.com"
Something is missing. Something simple, that im over looking. What could it be?
// Extend the ADIntegrationPlugin class
class BulkImportADIntegrationPlugin extends ADIntegrationPlugin {
/**
* Output formatted debug informations
*
* #param integer level
* #param string $notice
*/
protected function _log($level = 0, $info = '') {
if ($level <= $this->_loglevel) {
switch ($level) {
case ADI_LOG_DEBUG:
$class = 'debug';
$type = '[DEBUG] ';
break;
case ADI_LOG_INFO:
$class = 'info';
$type = '[INFO] ';
break;
case ADI_LOG_NOTICE:
$class = 'notice';
$type = '[NOTICE] ';
break;
case ADI_LOG_WARN:
$class = 'warn';
$type = '[WARN] ';
break;
case ADI_LOG_ERROR:
$class = 'error';
$type = '[ERROR] ';
break;
case ADI_LOG_FATAL:
$class = 'fatal';
$type = '[FATAL] ';
break;
default:
$class = '';
$type = '';
}
$output = '<span class="'.$class.'">'.$type;
$output .= str_replace("\n","<br /> ",$info).'</span><br />';
echo $output;
if (WP_DEBUG) {
if ($fh = #fopen($this->_logfile,'a+')) {
fwrite($fh,$type . str_replace("\n","\n ",$info) . "\n");
fclose($fh);
}
}
}
}
/**
* Do Bulk Import
*
* #param string $authcode
* #return bool true on success, false on error
*/
public function bulkimport($authcode)
{
global $wp_version;
global $wpdb;
$this->setLogFile(dirname(__FILE__).'/import.log');
$this->_log(ADI_LOG_INFO,"-------------------------------------\n".
"START OF BULK IMPORT\n".
date('Y-m-d / H:i:s')."\n".
"-------------------------------------\n");
$time = time();
$all_users = array();
// Is bulk import enabled?
if (!$this->_bulkimport_enabled) {
$this->_log(ADI_LOG_INFO,'Bulk Import is disabled.');
return false;
}
// DO we have the correct Auth Code?
if ($this->_bulkimport_authcode !== $authcode) {
$this->_log(ADI_LOG_ERROR,'Wrong Auth Code.');
return false;
}
$ad_password = $this->_decrypt($this->_bulkimport_pwd);
// Log informations
$this->_log(ADI_LOG_INFO,"Options for adLDAP connection:\n".
"- base_dn: $this->_base_dn\n".
"- domain_controllers: $this->_domain_controllers\n".
"- ad_username: $this->_bulkimport_user\n".
"- ad_password: **not shown**\n".
"- ad_port: $this->_port\n".
"- use_tls: ".(int) $this->_use_tls."\n".
"- network timeout: ". $this->_network_timeout);
// Connect to Active Directory
try {
$this->_adldap = #new adLDAP(array(
"base_dn" => $this->_base_dn,
"domain_controllers" => explode(';', $this->_domain_controllers),
"ad_username" => $this->_bulkimport_user, // Bulk Import User
"ad_password" => $ad_password, // password
"ad_port" => $this->_port, // AD port
"use_tls" => $this->_use_tls, // secure?
"network_timeout" => $this->_network_timeout // network timeout
));
} catch (Exception $e) {
$this->_log(ADI_LOG_ERROR,'adLDAP exception: ' . $e->getMessage());
return false;
}
$this->_log(ADI_LOG_NOTICE,'adLDAP object created.');
$this->_log(ADI_LOG_INFO,'Domain Controller: ' . $this->_adldap->get_last_used_dc());
// Let's give us some more time (60 minutes)
$max_execution_time = ini_get('max_execution_time');
if ($max_execution_time < 3600) {
ini_set('max_execution_time', 3600);
}
if (ini_get('max_execution_time') < 3600) {
$this->_log(ADI_LOG_ERROR,'Can not increase PHP configuration option "max_execution_time".');
return false;
}
// get all users of the chosen security groups from
$groups = explode(";",$this->_bulkimport_security_groups);
if (count($groups) < 1) {
$this->_log(ADI_LOG_WARN,'No security group.');
return false;
}
foreach ($groups AS $group) {
// get all members of group
$group = trim($group);
if ($group != '') {
// do we have a groupid?
if (($pos = stripos($group,'id:')) !== false) {
$pgid = substr($group,$pos+3);
$members = $this->_adldap->group_members_by_primarygroupid($pgid, true);
} else {
$members = $this->_adldap->group_members($group, true);
}
if ($members) {
$this->_log(ADI_LOG_INFO,count($members).' Members of group "'.$group.'".');
$this->_log(ADI_LOG_DEBUG,'Members of group "'.$group.'": ' . implode(', ',$members));
foreach ($members AS $user) {
$all_users[strtolower($user)] = $user;
}
} else {
$this->_log(ADI_LOG_ERROR,'Error retrieving group members for group "'.$group.'".');
}
} else {
$this->_log(ADI_LOG_WARN,'No group. Nothing to do.');
}
}
// Adding all local users with non empty entry adi_samaccountname in usermeta
$blogusers=$wpdb->get_results(
'
SELECT
users.user_login
FROM
'. $wpdb->users . ' users
INNER JOIN
' . $wpdb->usermeta ." meta ON meta.user_id = users.ID
where
meta.meta_key = 'adi_samaccountname'
AND
meta.meta_value IS NOT NULL
AND
meta.meta_value <> ''
AND
users.ID <> 1
"
);
if (is_array($blogusers)) {
foreach ($blogusers AS $user) {
$all_users[strtolower($user->user_login)] = $user->user_login;
}
}
$elapsed_time = time() - $time;
$this->_log(ADI_LOG_INFO,'Number of users to import/update: '.count($all_users).' (list generated in '. $elapsed_time .' seconds)');
if (version_compare($wp_version, '3.1', '<')) {
require_once(ABSPATH . WPINC . DIRECTORY_SEPARATOR . 'registration.php');
}
// import all relevant users
$added_users = 0;
$updated_users = 0;
foreach ($all_users AS $username) {
$ad_username = $username;
// getting user data
//$user = get_userdatabylogin($username); // deprecated
$user = get_user_by('login', $username);
// role
$user_role = $this->_get_user_role_equiv($ad_username); // important: use $ad_username not $username
// userinfo from AD
$this->_log(ADI_LOG_DEBUG, 'ATTRIBUTES TO LOAD: '.print_r($this->_all_user_attributes, true));
$userinfo = $this->_adldap->user_info($ad_username, $this->_all_user_attributes);
$userinfo = $userinfo[0];
$this->_log(ADI_LOG_DEBUG,"USERINFO[0]: \n".print_r($userinfo,true));
if (empty($userinfo)) {
$this->_log(ADI_LOG_INFO,'User "' . $ad_username . '" not found in Active Directory.');
if (isset($user->ID) && ($this->_disable_users)) {
$this->_log(ADI_LOG_WARN,'User "' . $username . '" disabled.');
$this->_disable_user($user->ID, sprintf(__('User "%s" not found in Active Directory.', 'ad-integration'), $username));
}
} else {
// Only user accounts (UF_NORMAL_ACCOUNT is set and other account flags are unset)
if (($userinfo["useraccountcontrol"][0] & (UF_NORMAL_ACCOUNT | ADI_NO_UF_NORMAL_ACOUNT)) == UF_NORMAL_ACCOUNT) {
//&& (($userinfo["useraccountcontrol"][0] & ADI_NO_UF_NORMAL_ACOUNT) == 0)) {
// users with flag UF_SMARTCARD_REQUIRED have no password so they can not logon with ADI
if (($userinfo["useraccountcontrol"][0] & UF_SMARTCARD_REQUIRED) == 0) {
// get display name
$display_name = $this->_get_display_name_from_AD($username, $userinfo);
// create new users or update them
if (!$user OR (strtolower($user->user_login) != strtolower($username))) { // use strtolower!!!
$user_id = $this->_create_user($ad_username, $userinfo, $display_name, $user_role, '', true);
$added_users++;
} else {
$user_id = $this->_update_user($ad_username, $userinfo, $display_name, $user_role, '', true);
$updated_users++;
}
// load user object (this shouldn't be necessary)
if (!$user_id) {
$user_id = username_exists($username);
$this->_log(ADI_LOG_NOTICE,'user_id: '.$user_id);
}
// if the user is disabled
if (($userinfo["useraccountcontrol"][0] & UF_ACCOUNT_DISABLE) == UF_ACCOUNT_DISABLE)
{
$this->_log(ADI_LOG_INFO,'The user "' . $username .'" is disabled in Active Directory.');
if ($this->_disable_users) {
$this->_log(ADI_LOG_WARN,'Disabling user "' . $username .'".');
$this->_disable_user($user_id, sprintf(__('User "%s" is disabled in Active Directory.', 'ad-integration'), $username));
}
} else {
// Enable user / turn off user_disabled
$this->_log(ADI_LOG_INFO,'Enabling user "' . $username .'".');
$this->_enable_user($user_id);
}
} else {
// Flag UF_SMARTCARD_REQUIRED is set
$this->_log(ADI_LOG_INFO,'The user "' . $username .'" requires a SmartCard to logon.');
if (isset($user->ID) && ($this->_disable_users)) {
$this->_log(ADI_LOG_WARN,'Disabling user "' . $username .'".');
$this->_disable_user($user->ID, sprintf(__('User "%s" requires a SmartCard to logon.', 'ad-integration'), $username));
}
}
} else {
// not a normal user account
$this->_log(ADI_LOG_INFO,'The user "' . $username .'" has no normal user account.');
if (isset($user->ID) && ($this->_disable_users)) {
$this->_log(ADI_LOG_WARN,'Disabling user "' . $username .'".');
$this->_disable_user($user->ID, sprintf(__('User "%s" has no normal user account.', 'ad-integration'), $username));
}
}
}
}
// Logging
$elapsed_time = time() - $time;
$this->_log(ADI_LOG_INFO,$added_users . ' Users added.');
$this->_log(ADI_LOG_INFO,$updated_users . ' Users updated.');
$this->_log(ADI_LOG_INFO,'In '. $elapsed_time . ' seconds.');
$this->_log(ADI_LOG_INFO,"-------------------------------------\n".
"END OF BULK IMPORT\n".
date('Y-m-d / H:i:s')."\n".
"-------------------------------------\n");
return true;
}
It looks like this is where I fails. But why wouldn't it be able to get group?
foreach ($groups AS $group) {
// get all members of group
$group = trim($group);
if ($group != '') {
// do we have a groupid?
if (($pos = stripos($group,'id:')) !== false) {
$pgid = substr($group,$pos+3);
$members = $this->_adldap->group_members_by_primarygroupid($pgid, true);
} else {
$members = $this->_adldap->group_members($group, true);
}
if ($members) {
$this->_log(ADI_LOG_INFO,count($members).' Members of group "'.$group.'".');
$this->_log(ADI_LOG_DEBUG,'Members of group "'.$group.'": ' . implode(', ',$members));
foreach ($members AS $user) {
$all_users[strtolower($user)] = $user;
}
} else {
$this->_log(ADI_LOG_ERROR,'Error retrieving group members for group "'.$group.'".');
}
I removed
$ad_password = $this->_decrypt($this->_bulkimport_pwd);
and added
$ad_password = 'my_password_here';
And it worked
Seems that this decrypt password is broken.
[INFO] 1000 Members of group "id:513".
[INFO] Number of users to import/update: 3439
I had the same problem when I filled twice the field "Bulk Import User Password". I launched the bulk import, which failed (all the users were disabled!). My Apache log below:
PHP Warning: mcrypt_decrypt(): Key of size 27 not supported by this
algorithm.Only keys of sizes 16, 24 or 32 supported in
/var/www/html/wordpress/wp-content/plugins/active-directory-integration/ad-integration.php
The problem seems come from the function mcrypt used to encrypt the password. We can see in the file ad-integration.php that the function used the Wordpress constant AUTH_SALT, which is defined by default like "put your unique phrase here", thus 27 char. So I defined this constant with a string of 32 char (you can define this in wp-config.php). I refilled the Bulk Import User Password and it works.
My host confirmed that Zend 2.3 is installed. I then proceeded to check the installation was working by uploading this script:
http://www.jarodmorris.com/zend_check.php
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license#zend.com so we can send you a copy immediately.
*
* #category Zend
* #package Zend_Gdata
* #subpackage Demos
* #copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
* #license http://framework.zend.com/license/new-bsd New BSD License
*/
/**
* Simple class to verify that the server that this is run on has a correct
* installation of the Zend Framework Gdata component.
*/
class InstallationChecker {
const CSS_WARNING = '.warning { color: #fff; background-color: #AF0007;}';
const CSS_SUCCESS = '.success { color: #000; background-color: #69FF4F;}';
const CSS_ERROR = '.error { color: #fff; background-color: #FF9FA3;}';
const PHP_EXTENSION_ERRORS = 'PHP Extension Errors';
const PHP_MANUAL_LINK_FRAGMENT = 'http://us.php.net/manual/en/book.';
const PHP_REQUIREMENT_CHECKER_ID = 'PHP Requirement checker v0.1';
const SSL_CAPABILITIES_ERRORS = 'SSL Capabilities Errors';
const YOUTUBE_API_CONNECTIVITY_ERRORS = 'YouTube API Connectivity Errors';
const ZEND_GDATA_INSTALL_ERRORS = 'Zend Framework Installation Errors';
const ZEND_SUBVERSION_URI = 'http://framework.zend.com/download/subversion';
private static $REQUIRED_EXTENSIONS = array(
'ctype', 'dom', 'libxml', 'spl', 'standard', 'openssl');
private $_allErrors = array(
self::PHP_EXTENSION_ERRORS => array(
'tested' => false, 'errors' => null),
self::ZEND_GDATA_INSTALL_ERRORS => array(
'tested' => false, 'errors' => null),
self::SSL_CAPABILITIES_ERRORS => array(
'tested' => false, 'errors' => null),
self::YOUTUBE_API_CONNECTIVITY_ERRORS => array(
'tested' => false, 'errors' => null)
);
private $_sapiModeCLI = null;
/**
* Create a new InstallationChecker object and run verifications.
* #return void
*/
public function __construct()
{
$this->determineIfInCLIMode();
$this->runAllVerifications();
$this->outputResults();
}
/**
* Set the sapiModeCLI variable to true if we are running CLI mode.
*
* #return void
*/
private function determineIfInCLIMode()
{
if (php_sapi_name() == 'cli') {
$this->_sapiModeCLI = true;
}
}
/**
* Getter for sapiModeCLI variable.
*
* #return boolean True if we are running in CLI mode.
*/
public function runningInCLIMode()
{
if ($this->_sapiModeCLI) {
return true;
} else {
return false;
}
}
/**
* Run verifications, stopping at each step if there is a failure.
*
* #return void
*/
public function runAllVerifications()
{
if (!$this->validatePHPExtensions()) {
return;
}
if (!$this->validateZendFrameworkInstallation()) {
return;
}
if (!$this->testSSLCapabilities()) {
return;
}
if (!$this->validateYouTubeAPIConnectivity()) {
return;
}
}
/**
* Validate that the required PHP Extensions are installed and available.
*
* #return boolean False if there were errors.
*/
private function validatePHPExtensions()
{
$phpExtensionErrors = array();
foreach (self::$REQUIRED_EXTENSIONS as $requiredExtension) {
if (!extension_loaded($requiredExtension)) {
$requiredExtensionError = $requiredExtension .
' extension missing';
$documentationLink = null;
if ($requiredExtension != 'standard') {
$documentationLink = self::PHP_MANUAL_LINK_FRAGMENT .
$requiredExtension . '.php';
$documentationLink =
$this->checkAndAddHTMLLink($documentationLink);
} else {
$documentationLink = self::PHP_MANUAL_LINK_FRAGMENT .
'spl.php';
$documentationLink =
$this->checkAndAddHTMLLink($documentationLink);
}
if ($documentationLink) {
$phpExtensionErrors[] = $requiredExtensionError .
' - refer to ' . $documentationLink;
}
}
}
$this->_allErrors[self::PHP_EXTENSION_ERRORS]['tested'] = true;
if (count($phpExtensionErrors) > 0) {
$this->_allErrors[self::PHP_EXTENSION_ERRORS]['errors'] =
$phpExtensionErrors;
return false;
}
return true;
}
/**
* Validate that the Gdata component of Zend Framework is installed
* properly. Also checks that the required YouTube API helper methods are
* found.
*
* #return boolean False if there were errors.
*/
private function validateZendFrameworkInstallation()
{
$zendFrameworkInstallationErrors = array();
$zendLoaderPresent = false;
try {
$zendLoaderPresent = #fopen('Zend/Loader.php', 'r', true);
} catch (Exception $e) {
$zendFrameworkInstallationErrors[] = 'Exception thrown trying to ' .
'access Zend/Loader.php using \'use_include_path\' = true ' .
'Make sure you include the Zend Framework in your ' .
'include_path which currently contains: "' .
ini_get('include_path') . '"';
}
if ($zendLoaderPresent) {
#fclose($zendLoaderPresent);
require_once('Zend/Loader.php');
require_once('Zend/Version.php');
Zend_Loader::loadClass('Zend_Gdata_YouTube');
Zend_Loader::loadClass('Zend_Gdata_YouTube_VideoEntry');
$yt = new Zend_Gdata_YouTube();
$videoEntry = $yt->newVideoEntry();
if (!method_exists($videoEntry, 'setVideoTitle')) {
$zendFrameworkMessage = 'Your version of the ' .
'Zend Framework ' . Zend_Version::VERSION . ' is too old' .
' to run the YouTube demo application and does not' .
' contain the new helper methods. Please check out a' .
' newer version from Zend\'s repository: ' .
checkAndAddHTMLLink(self::ZEND_SUBVERSION_URI);
$zendFrameworkInstallationErrors[] = $zendFrameworkMessage;
}
} else {
if (count($zendFrameworkInstallationErrors) < 1) {
$zendFrameworkInstallationErrors[] = 'Exception thrown trying' .
' to access Zend/Loader.php using \'use_include_path\' =' .
' true. Make sure you include Zend Framework in your' .
' include_path which currently contains: ' .
ini_get('include_path');
}
}
$this->_allErrors[self::ZEND_GDATA_INSTALL_ERRORS]['tested'] = true;
if (count($zendFrameworkInstallationErrors) > 0) {
$this->_allErrors[self::ZEND_GDATA_INSTALL_ERRORS]['errors'] =
$zendFrameworkInstallationErrors;
return false;
}
return true;
}
/**
* Create HTML link from an input string if not in CLI mode.
*
* #param string The error message to be converted to a link.
* #return string Either the original error message or an HTML version.
*/
private function checkAndAddHTMLLink($inputString) {
if (!$this->runningInCLIMode()) {
return $this->makeHTMLLink($inputString);
} else {
return $inputString;
}
}
/**
* Create an HTML link from a string.
*
* #param string The string to be made into link text and anchor target.
* #return string HTML link.
*/
private function makeHTMLLink($inputString)
{
return '<a href="'. $inputString . '" target="_blank">' .
$inputString . '</a>';
}
/**
* Validate that SSL Capabilities are available.
*
* #return boolean False if there were errors.
*/
private function testSSLCapabilities()
{
$sslCapabilitiesErrors = array();
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Http_Client');
$httpClient = new Zend_Http_Client(
'https://www.google.com/accounts/AuthSubRequest');
$response = $httpClient->request();
$this->_allErrors[self::SSL_CAPABILITIES_ERRORS]['tested'] = true;
if ($response->isError()) {
$sslCapabilitiesErrors[] = 'Response from trying to access' .
' \'https://www.google.com/accounts/AuthSubRequest\' ' .
$response->getStatus() . ' - ' . $response->getMessage();
}
if (count($sslCapabilitiesErrors) > 0) {
$this->_allErrors[self::SSL_CAPABILITIES_ERRORS]['errors'] =
$sslCapabilitiesErrors;
return false;
}
return true;
}
/**
* Validate that we can connect to the YouTube API.
*
* #return boolean False if there were errors.
*/
private function validateYouTubeAPIConnectivity()
{
$connectivityErrors = array();
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata_YouTube');
$yt = new Zend_Gdata_YouTube();
$topRatedFeed = $yt->getTopRatedVideoFeed();
if ($topRatedFeed instanceof Zend_Gdata_YouTube_VideoFeed) {
if ($topRatedFeed->getTotalResults()->getText() < 1) {
$connectivityErrors[] = 'There was less than 1 video entry' .
' in the \'Top Rated Video Feed\'';
}
} else {
$connectivityErrors[] = 'The call to \'getTopRatedVideoFeed()\' ' .
'did not result in a Zend_Gdata_YouTube_VideoFeed object';
}
$this->_allErrors[self::YOUTUBE_API_CONNECTIVITY_ERRORS]['tested'] =
true;
if (count($connectivityErrors) > 0) {
$this->_allErrors[self::YOUTUBE_API_CONNECTIVITY_ERRORS]['tested'] =
$connectivityErrors;
return false;
}
return true;
}
/**
* Dispatch a call to outputResultsInHTML or outputResultsInText pending
* the current SAPI mode.
*
* #return void
*/
public function outputResults()
{
if ($this->_sapiModeCLI) {
print $this->getResultsInText();
} else {
print $this->getResultsInHTML();
}
}
/**
* Return a string representing the results of the verifications.
*
* #return string A string representing the results.
*/
private function getResultsInText()
{
$output = "== Ran PHP Installation Checker using CLI ==\n";
$error_count = 0;
foreach($this->_allErrors as $key => $value) {
$output .= $key . ' -- ';
if (($value['tested'] == true) && (count($value['errors']) == 0)) {
$output .= "No errors found\n";
} elseif ($value['tested'] == true) {
$output .= "Tested\n";
$error_count = 0;
foreach ($value['errors'] as $error) {
$output .= "Error number: " . $error_count . "\n--" .
$error . "\n";
}
} else {
$output .= "Not tested\n";
}
$error_count++;
}
return $output;
}
/**
* Return an HTML table representing the results of the verifications.
*
* #return string An HTML string representing the results.
*/
private function getResultsInHTML()
{
$html = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" " .
"\"http://www.w3.org/TR/html4/strict.dtd\">\n".
"<html><head>\n<title>PHP Installation Checker</title>\n" .
"<style type=\"text/css\">\n" .
self::CSS_WARNING . "\n" .
self::CSS_SUCCESS . "\n" .
self::CSS_ERROR . "\n" .
"</style></head>\n" .
"<body>\n<table class=\"verification_table\">" .
"<caption>Ran PHP Installation Checker on " .
gmdate('c') . "</caption>\n";
$error_count = 0;
foreach($this->_allErrors as $key => $value) {
$html .= "<tr><td class=\"verification_type\">" . $key . "</td>";
if (($value['tested'] == true) && (count($value['errors']) == 0)) {
$html .= "<td class=\"success\">Tested</td></tr>\n" .
"<tr><td colspan=\"2\">No errors found</td></tr>\n";
} elseif ($value['tested'] == true) {
$html .= "<td class=\"warning\">Tested</td></tr>\n";
$error_count = 0;
foreach ($value['errors'] as $error) {
$html .= "<tr><td class=\"error\">" . $error_count . "</td>" .
"<td class=\"error\">" . $error . "</td></tr>\n";
}
} else {
$html .= "<td class=\"warning\">Not tested</td></tr>\n";
}
$error_count++;
}
$html .= "</body></html>";
return $html;
}
}
$installationChecker = new InstallationChecker();
Go to the above link to see the results. Specifically, I'm interested in this error message:
Exception thrown trying to access Zend/Loader.php using 'use_include_path' = true.
Make sure you include Zend Framework in your include_path which currently contains:
.:/usr/lib/php:/usr/local/lib/php
Here is the link to my php info printout: http://www.jarodmorris.com/cms/phpinfo.php
I've obtained the Zend Framework from the zend website and uploaded it to a /zend folder on my website. For whatever reason, my host won't give me access to the php.ini file. I have purchased a reseller account with my host.
I'm doing all of this because I want to integrate Google Calendar API into an application I'm building on one of my websites. Maybe there is a simpler solution to my ultimate goal, but I don't see it.
Thanks for pointing me in the right direction.
EDITED TO SHOW CURRENT PHP CODE WHERE INCLUDE IS CONCERNED:
set_include_path(get_include_path() . PATH_SEPARATOR . "/home/jarodmo/public_html/zend/library");
echo get_include_path();
echo "<br>";
///home/jarodmo/public_html/zend/library/Zend
Add the dir to your include path:
set_include_path(
get_include_path()
. PATH_SEPARATOR
. '/whatever/your/zend/dir/is');
A default error logging using vqmod is as follows:
---------- Date: 2012-10-09 19:46:06 ~ IP : 127.0.0.1 ----------
REQUEST URI : /oc/
MOD DETAILS:
modFile : C:\wamp\www\oc\vqmod\xml\templace.xml
id : Template
version : 1.5.2 - 1.5.2.1
vqmver : 1.0.8
author : templace.com
SEARCH NOT FOUND (ABORTING MOD): require_once(foo . 'library/template.php');
----------------------------------------------------------------------
Example vqmod causing the error
<modification>
<id>Templace</id>
<version>1.5.2 - 1.5.2.1</version>
<author>templace.com</author>
<vqmver>1.0.8</vqmver>
<file name="system/startup.php">
<operation>
<search position="before"><![CDATA[
require_once(foo . 'library/template.php');
]]></search>
<add><![CDATA[
require_once(DIR_SYSTEM . 'library/templace.php');
]]></add>
</operation>
</file>
</modification>
To resole this issue I would have to open the vqmod file templace.xml and search for the file[name] this error is referring too.
QUESTION: How could I add the parent file[name] the actual error is referring too?
E.g adding: "system/startup.php" to the error message to make it easier to debug.
vqmod.php
/**
* VQMod
* #description Main Object used
*/
final class VQMod {
private $_vqversion = '2.1.7';
private $_modFileList = array();
private $_mods = array();
private $_filesModded = array();
private $_cwd = '';
private $_doNotMod = array();
private $_virtualMode = true;
public $useCache = false;
public $logFilePath = 'vqmod/vqmod.log';
public $vqCachePath = 'vqmod/vqcache/';
public $protectedFilelist = 'vqmod/vqprotect.txt';
public $logging = true;
public $cacheTime = 5; // local=5secs live=60secs
public $log;
/**
* VQMod::__construct()
*
* #param bool $path File path to use
* #param bool $logging Enable/disabled logging
* #return null
* #description Startup of VQMod
*/
public function __construct($path = false, $logging = true) {
if(!class_exists('DOMDocument')) {
die('ERROR - YOU NEED DOMDocument INSTALLED TO USE VQMod');
}
if(!$path){
$path = dirname(dirname(__FILE__));
}
$this->_setCwd($path);
$this->logging = (bool) $logging;
$this->log = new VQModLog($this);
$this->_getMods();
$this->_loadProtected();
}
/**
* VQMod::modCheck()
*
* #param string $sourceFile path for file
* #return string
* #description Checks if a file has modifications and applies them, returning cache files or the file name
*/
public function modCheck($sourceFile) {
if(!preg_match('%^([a-z]:)?[\\\\/]%i', $sourceFile)) {
$sourcePath = $this->path($sourceFile);
} else {
$sourcePath = realpath($sourceFile);
}
if(!$sourcePath || is_dir($sourcePath) || in_array($sourcePath, $this->_doNotMod)) {
return $sourceFile;
}
$stripped_filename = preg_replace('~^' . preg_quote($this->getCwd(), '~') . '~', '', $sourcePath);
$cacheFile = $this->_cacheName($stripped_filename);
if($this->useCache && file_exists($cacheFile)) {
//return $cacheFile; // useCache being Deprecated in favor of cacheTime
}
if(isset($this->_filesModded[$sourcePath])) {
return $this->_filesModded[$sourcePath]['cached'] ? $cacheFile : $sourceFile;
}
$changed = false;
$fileHash = sha1_file($sourcePath);
$fileData = file_get_contents($sourcePath);
foreach($this->_mods as $modObject) {
foreach($modObject->mods as $path => $mods) {
if($this->_checkMatch($path, $sourcePath)) {
$modObject->applyMod($mods, $fileData);
}
}
}
// START QPHORIA CACHELOCK CODE
//
if (sha1($fileData) != $fileHash) {
$writePath = $cacheFile;
$cacheLock = false;
if(file_exists($writePath) && ((filemtime($writePath) + (float)$this->cacheTime) >= time())) {
$cacheLock = true;
$changed = true;
}
if(!$cacheLock && (!file_exists($writePath) || is_writable($writePath))) {
file_put_contents($writePath, $fileData);
$changed = true;
} else {
//file_put_contents('./cachelock.txt', "$writePath \r\n", FILE_APPEND); // debugging only.
}
//file_put_contents('./cachetotal.txt', "$writePath \r\n", FILE_APPEND);
} // END QPHORIA CACHELOCK CODE
/* Original Code
if(sha1($fileData) != $fileHash) {
$writePath = $this->_virtualMode ? $cacheFile : $sourcePath;
if(!file_exists($writePath) || is_writable($writePath)) {
file_put_contents($writePath, $fileData);
$changed = true;
}
}*/
$this->_filesModded[$sourcePath] = array('cached' => $changed);
return $changed ? $writePath : $sourcePath;
}
/**
* VQMod::path()
*
* #param string $path File path
* #param bool $skip_real If true path is full not relative
* #return bool, string
* #description Returns the full true path of a file if it exists, otherwise false
*/
public function path($path, $skip_real = false) {
$tmp = $this->_cwd . $path;
$realpath = $skip_real ? $tmp : realpath($tmp);
if(!$realpath) {
return false;
}
if(is_dir($realpath)) {
$realpath = rtrim($realpath, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
}
return $realpath;
}
/**
* VQMod::getCwd()
*
* #return string
* #description Returns current working directory
*/
public function getCwd() {
return $this->_cwd;
}
/**
* VQMod::_getMods()
*
* #return null
* #description Gets list of XML files in vqmod xml folder for processing
*/
private function _getMods() {
$this->_modFileList = glob($this->path('vqmod/xml/') . '*.xml');
if($this->_modFileList) {
$this->_parseMods();
} else {
$this->log->write('NO MODS IN USE');
}
}
/**
* VQMod::_parseMods()
*
* #return null
* #description Loops through xml files and attempts to load them as VQModObject's
*/
private function _parseMods() {
$dom = new DOMDocument('1.0', 'UTF-8');
foreach($this->_modFileList as $modFileKey => $modFile) {
if(file_exists($modFile)) {
if(#$dom->load($modFile)) {
$mod = $dom->getElementsByTagName('modification')->item(0);
$this->_mods[] = new VQModObject($mod, $modFile, $this);
} else {
$this->log->write('DOM UNABLE TO LOAD: ' . $modFile);
}
} else {
$this->log->write('FILE NOT FOUND: ' . $modFile);
}
}
}
/**
* VQMod::_loadProtected()
*
* #return null
* #description Loads protected list and adds them to _doNotMod array
*/
private function _loadProtected() {
$file = $this->path($this->protectedFilelist);
if($file && is_file($file)) {
$protected = file_get_contents($file);
if(!empty($protected)) {
$protected = preg_replace('~\r?\n~', "\n", $protected);
$paths = explode("\n", $protected);
foreach($paths as $path) {
$fullPath = $this->path($path);
if($fullPath && !in_array($fullPath, $this->_doNotMod)) {
$this->_doNotMod[] = $fullPath;
}
}
}
}
}
/**
* VQMod::_cacheName()
*
* #param string $file Filename to be converted to cache filename
* #return string
* #description Returns cache file name for a path
*/
private function _cacheName($file) {
return $this->path($this->vqCachePath) . 'vq2-' . preg_replace('~[/\\\\]+~', '_', $file);
}
/**
* VQMod::_setCwd()
*
* #param string $path Path to be used as current working directory
* #return null
* #description Sets the current working directory variable
*/
private function _setCwd($path) {
$realpath = realpath($path);
if(!$realpath) {
die('COULDNT RESOLVE CWD REALPATH');
}
$this->_cwd = rtrim($realpath, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
}
/**
* VQMod::_checkMatch()
*
* #param string $modFilePath Modification path from a <file> node
* #param string $checkFilePath File path
* #return bool
* #description Checks a modification path against a file path
*/
private function _checkMatch($modFilePath, $checkFilePath) {
$modFilePath = str_replace('\\', '/', $modFilePath);
$checkFilePath = str_replace('\\', '/', $checkFilePath);
$modFilePath = preg_replace('/([^*]+)/e', 'preg_quote("$1", "~")', $modFilePath);
$modFilePath = str_replace('*', '[^/]*', $modFilePath);
$return = (bool) preg_match('~^' . $modFilePath . '$~', $checkFilePath);
return $return;
}
}
/**
* VQModLog
* #description Object to log information to a file
*/
class VQModLog {
private $_sep;
private $_vqmod;
private $_defhash = 'da39a3ee5e6b4b0d3255bfef95601890afd80709';
private $_logs = array();
/**
* VQModLog::__construct()
*
* #param VQMod $vqmod VQMod main class as reference
* #return null
* #description Object instantiation method
*/
public function __construct(VQMod $vqmod) {
$this->_vqmod = $vqmod;
$this->_sep = str_repeat('-', 70);
}
/**
* VQModLog::__destruct()
*
* #return null
* #description Logs any messages to the log file just before object is destroyed
*/
public function __destruct() {
if(empty($this->_logs) || $this->_vqmod->logging == false) {
return;
}
$txt = array();
$txt[] = str_repeat('-', 10) . ' Date: ' . date('Y-m-d H:i:s') . ' ~ IP : ' . (isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : 'N/A') . ' ' . str_repeat('-', 10);
$txt[] = 'REQUEST URI : ' . $_SERVER['REQUEST_URI'];
foreach($this->_logs as $count => $log) {
if($log['obj']) {
$vars = get_object_vars($log['obj']);
$txt[] = 'MOD DETAILS:';
foreach($vars as $k => $v) {
if(is_string($v)) {
$txt[] = ' ' . str_pad($k, 10, ' ', STR_PAD_RIGHT) . ': ' . $v;
}
}
}
foreach($log['log'] as $msg) {
$txt[] = $msg;
}
if ($count > count($this->_logs)-1) {
$txt[] = '';
}
}
$txt[] = $this->_sep;
$txt[] = str_repeat(PHP_EOL, 2);
$logPath = $this->_vqmod->path($this->_vqmod->logFilePath, true);
if(!file_exists($logPath)) {
$res = file_put_contents($logPath, '');
if($res === false) {
die('COULD NOT WRITE TO LOG FILE');
}
}
file_put_contents($logPath, implode(PHP_EOL, $txt), FILE_APPEND);
}
/**
* VQModLog::write()
*
* #param string $data Text to be added to log file
* #param VQModObject $obj Modification the error belongs to
* #return null
* #description Adds error to log object ready to be output
*/
public function write($data, VQModObject $obj = NULL) {
if($obj) {
$hash = sha1($obj->id);
} else {
$hash = $this->_defhash;
}
if(empty($this->_logs[$hash])) {
$this->_logs[$hash] = array(
'obj' => $obj,
'log' => array()
);
}
$this->_logs[$hash]['log'][] = $data;
}
}
/**
* VQModObject
* #description Object for the <modification> that orchestrates each applied modification
*/
class VQModObject {
public $modFile = '';
public $id = '';
public $version = '';
public $vqmver = '';
public $author = '';
public $mods = array();
private $_vqmod;
private $_skip = false;
/**
* VQModObject::__construct()
*
* #param DOMNode $node <modification> node
* #param string $modFile File modification is from
* #param VQMod $vqmod VQMod object as reference
* #return null
* #description Loads modification meta information
*/
public function __construct(DOMNode $node, $modFile, VQmod $vqmod) {
if($node->hasChildNodes()) {
foreach($node->childNodes as $child) {
$name = (string) $child->nodeName;
if(isset($this->$name)) {
$this->$name = (string) $child->nodeValue;
}
}
}
$this->modFile = $modFile;
$this->_vqmod = $vqmod;
$this->_parseMods($node);
}
/**
* VQModObject::skip()
*
* #return bool
* #description Returns the skip status of a modification
*/
public function skip() {
return $this->_skip;
}
/**
* VQModObject::applyMod()
*
* #param array $mods Array of search add nodes
* #param string $data File contents to be altered
* #return null
* #description Applies all modifications to the text data
*/
public function applyMod($mods, &$data) {
if($this->_skip) return;
$tmp = $data;
foreach($mods as $mod) {
$indexCount = 0;
$tmp = $this->_explodeData($tmp);
$lineMax = count($tmp) - 1;
switch($mod['search']->position) {
case 'top':
$tmp[$mod['search']->offset] = $mod['add']->getContent() . $tmp[$mod['search']->offset];
break;
case 'bottom':
$offset = $lineMax - $mod['search']->offset;
if($offset < 0){
$tmp[-1] = $mod['add']->getContent();
} else {
$tmp[$offset] .= $mod['add']->getContent();
}
break;
case 'all':
$tmp = array($mod['add']->getContent());
break;
default:
$changed = false;
foreach($tmp as $lineNum => $line) {
if($mod['search']->regex == 'true') {
$pos = #preg_match($mod['search']->getContent(), $line);
if($pos === false) {
if($mod['error'] == 'log' || $mod['error'] == 'abort' ) {
$this->_vqmod->log->write('INVALID REGEX ERROR - ' . $mod['search']->getContent(), $this);
}
continue 2;
} elseif($pos == 0) {
$pos = false;
}
} else {
$pos = strpos($line, $mod['search']->getContent());
}
if($pos !== false) {
$indexCount++;
$changed = true;
if(!$mod['search']->indexes() || ($mod['search']->indexes() && in_array($indexCount, $mod['search']->indexes()))) {
switch($mod['search']->position) {
case 'before':
$offset = ($lineNum - $mod['search']->offset < 0) ? -1 : $lineNum - $mod['search']->offset;
$tmp[$offset] = empty($tmp[$offset]) ? $mod['add']->getContent() : $mod['add']->getContent() . "\n" . $tmp[$offset];
break;
case 'after':
$offset = ($lineNum + $mod['search']->offset > $lineMax) ? $lineMax : $lineNum + $mod['search']->offset;
$tmp[$offset] = $tmp[$offset] . "\n" . $mod['add']->getContent();
break;
default:
if(!empty($mod['search']->offset)) {
for($i = 1; $i <= $mod['search']->offset; $i++) {
if(isset($tmp[$lineNum + $i])) {
$tmp[$lineNum + $i] = '';
}
}
}
if($mod['search']->regex == 'true') {
$tmp[$lineNum] = preg_replace($mod['search']->getContent(), $mod['add']->getContent(), $line);
} else {
$tmp[$lineNum] = str_replace($mod['search']->getContent(), $mod['add']->getContent(), $line);
}
break;
}
}
}
}
if(!$changed) {
$skip = ($mod['error'] == 'skip' || $mod['error'] == 'log') ? ' (SKIPPED)' : ' (ABORTING MOD)';
if($mod['error'] == 'log' || $mod['error'] == 'abort') {
$this->_vqmod->log->write('SEARCH NOT FOUND' . $skip . ': ' . $mod['search']->getContent(), $this);
}
if($mod['error'] == 'abort') {
$this->_skip = true;
return;
}
}
break;
}
ksort($tmp);
$tmp = $this->_implodeData($tmp);
}
$data = $tmp;
}
/**
* VQModObject::_parseMods()
*
* #param DOMNode $node <modification> node to be parsed
* #return null
* #description Parses modifications in preparation for the applyMod method to work
*/
private function _parseMods(DOMNode $node){
$files = $node->getElementsByTagName('file');
foreach($files as $file) {
$fileToMod = $file->getAttribute('name');
$error = ($file->hasAttribute('error')) ? $file->getAttribute('error') : 'log';
$fullPath = $this->_vqmod->path($fileToMod);
if(!$fullPath){
if(strpos($fileToMod, '*') !== false) {
$fullPath = $this->_vqmod->getCwd() . $fileToMod;
} else {
if ($error == 'log' || $error == 'abort') {
$skip = ($error == 'log') ? ' (SKIPPED)' : ' (ABORTING MOD)';
$this->_vqmod->log->write('Could not resolve path for [' . $fileToMod . ']' . $skip, $this);
}
if ($error == 'log' || $error == 'skip') {
continue;
} elseif ($error == 'abort') {
return false;
}
}
}
$operations = $file->getElementsByTagName('operation');
foreach($operations as $operation) {
$error = ($operation->hasAttribute('error')) ? $operation->getAttribute('error') : 'abort';
$this->mods[$fullPath][] = array(
'search' => new VQSearchNode($operation->getElementsByTagName('search')->item(0)),
'add' => new VQAddNode($operation->getElementsByTagName('add')->item(0)),
'error' => $error
);
}
}
}
/**
* VQModObject::_explodeData()
*
* #param string $data File contents
* #return string
* #description Splits a file into an array of individual lines
*/
private function _explodeData($data) {
return explode("\n", $data);
}
/**
* VQModObject::_implodeData()
*
* #param array $data Array of lines
* #return string
* #description Joins an array of lines back into a text file
*/
private function _implodeData($data) {
return implode("\n", $data);
}
}
/**
* VQNode
* #description Basic node object blueprint
*/
class VQNode {
public $trim = 'false';
private $_content = '';
/**
* VQNode::__construct()
*
* #param DOMNode $node Search/add node
* #return null
* #description Parses the node attributes and sets the node property
*/
public function __construct(DOMNode $node) {
$this->_content = $node->nodeValue;
if($node->hasAttributes()) {
foreach($node->attributes as $attr) {
$name = $attr->nodeName;
if(isset($this->$name)) {
$this->$name = $attr->nodeValue;
}
}
}
}
/**
* VQNode::getContent()
*
* #return string
* #description Returns the content, trimmed if applicable
*/
public function getContent() {
$content = ($this->trim == 'true') ? trim($this->_content) : $this->_content;
return $content;
}
}
/**
* VQSearchNode
* #description Object for the <search> xml tags
*/
class VQSearchNode extends VQNode {
public $position = 'replace';
public $offset = 0;
public $index = 'false';
public $regex = 'false';
public $trim = 'true';
/**
* VQSearchNode::indexes()
*
* #return bool, array
* #description Returns the index values to use the search on, or false if none
*/
public function indexes() {
if($this->index == 'false') {
return false;
}
$tmp = explode(',', $this->index);
foreach($tmp as $k => $v) {
if(!is_int($v)) {
unset($k);
}
}
$tmp = array_unique($tmp);
return empty($tmp) ? false : $tmp;
}
}
/**
* VQAddNode
* #description Object for the <add> xml tags
*/
class VQAddNode extends VQNode {
}
Also couple of other ideas to make debugging even easier:
List any other vqmod files which have previously edited this same file.
This is another common issue where I find when two extensions are editing the same file and the latter is causing the error but it would be useful to know about any other vqmods editing the same file. Yes I suppose I could add error="skip" to everything but dont think this is the best approach to just hide all of the errors, the user should be made aware there is an error...
"Suggested Fix", maybe some smart way you can test what type of error it is.
Contradict what I said above but even at its most basic form you could suggest hiding the error if its not essential. So that anybody can read it and understand how it fix it.
E.g
OPEN: vqmod/xml/templace.xml (line:23)
FIND: <operation>
REPLACE <operation error="skip">
Adding the line number in the XML file the error is coming from. It would be lovely not having to search all of the time and could quickly go to the line number in the vqmod
The issue for the file being edited is certainly one that is way overdue and one I plan on adding in the next release of vQmod. As for the other suggestions
Interesting idea, and one that could certainly be considered. The only problem I see with this is that it would possibly make some log files enormous
This is going to be next to impossible to incorporate
This is impossible without some pretty expensive runtime. The error doesn't lie in the XML as such, so would require re-opening the xml that's been parsed, searching for the line in question line by line and then reporting that. it sounds simple, but you have to remember that xml's can have the same search parameter for multiple operations - so in that situation you'd be no better off than searching the file yourself