<?php
/**
* This is the handler for ANONYMOUS (non logged in) asynchronous 'AJAX' calls.
*
* This file is part of the evoCore framework - {@link http://evocore.net/}
* See also {@link https://github.com/b2evolution/b2evolution}.
*
* @license GNU GPL v2 - {@link http://b2evolution.net/about/gnu-gpl-license}
*
* @copyright (c)2003-2020 by Francois Planque - {@link http://fplanque.com/}
*
* @package evocore
*/
/**
* Do the MAIN initializations:
*/
require_once dirname(__FILE__).'/../conf/_config.php';
/**
* @global boolean Is this AJAX request? Use {@link is_ajax_request()} to query it, because it may change.
*/
$is_ajax_request = true;
// Disable log in with HTTP basic authentication because we need some action even for anonymous users,
// but it is impossible if wrong login was entered on "HTTP Basic Authentication" form.
// (Used to correct work of action "get_user_salt")
$disable_http_auth = true;
require_once $inc_path.'_main.inc.php';
load_funcs( '../inc/skins/_skin.funcs.php' );
global $skins_path, $ads_current_skin_path, $disp, $ctrl;
param( 'action', 'string', '' );
$item_ID = param( 'p', 'integer' );
$blog_ID = param( 'blog', 'integer' );
// Initialize this array in order to don't load JS files twice in they have been already loaded on parent page:
$required_js = param( 'required_js', 'array:string', array(), false, true );
// Send the predefined cookies:
evo_sendcookies();
// Make sure the async responses are never cached:
header_nocache();
header_content_type( 'text/html', $io_charset );
// Save current debug values
$current_debug = $debug;
$current_debug_jslog = $debug_jslog;
// Do not append Debuglog to response!
$debug = false;
// Do not append Debug JSlog to response!
$debug_jslog = false;
// Don't check new updates from b2evolution.net (@see b2evonet_get_updates()),
// in order to don't break the response data:
$allow_evo_stats = false;
// Init AJAX log
$ajax_Log = new Log();
ajax_log_add( sprintf( 'action: %s', $action ), 'note' );
$params = param( 'params', 'array', array() );
switch( $action )
{
case 'get_item_form':
// Display item form:
// Use the glyph or font-awesome icons if requested by skin
param( 'b2evo_icons_type', 'string', '' );
$cat_ID = param( 'cat', 'integer' );
$BlogCache = & get_BlogCache();
$Collection = $Blog = & $BlogCache->get_by_ID( $blog_ID );
locale_activate( $Blog->get( 'locale' ) );
$blog_skin_ID = $Blog->get_skin_ID();
if( ! empty( $blog_skin_ID ) )
{ // Initialize collection skin folder to check if it has a specific new item form:
$SkinCache = & get_SkinCache();
$Skin = & $SkinCache->get_by_ID( $blog_skin_ID );
$ads_current_skin_path = $skins_path.$Skin->folder.'/';
}
require skin_template_path( '_item_new_form.inc.php' );
break;
case 'get_comment_form':
// Display comment form:
// Use the glyph or font-awesome icons if requested by skin
param( 'b2evo_icons_type', 'string', '' );
$ItemCache = & get_ItemCache();
$Item = $ItemCache->get_by_ID( $item_ID );
$BlogCache = & get_BlogCache();
$Collection = $Blog = $BlogCache->get_by_ID( $blog_ID );
locale_activate( $Blog->get('locale') );
$disp = param( 'disp', '/^[a-z0-9\-_]+$/', '' );
$blog_skin_ID = $Blog->get_skin_ID();
if( ! empty( $blog_skin_ID ) )
{ // check if Blog skin has specific comment form
$SkinCache = & get_SkinCache();
$Skin = & $SkinCache->get_by_ID( $blog_skin_ID );
$ads_current_skin_path = $skins_path.$Skin->folder.'/';
}
require skin_template_path( '_item_comment_form.inc.php' );
break;
case 'get_msg_form':
// display send message form
$recipient_id = param( 'recipient_id', 'integer', 0 );
$recipient_name = param( 'recipient_name', 'string', '' );
$subject = param( 'subject', 'string', '' );
$subject_other = param( 'subject_other', 'string', '' );
$contact_method = param( 'contact_method', 'string', '' );
$email_author = param( 'email_author', 'string', '' );
$email_author_address = param( 'email_author_address', 'string', '' );
$redirect_to = param( 'redirect_to', 'url', '' );
$post_id = NULL;
$comment_id = param( 'comment_id', 'integer', 0 );
$BlogCache = & get_BlogCache();
$Collection = $Blog = $BlogCache->get_by_ID( $blog_ID );
locale_activate( $Blog->get('locale') );
$blog_skin_ID = $Blog->get_skin_ID();
if( ! empty( $blog_skin_ID ) )
{ // check if Blog skin has specific concact message form
$SkinCache = & get_SkinCache();
$Skin = & $SkinCache->get_by_ID( $blog_skin_ID );
$ads_current_skin_path = $skins_path.$Skin->folder.'/';
}
require skin_template_path( '_contact_msg.form.php' );
break;
case 'get_widget_form':
// Display widget form:
// Use the glyph or font-awesome icons if requested by skin
param( 'b2evo_icons_type', 'string', '' );
if( param( 'wi_ID', 'integer', 0 ) )
{ // Try to get a Widget by ID if it called from DB:
$WidgetCache = & get_WidgetCache();
$Widget = & $WidgetCache->get_by_ID( $wi_ID );
if( ! $Widget || ( $Widget->get( 'coll_ID' ) !== NULL && $Widget->get( 'coll_ID' ) != $blog_ID ) )
{
debug_die( 'Wrong widget request!' );
}
}
else
{ // Try to get a Widget by code if it called from content with inline short tag like [emailcapture]:
param( 'wi_code', 'string', true );
if( ! file_exists( $inc_path.'widgets/widgets/_'.$wi_code.'.widget.php' ) )
{ // For some reason, that widget doesn't seem to exist... (any more?)
debug_die( 'Wrong widget request!' );
}
require_once $inc_path.'widgets/widgets/_'.$wi_code.'.widget.php';
// Create new widget by provided code:
$widget_classname = $wi_code.'_Widget';
$Widget = new $widget_classname();
}
param( 'params', 'array', array() );
$BlogCache = & get_BlogCache();
$Collection = $Blog = $BlogCache->get_by_ID( $blog_ID );
locale_activate( $Blog->get('locale') );
$blog_skin_ID = $Blog->get_skin_ID();
if( ! empty( $blog_skin_ID ) )
{ // check if Blog skin has specific comment form
$SkinCache = & get_SkinCache();
$Skin = & $SkinCache->get_by_ID( $blog_skin_ID );
$ads_current_skin_path = $skins_path.$Skin->folder.'/';
}
// Display widget form:
$Widget->display_form( $params );
break;
case 'get_user_bubbletip':
// Get contents of a user bubbletip
// Displays avatar & name
$user_ID = param( 'userid', 'integer', 0 );
$comment_ID = param( 'commentid', 'integer', 0 );
if( strpos( $_SERVER["HTTP_REFERER"], $admin_url ) !== false )
{ // If ajax is requested from admin page we should to set a variable $is_admin_page = true if user has permissions
// Check global permission:
if( ! check_user_perm( 'admin', 'restricted' ) )
{ // No permission to access admin...
require $adminskins_path.'_access_denied.main.php';
}
else
{ // Set this page as admin page
$is_admin_page = true;
}
}
if( $blog_ID > 0 )
{ // Get Blog if ID is set
$BlogCache = & get_BlogCache();
$Collection = $Blog = $BlogCache->get_by_ID( $blog_ID );
}
if( $user_ID > 0 )
{ // Print info of the registered users
$UserCache = & get_UserCache();
$User = & $UserCache->get_by_ID( $user_ID );
ajax_log_add( 'User: #'.$user_ID.' '.$User->login );
if( check_user_perm( 'admin', 'restricted' ) &&
( $current_User->ID == $User->ID || $current_User->can_moderate_user( $User->ID ) ) &&
check_user_status( 'can_access_admin' ) )
{ // Display the moderation buttons only if current user has a permission:
$moderation_buttons = '<p class="bubbletip_user__buttons">';
if( ! is_admin_page() )
{
$moderation_buttons .= '<a href="'.url_add_param( $admin_url, 'ctrl=user&user_ID='.$User->ID ).'" class="btn btn-sm btn-block btn-primary">'
.T_('Edit in Back-Office').'</a>';
}
if( $current_User->ID != $User->ID && check_user_perm( 'users', 'edit' ) )
{ // Display a button to delete a spammer only for other users and if current user can edit them:
$moderation_buttons .= '<a href="'.url_add_param( $admin_url, 'ctrl=users&action=delete&deltype=spammer&user_ID='.$User->ID )
.'" class="btn btn-sm btn-block btn-danger">'
.T_('Delete Spammer')
.'</a>';
}
$moderation_buttons .= '</p>';
}
else
{ // No permission to moderate users:
$moderation_buttons = '';
}
echo '<div class="bubbletip_user">';
if( $User->check_status( 'is_closed' ) )
{ // display only info about closed accounts
echo T_( 'This account has been closed.' );
echo $moderation_buttons;
echo '</div>'; /* end of: <div class="bubbletip_user"> */
break;
}
$avatar_overlay_text = '';
$link_class = '';
if( is_admin_page() )
{ // Set avatar size for Back-office
$avatar_size = $Settings->get('bubbletip_size_admin');
}
else if( is_logged_in() )
{ // Set avatar size for logged in users in the Front-office
$avatar_size = $Settings->get('bubbletip_size_front');
}
else
{ // Set avatar size for Anonymous users
$avatar_size = $Settings->get('bubbletip_size_anonymous');
$avatar_overlay_text = $Settings->get('bubbletip_overlay');
$link_class = 'overlay_link';
}
$width = $thumbnail_sizes[$avatar_size][1];
$height = $thumbnail_sizes[$avatar_size][2];
// Display user avatar with login
// Attributes 'w' & 'h' we use for following js-scale div If image is downloading first time (Fix bubbletip)
echo '<div class="center" w="'.$width.'" h="'.$height.'">';
echo get_avatar_imgtag( $User->login, 'login', true, $avatar_size, 'avatar_above_login', '', $avatar_overlay_text, $link_class, true, '' );
echo '</div>';
if( ! ( $Settings->get( 'allow_anonymous_user_profiles' ) || ( check_user_perm( 'user', 'view', false, $User ) ) ) )
{ // User is not logged in and anonymous users may NOT view user profiles, or if current User has no permission to view additional information about the User
echo $moderation_buttons;
echo '</div>'; /* end of: <div class="bubbletip_user"> */
break;
}
// Additional user info
$user_info = array();
// Preferred Name
if( $User->get_preferred_name() != $User->login )
{
$user_info[] = $User->get_preferred_name();
}
// Location
$location = array();
if( !empty( $User->city_ID ) )
{ // City
$location[] = $User->get_city_name( false );
}
if( !empty( $User->subrg_ID ) )
{ // Subregion
if( !is_logged_in() )
{ // Display subregion for not logged in users
$location[] = $User->get_subregion_name();
}
else if( $current_User->subrg_ID != $User->subrg_ID )
{ // If subregions are different
$location[] = $User->get_subregion_name();
}
}
if( !empty( $User->rgn_ID ) )
{ // Region
if( !is_logged_in() )
{ // Display region for not logged in users
$location[] = $User->get_region_name();
}
else if( $current_User->rgn_ID != $User->rgn_ID )
{ // If regions are different
$location[] = $User->get_region_name();
}
}
if( !empty( $User->ctry_ID ) )
{ // Country
if( !is_logged_in() )
{ // Display country for not logged in users
$location[] = $User->get_country_name();
}
else if( $current_User->ctry_ID != $User->ctry_ID )
{ // If countries are different
$location[] = $User->get_country_name();
}
}
if( !empty( $location ) )
{ // Set location info
$user_info[] = implode( '<br />', $location );
}
// Age group
if( !empty( $User->age_min ) && !empty( $User->age_max ) && $User->age_min != $User->age_max )
{
$user_info[] = sprintf( T_('%d to %d years old '), $User->age_min, $User->age_max );
}
else if( !empty( $User->age_min ) || !empty( $User->age_max ) )
{ // Min age equals max age
$age = !empty( $User->age_min ) ? $User->age_min : $User->age_max;
$user_info[] = sprintf( T_('%d years old '), $age );
}
if( !empty( $user_info ) )
{ // Display additional user info
echo '<ul>';
foreach( $user_info as $info )
{
echo '<li>'.$info.'</li>';
}
echo '</ul>';
}
echo $moderation_buttons;
echo '</div>'; /* end of: <div class="bubbletip_user"> */
}
else if( $comment_ID > 0 )
{ // Print info for an anonymous user who posted a comment
$CommentCache = & get_CommentCache();
$Comment = $CommentCache->get_by_ID( $comment_ID );
ajax_log_add( 'Comment: #'.$comment_ID.' '.$Comment->get_author_name() );
echo '<div class="bubbletip_anon">';
echo $Comment->get_avatar( 'fit-160x160', 'bCommentAvatarCenter' );
echo '<div>'.$Comment->get_author_name_anonymous( 'htmlbody', array( 'rel' => '' ) ).'</div>';
echo '<div>'.T_('This user is not registered on this site.').'</div>';
echo $Comment->get_author_url_link( '', '<div>', '</div>');
if( isset( $Blog ) )
{ // Link to send message
echo '<div>';
$Comment->msgform_link( $Blog->get('msgformurl'), '', '', get_icon( 'email', 'imgtag' ).' '.T_('Send a message') );
echo '</div>';
}
echo '</div>';
}
else
{ // user_ID and comment_ID are both null, this can happen when the user was deleted
echo '<div class="bubbletip_user">';
echo T_( 'This account has been deleted.' );
echo '</div>';
break;
}
break;
case 'set_comment_vote':
// Used for quick SPAM vote of comments
// Check that this action request is not a CSRF hacked request:
$Session->assert_received_crumb( 'comment' );
if( !is_logged_in( false ) )
{ // Only active logged in users can vote
break;
}
// Use the glyph or font-awesome icons if requested by skin
param( 'b2evo_icons_type', 'string', '' );
if( param( 'is_backoffice', 'integer', 0 ) )
{ // Set admin skin, used for buttons, @see button_class()
global $current_User, $UserSettings, $is_admin_page, $adminskins_path;
$admin_skin = $UserSettings->get( 'admin_skin', $current_User->ID );
$is_admin_page = true;
require_once $adminskins_path.$admin_skin.'/_adminUI.class.php';
$AdminUI = new AdminUI();
}
else
{
$BlogCache = &get_BlogCache();
$Collection = $Blog = & $BlogCache->get_by_ID( $blog_ID, true );
$skin_ID = $Blog->get_skin_ID();
$SkinCache = & get_SkinCache();
$Skin = & $SkinCache->get_by_ID( $skin_ID );
}
// Check permission for spam voting
check_user_perm( 'blog_vote_spam_comments', 'edit', true, $blog_ID );
$type = param( 'type', 'string' );
$commentid = param( 'commentid', 'integer' );
if( $type != 'spam' || empty( $commentid ) )
{ // Incorrect params
break;
}
$edited_Comment = & Comment_get_by_ID( $commentid, false );
if( $edited_Comment !== false )
{ // The comment still exists
if( $current_User->ID == $edited_Comment->author_user_ID )
{ // Do not allow users to vote on their own comments
break;
}
// Update a vote of the comment for current User:
$edited_Comment->set_vote( 'spam', param( 'vote', 'string' ) );
$edited_Comment->dbupdate();
// Display a panel for next spam voting:
$edited_Comment->vote_spam( '', '', '&', true, true, array(
'display' => true,
'button_group_class' => button_class( 'group' ).( is_admin_page() ? ' btn-group-sm' : '' ),
) );
}
break;
case 'voting':
// Actions for voting by AJAX
if( !is_logged_in( false ) )
{ // Only active logged in users can vote
break;
}
param( 'vote_action', 'string', '' );
if( !empty( $vote_action ) )
{ // Use crumb checking only for actions
// Check that this action request is not a CSRF hacked request:
$Session->assert_received_crumb( 'voting' );
}
param( 'vote_type', 'string', '' );
param( 'vote_ID', 'string', 0 );
param( 'checked', 'integer', 0 );
param( 'redirect_to', 'url', '' );
// Use the glyph or font-awesome icons if requested by skin
param( 'b2evo_icons_type', 'string', '' );
ajax_log_add( sprintf( 'vote action: %s', $vote_action ), 'note' );
ajax_log_add( sprintf( 'vote type: %s', $vote_type ), 'note' );
ajax_log_add( sprintf( 'vote ID: %s', $vote_ID ), 'note' );
$voting_form_params = array(
'vote_type' => $vote_type,
);
switch( $vote_type )
{
case 'link':
// Vote on pictures
$link_ID = preg_replace( '/link_(\d+)/i', '$1', $vote_ID );
if( empty( $link_ID ) || ( ! is_decimal( $link_ID ) ) )
{ // There is no correct link ID
break 2;
}
$LinkCache = & get_LinkCache();
$Link = & $LinkCache->get_by_ID( $link_ID, false );
if( !$Link )
{ // Incorrect link ID
break 2;
}
$File = & $Link->get_File();
if( !$File )
{ // The Link File is not available
break 2;
}
if( empty( $File->hash ) )
{ // File hash still is not defined, we should create and save it
$File->set_param( 'hash', 'string', md5_file( $File->get_full_path(), true ) );
$File->dbsave();
}
if( !empty( $vote_action ) )
{ // Vote for this file link
link_vote( $link_ID, $current_User->ID, $vote_action, $checked );
}
$voting_form_params['vote_ID'] = $link_ID;
if( empty( $vote_action ) || in_array( $vote_action, array( 'like', 'noopinion', 'dontlike' ) ) )
{ // Display a voting form if no action
// or Refresh a voting form only for these actions (in order to disable icons)
if( ! empty( $blog_ID ) )
{ // If blog is defined we should check if we can display info about number of votes
$BlogCache = & get_BlogCache();
if( ( $Collection = $Blog = & $BlogCache->get_by_ID( $blog_ID, false, false ) ) &&
$blog_skin_ID = $Blog->get_skin_ID() )
{
$LinkOwner = & $Link->get_LinkOwner();
$SkinCache = & get_SkinCache();
if( $Skin = & $SkinCache->get_by_ID( $blog_skin_ID, false, false ) &&
$Skin->get_setting( 'colorbox_vote_'.$LinkOwner->get( 'name' ).'_numbers' ) )
{ // Display number of votes for current link type if it is enabled by blog skin
$voting_form_params['display_numbers'] = true;
}
}
}
display_voting_form( $voting_form_params );
}
break;
case 'comment':
// Vote on comments
$comment_ID = (int)$vote_ID;
if( empty( $comment_ID ) )
{ // No comment ID
break 2;
}
$CommentCache = & get_CommentCache();
$Comment = $CommentCache->get_by_ID( $comment_ID, false );
if( !$Comment )
{ // Incorrect comment ID
break 2;
}
if( $current_User->ID == $Comment->author_user_ID )
{ // Do not allow users to vote on their own comments
break 2;
}
$comment_Item = & $Comment->get_Item();
$comment_Item->load_Blog();
if( ! $comment_Item->Blog->get_setting('allow_rating_comment_helpfulness') )
{ // If Users cannot vote
break 2;
}
if( !empty( $vote_action ) )
{ // Vote for this comment
switch( $vote_action )
{ // Set field value
case 'like':
$field_value = 'yes';
break;
case 'noopinion':
$field_value = 'noopinion';
break;
case 'dontlike':
$field_value = 'no';
break;
}
if( isset( $field_value ) )
{ // Update a vote of current user
$Comment->set_vote( 'helpful', $field_value );
$Comment->dbupdate();
}
}
if( !empty( $redirect_to ) )
{ // Redirect to back page, It is used by browsers without JavaScript
header_redirect( $redirect_to, 303 ); // Will EXIT
// We have EXITed already at this point!!
}
if( param( 'skin_ID', 'integer', 0 ) > 0 )
{ // If request is from skin:
$SkinCache = & get_SkinCache();
// Initialize global Collection in order to get Skin settings values from the Collection and not from defaults of the Skin:
$Blog = $comment_Item->get_Blog();
$request_Skin = & $SkinCache->get_by_ID( get_param( 'skin_ID' ), false, false );
if( $request_Skin && method_exists( $request_Skin, 'display_comment_voting_panel' ) )
{ // Request skin to display a voting panel for item:
$request_Skin->display_comment_voting_panel( $Comment, $request_Skin->get_setting( 'voting_place' ), array( 'display_wrapper' => false ) );
break 2;
}
}
$Comment->vote_helpful( '', '', '&', true, true, array( 'display_wrapper' => false ) );
break;
case 'item':
// Vote on items:
$item_ID = intval( $vote_ID );
if( empty( $item_ID ) )
{ // No item ID
break 2;
}
$ItemCache = & get_ItemCache();
$Item = $ItemCache->get_by_ID( $item_ID, false );
if( ! $Item )
{ // Incorrect item ID:
break 2;
}
if( $current_User->ID == $Item->creator_user_ID )
{ // Do not allow users to vote on their own comments:
break 2;
}
$item_Blog = & $Item->get_Blog();
if( empty( $item_Blog ) || ! $item_Blog->get_setting( 'voting_positive' ) )
{ // If Users cannot vote:
break 2;
}
if( ! empty( $vote_action ) )
{ // Vote for the item:
switch( $vote_action )
{ // Set field value
case 'like':
$field_value = 'positive';
break;
case 'noopinion':
$field_value = 'neutral';
break;
case 'dontlike':
$field_value = 'negative';
break;
}
if( isset( $field_value ) )
{ // Update a vote of current user
$Item->set_vote( $field_value );
$Item->dbupdate();
// Invalidate key for the voted Item:
BlockCache::invalidate_key( 'item_ID', $Item->ID );
}
}
if( ! empty( $redirect_to ) )
{ // Redirect to back page, It is used by browsers without JavaScript:
header_redirect( $redirect_to, 303 ); // Will EXIT
// We have EXITed already at this point!!
}
if( param( 'widget_ID', 'integer', 0 ) > 0 )
{ // If request is from widget:
$WidgetCache = & get_WidgetCache();
$item_Widget = & $WidgetCache->get_by_ID( get_param( 'widget_ID' ), false, false );
if( $item_Widget && $item_Widget->code == 'item_vote' )
{ // Request widget to display a voting panel for item:
$item_Widget->display_voting_panel( $Item, array( 'display_wrapper' => false ) );
break 2;
}
}
elseif( param( 'skin_ID', 'integer', 0 ) > 0 )
{ // If request is from skin:
$SkinCache = & get_SkinCache();
// Initialize global Collection in order to get Skin settings values from the Collection and not from defaults of the Skin:
$Blog = $item_Blog;
$request_Skin = & $SkinCache->get_by_ID( get_param( 'skin_ID' ), false, false );
if( $request_Skin && method_exists( $request_Skin, 'display_item_voting_panel' ) )
{ // Request skin to display a voting panel for item:
$request_Skin->display_item_voting_panel( $Item, $request_Skin->get_setting( 'voting_place' ), array( 'display_wrapper' => false ) );
break 2;
}
}
// Display a voting panel for item:
$Item->display_voting_panel( array( 'display_wrapper' => false ) );
break;
}
break;
case 'get_user_new_field':
// Used in the identity user form to add a new field
$field_ID = param( 'field_id', 'integer', 0 );
$user_ID = param( 'user_id', 'integer', 0 );
if( $field_ID == 0 )
{ // Bad request
break;
}
$userfields = $DB->get_results( '
SELECT T_users__fielddefs.*, "0" AS uf_ID, "" AS uf_varchar, ufgp_ID, ufgp_name
FROM T_users__fielddefs
LEFT JOIN T_users__fieldgroups ON ufgp_ID = ufdf_ufgp_ID
WHERE ufdf_ID = "'.$field_ID.'"' );
if( $userfields[0]->ufdf_duplicated == 'forbidden' )
{ // This field can be only one instance for one user
echo '[0]'; // not duplicated field
$user_field_exist = $DB->get_var( '
SELECT uf_ID
FROM T_users__fields
WHERE uf_user_ID = "'.$user_ID.'" AND uf_ufdf_ID = "'.$field_ID.'"' );
if( $user_field_exist > 0 )
{ // User already has a current field type
break;
}
}
else
{ // It Means: this field can be duplicated
echo '[1]';
}
// Use the glyph or font-awesome icons if requested by skin
param( 'b2evo_icons_type', 'string', '' );
$Form = new Form();
$Form->fieldstart = '#fieldstart#';
$Form->fieldend = '#fieldend#';
$Form->labelclass = '#labelclass#';
$Form->labelstart = '#labelstart#';
$Form->labelend = '#labelend#';
$Form->inputstart = '#inputstart#';
$Form->inputend = '#inputend#';
userfields_display( $userfields, $Form, 'add', false, $user_ID );
break;
case 'get_user_field_autocomplete':
// Used for autocompletion of the user field
/**
* Possible values of var $attr_id
* 1) 111 - this goes from filter search, it is ufdf_ID
* 2) uf_new_222_ - field from identity form ( doesn't still exist in DB (recommened & required fields) )
* 3) uf_add_222_ - field from identity form ( user want add this field )
* where 222 == ufdf_ID
* 4) uf_333 - field exists in DB (where 333 == uf_ID from table T_users__fields)
*/
$attr_id = param( 'attr_id', 'string' );
$term = param( 'term', 'string' );
$field_type_id = 0;
if( (int)$attr_id > 0 )
{ // From filter 'Specific criteria'
$field_type_id = (int)$attr_id;
}
else if( preg_match( '/^uf_(new|add)_(\d+)_/i', $attr_id, $match ) )
{ // From new fields we can get the value for uf_ufdf_ID
$field_type_id = (int)$match[2];
}
else if( preg_match( '/^uf_(\d+)$/i', $attr_id, $match ) )
{ // From fields in DB we can get only uf_ID, then we should get a value uf_ufdf_ID from DB
$field_id = (int)$match[1];
$field_type_id = $DB->get_var( '
SELECT uf_ufdf_ID
FROM T_users__fields
WHERE uf_ID = "'.$field_id.'"' );
}
if( $field_type_id == 0 )
{ // Bad request
break;
}
echo evo_json_encode( $DB->get_col( '
SELECT DISTINCT ( uf_varchar )
FROM T_users__fields
WHERE uf_varchar LIKE '.$DB->quote('%'.$term.'%').'
AND uf_ufdf_ID = "'.$field_type_id.'"
ORDER BY uf_varchar' ) );
exit(0); // Exit here in order to don't display the AJAX debug info after JSON formatted data
break;
case 'get_regions_option_list':
// Get option list with regions by selected country
$country_ID = param( 'ctry_id', 'integer', 0 );
$region_ID = param( 'rgn_id', 'integer', 0 );
$page = param( 'page', 'string', '' );
$mode = param( 'mode', 'string', '' );
$params = array();
if( $page == 'edit' )
{
$params['none_option_text'] = T_( 'Unknown' );
}
load_funcs( 'regional/model/_regional.funcs.php' );
echo get_regions_option_list( $country_ID, 0, $params );
if( $mode == 'load_subregions' || $mode == 'load_all' )
{ // Load also the subregions
echo '-##-'.get_subregions_option_list( $region_ID, 0, $params );
}
if( $mode == 'load_all' )
{ // Load also the cities
echo '-##-'.get_cities_option_list( $country_ID, $region_ID, 0, 0, $params );
}
break;
case 'get_subregions_option_list':
// Get option list with sub-regions by selected region
$country_ID = param( 'ctry_id', 'integer', 0 );
$region_ID = param( 'rgn_id', 'integer', 0 );
$page = param( 'page', 'string', '' );
$mode = param( 'mode', 'string', '' );
$params = array();
if( $page == 'edit' )
{
$params['none_option_text'] = T_( 'Unknown' );
}
load_funcs( 'regional/model/_regional.funcs.php' );
echo get_subregions_option_list( $region_ID, 0, $params );
if( $mode == 'load_all' )
{ // Load also the cities
echo '-##-'.get_cities_option_list( $country_ID, $region_ID, 0, 0, $params );
}
break;
case 'get_cities_option_list':
// Get option list with cities by selected country, region or sub-region
$country_ID = param( 'ctry_id', 'integer', 0 );
$region_ID = param( 'rgn_id', 'integer', 0 );
$subregion_ID = param( 'subrg_id', 'integer', 0 );
$page = param( 'page', 'string', '' );
$params = array();
if( $page == 'edit' )
{
$params['none_option_text'] = T_( 'Unknown' );
}
load_funcs( 'regional/model/_regional.funcs.php' );
echo get_cities_option_list( $country_ID, $region_ID, $subregion_ID, 0, $params );
break;
case 'get_field_bubbletip':
// Get info for user field
$field_ID = param( 'field_ID', 'integer', 0 );
if( $field_ID > 0 )
{ // Get field info from DB
$field = $DB->get_row( '
SELECT ufdf_bubbletip, ufdf_duplicated
FROM T_users__fielddefs
WHERE ufdf_ID = '.$DB->quote( $field_ID ) );
if( is_null( $field ) )
{ // No field in DB
break;
}
if( !empty( $field->ufdf_bubbletip ) )
{ // Field has a defined bubbletip text
$field_info = nl2br( $field->ufdf_bubbletip );
}
else if( in_array( $field->ufdf_duplicated, array( 'allowed', 'list' ) ) )
{ // Default info for fields with multiple values
$field_info = T_('To enter multiple values,<br />please click on (+)');
}
}
if( !empty( $field_info ) )
{ // Replace mask text (+) with img tag
// Use the glyph or font-awesome icons if requested by skin
param( 'b2evo_icons_type', 'string', '' );
echo str_replace( '(+)', get_icon( 'add' ), $field_info );
}
break;
case 'validate_login':
// Validate if username is available
param( 'login', 'string', '' );
if( param_check_valid_login( 'login' ) )
{ // Login format is correct
if( !empty( $login ) )
{
$SQL = new SQL( 'Validate if username is available' );
$SQL->SELECT( 'user_ID' );
$SQL->FROM( 'T_users' );
$SQL->WHERE( 'user_login = "'.$DB->escape( $login ).'"' );
if( $DB->get_var( $SQL ) )
{ // Login already exists
echo 'exists';
}
else
{ // Login is available
echo 'available';
}
}
}
else
{ // Incorrect format of login
echo param_get_error_msg( 'login' );
}
break;
case 'results':
// Refresh a results table (To change page, page size, an order)
/**
* Variable to define a current request as ajax content
* It is used to don't display a wrapper data such as header, footer and etc.
* @see is_ajax_content()
*
* @var boolean
*/
$ajax_content_mode = true;
// get callback function param, this function will display the results content
$callback_function = param( 'callback_function', 'string', '' );
if( param( 'is_backoffice', 'integer', 0 ) )
{
global $current_User, $UserSettings, $is_admin_page;
$admin_skin = $UserSettings->get( 'admin_skin', $current_User->ID );
$params = array( 'skin_type' => 'admin', 'skin_name' => $admin_skin );
$is_admin_page = true;
/**
* Load the AdminUI class for the skin.
*/
require_once $adminskins_path.$admin_skin.'/_adminUI.class.php';
$AdminUI = new AdminUI();
// Get the requested params and memorize it to make correct links for paging, ordering and etc.
param( 'ctrl', '/^[a-z0-9_]+$/', $default_ctrl, true );
param( 'blog', 'integer', NULL, true );
$ReqPath = $admin_url;
}
else
{
$BlogCache = &get_BlogCache();
$Collection = $Blog = & $BlogCache->get_by_ID( $blog_ID, true );
$skin_ID = $Blog->get_skin_ID();
$SkinCache = & get_SkinCache();
$Skin = & $SkinCache->get_by_ID( $skin_ID );
$params = array( 'skin_type' => 'front', 'skin_name' => $Skin->folder );
}
// load required resource for each callback function
switch( $callback_function )
{
case 'hits_results_block':
load_funcs('sessions/model/_hitlog.funcs.php');
break;
case 'items_created_results_block':
case 'items_edited_results_block':
case 'comments_results_block':
case 'threads_results_block':
case 'received_threads_results_block':
case 'user_reports_results_block':
case 'blogs_user_results_block':
case 'blogs_all_results_block':
case 'items_list_block_by_page':
case 'items_manual_results_block':
case 'user_sent_emails_results_block':
case 'user_email_returns_results_block':
break;
default:
ajax_log_add( 'Incorrect callback function name!', 'error' );
debug_die( 'Incorrect callback function!' );
}
// Call the requested callback function to display the results
call_user_func( $callback_function, $params );
break;
case 'set_comment_status':
// Used for quick moderation of comments in dashboard, item list full view, comment list and front-office screens
// Check that this action request is not a CSRF hacked request:
$Session->assert_received_crumb( 'comment' );
$result_success = false;
if( is_logged_in() )
{ // Only logged in users can moderate comments
// Check comment moderate permission below after we have the $edited_Comment object
$request_from = param( 'request_from', 'string', NULL );
$is_admin_page = $request_from != 'front';
$blog = param( 'blogid', 'integer' );
$moderation = param( 'moderation', 'string', NULL );
$status = param( 'status', 'string' );
$expiry_status = param( 'expiry_status', 'string', 'active' );
$limit = param( 'limit', 'integer', 0 );
$edited_Comment = & Comment_get_by_ID( param( 'commentid', 'integer' ), false );
if( $edited_Comment !== false )
{ // The comment still exists
// Check permission:
check_user_perm( 'comment!'.$status, 'moderate', true, $edited_Comment );
$redirect_to = param( 'redirect_to', 'url', NULL );
$edited_Comment->set( 'status', $status );
// Comment moderation is done, handle moderation "secret"
$edited_Comment->handle_qm_secret();
$result_success = $edited_Comment->dbupdate();
if( $result_success !== false )
{
$edited_Comment->handle_notifications();
}
}
}
if( $result_success === false )
{ // Some errors on deleting of the comment, Exit here
header_http_response( '500 '.T_('Comment cannot be updated!'), 500 );
exit(0);
}
if( $moderation != NULL && in_array( $request_from, array( 'items', 'comments' ) ) )
{ // AJAX request goes from backoffice and ctrl = items or comments
if( param( 'is_backoffice', 'integer', 0 ) )
{ // Set admin skin, used for buttons, @see button_class()
global $current_User, $UserSettings, $is_admin_page, $adminskins_path;
$admin_skin = $UserSettings->get( 'admin_skin', $current_User->ID );
$is_admin_page = true;
require_once $adminskins_path.$admin_skin.'/_adminUI.class.php';
$AdminUI = new AdminUI();
}
$statuses = param( 'statuses', 'string', NULL );
$item_ID = param( 'itemid', 'integer' );
$currentpage = param( 'currentpage', 'integer', 1 );
// In case of comments_fullview we must set a filterset name to be abble to restore filterset.
// If $moderation is not NULL, then this requests came from the comments_fullview
// TODO: asimo> This should be handled with a better solution
$filterset_name = ( $item_ID > 0 ) ? '' : 'fullview';
echo_item_comments( $blog, $item_ID, $statuses, $currentpage, $limit, array(), $filterset_name, $expiry_status );
}
elseif( $request_from == 'front' )
{ // AJAX request goes from frontoffice
// Send new current status as ajax response
echo $edited_Comment->status;
// Also send the statuses which will be after raising/lowering of a status by current user
$comment_raise_status = $edited_Comment->get_next_status( true, $edited_Comment->status );
$comment_lower_status = $edited_Comment->get_next_status( false, $edited_Comment->status );
echo ':'.( $comment_raise_status ? $comment_raise_status[0] : '' );
echo ':'.( $comment_lower_status ? $comment_lower_status[0] : '' );
}
break;
case 'get_user_new_org':
// Used in the identity user form to add a new organization
if( ! is_logged_in() )
{ // User must be logged in
break;
}
$first_org = param( 'first_org', 'integer', 0 );
// Use the glyph or font-awesome icons if it is defined by skin
param( 'b2evo_icons_type', 'string', '' );
$Form = new Form();
$OrganizationCache = & get_OrganizationCache();
$OrganizationCache->clear();
// Load only organizations that allow to join members or own organizations of the current user:
$OrganizationCache->load_where( '( org_accept != "no" OR org_owner_user_ID = "'.$current_User->ID.'" )' );
$Form->output = false;
$Form->switch_layout( 'none' );
$org_suffix = ' <strong>'.T_('Role').':</strong> '.$Form->text_input( 'org_roles[]', '', 20, '', '', array( 'maxlength' => 255 ) ).' ';
$org_suffix .= ' <strong>'.T_('Order').':</strong> '.$Form->text_input( 'org_priorities[]', '', 10, '', '', array( 'type' => 'number', 'min' => -2147483648, 'max' => 2147483647 ) ).' ';
$Form->switch_layout( NULL );
$Form->output = true;
// Special form template that will be replaced to current skin on ajax response
$Form->fieldstart = '#fieldstart#';
$Form->fieldend = '#fieldend#';
$Form->labelclass = '#labelclass#';
$Form->labelstart = '#labelstart#';
$Form->labelend = '#labelend#';
$Form->inputstart = '#inputstart#';
$Form->inputend = '#inputend#';
$org_suffix .= ' '.get_icon( 'add', 'imgtag', array( 'class' => 'add_org', 'style' => 'cursor:pointer' ) );
$org_suffix .= ' '.get_icon( 'minus', 'imgtag', array( 'class' => 'remove_org', 'style' => 'cursor:pointer' ) );
$Form->select_input_object( 'organizations[]', 0, $OrganizationCache, T_('Organization'), array( 'allow_none' => $first_org ? true : false, 'field_suffix' => $org_suffix ) );
break;
case 'change_user_org_status':
// Used in the identity user form to change an accept status of organization by Admin users
if( ! is_logged_in() )
{ // User must be logged in
break;
}
// Check that this action request is not a CSRF hacked request:
$Session->assert_received_crumb( 'userorg' );
/**
* This string is value of "rel" attibute of span icon element
* The format of this string is: 'org_status_y_1_2' or 'org_status_n_1_2', where:
* 'y' - organization was accepted by admin,
* 'n' - not accepted
* '1' - this number is ID of organization - uorg_org_ID from the DB table T_users__user_org
* '2' - this number is ID of user - uorg_user_ID from the DB table T_users
*/
$status = explode( '_', param( 'status', 'string' ) );
// ID of organization
$org_ID = isset( $status[3] ) ? intval( $status[3] ) : 0;
// ID of organization
$user_ID = isset( $status[4] ) ? intval( $status[4] ) : 0;
// Get organization by ID:
$OrganizationCache = & get_OrganizationCache();
$user_Organization = & $OrganizationCache->get_by_ID( $org_ID, false, false );
if( count( $status ) != 5 || ( $status[2] != 'y' && $status[2] != 'n' ) || $org_ID == 0 || ! $user_Organization )
{ // Incorrect format of status param
ajax_log_add( /* DEBUG: do not translate */ 'Incorrect request to accept organization!', 'error' );
break;
}
// Check permission:
check_user_perm( 'orgs', 'edit', true, $user_Organization );
// Use the glyph or font-awesome icons if it is defined by skin
param( 'b2evo_icons_type', 'string', '' );
if( $status[2] == 'y' )
{ // Status will be change to "Not accepted"
$org_is_accepted = false;
}
else
{ // Status will be change to "Accepted"
$org_is_accepted = true;
}
// Change an accept status of organization for edited user
$DB->query( 'UPDATE T_users__user_org
SET uorg_accepted = '.$DB->quote( $org_is_accepted ? 1 : 0 ).'
WHERE uorg_user_ID = '.$DB->quote( $user_ID ).'
AND uorg_org_ID = '.$DB->quote( $org_ID ) );
$accept_icon_params = array( 'style' => 'cursor: pointer;', 'rel' => 'org_status_'.( $org_is_accepted ? 'y' : 'n' ).'_'.$org_ID.'_'.$user_ID );
if( $org_is_accepted )
{ // Organization is accepted by admin
$accept_icon = get_icon( 'allowback', 'imgtag', array_merge( array( 'title' => T_('Accepted') ), $accept_icon_params ) );
}
else
{ // Organization is not accepted by admin yet
$accept_icon = get_icon( 'bullet_red', 'imgtag', array_merge( array( 'title' => T_('Not accepted') ), $accept_icon_params ) );
}
// Display icon with new status
echo $accept_icon;
break;
case 'get_regform_crumb':
// Get crumb value for register form:
// (Used for widget "Email capture / Quick registration" when page caching is enabled)
echo get_crumb( 'regform' );
break;
case 'get_user_salt':
// Get the salt of the user from the given login info
// Note: If there are more users with the received login then give at most 3 salt values for the 3 most recently active users
// It always returns at least one salt value to show no difference between the existing and not existing user names
$get_widget_login_hidden_fields = param( 'get_widget_login_hidden_fields', 'boolean', false );
// Check that this action request is not a CSRF hacked request:
if( ! $get_widget_login_hidden_fields )
{ // If the request was received from the normal login form check the loginsalt crumb
$Session->assert_received_crumb( 'loginsalt' );
}
$result = array();
if( $get_widget_login_hidden_fields )
{ // Get the loginform crumb, the password encryption salt, and the Session ID for the widget login form:
$pepper = $Session->get( 'core.pepper' );
if( empty( $pepper ) )
{ // Session salt is not generated yet, needs to generate:
$pepper = generate_random_key(64);
$Session->set( 'core.pepper', $pepper, 86400 /* expire in 1 day */ );
$Session->dbsave(); // save now, in case there's an error later, and not saving it would prevent the user from logging in.
}
$result['crumb'] = get_crumb( 'loginform' );
$result['pepper'] = $pepper;
$result['session_id'] = $Session->ID;
}
$login = param( $dummy_fields[ 'login' ], 'string', '' );
$check_field = is_email( $login ) ? 'user_email' : 'user_login';
// Get the most recently used 3 users with matching email address:
$salts = $DB->get_results( 'SELECT user_salt, user_pass_driver FROM T_users
WHERE '.$check_field.' = '.$DB->quote( utf8_strtolower( $login ) ).'
ORDER BY user_lastseen_ts DESC, user_status ASC
LIMIT 3', ARRAY_A );
// Make sure to return at least one hashed password, to make it unable to guess if user exists with the given login
if( empty( $salts ) )
{ // User with the given login was not found add one random salt value
$salts[] = array(
'user_salt' => generate_random_key( 8 ),
'user_pass_driver' => 'evo$salted',
);
}
$result['salts'] = array();
$result['hash_algo'] = array();
foreach( $salts as $salt )
{
// Get password driver by code:
$user_PasswordDriver = get_PasswordDriver( $salt['user_pass_driver'] );
if( ! $user_PasswordDriver )
{ // Skip this user because he has an unknown password driver:
continue;
}
$result['salts'][] = $salt['user_salt'];
$result['hash_algo'][] = $user_PasswordDriver->get_javascript_hash_code( 'raw_password', 'salts[index]' );
}
echo evo_json_encode( $result );
exit(0); // Exit here in order to don't display the AJAX debug info after JSON formatted data
break;
case 'crop':
// Get form to crop profile picture
if( ! is_logged_in() )
{ // Only the logged in user can crop pictures
break;
}
$file_ID = param( 'file_ID', 'integer' );
$cropped_File = & $current_User->get_File_by_ID( $file_ID, $error_code );
if( ! $cropped_File )
{ // Wrong file for cropping
break;
}
$BlogCache = &get_BlogCache();
$Collection = $Blog = & $BlogCache->get_by_ID( $blog_ID, true );
$skin_ID = $Blog->get_skin_ID();
$SkinCache = & get_SkinCache();
$Skin = & $SkinCache->get_by_ID( $skin_ID );
$display_mode = 'js';
$form_action = get_htsrv_url().'profile_update.php';
$window_width = param( 'window_width', 'integer' );
$window_height = param( 'window_height', 'integer' );
require $inc_path.'users/views/_user_crop.form.php';
break;
case 'get_user_report_form':
// Get form to report for user
// Check that this action request is not a CSRF hacked request:
$Session->assert_received_crumb( 'user' );
$user_ID = param( 'user_ID', 'integer', true );
if( ! is_logged_in() || ( isset( $User ) && $current_User->ID == $User->ID ) || ! check_user_status( 'can_report_user', $user_ID ) )
{ // Only if current user can reports
break;
}
$UserCache = & get_UserCache();
$edited_User = & $UserCache->get_by_ID( $user_ID );
if( param( 'is_backoffice', 'integer', 0 ) )
{ // Load the AdminUI class for the skin.
$user_tab = param( 'user_tab', 'string' );
global $current_User, $UserSettings, $is_admin_page;
$admin_skin = $UserSettings->get( 'admin_skin', $current_User->ID );
$is_admin_page = true;
require_once $adminskins_path.$admin_skin.'/_adminUI.class.php';
$AdminUI = new AdminUI();
}
else
{ // Load Blog skin
$BlogCache = & get_BlogCache();
$Collection = $Blog = & $BlogCache->get_by_ID( $blog_ID, true );
$skin_ID = $Blog->get_skin_ID();
$SkinCache = & get_SkinCache();
$Skin = & $SkinCache->get_by_ID( $skin_ID );
}
$display_mode = 'js';
$form_action = get_htsrv_url().'profile_update.php';
require $inc_path.'users/views/_user_report.form.php';
break;
case 'get_user_contact_form':
// Get form to add/edit user to contact
// Check that this action request is not a CSRF hacked request:
$Session->assert_received_crumb( 'user' );
if( ! is_logged_in() || ( isset( $User ) && $current_User->ID == $User->ID ) ||
! check_user_perm( 'perm_messaging', 'reply' ) ||
! check_user_status( 'can_edit_contacts' ) )
{ // Only if current user can reports
break;
}
$user_ID = param( 'user_ID', 'integer', true );
$UserCache = & get_UserCache();
$edited_User = & $UserCache->get_by_ID( $user_ID );
if( param( 'is_backoffice', 'integer', 0 ) )
{ // Load the AdminUI class for the skin.
$user_tab = param( 'user_tab', 'string' );
global $current_User, $UserSettings, $is_admin_page;
$admin_skin = $UserSettings->get( 'admin_skin', $current_User->ID );
$is_admin_page = true;
require_once $adminskins_path.$admin_skin.'/_adminUI.class.php';
$AdminUI = new AdminUI();
}
else
{ // Load Blog skin
$BlogCache = & get_BlogCache();
$Collection = $Blog = & $BlogCache->get_by_ID( $blog_ID, true );
$skin_ID = $Blog->get_skin_ID();
$SkinCache = & get_SkinCache();
$Skin = & $SkinCache->get_by_ID( $skin_ID );
}
$display_mode = 'js';
$form_action = get_htsrv_url().'profile_update.php';
require $inc_path.'users/views/_user_groups.form.php';
break;
case 'render_inlines':
$target_ID = param( 'id', 'integer', 0 );
$target_type = param( 'type', 'string' );
$tags = param( 'tags', 'array:string', array() );
// 'temp_link_owner_ID' param will be passed for objects with temporary ID
// Default params from skins/skins_fallback_v6/_item_content.inc.php
$params = array(
'before_image' => '<figure'.( $target_type == 'EmailCampaign' ? emailskin_style( '.evo_image_block' ) : ' class="evo_image_block"' ).'>',
'before_image_legend' => '<figcaption'.( $target_type == 'EmailCampaign' ? emailskin_style( '.evo_image_legend' ) : ' class="evo_image_legend"' ).'>',
'after_image_legend' => '</figcaption>',
'after_image' => '</figure>',
'after_images' => '</div>',
'image_class' => 'img-responsive',
'image_size' => param( 'image_size', 'string', 'fit-256x256' ),
'image_limit' => 1000,
'image_link_to' => 'original', // Can be 'original', 'single' or empty
);
switch( $target_type )
{
case 'Item':
$ItemCache = & get_ItemCache();
$edited_Item = $ItemCache->get_by_ID( $target_ID, false, false );
if( ! $edited_Item )
{
$edited_Item = new Item();
}
$rendered_tags = render_inline_tags( $edited_Item, $tags, $params );
break;
case 'Comment':
$CommentCache = & get_CommentCache();
$edited_Comment = $CommentCache->get_by_ID( $target_ID, false, false );
if( ! $edited_Comment )
{
$edited_Comment = new Comment();
}
$rendered_tags = render_inline_tags( $edited_Comment, $tags, $params );
break;
case 'EmailCampaign':
$EmailCampaignCache = & get_EmailCampaignCache();
$edited_EmailCampaign = $EmailCampaignCache->get_by_ID( $target_ID );
$rendered_tags = render_inline_tags( $edited_EmailCampaign, $tags, $params );
break;
case 'Message':
$MessageCache = & get_MessageCache();
$edited_Message = $MessageCache->get_by_ID( $target_ID, false, false );
if( ! $edited_Message )
{
$edited_Message = new Message();
}
$rendered_tags = render_inline_tags( $edited_Message, $tags, $params );
break;
}
if( $rendered_tags )
{
echo json_encode( $rendered_tags );
}
exit(0); // Exit here in order to don't display the AJAX debug info after JSON formatted data
case 'get_insert_image_form':
case 'get_edit_image_form':
$restrict_tag = false;
$request_from = param( 'request_from', 'string', NULL );
global $is_admin_page;
init_fontawesome_icons();
$is_admin_page = is_logged_in() && $request_from == 'back';
if( is_admin_page() )
{
global $UserSettings, $adminskins_path, $AdminUI;
$admin_skin = $UserSettings->get( 'admin_skin', $current_User->ID );
require_once $adminskins_path.$admin_skin.'/_adminUI.class.php';
$AdminUI = new AdminUI();
}
else
{
$BlogCache = & get_BlogCache();
$Collection = $Blog = & $BlogCache->get_by_ID( $blog_ID, false, false );
if( $Blog )
{
$blog_skin_ID = $Blog->get_skin_ID();
if( ! empty( $blog_skin_ID ) )
{
$SkinCache = & get_SkinCache();
$Skin = & $SkinCache->get_by_ID( $blog_skin_ID );
}
}
}
// Default values:
$image_caption = NULL;
$image_disable_caption = false;
$image_alt = NULL;
$image_disable_alt = false;
$image_href = NULL;
$image_class = NULL;
$thumbnail_href = NULL;
$thumbnail_size = 'medium';
$thumbnail_alignment = 'left';
$thumbnail_class = NULL;
$inline_class = NULL;
if( $action == 'get_insert_image_form' )
{
$tag_type = param( 'tag_type', 'string', 'image' );
$link_ID = param( 'link_ID', 'integer', true );
$replace = 0;
}
else
{
// Uncomment line below to hide inline type tabs
//$restrict_tag = true;
$short_tag = param( 'short_tag', 'string', true );
$short_tag = rawurldecode( $short_tag );
$replace = 1;
$parts = trim( $short_tag, '[]' );
$parts = explode( ':', $parts );
$opt_index = 2;
$tag_type = $parts[0];
$link_ID = $parts[1];
switch( $tag_type )
{
case 'image':
// Caption:
$image_disable_caption = ( isset( $parts[ $opt_index ] ) && $parts[ $opt_index ] == '-' );
if( isset( $parts[ $opt_index ] ) )
{
if( $parts[ $opt_index ] != '-' )
{
$image_caption = $parts[ $opt_index ];
}
$opt_index++;
}
$href_regexp = '#^(https?|\(\((.*?)\)\))$#i';
// Alt text:
$image_disable_alt = ( isset( $parts[ $opt_index ] ) && $parts[ $opt_index ] == '-' );
if( isset( $parts[ $opt_index ] ) &&
substr( $parts[ $opt_index ], 0, 1 ) != '.' &&
! preg_match( $href_regexp, $parts[ $opt_index ] ) )
{
if( $parts[ $opt_index ] != '-' )
{
$image_alt = $parts[ $opt_index ];
}
$opt_index++;
}
// HRef:
if( ! empty( $parts[ $opt_index ] ) &&
preg_match( $href_regexp, $parts[ $opt_index ], $href_match ) )
{
if( stripos( $href_match[0], 'http' ) === 0 )
{ // Absolute URL:
$image_href = $href_match[0].':'.$parts[ $opt_index + 1 ];
$opt_index++;
}
else
{ // Item slug:
$image_href = $href_match[0];
}
$opt_index++;
}
// TODO: Size:
// Class:
if( isset( $parts[ $opt_index ] ) )
{
$image_class = $parts[ $opt_index ];
}
break;
case 'thumbnail':
$href_regexp = '#^(https?|\(\((.*?)\)\))$#i';
// Alt text:
$image_disable_alt = ( isset( $parts[ $opt_index ] ) && $parts[ $opt_index ] == '-' );
if( isset( $parts[ $opt_index ] ) &&
substr( $parts[ $opt_index ], 0, 1 ) != '.' &&
! preg_match( $href_regexp, $parts[ $opt_index ] ) &&
! in_array( $parts[ $opt_index ], array( 'small', 'medium', 'large', 'left', 'right' ) ) )
{
if( $parts[ $opt_index ] != '-' )
{
$image_alt = $parts[ $opt_index ];
}
$opt_index++;
}
// HRef:
if( ! empty( $parts[ $opt_index ] ) &&
preg_match( $href_regexp, $parts[ $opt_index ], $href_match ) )
{
if( stripos( $href_match[0], 'http' ) === 0 )
{ // Absolute URL:
$thumbnail_href = $href_match[0].':'.$parts[ $opt_index + 1 ];
$opt_index++;
}
else
{ // Item slug:
$thumbnail_href = $href_match[0];
}
$opt_index++;
}
// Size:
$valid_thumbnail_sizes = array( 'small', 'medium', 'large' );
if( isset( $parts[ $opt_index ] ) && in_array( $parts[ $opt_index ], $valid_thumbnail_sizes ) )
{
$thumbnail_size = $parts[ $opt_index ];
$opt_index++;
}
// Alignment:
$valid_thumbnail_positions = array( 'left', 'right' );
if( isset( $parts[ $opt_index ] ) && in_array( $parts[ $opt_index ], $valid_thumbnail_positions ) )
{
$thumbnail_alignment = $parts[ $opt_index ];
$opt_index++;
}
// Class:
if( isset( $parts[ $opt_index ] ) )
{
$thumbnail_class = $parts[ $opt_index ];
$opt_index++;
}
break;
case 'inline':
// Alt text:
$image_disable_alt = ( isset( $parts[ $opt_index ] ) && $parts[ $opt_index ] == '-' );
if( isset( $parts[ $opt_index ] ) &&
substr( $parts[ $opt_index ], 0, 1 ) != '.' &&
! in_array( $parts[ $opt_index ], array( 'small', 'medium', 'large', 'original' ) ) )
{
if( $parts[ $opt_index ] != '-' )
{
$image_alt = $parts[ $opt_index ];
}
$opt_index++;
}
// Class:
if( isset( $parts[ $opt_index ] ) )
{
$inline_class = $parts[ $opt_index ];
}
break;
default:
// Initialize additional inline tag form from active plugins:
$plugin_data = $Plugins->get_trigger_event_first_return( 'InitImageInlineTagForm', array(
'source_tag' => $short_tag,
'tag_type' => $tag_type,
'link_ID' => $link_ID,
) );
if( isset( $plugin_data['tag_type'] ) )
{ // Override active tag type from plugins:
$tag_type = $plugin_data['tag_type'];
}
if( isset( $plugin_data['link_ID'] ) )
{ // Override link ID from plugins:
$link_ID = $plugin_data['link_ID'];
}
}
}
$LinkCache = & get_LinkCache();
if( ! ( $Link = & $LinkCache->get_by_ID( $link_ID, false, false ) ) )
{ // Bad request with incorrect link ID
echo '';
exit(0);
}
if( ! ( $File = & $Link->get_File() ) )
{ // File no longer available
echo '';
exit(0);
}
require $inc_path.'items/views/_item_image.form.php';
break;
case 'set_object_link_position':
// Change a position of a link on the edit item screen (fieldset "Images & Attachments")
// Check that this action request is not a CSRF hacked request:
$Session->assert_received_crumb( 'link' );
// Check item/comment edit permission below after we have the $LinkOwner object ( we call LinkOwner->check_perm ... )
param('link_ID', 'integer', true);
param('link_position', 'string', true);
// Don't display the inline position reminder again until the user logs out or loses the session cookie
if( $link_position == 'inline' )
{
$Session->set( 'display_inline_reminder', 'false' );
}
$LinkCache = & get_LinkCache();
if( ( $Link = & $LinkCache->get_by_ID( $link_ID ) ) === false )
{ // Bad request with incorrect link ID
echo '';
exit(0);
}
$LinkOwner = & $Link->get_LinkOwner();
// Check permission:
$LinkOwner->check_perm( 'edit', true );
if( $Link->set( 'position', $link_position ) && $Link->dbupdate() )
{ // update was successful
echo 'OK';
// Update last touched date of Owners
$LinkOwner->update_last_touched_date();
if( $LinkOwner->type == 'item' &&
( $link_position == 'cover' || $link_position == 'background' ) )
{ // Position "Cover" or "Background" can be used only by one link
// Replace previous position with "After more":
$DB->query( 'UPDATE T_links
SET link_position = "aftermore"
WHERE link_ID != '.$DB->quote( $link_ID ).'
AND link_itm_ID = '.$DB->quote( $LinkOwner->Item->ID ).'
AND link_position = '.$DB->quote( $link_position ) );
}
}
else
{ // return the current value on failure
echo $Link->get( 'position' );
}
break;
case 'update_links_order':
global $localtimenow;
// Update the order of all links at one time:
// Check that this action request is not a CSRF hacked request:
$Session->assert_received_crumb( 'link' );
$link_IDs = param( 'links', 'string' );
if( empty( $link_IDs ) )
{ // No links to update, wrong request, exit here:
break;
}
$link_IDs = explode( ',', $link_IDs );
// Check permission by first link:
$LinkCache = & get_LinkCache();
if( ( $Link = & $LinkCache->get_by_ID( $link_IDs[0] ) ) === false )
{ // Bad request with incorrect link ID
exit(0);
}
$LinkOwner = & $Link->get_LinkOwner();
// Check permission:
$LinkOwner->check_perm( 'edit', true );
$DB->begin( 'SERIALIZABLE' );
// Get max order value of the links:
$max_link_order = intval( $DB->get_var( 'SELECT MAX( link_order )
FROM T_links
WHERE link_ID IN ( '.$DB->quote( $link_IDs ).' )' ) );
// Initialize parts of sql queries to update the links order:
$fake_sql_update_strings = '';
$real_sql_update_strings = '';
$real_link_order = 0;
$link_order = array();
foreach( $link_IDs as $link_ID )
{
$max_link_order++;
$fake_sql_update_strings .= ' WHEN link_ID = '.$DB->quote( $link_ID ).' THEN '.$max_link_order;
$real_link_order++;
$real_sql_update_strings .= ' WHEN link_ID = '.$DB->quote( $link_ID ).' THEN '.$real_link_order;
$link_order[$link_ID] = $real_link_order;
}
if( $LinkOwner->type == 'item' && ( $localtimenow - strtotime( $LinkOwner->Item->last_touched_ts ) ) > 90 )
{
$LinkOwner->Item->create_revision();
}
// Do firstly fake ordering start with max order, to avoid duplicate entry error:
$DB->query( 'UPDATE T_links
SET link_order = CASE '.$fake_sql_update_strings.' ELSE link_order END
WHERE link_ID IN ( '.$DB->quote( $link_IDs ).' )' );
// Do real ordering start with number 1:
$DB->query( 'UPDATE T_links
SET link_order = CASE '.$real_sql_update_strings.' ELSE link_order END
WHERE link_ID IN ( '.$DB->quote( $link_IDs ).' )' );
$LinkOwner->update_last_touched_date();
$DB->commit();
echo json_encode( $link_order );
break;
case 'test_api':
// Spec action to test API from ctrl=system:
echo 'ok';
break;
case 'get_file_select_item':
$field_params = param( 'params', 'array', true );
$field_name = param( 'field_name', 'string', true );
$root = param( 'root', 'string', true );
$file_path = param( 'path', 'string', true );
$FileCache = & get_FileCache();
list( $root_type, $root_in_type_ID ) = explode( '_', $root, 2 );
if( ! ( $current_File = $FileCache->get_by_root_and_path( $root_type, $root_in_type_ID, $file_path ) ) )
{ // No file:
debug_die( 'No such file' );
// Exit here.
}
if( ! $current_File->is_image() )
{
debug_die( 'Incorrect file type for '.$field_name );
}
// decode params with HTML tags
$field_params['field_item_start'] = base64_decode( $field_params['field_item_start'] );
$field_params['field_item_end'] = base64_decode( $field_params['field_item_end'] );
$current_File->load_meta( true ); // erhsatingin > can we force create file meta in DB here or should this whole thing require login?
$r = file_select_item( $current_File->ID, $field_params );
echo json_encode( array(
'fieldName' => $field_name,
'fieldValue' => $current_File->ID,
'item' => base64_encode( $r )
) );
break;
case "colorpicker":
// Save last selected colors in bootstrap colorpicker per User:
// Check that this action request is not a CSRF hacked request:
$Session->assert_received_crumb( 'colorpicker' );
if( ! is_logged_in() )
{ // User must be loggedin for this action:
break;
}
param( 'colors', 'string' );
$UserSettings->set( 'colorpicker', $colors, $current_User->ID );
$UserSettings->dbupdate();
break;
case 'reorder_widgets':
// Reorder widgets in container (Designer Mode):
if( ! is_logged_in() )
{ // Only the logged in users can edit widgets:
echo T_('You must be logged in to edit widgets.');
break;
}
// Check that this action request is not a CSRF hacked request:
$Session->assert_received_crumb( 'widget', true, array(
'msg_format' => 'text',
) );
// Collection ID:
param( 'blog', 'integer', true );
// Get collection by ID:
$BlogCache = & get_BlogCache();
$Blog = & $BlogCache->get_by_ID( $blog );
// Check permission:
check_user_perm( 'blog_properties', 'edit', true, $blog );
// Container code:
param( 'container', 'string' );
// Widgets IDs:
param( 'widgets', 'array:integer' );
if( empty( $widgets ) )
{ // No widgets to reorder:
break;
}
$SQL = new SQL( 'Get widget container by code, first widget ID and current skin type before reordering (Designer Mode)' );
$SQL->SELECT( 'wico_ID' );
$SQL->FROM( 'T_widget__container' );
$SQL->FROM_add( 'INNER JOIN T_widget__widget ON wi_wico_ID = wico_ID' );
$SQL->WHERE( 'wi_ID = '.$DB->quote( $widgets[0] ) );
$SQL->WHERE_and( 'wico_code = '.$DB->quote( $container ) );
$SQL->WHERE_and( 'wico_skin_type = '.$DB->quote( $Blog->get_skin_type() ) );
$container_ID = $DB->get_var( $SQL );
$SQL = new SQL( 'Get all widgets of container "'.$container.'" before reordering (Designer Mode)' );
$SQL->SELECT( 'wi_ID, wi_order, wi_enabled' );
$SQL->FROM( 'T_widget__widget' );
$SQL->WHERE( 'wi_wico_ID = '.$DB->quote( $container_ID ) );
$all_widgets = $DB->get_results( $SQL );
$container_widgets = array();
$enabled_widgets = array();
foreach( $all_widgets as $widget )
{
$container_widgets[ $widget->wi_ID ] = $widget->wi_order;
if( $widget->wi_enabled )
{ // Store in this array only enabled widgets:
$enabled_widgets[] = $widget->wi_ID;
}
}
$client_widgets = array_diff( $widgets, $enabled_widgets );
$server_widgets = array_diff( $enabled_widgets, $widgets );
if( ! empty( $client_widgets ) || ! empty( $server_widgets ) )
{ // Display error if at least one widget was added or deleted in the container:
echo T_('The widgets have been changed since you last loaded this page.').' '.T_('Please reload the page to be in sync with the server.').' '.T_('If the problem persists, check the widgets in the backoffice.');
// Additional data for log:
$SQL = new SQL( 'Get widgets for more log of reordering (Designer Mode)' );
$SQL->SELECT( 'wi_ID, wi_code' );
$SQL->FROM( 'T_widget__widget' );
$SQL->WHERE( 'wi_ID IN ( '.$DB->quote( array_merge( $client_widgets, $server_widgets ) ).' )' );
$code_widgets = $DB->get_assoc( $SQL );
if( ! empty( $client_widgets ) )
{ // Log what widgets were missed on server side:
$client_widgets_data = array();
foreach( $client_widgets as $client_widget_ID )
{
$client_widgets_data[] = '#'.$client_widget_ID.( isset( $code_widgets[ $client_widget_ID ] ) ? '('.$code_widgets[ $client_widget_ID ].')' : '' );
}
ajax_log_add( 'Widgets: '.implode( ', ', $client_widgets_data ).' are found on the page but not found in DB or they are disabled!', 'error' );
}
if( ! empty( $server_widgets ) )
{ // Log what widgets were missed on client side:
$server_widgets_data = array();
foreach( $server_widgets as $server_widget_ID )
{
$server_widgets_data[] = '#'.$server_widget_ID.( isset( $code_widgets[ $server_widget_ID ] ) ? '('.$code_widgets[ $server_widget_ID ].')' : '' );
}
ajax_log_add( 'Widgets: '.implode( ', ', $server_widgets_data ).' are enabled and found in DB but not found on the page!', 'error' );
}
break;
}
// Get what widgets are disabled or hidden on current view but exist in DB:
$disabled_widgets = array_diff( array_keys( $container_widgets ), $widgets );
// Append the disabled/hidden widgets at the end of list(so they will be ordered at the end):
$widgets = array_merge( $widgets, $disabled_widgets );
// Run reordering two times:
// - first is used to set orders starting with max order of the existing widgets,
// - second is starting orders with 1.
// Such complex is required to avoid error of duplicate entry of unique index (wi_wico_ID, wi_order).
$wi_start_orders = array( max( $container_widgets ) + 1, 1 );
foreach( $wi_start_orders as $wi_order )
{
$update_conditions = array();
foreach( $widgets as $widget_ID )
{
$update_conditions[] = 'WHEN wi_ID = '.$widget_ID.' THEN '.( $wi_order++ );
}
$DB->query( 'UPDATE T_widget__widget
SET wi_order = CASE '.implode( ' ', $update_conditions ).' ELSE 0 END
WHERE wi_wico_ID = '.$DB->quote( $container_ID ) );
}
break;
case 'disable_widget':
// Disable widget (Designer Mode):
if( ! is_logged_in() )
{ // Only the logged in users can edit widgets:
echo T_('You must be logged in to edit widgets.');
break;
}
// Check that this action request is not a CSRF hacked request:
$Session->assert_received_crumb( 'widget', true, array(
'msg_format' => 'text',
) );
param( 'blog', 'integer', 0 );
// Colection initialization is required for some widgets:
$BlogCache = & get_BlogCache();
$Blog = $BlogCache->get_by_ID( $blog );
// Check permission:
check_user_perm( 'blog_properties', 'edit', true, $blog );
param( 'wi_ID', 'integer' );
$WidgetCache = & get_WidgetCache();
$disabled_Widget = & $WidgetCache->get_by_ID( $wi_ID, false, false );
if( ! $disabled_Widget || ! $disabled_Widget->get( 'enabled' ) )
{ // Display error if widget doesn't exist or it is already disabled:
echo T_('The widgets have been changed since you last loaded this page.').' '.T_('Please reload the page to be in sync with the server.').' '.T_('If the problem persists, check the widgets in the backoffice.');
break;
}
// Disable widget:
$disabled_Widget->set( 'enabled', 0 );
$disabled_Widget->dbupdate();
break;
case 'get_url_alias_new_field':
param( 'b2evo_icons_type', 'string', '' );
$Form = new Form();
$Form->fieldstart = '#fieldstart#';
$Form->fieldend = '#fieldend#';
$Form->labelclass = '#labelclass#';
$Form->labelstart = '#labelstart#';
$Form->labelend = '#labelend#';
$Form->inputstart = '#inputstart#';
$Form->inputend = '#inputend#';
$alias_field_note = get_icon( 'add', 'imgtag', array( 'class' => 'url_alias_add', 'style' => 'cursor: pointer; position: relative;' ) );
$alias_field_note .= get_icon( 'minus', 'imgtag', array( 'class' => 'url_alias_minus', 'style' => 'margin-left: 2px; cursor: pointer; position: relative;' ) );
$Form->text_input( 'blog_url_alias[]', '', 50, T_('Alias URL'), $alias_field_note, array( 'class' => 'evo_url_alias', 'maxlength' => 255 ) );
break;
case 'get_item_selector_info':
// Get Item's info after selector from Modal/AJAX window by $Form->item_selector():
// Check that this action request is not a CSRF hacked request:
$Session->assert_received_crumb( 'item_selector' );
// Use the glyph or font-awesome icons if requested by skin
param( 'b2evo_icons_type', 'string', 'fontawesome-glyphicons' );
param( 'item_ID', 'integer', true );
$ItemCache = & get_ItemCache();
$item_selector_info = array();
if( $selected_Item = & $ItemCache->get_by_ID( $item_ID, false, false ) )
{
if( is_logged_in() )
{ // Remember what last collection was used for linking in order to display it by default on next linking:
global $UserSettings;
$UserSettings->set( 'last_selected_item_coll_ID', $selected_Item->get_blog_ID() );
$UserSettings->dbupdate();
}
$item_selector_info['item_ID'] = $selected_Item->ID;
$item_selector_info['item_info'] = $selected_Item->get_form_selector_info();
$item_selector_info['coll_ID'] = $selected_Item->get_blog_ID();
}
echo json_encode( $item_selector_info );
break;
case 'get_user_default_filters_form':
// Get form to change default users list filters:
// Check permission:
check_user_perm( 'users', 'edit', true );
// Load the AdminUI class for the skin:
global $current_User, $UserSettings, $is_admin_page;
$admin_skin = $UserSettings->get( 'admin_skin', $current_User->ID );
$is_admin_page = true;
require_once $adminskins_path.$admin_skin.'/_adminUI.class.php';
$AdminUI = new AdminUI();
$display_mode = 'js';
require $inc_path.'users/views/_user_list_default_filters.form.php';
break;
default:
ajax_log_add( T_('Incorrect action!'), 'error' );
break;
}
$disp = NULL;
$ctrl = NULL;
// Display AJAX Log:
ajax_log_display();
// Add ajax response end comment:
echo '<!-- Ajax response end -->';
exit(0);
?>