Merge commit 'release-3.0.6-RC1'

This commit is contained in:
Nils Adermann 2010-03-02 01:05:40 +01:00
commit 021c186be9
303 changed files with 15108 additions and 2860 deletions

View file

@ -246,7 +246,7 @@ function h_radio($name, &$input_ary, $input_default = false, $id = false, $key =
foreach ($input_ary as $value => $title)
{
$selected = ($input_default !== false && $value == $input_default) ? ' checked="checked"' : '';
$html .= '<label><input type="radio" name="' . $name . '"' . (($id && !$id_assigned) ? ' id="' . $id . '"' : '') . ' value="' . $value . '"' . $selected . (($key) ? ' accesskey="' . $key . '"' : '') . ' class="radio" /> ' . $user->lang[$title] . '</label>';
$html .= '<label><input type="radio" name="' . $name . '"' . (($id && !$id_assigned) ? ' id="' . $id . '"' : '') . ' value="' . $value . '"' . $selected . (($key) ? ' accesskey="' . $key . '"' : '') . ' class="radio" /> ' . $user->lang[$title] . '</label> ';
$id_assigned = true;
}
@ -263,6 +263,12 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars)
$tpl = '';
$name = 'config[' . $config_key . ']';
// Make sure there is no notice printed out for non-existent config options (we simply set them)
if (!isset($new[$config_key]))
{
$new[$config_key] = '';
}
switch ($tpl_type[0])
{
case 'text':
@ -301,7 +307,6 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars)
break;
case 'select':
case 'select_multiple':
case 'custom':
$return = '';
@ -340,21 +345,12 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars)
}
else
{
if ($tpl_type[0] == 'select_multiple')
{
$new[$config_key] = @unserialize(trim($new[$config_key]));
}
$args = array($new[$config_key], $key);
}
$return = call_user_func_array($call, $args);
if ($tpl_type[0] == 'select_multiple')
{
$tpl = '<select id="' . $key . '" name="' . $name . '[]" multiple="multiple">' . $return . '</select>';
}
else if ($tpl_type[0] == 'select')
if ($tpl_type[0] == 'select')
{
$tpl = '<select id="' . $key . '" name="' . $name . '">' . $return . '</select>';
}

View file

@ -17,6 +17,10 @@
<dd><label><input type="radio" class="radio" id="enable_confirm" name="enable_confirm" value="1"<!-- IF REG_ENABLE --> checked="checked"<!-- ENDIF --> /> {L_ENABLED}</label>
<label><input type="radio" class="radio" name="enable_confirm" value="0"<!-- IF not REG_ENABLE --> checked="checked"<!-- ENDIF --> /> {L_DISABLED}</label></dd>
</dl>
<dl>
<dt><label for="max_reg_attempts">{L_REG_LIMIT}:</label><br /><span>{L_REG_LIMIT_EXPLAIN}</span></dt>
<dd><input id="max_reg_attempts" type="text" size="4" maxlength="4" name="max_reg_attempts" value="{REG_LIMIT}" /></dd>
</dl>
<dl>
<dt><label for="enable_post_confirm">{L_VISUAL_CONFIRM_POST}:</label><br /><span>{L_VISUAL_CONFIRM_POST_EXPLAIN}</span></dt>
<dd><label><input type="radio" class="radio" id="enable_post_confirm" name="enable_post_confirm" value="1"<!-- IF POST_ENABLE --> checked="checked"<!-- ENDIF --> /> {L_ENABLED}</label>
@ -25,69 +29,35 @@
<dl>
<dt><label for="confirm_refresh">{L_VISUAL_CONFIRM_REFRESH}:</label><br /><span>{L_VISUAL_CONFIRM_REFRESH_EXPLAIN}</span></dt>
<dd><label><input type="radio" class="radio" id="confirm_refresh" name="confirm_refresh" value="1"<!-- IF CONFIRM_REFRESH --> checked="checked"<!-- ENDIF --> /> {L_ENABLED}</label>
<label><input type="radio" class="radio" name="confirm_refresh" value="0"<!-- IF not CONFIRM_REFRESH --> checked="checked"<!-- ENDIF --> /> {L_DISABLED}</label></dd>
<label><input type="radio" class="radio" name="confirm_refresh" value="0"<!-- IF not CONFIRM_REFRESH --> checked="checked"<!-- ENDIF --> /> {L_DISABLED}</label></dd>
</dl>
<!-- IF GD -->
<dl>
<dt><label for="captcha_gd">{L_CAPTCHA_GD}:</label><br /><span>{L_CAPTCHA_GD_EXPLAIN}</span></dt>
<dd><label><input id="captcha_gd" name="captcha_gd" value="1" class="radio" type="radio"<!-- IF CAPTCHA_GD --> checked="checked"<!-- ENDIF --> /> {L_YES}</label>
<label><input name="captcha_gd" value="0" class="radio" type="radio"<!-- IF not CAPTCHA_GD --> checked="checked"<!-- ENDIF --> /> {L_NO}</label></dd>
</dl>
<dl>
<dt><label for="captcha_gd_foreground_noise">{L_CAPTCHA_GD_FOREGROUND_NOISE}:</label><br /><span>{L_CAPTCHA_GD_FOREGROUND_NOISE_EXPLAIN}</span></dt>
<dd><label><input id="captcha_gd_foreground_noise" name="captcha_gd_foreground_noise" value="1" class="radio" type="radio"<!-- IF CAPTCHA_GD_FOREGROUND_NOISE --> checked="checked"<!-- ENDIF --> /> {L_YES}</label>
<label><input name="captcha_gd_foreground_noise" value="0" class="radio" type="radio"<!-- IF not CAPTCHA_GD_FOREGROUND_NOISE --> checked="checked"<!-- ENDIF --> /> {L_NO}</label></dd>
</dl>
<dl>
<dt><label for="captcha_gd_x_grid">{L_CAPTCHA_GD_X_GRID}:</label><br /><span>{L_CAPTCHA_GD_X_GRID_EXPLAIN}</span></dt>
<dd><input id="captcha_gd_x_grid" name="captcha_gd_x_grid" value="{CAPTCHA_GD_X_GRID}" type="text" /></dd>
</dl>
<dl>
<dt><label for="captcha_gd_y_grid">{L_CAPTCHA_GD_Y_GRID}:</label><br /><span>{L_CAPTCHA_GD_Y_GRID_EXPLAIN}</span></dt>
<dd><input id="captcha_gd_y_grid" name="captcha_gd_y_grid" value="{CAPTCHA_GD_Y_GRID}" type="text" /></dd>
</dl>
<dl>
<dt><label for="captcha_gd_wave">{L_CAPTCHA_GD_WAVE}:</label><br /><span>{L_CAPTCHA_GD_WAVE_EXPLAIN}</span></dt>
<dd><label><input id="captcha_gd_wave" name="captcha_gd_wave" value="1" class="radio" type="radio"<!-- IF CAPTCHA_GD_WAVE --> checked="checked"<!-- ENDIF --> /> {L_YES}</label>
<label><input name="captcha_gd_wave" value="0" class="radio" type="radio"<!-- IF not CAPTCHA_GD_WAVE --> checked="checked"<!-- ENDIF --> /> {L_NO}</label>
</dd>
</dl>
<dl>
<dt><label for="captcha_gd_3d_noise">{L_CAPTCHA_GD_3D_NOISE}:</label><br /><span>{L_CAPTCHA_GD_3D_NOISE_EXPLAIN}</span></dt>
<dd><label><input id="captcha_gd_3d_noise" name="captcha_gd_3d_noise" value="1" class="radio" type="radio"<!-- IF CAPTCHA_GD_3D_NOISE --> checked="checked"<!-- ENDIF --> /> {L_YES}</label>
<label><input name="captcha_gd_3d_noise" value="0" class="radio" type="radio"<!-- IF not CAPTCHA_GD_3D_NOISE --> checked="checked"<!-- ENDIF --> /> {L_NO}</label>
</dd>
</dl>
<dl>
<dt><label for="captcha_gd_fonts">{L_CAPTCHA_GD_FONTS}:</label><br /><span>{L_CAPTCHA_GD_FONTS_EXPLAIN}</span></dt>
<dd><label><input id="captcha_gd_fonts" name="captcha_gd_fonts" value="1" class="radio" type="radio"<!-- IF CAPTCHA_GD_FONTS == 1 --> checked="checked"<!-- ENDIF --> /> {L_CAPTCHA_FONT_DEFAULT}</label>
<label><input name="captcha_gd_fonts" value="2" class="radio" type="radio"<!-- IF CAPTCHA_GD_FONTS == 2 --> checked="checked"<!-- ENDIF --> /> {L_CAPTCHA_FONT_NEW}</label>
<label><input name="captcha_gd_fonts" value="3" class="radio" type="radio"<!-- IF CAPTCHA_GD_FONTS == 3 --> checked="checked"<!-- ENDIF --> /> {L_CAPTCHA_FONT_LOWER}</label>
</fieldset>
</dd>
<fieldset>
<legend>{L_AVAILABLE_CAPTCHAS}</legend>
<dl>
<dt><label for="captcha_select">{L_CAPTCHA_SELECT}:</label><br /><span>{L_CAPTCHA_SELECT_EXPLAIN}</span></dt>
<dd><select id="captcha_select" name="select_captcha" onchange="(document.getElementById('acp_captcha')).submit()" >{CAPTCHA_SELECT}</select></dd>
</dl>
<!-- IF S_CAPTCHA_HAS_CONFIG -->
<dl>
<dt><label for="configure">{L_CAPTCHA_CONFIGURE}:</label><br /><span>{L_CAPTCHA_CONFIGURE_EXPLAIN}</span></dt>
<dd><input class="button2" type="submit" id="configure" name="configure" value="{L_CONFIGURE}" /></dd>
</dl>
<!-- ENDIF -->
</fieldset>
<!-- IF CAPTCHA_PREVIEW_TPL -->
<fieldset>
<legend>{L_PREVIEW}</legend>
<!-- IF PREVIEW -->
<div class="successbox">
<h3>{L_WARNING}</h3>
<p>{L_CAPTCHA_PREVIEW_MSG}</p>
</div>
<!-- ENDIF -->
<dl>
<dt><label for="captcha_preview">{L_PREVIEW}:</label><br /><span>{L_CAPTCHA_PREVIEW_EXPLAIN}</span></dt>
<dd><img src="{CAPTCHA_PREVIEW}" alt="{L_PREVIEW}" <!-- IF CAPTCHA_GD_PREVIEWED -->width="360" height="96"<!-- ELSE --> width="320" height="50"<!-- ENDIF --> id="captcha_preview" /></dd>
</dl>
<!-- INCLUDE {CAPTCHA_PREVIEW_TPL} -->
</fieldset>
<!-- ENDIF -->
<fieldset class="submit-buttons">
<legend>{L_SUBMIT}</legend>
<input class="button1" type="submit" id="submit" name="submit" value="{L_SUBMIT}" />&nbsp;
<input class="button2" type="reset" id="reset" name="reset" value="{L_RESET}" />&nbsp;
<input class="button2" type="submit" id="preview" name="preview" value="{L_PREVIEW}" />
<input class="button1" type="submit" id="main_submit" name="main_submit" value="{L_SUBMIT}" />&nbsp;
<input class="button2" type="reset" id="form_reset" name="reset" value="{L_RESET}" />&nbsp;
{S_FORM_TOKEN}
</fieldset>
</form>

View file

@ -217,6 +217,11 @@
<dd><label><input type="radio" class="radio" name="enable_post_review" value="1"<!-- IF S_ENABLE_POST_REVIEW --> id="enable_post_review" checked="checked"<!-- ENDIF --> /> {L_YES}</label>
<label><input type="radio" class="radio" name="enable_post_review" value="0"<!-- IF not S_ENABLE_POST_REVIEW --> id="enable_post_review" checked="checked"<!-- ENDIF --> /> {L_NO}</label></dd>
</dl>
<dl>
<dt><label for="enable_quick_reply">{L_ENABLE_QUICK_REPLY}:</label><br /><span>{L_ENABLE_QUICK_REPLY_EXPLAIN}</span></dt>
<dd><label><input type="radio" class="radio" name="enable_quick_reply" value="1"<!-- IF S_ENABLE_QUICK_REPLY --> id="enable_quick_reply" checked="checked"<!-- ENDIF --> /> {L_YES}</label>
<label><input type="radio" class="radio" name="enable_quick_reply" value="0"<!-- IF not S_ENABLE_QUICK_REPLY --> id="enable_quick_reply" checked="checked"<!-- ENDIF --> /> {L_NO}</label></dd>
</dl>
<dl>
<dt><label for="enable_indexing">{L_ENABLE_INDEXING}:</label><br /><span>{L_ENABLE_INDEXING_EXPLAIN}</span></dt>
<dd><label><input type="radio" class="radio" name="enable_indexing" value="1"<!-- IF S_ENABLE_INDEXING --> id="enable_indexing" checked="checked"<!-- ENDIF --> /> {L_YES}</label>

View file

@ -0,0 +1,21 @@
<!-- INCLUDE overall_header.html -->
<form id="confirm" method="post" action="{S_COPY_ACTION}">
<fieldset>
<h1>{L_COPY_PERMISSIONS}</h1>
<p>{L_COPY_PERMISSIONS_EXPLAIN}</p>
<p>{L_ACL_LINK}</p>
<dl>
<dt><label for="forum_perm_from">{L_COPY_PERMISSIONS}:</label><br /><span>{L_COPY_PERMISSIONS_EXPLAIN}</span></dt>
<dd><select id="forum_perm_from" name="forum_perm_from"><option value="0">{L_NO_PERMISSIONS}</option>{S_FORUM_OPTIONS}</select></dd>
</dl>
<div style="text-align: center;">{S_FORM_TOKEN}{S_HIDDEN_FIELDS}
<input type="submit" name="update" value="{L_CONTINUE}" class="button2" />&nbsp;
</div>
</fieldset>
</form>
<!-- INCLUDE overall_footer.html -->

View file

@ -55,21 +55,29 @@
</fieldset>
<fieldset>
<legend>{L_GROUP_SETTINGS_SAVE}</legend>
<legend>{L_GROUP_OPTIONS_SAVE}</legend>
<!-- IF S_USER_FOUNDER -->
<dl>
<dt><label for="group_founder_manage">{L_GROUP_FOUNDER_MANAGE}:</label><br /><span>{L_GROUP_FOUNDER_MANAGE_EXPLAIN}</span></dt>
<dd><input name="group_founder_manage" type="checkbox" class="radio" id="group_founder_manage"{GROUP_FOUNDER_MANAGE} /></dd>
<dd><input name="group_founder_manage" type="checkbox" value="1" class="radio" id="group_founder_manage"{GROUP_FOUNDER_MANAGE} /></dd>
</dl>
<!-- ENDIF -->
<dl>
<dt><label for="group_skip_auth">{L_GROUP_SKIP_AUTH}:</label><br /><span>{L_GROUP_SKIP_AUTH_EXPLAIN}</span></dt>
<dd><input name="group_skip_auth" type="checkbox" value="1" class="radio" id="group_skip_auth"{GROUP_SKIP_AUTH} /></dd>
</dl>
<dl>
<dt><label for="group_legend">{L_GROUP_LEGEND}:</label></dt>
<dd><input name="group_legend" type="checkbox" class="radio" id="group_legend"{GROUP_LEGEND} /></dd>
<dd><input name="group_legend" type="checkbox" value="1" class="radio" id="group_legend"{GROUP_LEGEND} /></dd>
</dl>
<dl>
<dt><label for="group_receive_pm">{L_GROUP_RECEIVE_PM}:</label><br /><span>{L_GROUP_RECEIVE_PM_EXPLAIN}</span></dt>
<dd><input name="group_receive_pm" type="checkbox" class="radio" id="group_receive_pm"{GROUP_RECEIVE_PM} /></dd>
<dd><input name="group_receive_pm" type="checkbox" value="1" class="radio" id="group_receive_pm"{GROUP_RECEIVE_PM} /></dd>
</dl>
</fieldset>
<fieldset>
<legend>{L_GROUP_SETTINGS_SAVE}</legend>
<dl>
<dt><label for="group_message_limit">{L_GROUP_MESSAGE_LIMIT}:</label><br /><span>{L_GROUP_MESSAGE_LIMIT_EXPLAIN}</span></dt>
<dd><input name="group_message_limit" type="text" id="group_message_limit" maxlength="4" size="4" value="{GROUP_MESSAGE_LIMIT}" /></dd>
@ -80,7 +88,7 @@
</dl>
<dl>
<dt><label for="group_colour">{L_GROUP_COLOR}:</label><br /><span>{L_GROUP_COLOR_EXPLAIN}</span></dt>
<dd><input name="group_colour" type="text" id="group_colour" value="{GROUP_COLOUR}" size="6" maxlength="6" />&nbsp;&nbsp;<span>[ <a href="{U_SWATCH}" onclick="popup(this.href, 636, 150, '_swatch'); return false">{L_COLOUR_SWATCH}</a> ]</span></dd>
<dd><input name="group_colour" type="text" id="group_colour" value="{GROUP_COLOUR}" size="6" maxlength="6" /><!-- IF GROUP_COLOUR -->&nbsp;<span style="background-color: #{GROUP_COLOUR}">&nbsp; &nbsp;</span><!-- ENDIF -->&nbsp;&nbsp;<span>[ <a href="{U_SWATCH}" onclick="popup(this.href, 636, 150, '_swatch'); return false">{L_COLOUR_SWATCH}</a> ]</span></dd>
</dl>
<dl>
<dt><label for="group_rank">{L_GROUP_RANK}:</label></dt>
@ -97,7 +105,7 @@
</dl>
<!-- IF not S_IN_AVATAR_GALLERY -->
<!-- IF S_CAN_UPLOAD -->
<dl>
<dl>
<dt><label for="uploadfile">{L_UPLOAD_AVATAR_FILE}:</label></dt>
<dd><input type="file" id="uploadfile" name="uploadfile" /></dd>
</dl>
@ -115,7 +123,7 @@
<dd><input name="width" type="text" id="width" size="3" value="{AVATAR_WIDTH}" /> <span>px X </span> <input type="text" name="height" size="3" value="{AVATAR_HEIGHT}" /> <span>px</span></dd>
</dl>
<!-- IF S_DISPLAY_GALLERY -->
<dl>
<dl>
<dt><label>{L_AVATAR_GALLERY}:</label></dt>
<dd><input class="button2" type="submit" name="display_gallery" value="{L_DISPLAY_GALLERY}" /></dd>
</dl>
@ -132,7 +140,7 @@
<dl>
<table cellspacing="1">
<!-- BEGIN avatar_row -->
<tr>
<tr>
<!-- BEGIN avatar_column -->
<td class="row1" style="text-align: center;"><img src="{avatar_row.avatar_column.AVATAR_IMAGE}" alt="{avatar_row.avatar_column.AVATAR_NAME}" title="{avatar_row.avatar_column.AVATAR_NAME}" /></td>
<!-- END avatar_column -->
@ -146,11 +154,11 @@
</table>
</dl>
</fieldset>
<fieldset class="quick" style="margin-top: -15px;">
<input class="button2" type="submit" name="cancel" value="{L_CANCEL}" />
</fieldset>
<!-- ENDIF -->
</fieldset>
@ -192,7 +200,7 @@
</tr>
<!-- BEGIN leader -->
<!-- IF leader.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
<td><a href="{leader.U_USER_EDIT}">{leader.USERNAME}</a></td>
<td><!-- IF leader.USERNAME_COLOUR --><a href="{leader.U_USER_EDIT}" style="color: #{leader.USERNAME_COLOUR};" class="username-coloured">{leader.USERNAME}</a><!-- ELSE --><a href="{leader.U_USER_EDIT}">{leader.USERNAME}</a><!-- ENDIF --></td>
<td style="text-align: center;"><!-- IF leader.S_GROUP_DEFAULT -->{L_YES}<!-- ELSE -->{L_NO}<!-- ENDIF --></td>
<td style="text-align: center;">{leader.JOINED}</td>
<td style="text-align: center;">{leader.USER_POSTS}</td>
@ -213,7 +221,7 @@
</tr>
<!-- ELSE -->
<!-- IF member.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
<td><a href="{member.U_USER_EDIT}">{member.USERNAME}</a></td>
<td><!-- IF member.USERNAME_COLOUR --><a href="{member.U_USER_EDIT}" style="color: #{member.USERNAME_COLOUR};" class="username-coloured">{member.USERNAME}</a><!-- ELSE --><a href="{member.U_USER_EDIT}">{member.USERNAME}</a><!-- ENDIF --></td>
<td style="text-align: center;"><!-- IF member.S_GROUP_DEFAULT -->{L_YES}<!-- ELSE -->{L_NO}<!-- ENDIF --></td>
<td style="text-align: center;">{member.JOINED}</td>
<td style="text-align: center;">{member.USER_POSTS}</td>
@ -231,12 +239,12 @@
<div class="pagination">
<a href="#" onclick="jumpto(); return false;" title="{L_JUMP_TO_PAGE}">{S_ON_PAGE}</a> &bull; <span>{PAGINATION}</span>
</div>
<!-- ENDIF -->
<!-- ENDIF -->
<fieldset class="quick">
<select name="action"><option class="sep" value="">{L_SELECT_OPTION}</option>{S_ACTION_OPTIONS}</select>
<input class="button2" type="submit" name="update" value="{L_SUBMIT}" />
<p class="small"><a href="#" onclick="marklist('list', 'mark', true); return false;">{L_MARK_ALL}</a> &bull; <a href="#" onclick="marklist('list', 'mark', false); return false;">{L_UNMARK_ALL}</a></p>
<p class="small"><a href="#" onclick="marklist('list', 'mark', true); return false;">{L_MARK_ALL}</a> &bull; <a href="#" onclick="marklist('list', 'mark', false); return false;">{L_UNMARK_ALL}</a></p>
</fieldset>
<h1>{L_ADD_USERS}</h1>

View file

@ -243,8 +243,8 @@
<td style="text-align: center;">{items.EMOTION}</td>
<!-- ENDIF -->
<td style="text-align: right; white-space: nowrap;">
<!-- IF items.S_FIRST_ROW -->{ICON_MOVE_UP_DISABLED}<!-- ELSE --><a href="{items.U_MOVE_UP}">{ICON_MOVE_UP}</a><!-- ENDIF -->&nbsp;
<!-- IF items.S_LAST_ROW -->{ICON_MOVE_DOWN_DISABLED}<!-- ELSE --><a href="{items.U_MOVE_DOWN}">{ICON_MOVE_DOWN}</a><!-- ENDIF -->
<!-- IF items.S_FIRST_ROW and not PREVIOUS_PAGE -->{ICON_MOVE_UP_DISABLED}<!-- ELSE --><a href="{items.U_MOVE_UP}">{ICON_MOVE_UP}</a><!-- ENDIF -->&nbsp;
<!-- IF items.S_LAST_ROW and not NEXT_PAGE -->{ICON_MOVE_DOWN_DISABLED}<!-- ELSE --><a href="{items.U_MOVE_DOWN}">{ICON_MOVE_DOWN}</a><!-- ENDIF -->
&nbsp;<a href="{items.U_EDIT}">{ICON_EDIT}</a> <a href="{items.U_DELETE}">{ICON_DELETE}</a>
</td>
</tr>
@ -255,7 +255,7 @@
<!-- END items -->
</tbody>
</table>
<div>{PAGINATION}</div>
<p class="quick">
<input class="button2" name="add" type="submit" value="{L_ICON_ADD}" />&nbsp; &nbsp;<input class="button2" type="submit" name="edit" value="{L_ICON_EDIT}" />
</p>

View file

@ -12,7 +12,7 @@
<!-- IF PAGINATION -->
<div class="pagination">
<a href="#" onclick="jumpto(); return false;" title="{L_JUMP_TO_PAGE}">{S_ON_PAGE}</a> &bull; <span>{PAGINATION}</span>
<a href="#" onclick="jumpto(); return false;" title="{L_JUMP_TO_PAGE}">{S_ON_PAGE}</a> &bull; <span>{PAGINATION}</span>
</div>
<!-- ENDIF -->
@ -22,8 +22,8 @@
<th>{L_USERNAME}</th>
<th>{L_JOINED}</th>
<th>{L_INACTIVE_DATE}</th>
<th>{L_INACTIVE_REASON}</th>
<th>{L_LAST_VISIT}</th>
<th>{L_INACTIVE_REASON}</th>
<th>{L_MARK}</th>
</tr>
</thead>
@ -31,11 +31,16 @@
<!-- BEGIN inactive -->
<!-- IF inactive.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
<td><a href="{inactive.U_USER_ADMIN}">{inactive.USERNAME}</a></td>
<td>{inactive.JOINED}</td>
<td>{inactive.INACTIVE_DATE}</td>
<td>{inactive.REASON}</td>
<td>{inactive.LAST_VISIT}</td>
<td style="vertical-align: top;">
{inactive.USERNAME_FULL}
<!-- IF inactive.POSTS --><br />{L_POSTS}: <strong>{inactive.POSTS}</strong> [<a href="{inactive.U_SEARCH_USER}">{L_SEARCH_USER_POSTS}</a>]<!-- ENDIF -->
</td>
<td style="vertical-align: top;">{inactive.JOINED}</td>
<td style="vertical-align: top;">{inactive.INACTIVE_DATE}</td>
<td style="vertical-align: top;">{inactive.LAST_VISIT}</td>
<td style="vertical-align: top;">
{inactive.REASON}
<!-- IF inactive.REMINDED --><br />{inactive.REMINDED_EXPLAIN}<!-- ENDIF -->
<td>&nbsp;<input type="checkbox" class="radio" name="mark[]" value="{inactive.USER_ID}" />&nbsp;</td>
</tr>
<!-- BEGINELSE -->
@ -46,25 +51,25 @@
</tbody>
</table>
<fieldset class="display-options">
{L_DISPLAY_LOG}: &nbsp;{S_LIMIT_DAYS}&nbsp;{L_SORT_BY}: {S_SORT_KEY} {S_SORT_DIR}
<input class="button2" type="submit" value="{L_GO}" name="sort" />
</fieldset>
<hr />
<!-- IF PAGINATION -->
<fieldset class="display-options">
{L_DISPLAY_LOG}: &nbsp;{S_LIMIT_DAYS}&nbsp;{L_SORT_BY}: {S_SORT_KEY} {S_SORT_DIR}<!-- IF PAGINATION -->&nbsp;Users per page: <input class="inputbox autowidth" type="text" name="users_per_page" id="users_per_page" size="3" value="{USERS_PER_PAGE}" /><!-- ENDIF -->
<input class="button2" type="submit" value="{L_GO}" name="sort" />
</fieldset>
<hr />
<!-- IF PAGINATION -->
<div class="pagination">
<a href="#" onclick="jumpto(); return false;" title="{L_JUMP_TO_PAGE}">{S_ON_PAGE}</a> &bull; <span>{PAGINATION}</span>
<a href="#" onclick="jumpto(); return false;" title="{L_JUMP_TO_PAGE}">{S_ON_PAGE}</a> &bull; <span>{PAGINATION}</span>
</div>
<!-- ENDIF -->
<fieldset class="quick">
<select name="action">{S_INACTIVE_OPTIONS}</select>
<input class="button2" type="submit" name="submit" value="{L_SUBMIT}" />
<p class="small"><a href="#" onclick="marklist('inactive', 'mark', true); return false;">{L_MARK_ALL}</a> &bull; <a href="#" onclick="marklist('inactive', 'mark', false); return false;">{L_UNMARK_ALL}</a></p>
{S_FORM_TOKEN}
</fieldset>
<!-- ENDIF -->
<fieldset class="quick">
<select name="action">{S_INACTIVE_OPTIONS}</select>
<input class="button2" type="submit" name="submit" value="{L_SUBMIT}" />
<p class="small"><a href="#" onclick="marklist('inactive', 'mark', true); return false;">{L_MARK_ALL}</a> &bull; <a href="#" onclick="marklist('inactive', 'mark', false); return false;">{L_UNMARK_ALL}</a></p>
{S_FORM_TOKEN}
</fieldset>
</form>

View file

@ -8,12 +8,18 @@
<form id="list" method="post" action="{U_ACTION}">
<fieldset class="display-options" style="float: left">
{L_SEARCH_KEYWORDS}: <input type="text" name="keywords" value="{S_KEYWORDS}" />&nbsp;<input type="submit" class="button2" name="filter" value="{L_SEARCH}" />
</fieldset>
<!-- IF PAGINATION -->
<div class="pagination">
<div class="pagination" style="float: right; margin: 15px 0 2px 0">
<a href="#" onclick="jumpto(); return false;" title="{L_JUMP_TO_PAGE}">{S_ON_PAGE}</a> &bull; <span>{PAGINATION}</span>
</div>
<!-- ENDIF -->
<div class="clearfix">&nbsp;</div><br style="clear: both;" />
<!-- IF .log -->
<table cellspacing="1">
<thead>
@ -22,13 +28,14 @@
<th>{L_IP}</th>
<th>{L_TIME}</th>
<th>{L_ACTION}</th>
<th>{L_MARK}</th>
<!-- IF S_CLEARLOGS -->
<th>{L_MARK}</th>
<!-- ENDIF -->
</tr>
</thead>
<tbody>
<!-- BEGIN log -->
<!-- IF log.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
<td>
{log.USERNAME}
<!-- IF log.REPORTEE_USERNAME -->
@ -38,32 +45,33 @@
<td style="text-align: center;">{log.IP}</td>
<td style="text-align: center;">{log.DATE}</td>
<td>{log.ACTION}<!-- IF log.DATA --><br /><span>{log.DATA}</span><!-- ENDIF --></td>
<td style="text-align: center;"><input type="checkbox" class="radio" name="mark[]" value="{log.ID}" /></td>
<!-- IF S_CLEARLOGS -->
<td style="text-align: center;"><input type="checkbox" class="radio" name="mark[]" value="{log.ID}" /></td>
<!-- ENDIF -->
</tr>
<!-- END log -->
</tbody>
</table>
<!-- ELSE -->
<!-- IF PAGINATION -->
<div class="pagination">
<a href="#" onclick="jumpto(); return false;" title="{L_JUMP_TO_PAGE}">{S_ON_PAGE}</a> &bull; <span>{PAGINATION}</span>
</div>
<!-- ENDIF -->
<!-- ELSE -->
<div class="errorbox">
<p>{L_NO_ENTRIES}</p>
</div>
<!-- ENDIF -->
<fieldset class="display-options">
{L_DISPLAY_LOG}: &nbsp;{S_LIMIT_DAYS}&nbsp;{L_SORT_BY}: {S_SORT_KEY} {S_SORT_DIR}
<input class="button2" type="submit" value="{L_GO}" name="sort" />
{S_FORM_TOKEN}
</fieldset>
<hr />
<!-- IF PAGINATION -->
<div class="pagination">
<a href="#" onclick="jumpto(); return false;" title="{L_JUMP_TO_PAGE}">{S_ON_PAGE}</a> &bull; <span>{PAGINATION}</span>
</div>
<!-- ENDIF -->
<!-- IF S_SHOW_FORUMS -->
<fieldset class="quick">
{L_SELECT_FORUM}: <select name="f" onchange="if(this.options[this.selectedIndex].value != -1){ this.form.submit(); }">{S_FORUM_BOX}</select>
@ -71,7 +79,7 @@
</fieldset>
<!-- ENDIF -->
<!-- IF S_CLEARLOGS -->
<!-- IF .log and S_CLEARLOGS -->
<fieldset class="quick">
<input class="button2" type="submit" name="delall" value="{L_DELETE_ALL}" />&nbsp;
<input class="button2" type="submit" name="delmarked" value="{L_DELETE_MARKED}" /><br />
@ -79,7 +87,6 @@
</fieldset>
<!-- ENDIF -->
</form>
<!-- INCLUDE overall_footer.html -->
<!-- INCLUDE overall_footer.html -->

View file

@ -14,6 +14,19 @@
<p>{L_ADMIN_INTRO}</p>
<!-- IF S_VERSIONCHECK_FAIL -->
<div class="errorbox notice">
<p>{L_VERSIONCHECK_FAIL}</p>
<p><a href="{U_VERSIONCHECK_FORCE}">{L_VERSIONCHECK_FORCE_UPDATE}</a> &middot; <a href="{U_VERSIONCHECK}">{L_MORE_INFORMATION}</a></p>
</div>
<!-- ELSEIF not S_VERSION_UP_TO_DATE -->
<div class="errorbox">
<p>{L_VERSION_NOT_UP_TO_DATE_TITLE}</p>
<p><a href="{U_VERSIONCHECK_FORCE}">{L_VERSIONCHECK_FORCE_UPDATE}</a> &middot; <a href="{U_VERSIONCHECK}">{L_MORE_INFORMATION}</a></p>
</div>
<!-- ENDIF -->
<!-- IF S_REMOVE_INSTALL -->
<div class="errorbox">
<h3>{L_WARNING}</h3>
@ -85,7 +98,9 @@
</tr>
<tr>
<td>{L_BOARD_VERSION}: </td>
<td><strong>{BOARD_VERSION}</strong></td>
<td>
<strong><a href="{U_VERSIONCHECK}" <!-- IF S_VERSION_UP_TO_DATE -->style="color: #228822;"<!-- ELSE -->style="color: #BC2A4D;"<!-- ENDIF --> title="{L_MORE_INFORMATION}">{BOARD_VERSION}</a></strong> [&nbsp;<a href="{U_VERSIONCHECK_FORCE}">{L_VERSIONCHECK_FORCE_UPDATE}</a>&nbsp;]
</td>
<!-- IF S_TOTAL_ORPHAN -->
<td>{L_NUMBER_ORPHAN}: </td>
<td><strong>{TOTAL_ORPHAN}</strong></td>
@ -137,6 +152,12 @@
</form>
<!-- IF S_FOUNDER -->
<form id="action_purge_sessions_form" method="post" action="{U_ACTION}">
<dl>
<dt><label for="action_purge_sessions">{L_PURGE_SESSIONS}</label><br /><span>{L_PURGE_SESSIONS_EXPLAIN}</span></dt>
<dd><input type="hidden" name="action" value="purge_sessions" /><input class="button2" type="submit" id="action_purge_sessions" name="action_purge_sessions" value="{L_RUN}" /></dd>
</dl>
</form>
<form id="action_purge_cache_form" method="post" action="{U_ACTION}">
<dl>
<dt><label for="action_purge_cache">{L_PURGE_CACHE}</label><br /><span>{L_PURGE_CACHE_EXPLAIN}</span></dt>
@ -193,19 +214,24 @@
<th>{L_USERNAME}</th>
<th>{L_JOINED}</th>
<th>{L_INACTIVE_DATE}</th>
<th>{L_INACTIVE_REASON}</th>
<th>{L_LAST_VISIT}</th>
<th>{L_INACTIVE_REASON}</th>
</tr>
</thead>
<tbody>
<!-- BEGIN inactive -->
<!-- IF inactive.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
<td><a href="{inactive.U_USER_ADMIN}">{inactive.USERNAME}</a></td>
<td>{inactive.JOINED}</td>
<td>{inactive.INACTIVE_DATE}</td>
<td>{inactive.REASON}</td>
<td>{inactive.LAST_VISIT}</td>
<td style="vertical-align: top;">
{inactive.USERNAME_FULL}
<!-- IF inactive.POSTS --><br />{L_POSTS}: <strong>{inactive.POSTS}</strong> [<a href="{inactive.U_SEARCH_USER}">{L_SEARCH_USER_POSTS}</a>]<!-- ENDIF -->
</td>
<td style="vertical-align: top;">{inactive.JOINED}</td>
<td style="vertical-align: top;">{inactive.INACTIVE_DATE}</td>
<td style="vertical-align: top;">{inactive.LAST_VISIT}</td>
<td style="vertical-align: top;">
{inactive.REASON}
<!-- IF inactive.REMINDED --><br />{inactive.REMINDED_EXPLAIN}<!-- ENDIF -->
</tr>
<!-- BEGINELSE -->
<tr>

View file

@ -55,6 +55,10 @@
<dt><label for="field_show_on_reg">{L_DISPLAY_AT_REGISTER}:</label><br /><span>{L_DISPLAY_AT_REGISTER_EXPLAIN}</span></dt>
<dd><input type="checkbox" class="radio" id="field_show_on_reg" name="field_show_on_reg" value="1"<!-- IF S_SHOW_ON_REG --> checked="checked"<!-- ENDIF --> /></dd>
</dl>
<dl>
<dt><label for="field_show_on_vt">{L_DISPLAY_ON_VT}:</label><br /><span>{L_DISPLAY_ON_VT_EXPLAIN}</span></dt>
<dd><input type="checkbox" class="radio" id="field_show_on_vt" name="field_show_on_vt" value="1"<!-- IF S_SHOW_ON_VT --> checked="checked"<!-- ENDIF --> /></dd>
</dl>
<dl>
<dt><label for="field_required">{L_REQUIRED_FIELD}:</label><br /><span>{L_REQUIRED_FIELD_EXPLAIN}</span></dt>
<dd><input type="checkbox" class="radio" id="field_required" name="field_required" value="1"<!-- IF S_FIELD_REQUIRED --> checked="checked"<!-- ENDIF --> /></dd>
@ -127,7 +131,7 @@
<fieldset class="quick" style="float: {S_CONTENT_FLOW_BEGIN};">
<input class="button1" type="submit" name="prev" value="{L_PROFILE_BASIC_OPTIONS}" />
</fieldset>
<fieldset class="quick" style="float: {S_CONTENT_FLOW_END};">
{S_HIDDEN_FIELDS}
{S_FORM_TOKEN}
@ -151,15 +155,15 @@
<fieldset class="quick" style="float: {S_CONTENT_FLOW_BEGIN};">
<input class="button1" type="submit" name="prev" value="{L_PROFILE_TYPE_OPTIONS}" />
</fieldset>
<fieldset class="quick" style="float: {S_CONTENT_FLOW_END};">
{S_HIDDEN_FIELDS}
<input class="button1" type="submit" name="save" value="{L_SAVE}" />
{S_FORM_TOKEN}
</fieldset>
<!-- ENDIF -->
</form>
<!-- ELSE -->
@ -194,14 +198,14 @@
{ICON_MOVE_UP_DISABLED}
<a href="{fields.U_MOVE_DOWN}">{ICON_MOVE_DOWN}</a>
<!-- ELSEIF not fields.S_FIRST_ROW && not fields.S_LAST_ROW-->
<a href="{fields.U_MOVE_UP}">{ICON_MOVE_UP}</a>
<a href="{fields.U_MOVE_DOWN}">{ICON_MOVE_DOWN}</a>
<a href="{fields.U_MOVE_UP}">{ICON_MOVE_UP}</a>
<a href="{fields.U_MOVE_DOWN}">{ICON_MOVE_DOWN}</a>
<!-- ELSEIF fields.S_LAST_ROW && not fields.S_FIRST_ROW -->
<a href="{fields.U_MOVE_UP}">{ICON_MOVE_UP}</a>
{ICON_MOVE_DOWN_DISABLED}
{ICON_MOVE_DOWN_DISABLED}
<!-- ENDIF -->
<!-- IF not fields.S_NEED_EDIT -->
<a href="{fields.U_EDIT}">{ICON_EDIT}</a>
<a href="{fields.U_EDIT}">{ICON_EDIT}</a>
<!-- ELSE -->
{ICON_EDIT_DISABLED}
<!-- ENDIF -->
@ -209,12 +213,16 @@
</td>
</tr>
<!-- BEGINELSE -->
<tr class="row3">
<td colspan="4">{L_ACP_NO_ITEMS}</td>
</tr>
<!-- END fields -->
</tbody>
</table>
<form id="profile_fields" method="post" action="{U_ACTION}">
<fieldset class="quick">
<input class="text small" type="text" name="field_ident" /> <select name="field_type">{S_TYPE_OPTIONS}</select>
<input class="button1" type="submit" name="submit" value="{L_CREATE_NEW_FIELD}" />

View file

@ -0,0 +1,71 @@
<!-- INCLUDE overall_header.html -->
<a name="maincontent"></a>
<h1>{L_SEND_STATISTICS}</h1>
<p>{L_EXPLAIN_SEND_STATISTICS}</p>
<script type="text/javascript">
//<![CDATA[
var iframect = 0;
function iframe_updated()
{
if (iframect++ == 0)
{
return;
}
dE('questionnaire-form', -1);
dE('questionnaire-thanks', 1);
}
//]]>
</script>
<iframe onload="iframe_updated();" name="questionaire_result" style="display: none;"></iframe>
<form action="{U_COLLECT_STATS}" method="post" target="questionaire_result" id="questionnaire-form">
<p><a href="{U_ACP_MAIN}">{L_DONT_SEND_STATISTICS}</a></p>
<p>{L_EXPLAIN_SHOW_STATISTICS}</p>
<p id="show-button"><input type="button" class="button2" onclick="dE('configlist', 1); dE('show-button', -1);" value="{L_SHOW_STATISTICS}" /></p>
<div id="configlist">
<input type="button" class="button2" onclick="dE('show-button', 1); dE('configlist', -1);" value="{L_HIDE_STATISTICS}" />
<p class="submit-buttons">
<input class="button1" type="submit" id="submit" name="submit" value="{L_SEND_STATISTICS}" />
</p>
<!-- BEGIN providers -->
<fieldset>
<legend>{providers.NAME}</legend>
<!-- BEGIN values -->
<dl>
<dt>{providers.values.KEY}</dt>
<dd>{providers.values.VALUE}</dd>
</dl>
<!-- END values -->
</fieldset>
<!-- END providers -->
</div>
<p class="submit-buttons">
<input type="hidden" name="systemdata" value="{RAW_DATA}" />
<input class="button1" type="submit" id="submit" name="submit" value="{L_SEND_STATISTICS}" />
</p>
</form>
<div id="questionnaire-thanks" class="successbox">
<p><strong>{L_THANKS_SEND_STATISTICS}</strong><br /><br /><a href="{U_ACP_MAIN}">&laquo; {L_GO_ACP_MAIN}</a></p>
</div>
<script type="text/javascript">
//<![CDATA[
dE('configlist', -1);
dE('questionnaire-thanks', -1);
//]]>
</script>
<!-- INCLUDE overall_footer.html -->

View file

@ -10,11 +10,11 @@
<!-- IF S_UP_TO_DATE and S_UP_TO_DATE_AUTO -->
<div class="successbox">
<p>{L_VERSION_UP_TO_DATE_ACP}</p>
<p>{L_VERSION_UP_TO_DATE_ACP} - <a href="{U_VERSIONCHECK_FORCE}">{L_VERSIONCHECK_FORCE_UPDATE}</a></p>
</div>
<!-- ELSE -->
<div class="errorbox">
<p>{L_VERSION_NOT_UP_TO_DATE_ACP}</p>
<p>{L_VERSION_NOT_UP_TO_DATE_ACP} - <a href="{U_VERSIONCHECK_FORCE}">{L_VERSIONCHECK_FORCE_UPDATE}</a></p>
</div>
<!-- ENDIF -->

View file

@ -83,6 +83,10 @@
<!-- INCLUDE acp_users_feedback.html -->
<!-- ELSEIF S_WARNINGS -->
<!-- INCLUDE acp_users_warnings.html -->
<!-- ELSEIF S_PROFILE -->
<!-- INCLUDE acp_users_profile.html -->
@ -131,8 +135,8 @@
<!-- ELSE -->
<!-- IF group.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
<td><a href="{group.U_EDIT_GROUP}">{group.GROUP_NAME}</a></td>
<td><!-- IF group.S_NO_DEFAULT --><a href="{group.U_DEFAULT}">{L_GROUP_DEFAULT}</a><!-- ELSE --><strong>{L_GROUP_DEFAULT}</strong><!-- ENDIF --></td>
<td><!-- IF not group.S_SPECIAL_GROUP --><a href="{group.U_DEMOTE_PROMOTE}">{group.L_DEMOTE_PROMOTE}</a><!-- ELSE -->&nbsp;<!-- ENDIF --></td>
<td><!-- IF group.S_IS_MEMBER --><!-- IF group.S_NO_DEFAULT --><a href="{group.U_DEFAULT}">{L_GROUP_DEFAULT}</a><!-- ELSE --><strong>{L_GROUP_DEFAULT}</strong><!-- ENDIF --><!-- ELSEIF not group.S_IS_MEMBER and group.U_APPROVE --><a href="{group.U_APPROVE}">{L_GROUP_APPROVE}</a><!-- ELSE -->&nbsp;<!-- ENDIF --></td>
<td><!-- IF group.S_IS_MEMBER and not group.S_SPECIAL_GROUP --><a href="{group.U_DEMOTE_PROMOTE}">{group.L_DEMOTE_PROMOTE}</a><!-- ELSE -->&nbsp;<!-- ENDIF --></td>
<td><a href="{group.U_DELETE}">{L_GROUP_DELETE}</a></td>
</tr>
<!-- ENDIF -->

View file

@ -8,11 +8,13 @@
<dd><label><input type="checkbox" class="radio" name="delete" /> {L_DELETE_AVATAR}</label></dd>
</dl>
<!-- IF not S_IN_AVATAR_GALLERY -->
<!-- IF S_CAN_UPLOAD -->
<!-- IF S_UPLOAD_FILE -->
<dl>
<dt><label for="uploadfile">{L_UPLOAD_AVATAR_FILE}:</label></dt>
<dd><input type="hidden" name="MAX_FILE_SIZE" value="{AVATAR_MAX_FILESIZE}" /><input type="file" id="uploadfile" name="uploadfile" /></dd>
</dl>
<!-- ENDIF -->
<!-- IF S_REMOTE_UPLOAD -->
<dl>
<dt><label for="uploadurl">{L_UPLOAD_AVATAR_URL}:</label><br /><span>{L_UPLOAD_AVATAR_URL_EXPLAIN}</span></dt>
<dd><input name="uploadurl" type="text" id="uploadurl" value="" /></dd>

View file

@ -93,7 +93,7 @@
// ]]>
</script>
</dt>
<dd style="margin-left: 90px;"><textarea name="signature" rows="10" cols="60" style="width: 95%;" onselect="storeCaret(this);" onclick="storeCaret(this);" onkeyup="storeCaret(this);">{SIGNATURE}</textarea></dd>
<dd style="margin-left: 90px;"><textarea name="signature" rows="10" cols="60" style="width: 95%;" onselect="storeCaret(this);" onclick="storeCaret(this);" onkeyup="storeCaret(this);" onfocus="initInsertions();">{SIGNATURE}</textarea></dd>
<dd style="margin-left: 90px; margin-top: 5px;">
<!-- IF S_BBCODE_ALLOWED -->
<label><input type="checkbox" class="radio" name="disable_bbcode"{S_BBCODE_CHECKED} /> {L_DISABLE_BBCODE}</label>

View file

@ -0,0 +1,39 @@
<form id="list" method="post" action="{U_ACTION}">
<!-- IF .warn -->
<table cellspacing="1">
<thead>
<tr>
<th>{L_REPORT_BY}</th>
<th>{L_TIME}</th>
<th>{L_FEEDBACK}</th>
<!-- IF S_CLEARLOGS --><th>{L_MARK}</th><!-- ENDIF -->
</tr>
</thead>
<tbody>
<!-- BEGIN warn -->
<!-- IF warn.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
<td>{warn.USERNAME}</td>
<td style="text-align: center; nowrap: nowrap;">{warn.DATE}</td>
<td>{warn.ACTION}</td>
<!-- IF S_CLEARLOGS --><td style="text-align: center;"><input type="checkbox" class="radio" name="mark[]" value="{warn.ID}" /></td><!-- ENDIF -->
</tr>
<!-- END warn -->
</tbody>
</table>
<!-- ELSE -->
<div class="errorbox">
<p>{L_NO_WARNINGS}</p>
</div>
<!-- ENDIF -->
<!-- IF S_CLEARLOGS -->
<fieldset class="quick">
<input class="button2" type="submit" name="delall" value="{L_DELETE_ALL}" />&nbsp;
<input class="button2" type="submit" name="delmarked" value="{L_DELETE_MARKED}" />
<p class="small"><a href="#" onclick="marklist('list', 'mark', true);">{L_MARK_ALL}</a> &bull; <a href="#" onclick="marklist('list', 'mark', false);">{L_UNMARK_ALL}</a></p>
</fieldset>
<!-- ENDIF -->
{S_FORM_TOKEN}
</form>

View file

@ -121,6 +121,17 @@ a:active {
font-weight: bold;
}
/* List items */
ul, ol {
list-style-position: inside;
margin-left: 1em;
}
li {
display: list-item;
list-style-type: inherit;
}
/* Main blocks
---------------------------------------- */
#wrap {
@ -184,6 +195,7 @@ a:active {
width: 76%;
margin: 0 0 0 3%;
min-height: 350px;
overflow-y: auto;
}
.rtl #main {

View file

@ -0,0 +1,4 @@
<dl>
<dt><label for="captcha_preview">{L_PREVIEW}:</label><br /><span>{L_CAPTCHA_PREVIEW_EXPLAIN}</span></dt>
<dd><img src="{CONFIRM_IMAGE}" alt="{L_PREVIEW}" width="360" height="96" id="captcha_preview" /></dd>
</dl>

View file

@ -0,0 +1,72 @@
<!-- INCLUDE overall_header.html -->
<a name="maincontent"></a>
<a href="{U_ACTION}" style="float: {S_CONTENT_FLOW_END};">&laquo; {L_BACK}</a>
<h1>{L_ACP_VC_SETTINGS}</h1>
<p>{L_ACP_VC_SETTINGS_EXPLAIN}</p>
<form id="acp_captcha" method="post" action="{U_ACTION}">
<fieldset>
<legend>{L_GENERAL_OPTIONS}</legend>
<dl>
<dt><label for="captcha_gd_foreground_noise">{L_CAPTCHA_GD_FOREGROUND_NOISE}:</label><br /><span>{L_CAPTCHA_GD_FOREGROUND_NOISE_EXPLAIN}</span></dt>
<dd><label><input id="captcha_gd_foreground_noise" name="captcha_gd_foreground_noise" value="1" class="radio" type="radio"<!-- IF CAPTCHA_GD_FOREGROUND_NOISE --> checked="checked"<!-- ENDIF --> /> {L_YES}</label>
<label><input name="captcha_gd_foreground_noise" value="0" class="radio" type="radio"<!-- IF not CAPTCHA_GD_FOREGROUND_NOISE --> checked="checked"<!-- ENDIF --> /> {L_NO}</label></dd>
</dl>
<dl>
<dt><label for="captcha_gd_x_grid">{L_CAPTCHA_GD_X_GRID}:</label><br /><span>{L_CAPTCHA_GD_X_GRID_EXPLAIN}</span></dt>
<dd><input id="captcha_gd_x_grid" name="captcha_gd_x_grid" value="{CAPTCHA_GD_X_GRID}" type="text" /></dd>
</dl>
<dl>
<dt><label for="captcha_gd_y_grid">{L_CAPTCHA_GD_Y_GRID}:</label><br /><span>{L_CAPTCHA_GD_Y_GRID_EXPLAIN}</span></dt>
<dd><input id="captcha_gd_y_grid" name="captcha_gd_y_grid" value="{CAPTCHA_GD_Y_GRID}" type="text" /></dd>
</dl>
<dl>
<dt><label for="captcha_gd_wave">{L_CAPTCHA_GD_WAVE}:</label><br /><span>{L_CAPTCHA_GD_WAVE_EXPLAIN}</span></dt>
<dd><label><input id="captcha_gd_wave" name="captcha_gd_wave" value="1" class="radio" type="radio"<!-- IF CAPTCHA_GD_WAVE --> checked="checked"<!-- ENDIF --> /> {L_YES}</label>
<label><input name="captcha_gd_wave" value="0" class="radio" type="radio"<!-- IF not CAPTCHA_GD_WAVE --> checked="checked"<!-- ENDIF --> /> {L_NO}</label>
</dd>
</dl>
<dl>
<dt><label for="captcha_gd_3d_noise">{L_CAPTCHA_GD_3D_NOISE}:</label><br /><span>{L_CAPTCHA_GD_3D_NOISE_EXPLAIN}</span></dt>
<dd><label><input id="captcha_gd_3d_noise" name="captcha_gd_3d_noise" value="1" class="radio" type="radio"<!-- IF CAPTCHA_GD_3D_NOISE --> checked="checked"<!-- ENDIF --> /> {L_YES}</label>
<label><input name="captcha_gd_3d_noise" value="0" class="radio" type="radio"<!-- IF not CAPTCHA_GD_3D_NOISE --> checked="checked"<!-- ENDIF --> /> {L_NO}</label>
</dd>
</dl>
<dl>
<dt><label for="captcha_gd_fonts">{L_CAPTCHA_GD_FONTS}:</label><br /><span>{L_CAPTCHA_GD_FONTS_EXPLAIN}</span></dt>
<dd><label><input id="captcha_gd_fonts" name="captcha_gd_fonts" value="1" class="radio" type="radio"<!-- IF CAPTCHA_GD_FONTS == 1 --> checked="checked"<!-- ENDIF --> /> {L_CAPTCHA_FONT_DEFAULT}</label>
<label><input name="captcha_gd_fonts" value="2" class="radio" type="radio"<!-- IF CAPTCHA_GD_FONTS == 2 --> checked="checked"<!-- ENDIF --> /> {L_CAPTCHA_FONT_NEW}</label>
<label><input name="captcha_gd_fonts" value="3" class="radio" type="radio"<!-- IF CAPTCHA_GD_FONTS == 3 --> checked="checked"<!-- ENDIF --> /> {L_CAPTCHA_FONT_LOWER}</label>
</dd>
</dl>
</fieldset>
<fieldset>
<legend>{L_PREVIEW}</legend>
<!-- IF CAPTCHA_PREVIEW -->
<!-- INCLUDE {CAPTCHA_PREVIEW} -->
<!-- ENDIF -->
</fieldset>
<fieldset class="submit-buttons">
<legend>{L_SUBMIT}</legend>
<input class="button1" type="submit" id="submit" name="submit" value="{L_SUBMIT}" />&nbsp;
<input class="button2" type="reset" id="reset" name="reset" value="{L_RESET}" />&nbsp;
<input class="button2" type="submit" id="preview" name="preview" value="{L_PREVIEW}" />&nbsp;
<input type="hidden" name="select_captcha" value="{CAPTCHA_NAME}" />
<input type="hidden" name="configure" value="1" />
{S_FORM_TOKEN}
</fieldset>
</form>
<!-- INCLUDE overall_footer.html -->

View file

@ -0,0 +1,92 @@
<!-- INCLUDE overall_header.html -->
<a name="maincontent"></a>
<a href="<!-- IF U_LIST -->{U_LIST}<!-- ELSE -->{U_ACTION}<!-- ENDIF -->" style="float: {S_CONTENT_FLOW_END};">&laquo; {L_BACK}</a>
<h1>{L_QUESTIONS}</h1>
<p>{L_QUESTIONS_EXPLAIN}</p>
<!-- IF S_LIST -->
<form id="captcha_qa" method="post" action="{U_ACTION}">
<fieldset class="tabulated">
<legend>{L_QUESTIONS}</legend>
<table cellspacing="1">
<thead>
<tr>
<th colspan="3">{L_QUESTIONS}</th>
</tr>
<tr class="row3">
<td style="text-align: center;">{L_QUESTION_TEXT}</td>
<td style="width: 5%; text-align: center;">{L_QUESTION_LANG}</td>
<td style="vertical-align: top; width: 50px; text-align: center; white-space: nowrap;">{L_ACTION}</td>
</tr>
</thead>
<tbody>
<!-- BEGIN questions -->
<!-- IF questions.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
<td style="text-align: left;">{questions.QUESTION_TEXT}</td>
<td style="text-align: center;">{questions.QUESTION_LANG}</td>
<td style="text-align: center;"><a href="{questions.U_EDIT}">{ICON_EDIT}</a>&nbsp;<a href="{questions.U_DELETE}">{ICON_DELETE}</a></td>
</tr>
<!-- END questions -->
</tbody>
</table>
<fieldset class="quick">
<input class="button1" type="submit" name="add" value="{L_ADD}" />
<input type="hidden" name="action" value="add" />
<input type="hidden" name="configure" value="1" />
<input type="hidden" name="select_captcha" value="{CLASS}" />
{S_FORM_TOKEN}
</fieldset>
{S_FORM_TOKEN}
</fieldset>
</form>
<!-- ELSE -->
<!-- IF S_ERROR -->
<div class="errorbox">
<h3>{L_WARNING}</h3>
<p>{L_QA_ERROR_MSG}</p>
</div>
<!-- ENDIF -->
<form id="captcha_qa" method="post" action="{U_ACTION}">
<fieldset>
<legend>{L_EDIT_QUESTION}</legend>
<dl>
<dt><label for="strict">{L_QUESTION_STRICT}:</label><br /><span>{L_QUESTION_STRICT_EXPLAIN}</span></dt>
<dd><label><input type="radio" class="radio" name="strict" value="1"<!-- IF STRICT --> id="strict" checked="checked"<!-- ENDIF --> /> {L_YES}</label>
<label><input type="radio" class="radio" name="strict" value="0"<!-- IF not STRICT --> id="strict" checked="checked"<!-- ENDIF --> /> {L_NO}</label></dd>
</dl>
<dl>
<dt><label for="lang_iso">{L_QUESTION_LANG}</label><br /><span>{L_QUESTION_LANG_EXPLAIN}</span></dt>
<dd><select id="lang_iso" name="lang_iso"><!-- BEGIN langs --><option value="{langs.ISO}" <!-- IF langs.ISO == LANG_ISO --> selected="selected" <!-- ENDIF -->>{langs.NAME}</option><!-- END langs --></select></dd>
</dl>
<dl>
<dt><label for="question_text">{L_QUESTION_TEXT}</label><br /><span>{L_QUESTION_TEXT_EXPLAIN}</span></dt>
<dd><input id="question_text" maxlength="255" size="60" name="question_text" type="text" value="{QUESTION_TEXT}" /></dd>
</dl>
<dl>
<dt><label for="answers">{L_QUESTION_ANSWERS}</label><br /><span>{L_ANSWERS_EXPLAIN}</span></dt>
<dd><textarea id="answers" style="word-wrap: normal; overflow-x: scroll;" name="answers" rows="15" cols="800" >{ANSWERS}</textarea></dd>
</dl>
</fieldset>
<fieldset class="quick">
<input class="button1" type="submit" name="submit" value="{L_SUBMIT}" />
<input type="hidden" name="question_id" value="{QUESTION_ID}" />
<input type="hidden" name="action" value="add" />
<input type="hidden" name="configure" value="1" />
<input type="hidden" name="select_captcha" value="{CLASS}" />
{S_FORM_TOKEN}
</fieldset>
</form>
<!-- ENDIF -->
<!-- INCLUDE overall_footer.html -->

View file

@ -0,0 +1,7 @@
<dl>
<dt><label for="answer">{L_CONFIRM_QUESTION}:</label><br /><span>{L_CONFIRM_QUESTION_EXPLAIN}</span></dt>
<dd>
<input type="text" tabindex="10" name="answer" id="answer" size="45" class="inputbox autowidth" title="{L_ANSWER}" />
</dd>
</dl>

View file

@ -0,0 +1,25 @@
<!-- IF S_RECAPTCHA_AVAILABLE -->
<dl>
<dd>
<script type="text/javascript" src="{RECAPTCHA_SERVER}/challenge?k={RECAPTCHA_PUBKEY}{RECAPTCHA_ERRORGET}">
// <![CDATA[
var RecaptchaOptions = {
lang : {L_RECAPTCHA_LANG}
};
// ]]>
</script>
<noscript>
<div>
<object data="{RECAPTCHA_SERVER}/noscript?k={RECAPTCHA_PUBKEY}{RECAPTCHA_ERRORGET}" type="text/html" height="300" width="500"></object><br />
<textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
<input type="hidden" name="recaptcha_response_field" value="manual_challenge" />
</div>
</noscript>
</dd>
</dl>
<!-- ELSE -->
{L_RECAPTCHA_NOT_AVAILABLE}
<!-- ENDIF -->

View file

@ -0,0 +1,48 @@
<!-- INCLUDE overall_header.html -->
<a name="maincontent"></a>
<h1>{L_ACP_VC_SETTINGS}</h1>
<p>{L_ACP_VC_SETTINGS_EXPLAIN}</p>
<form id="acp_captcha" method="post" action="{U_ACTION}">
<fieldset>
<legend>{L_GENERAL_OPTIONS}</legend>
<dl>
<dt><label for="recaptcha_pubkey">{L_RECAPTCHA_PUBLIC}:</label><br /><span>{L_RECAPTCHA_PUBLIC_EXPLAIN}</span></dt>
<dd><input id="recaptcha_pubkey" name="recaptcha_pubkey" value="{RECAPTCHA_PUBKEY}" size="50" type="text" /></dd>
</dl>
<dl>
<dt><label for="recaptcha_privkey">{L_RECAPTCHA_PRIVATE}:</label><br /><span>{L_RECAPTCHA_PRIVATE_EXPLAIN}</span></dt>
<dd><input id="recaptcha_privkey" name="recaptcha_privkey" value="{RECAPTCHA_PRIVKEY}" size="50" type="text" /></dd>
</dl>
</fieldset>
<fieldset>
<legend>{L_PREVIEW}</legend>
<!-- IF PREVIEW -->
<div class="successbox">
<h3>{L_WARNING}</h3>
<p>{L_CAPTCHA_PREVIEW_MSG}</p>
</div>
<!-- ENDIF -->
<!-- INCLUDE {CAPTCHA_PREVIEW} -->
</fieldset>
<fieldset class="submit-buttons">
<legend>{L_SUBMIT}</legend>
<input class="button1" type="submit" id="submit" name="submit" value="{L_SUBMIT}" />&nbsp;
<input class="button2" type="reset" id="reset" name="reset" value="{L_RESET}" />&nbsp;
<input type="hidden" name="select_captcha" value="{CAPTCHA_NAME}" />
<input type="hidden" name="configure" value="1" />
{S_FORM_TOKEN}
</fieldset>
</form>
<!-- INCLUDE overall_footer.html -->

View file

@ -16,7 +16,6 @@ var is_ie = ((clientPC.indexOf('msie') != -1) && (clientPC.indexOf('opera') == -
var is_win = ((clientPC.indexOf('win') != -1) || (clientPC.indexOf('16bit') != -1));
var baseHeight;
window.onload = initInsertions;
/**
* Shows the help messages in the helpline window
@ -259,7 +258,7 @@ function addquote(post_id, username)
*/
function mozWrap(txtarea, open, close)
{
var selLength = txtarea.textLength;
var selLength = (typeof(txtarea.textLength) == 'undefined') ? txtarea.value.length : txtarea.textLength;
var selStart = txtarea.selectionStart;
var selEnd = txtarea.selectionEnd;
var scrollTop = txtarea.scrollTop;

View file

@ -2,6 +2,7 @@
</div>
</div>
<span class="corners-bottom"><span></span></span>
<div class="clear"></div>
</div>
</div>
</div>

View file

@ -219,8 +219,7 @@
<!-- IF new.S_CUSTOM --><br /><span><em>{L_FILE_USED}: </em>{new.CUSTOM_ORIGINAL}</span><!-- ENDIF -->
</dt>
<dd style="margin-left: 60%;">
<!-- IF not new.S_BINARY -->[ <a href="{new.U_SHOW_DIFF}" onclick="diff_popup(this.href); return false;">{new.L_SHOW_DIFF}</a>
<!-- ELSE -->{L_BINARY_FILE}<!-- ENDIF -->
<!-- IF not new.S_BINARY -->[<a href="{new.U_SHOW_DIFF}" onclick="diff_popup(this.href); return false;">{new.L_SHOW_DIFF}</a>]<!-- ELSE -->{L_BINARY_FILE}<!-- ENDIF -->
</dd>
<!-- IF new.S_CUSTOM -->
<dd style="margin-left: 60%;"><label><input type="checkbox" name="no_update[]" value="{new.FILENAME}" class="radio" /> {L_DO_NOT_UPDATE}</label></dd>
@ -243,7 +242,7 @@
<dt style="width: 60%;"><strong><!-- IF not_modified.DIR_PART -->{not_modified.DIR_PART}<br /><!-- ENDIF -->{not_modified.FILE_PART}</strong>
<!-- IF not_modified.S_CUSTOM --><br /><span><em>{L_FILE_USED}: </em>{not_modified.CUSTOM_ORIGINAL}</span><!-- ENDIF -->
</dt>
<dd style="margin-left: 60%;"><!-- IF not not_modified.S_BINARY -->[ <a href="{not_modified.U_SHOW_DIFF}" onclick="diff_popup(this.href); return false;">{not_modified.L_SHOW_DIFF}</a> ]<!-- ELSE -->{L_BINARY_FILE}<!-- ENDIF --></dd>
<dd style="margin-left: 60%;"><!-- IF not not_modified.S_BINARY -->[<a href="{not_modified.U_SHOW_DIFF}" onclick="diff_popup(this.href); return false;">{not_modified.L_SHOW_DIFF}</a>]<!-- ELSE -->{L_BINARY_FILE}<!-- ENDIF --></dd>
<!-- IF not_modified.S_CUSTOM -->
<dd style="margin-left: 60%;"><label><input type="checkbox" name="no_update[]" value="{not_modified.FILENAME}" class="radio" /> {L_DO_NOT_UPDATE}</label></dd>
<!-- ENDIF -->
@ -271,7 +270,7 @@
</dl>
<dl>
<dt style="width: 60%"><label><input type="radio" class="radio" name="modified[{modified.FILENAME}]" value="0" checked="checked" /> {L_MERGE_MODIFICATIONS_OPTION}</label></dt>
<dd style="margin-left: 60%;"><!-- IF not modified.S_BINARY -->[ <a href="{modified.U_SHOW_DIFF}" onclick="diff_popup(this.href); return false;">{modified.L_SHOW_DIFF}</a> ]<!-- ELSE -->{L_BINARY_FILE}<!-- ENDIF --></dd>
<dd style="margin-left: 60%;"><!-- IF not modified.S_BINARY -->[<a href="{modified.U_SHOW_DIFF}" onclick="diff_popup(this.href); return false;">{modified.L_SHOW_DIFF}</a>]<!-- ELSE -->{L_BINARY_FILE}<!-- ENDIF --></dd>
</dl>
<dl>
<dt style="width: 60%"><label><input type="radio" class="radio" name="modified[{modified.FILENAME}]" value="1" /> {L_MERGE_NO_MERGE_NEW_OPTION}</label></dt>
@ -298,8 +297,7 @@
<!-- IF new_conflict.S_CUSTOM --><br /><span><em>{L_FILE_USED}: </em>{new_conflict.CUSTOM_ORIGINAL}</span><!-- ENDIF -->
</dt>
<dd style="margin-left: 60%;">
<!-- IF not new_conflict.S_BINARY -->[ <a href="{new_conflict.U_SHOW_DIFF}" onclick="diff_popup(this.href); return false;">{new_conflict.L_SHOW_DIFF}</a>
<!-- ELSE -->{L_BINARY_FILE}<!-- ENDIF -->
<!-- IF not new_conflict.S_BINARY -->[<a href="{new_conflict.U_SHOW_DIFF}" onclick="diff_popup(this.href); return false;">{new_conflict.L_SHOW_DIFF}</a>]<!-- ELSE -->{L_BINARY_FILE}<!-- ENDIF -->
</dd>
<!-- IF new_conflict.S_CUSTOM -->
<dd style="margin-left: 60%;"><label><input type="checkbox" name="no_update[]" value="{new_conflict.FILENAME}" class="radio" /> {L_DO_NOT_UPDATE}</label></dd>
@ -323,7 +321,7 @@
<!-- IF conflict.NUM_CONFLICTS --><br /><span>{L_NUM_CONFLICTS}: {conflict.NUM_CONFLICTS}</span><!-- ENDIF -->
</dt>
<dd style="margin-left: 60%;">
<!-- IF not conflict.S_BINARY -->[ <a href="{conflict.U_SHOW_DIFF}">{L_DOWNLOAD_CONFLICTS}</a> ]<br />{L_DOWNLOAD_CONFLICTS_EXPLAIN}
<!-- IF not conflict.S_BINARY -->[<a href="{conflict.U_SHOW_DIFF}">{L_DOWNLOAD_CONFLICTS}</a>]<br />{L_DOWNLOAD_CONFLICTS_EXPLAIN}
<!-- ELSE -->{L_BINARY_FILE}<!-- ENDIF -->
</dd>
<!-- IF conflict.S_CUSTOM -->
@ -396,7 +394,7 @@
<fieldset class="submit-buttons">
{S_HIDDEN_FIELDS}
<input type="submit" class="button2" value="{L_CHECK_FILES_AGAIN}" name="check_again" />&nbsp; &nbsp;<input type="submit" class="button1" value="{L_DOWNLOAD}" name="download" />
<input type="submit" class="button2" value="{L_CONTINUE_UPDATE}" name="check_again" />&nbsp; &nbsp;<input type="submit" class="button1" value="{L_DOWNLOAD}" name="download" />
</fieldset>
</form>
@ -462,7 +460,7 @@
</dl>
<!-- END data -->
</fieldset>
<fieldset class="submit-buttons">
{S_HIDDEN_FIELDS}
<input class="button2" type="submit" name="check_again" value="{L_BACK}" />

View file

@ -28,6 +28,9 @@ function resize_panel()
//whatever IE needs to do this
}
}
window.onresize = resize_panel;
// ]]>
</script>
@ -48,10 +51,7 @@ function resize_panel()
<!-- IF DIFF_MODE neq 'side_by_side' and DIFF_MODE neq 'raw' -->
div#codepanel {
overflow: auto;
width: 100%;
height: 350px;
display: inline-block;
}
<!-- ELSE -->
div#codepanel {
@ -59,12 +59,22 @@ div#codepanel {
}
<!-- ENDIF -->
<!-- IF DIFF_MODE neq 'unified' and DIFF_MODE neq 'side_by_side' -->
div#diff_content pre {
overflow: auto;
height: 414px;
width: 100% !important;
}
<!-- ENDIF -->
<!-- IF not S_DIFF_NEW_FILE -->
/**
* Unified Diff
*/
.file {
line-height: .7em;
overflow: auto;
height: 414px;
}
.diff {
@ -203,9 +213,8 @@ table.hrdiff caption span {
</head>
<!-- IF DIFF_MODE neq 'side_by_side' and DIFF_MODE neq 'raw' -->
<body onresize="resize_panel();" onload="resize_panel();">
<body onload="resize_panel();">
<!-- ELSE -->
<body>
<!-- ENDIF -->
@ -220,7 +229,7 @@ table.hrdiff caption span {
<!-- ENDIF -->
<!-- IF not S_DIFF_NEW_FILE -->
<p id="skip"><a href="#acp">{L_SKIP}</a></p>
<form method="post">
<form method="post" action="">
<fieldset class="quick">
<label for="diff_mode">{L_SELECT_DIFF_MODE}:</label>
<select name="diff_mode" id="diff_mode">{S_DIFF_MODE_OPTIONS}</select>

View file

@ -2,6 +2,7 @@
</div>
</div>
<span class="corners-bottom"><span></span></span>
<div class="clear"></div>
</div>
</div>
</div>

View file

@ -194,21 +194,27 @@ function switch_menu()
<div id="menu">
<p>{L_LOGGED_IN_AS}<br /><strong>{USERNAME}</strong> [&nbsp;<a href="{U_LOGOUT}">{L_LOGOUT}</a>&nbsp;][&nbsp;<a href="{U_ADM_LOGOUT}">{L_ADM_LOGOUT}</a>&nbsp;]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<ul>
<!-- DEFINE $LI_USED = 0 -->
<!-- BEGIN l_block1 -->
<!-- IF l_block1.S_SELECTED -->
<!-- BEGIN l_block2 -->
<!-- IF .l_block1.l_block2.l_block3 -->
<li class="header">{l_block1.l_block2.L_TITLE}</li>
<!-- DEFINE $LI_USED = 1 -->
<!-- ENDIF -->
<!-- BEGIN l_block3 -->
<li<!-- IF l_block1.l_block2.l_block3.S_SELECTED --> id="activemenu"<!-- ENDIF -->><a href="{l_block1.l_block2.l_block3.U_TITLE}"><span>{l_block1.l_block2.l_block3.L_TITLE}</span></a></li>
<!-- DEFINE $LI_USED = 1 -->
<!-- END l_block3 -->
<!-- END l_block2 -->
<!-- ENDIF -->
<!-- END l_block1 -->
<!-- IF not $LI_USED -->
<li></li>
<!-- ENDIF -->
</ul>
</div>

View file

@ -0,0 +1,40 @@
<!-- INCLUDE overall_header.html -->
<a name="maincontent"></a>
<h1>{L_ACP_FORUM_PERMISSIONS_COPY}</h1>
{L_ACP_FORUM_PERMISSIONS_COPY_EXPLAIN}
<form id="forum_perm_copy" method="post" action="{U_ACTION}">
<fieldset>
<legend>{L_LOOK_UP_FORUM}</legend>
<dl>
<dt><label for="src_forum">{L_COPY_PERMISSIONS_FROM}:</label><br /><span>{L_COPY_PERMISSIONS_FORUM_FROM_EXPLAIN}</span></dt>
<dd><select id="src_forum" name="src_forum_id"><option value="0">{L_SELECT_FORUM}</option><option value="-1">------------------</option>{S_FORUM_OPTIONS}</select></dd>
</dl>
</fieldset>
<fieldset>
<legend>{L_LOOK_UP_FORUM}</legend>
<p>{L_LOOK_UP_FORUMS_EXPLAIN}</p>
<dl>
<dt><label for="dest_forums">{L_COPY_PERMISSIONS_TO}:</label><br /><span>{L_COPY_PERMISSIONS_FORUM_TO_EXPLAIN}</span></dt>
<dd><select id="dest_forums" name="dest_forum_ids[]" multiple="multiple" size="10">{S_FORUM_OPTIONS}</select></dd>
</dl>
</fieldset>
<fieldset class="submit-buttons">
<legend>{L_SUBMIT}</legend>
<input class="button1" type="submit" id="submit" name="submit" value="{L_SUBMIT}" />&nbsp;
<input class="button2" type="reset" id="reset" name="reset" value="{L_RESET}" />
{S_HIDDEN_FIELDS}
{S_FORM_TOKEN}
</fieldset>
</form>
<!-- INCLUDE overall_footer.html -->

View file

@ -983,6 +983,7 @@ function get_schema_struct()
'confirm_type' => array('TINT:3', 0),
'code' => array('VCHAR:8', ''),
'seed' => array('UINT:10', 0),
'attempts' => array('UINT', 0),
),
'PRIMARY_KEY' => array('session_id', 'confirm_id'),
'KEYS' => array(
@ -1072,6 +1073,7 @@ function get_schema_struct()
'forum_last_poster_name'=> array('VCHAR_UNI', ''),
'forum_last_poster_colour'=> array('VCHAR:6', ''),
'forum_flags' => array('TINT:4', 32),
'forum_options' => array('UINT:20', 0),
'display_subforum_list' => array('BOOL', 1),
'display_on_index' => array('BOOL', 1),
'enable_indexing' => array('BOOL', 1),
@ -1125,6 +1127,7 @@ function get_schema_struct()
'group_id' => array('UINT', NULL, 'auto_increment'),
'group_type' => array('TINT:4', 1),
'group_founder_manage' => array('BOOL', 0),
'group_skip_auth' => array('BOOL', 0),
'group_name' => array('VCHAR_CI', ''),
'group_desc' => array('TEXT_UNI', ''),
'group_desc_bitfield' => array('VCHAR:255', ''),
@ -1195,6 +1198,7 @@ function get_schema_struct()
'PRIMARY_KEY' => 'log_id',
'KEYS' => array(
'log_type' => array('INDEX', 'log_type'),
'log_time' => array('INDEX', 'log_time'),
'forum_id' => array('INDEX', 'forum_id'),
'topic_id' => array('INDEX', 'topic_id'),
'reportee_id' => array('INDEX', 'reportee_id'),
@ -1302,6 +1306,7 @@ function get_schema_struct()
'poster_ip' => array('INDEX', 'poster_ip'),
'poster_id' => array('INDEX', 'poster_id'),
'post_approved' => array('INDEX', 'post_approved'),
'post_username' => array('INDEX', 'post_username'),
'tid_post_time' => array('INDEX', array('topic_id', 'post_time')),
),
);
@ -1329,6 +1334,7 @@ function get_schema_struct()
'message_edit_count' => array('USINT', 0),
'to_address' => array('TEXT_UNI', ''),
'bcc_address' => array('TEXT_UNI', ''),
'message_reported' => array('BOOL', 0),
),
'PRIMARY_KEY' => 'msg_id',
'KEYS' => array(
@ -1404,6 +1410,7 @@ function get_schema_struct()
'field_validation' => array('VCHAR_UNI:20', ''),
'field_required' => array('BOOL', 0),
'field_show_on_reg' => array('BOOL', 0),
'field_show_on_vt' => array('BOOL', 0),
'field_show_profile' => array('BOOL', 0),
'field_hide' => array('BOOL', 0),
'field_no_view' => array('BOOL', 0),
@ -1462,6 +1469,7 @@ function get_schema_struct()
'report_id' => array('UINT', NULL, 'auto_increment'),
'reason_id' => array('USINT', 0),
'post_id' => array('UINT', 0),
'pm_id' => array('UINT', 0),
'user_id' => array('UINT', 0),
'user_notify' => array('BOOL', 0),
'report_closed' => array('BOOL', 0),
@ -1469,6 +1477,10 @@ function get_schema_struct()
'report_text' => array('MTEXT_UNI', ''),
),
'PRIMARY_KEY' => 'report_id',
'KEYS' => array(
'post_id' => array('INDEX', 'post_id'),
'pm_id' => array('INDEX', 'pm_id'),
),
);
$schema_data['phpbb_reports_reasons'] = array(
@ -1830,7 +1842,7 @@ function get_schema_struct()
'user_allow_viewonline' => array('BOOL', 1),
'user_allow_viewemail' => array('BOOL', 1),
'user_allow_massemail' => array('BOOL', 1),
'user_options' => array('UINT:11', 895),
'user_options' => array('UINT:11', 230271),
'user_avatar' => array('VCHAR', ''),
'user_avatar_type' => array('TINT:2', 0),
'user_avatar_width' => array('USINT', 0),
@ -1850,7 +1862,9 @@ function get_schema_struct()
'user_actkey' => array('VCHAR:32', ''),
'user_newpasswd' => array('VCHAR_UNI:40', ''),
'user_form_salt' => array('VCHAR_UNI:32', ''),
'user_new' => array('BOOL', 1),
'user_reminded' => array('TINT:4', 0),
'user_reminded_time' => array('TIMESTAMP', 0),
),
'PRIMARY_KEY' => 'user_id',
'KEYS' => array(

View file

@ -40,13 +40,18 @@ $row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
$mysql_indexer = false;
$mysql_indexer = $drop_index = false;
if (strtolower($row['Type']) === 'mediumtext')
{
$mysql_indexer = true;
}
if (strtolower($row['Key']) === 'mul')
{
$drop_index = true;
}
echo "USE $dbname;$newline$newline";
@ -124,6 +129,13 @@ foreach ($schema_data as $table_name => $table_data)
// Create Table statement
$generator = $textimage = false;
// Do we need to DROP a fulltext index before we alter the table?
if ($table_name == ($prefix . 'posts') && $drop_index)
{
echo "ALTER TABLE {$table_name}{$newline}";
echo "DROP INDEX post_text,{$newline}DROP INDEX post_subject,{$newline}DROP INDEX post_content;{$newline}{$newline}";
}
$line = "ALTER TABLE {$table_name} $newline";
// Table specific so we don't get overlap
@ -236,6 +248,12 @@ foreach ($schema_data as $table_name => $table_data)
$line .= "\tDEFAULT CHARSET=utf8 COLLATE=utf8_bin;$newline$newline";
echo $line . "$newline";
// Do we now need to re-add the fulltext index? ;)
if ($table_name == ($prefix . 'posts') && $drop_index)
{
echo "ALTER TABLE $table_name ADD FULLTEXT (post_subject), ADD FULLTEXT (post_text), ADD FULLTEXT post_content (post_subject, post_text){$newline}";
}
}
/**
@ -455,6 +473,7 @@ function get_schema_struct()
'confirm_type' => array('TINT:3', 0),
'code' => array('VCHAR:8', ''),
'seed' => array('UINT:10', 0),
'attempts' => array('UINT', 0),
),
'PRIMARY_KEY' => array('session_id', 'confirm_id'),
'KEYS' => array(
@ -544,6 +563,7 @@ function get_schema_struct()
'forum_last_poster_name'=> array('VCHAR_UNI', ''),
'forum_last_poster_colour'=> array('VCHAR:6', ''),
'forum_flags' => array('TINT:4', 32),
'forum_options' => array('UINT:20', 0),
'display_subforum_list' => array('BOOL', 1),
'display_on_index' => array('BOOL', 1),
'enable_indexing' => array('BOOL', 1),
@ -597,6 +617,7 @@ function get_schema_struct()
'group_id' => array('UINT', NULL, 'auto_increment'),
'group_type' => array('TINT:4', 1),
'group_founder_manage' => array('BOOL', 0),
'group_skip_auth' => array('BOOL', 0),
'group_name' => array('VCHAR_CI', ''),
'group_desc' => array('TEXT_UNI', ''),
'group_desc_bitfield' => array('VCHAR:255', ''),
@ -667,6 +688,7 @@ function get_schema_struct()
'PRIMARY_KEY' => 'log_id',
'KEYS' => array(
'log_type' => array('INDEX', 'log_type'),
'log_time' => array('INDEX', 'log_time'),
'forum_id' => array('INDEX', 'forum_id'),
'topic_id' => array('INDEX', 'topic_id'),
'reportee_id' => array('INDEX', 'reportee_id'),
@ -801,6 +823,7 @@ function get_schema_struct()
'message_edit_count' => array('USINT', 0),
'to_address' => array('TEXT_UNI', ''),
'bcc_address' => array('TEXT_UNI', ''),
'message_reported' => array('BOOL', 0),
),
'PRIMARY_KEY' => 'msg_id',
'KEYS' => array(
@ -876,6 +899,7 @@ function get_schema_struct()
'field_validation' => array('VCHAR_UNI:20', ''),
'field_required' => array('BOOL', 0),
'field_show_on_reg' => array('BOOL', 0),
'field_show_on_vt' => array('BOOL', 0),
'field_show_profile' => array('BOOL', 0),
'field_hide' => array('BOOL', 0),
'field_no_view' => array('BOOL', 0),
@ -934,6 +958,7 @@ function get_schema_struct()
'report_id' => array('UINT', NULL, 'auto_increment'),
'reason_id' => array('USINT', 0),
'post_id' => array('UINT', 0),
'pm_id' => array('UINT', 0),
'user_id' => array('UINT', 0),
'user_notify' => array('BOOL', 0),
'report_closed' => array('BOOL', 0),
@ -941,6 +966,10 @@ function get_schema_struct()
'report_text' => array('MTEXT_UNI', ''),
),
'PRIMARY_KEY' => 'report_id',
'KEYS' => array(
'post_id' => array('INDEX', 'post_id'),
'pm_id' => array('INDEX', 'pm_id'),
),
);
$schema_data['phpbb_reports_reasons'] = array(
@ -1302,7 +1331,7 @@ function get_schema_struct()
'user_allow_viewonline' => array('BOOL', 1),
'user_allow_viewemail' => array('BOOL', 1),
'user_allow_massemail' => array('BOOL', 1),
'user_options' => array('UINT:11', 895),
'user_options' => array('UINT:11', 230271),
'user_avatar' => array('VCHAR', ''),
'user_avatar_type' => array('TINT:2', 0),
'user_avatar_width' => array('USINT', 0),
@ -1322,7 +1351,9 @@ function get_schema_struct()
'user_actkey' => array('VCHAR:32', ''),
'user_newpasswd' => array('VCHAR_UNI:40', ''),
'user_form_salt' => array('VCHAR_UNI:32', ''),
'user_new' => array('BOOL', 1),
'user_reminded' => array('TINT:4', 0),
'user_reminded_time' => array('TIMESTAMP', 0),
),
'PRIMARY_KEY' => 'user_id',
'KEYS' => array(

View file

@ -0,0 +1,57 @@
<?php
/**
* Corrects user_email_hash values if DB moved from 32-bit system to 64-bit system or vice versa.
* The CRC32 function in PHP generates different results for both systems.
* @PHP dev team: no, a hexdec() applied to it does not solve the issue. And please document it.
*
*/
die("Please read the first lines of this script for instructions on how to enable it");
set_time_limit(0);
define('IN_PHPBB', true);
$phpbb_root_path = './../';
$phpEx = substr(strrchr(__FILE__, '.'), 1);
include($phpbb_root_path . 'common.' . $phpEx);
// Start session management
$user->session_begin();
$auth->acl($user->data);
$user->setup();
$start = request_var('start', 0);
$num_items = 1000;
echo '<br />Updating user email hashes' . "\n";
$sql = 'SELECT user_id, user_email
FROM ' . USERS_TABLE . '
ORDER BY user_id ASC';
$result = $db->sql_query($sql);
$echos = 0;
while ($row = $db->sql_fetchrow($result))
{
$echos++;
$sql = 'UPDATE ' . USERS_TABLE . "
SET user_email_hash = '" . $db->sql_escape(phpbb_email_hash($row['user_email'])) . "'
WHERE user_id = " . (int) $row['user_id'];
$db->sql_query($sql);
if ($echos == 200)
{
echo '<br />';
$echos = 0;
}
echo '.';
flush();
}
$db->sql_freeresult($result);
echo 'FINISHED';
// Done
$db->sql_close();
?>

View file

@ -20,32 +20,39 @@
Please see: http://www.phpbb.com/about/team/ for a list of all the people currently
involved in phpBB.
phpBB Lead Developer : Acyd Burn (Meik Sievertsen)
phpBB Lead Developer : Acyd Burn (Meik Sievertsen)
phpBB Developers : APTX (Marek A. R.)
DavidMJ (David M.)
dhn (Dominik Dröscher)
kellanved (Henry Sudhof)
naderman (Nils Adermann)
ToonArmy (Chris Smith)
Vic D'Elfant (Vic D'Elfant)
phpBB Developers : APTX (Marek A. R.)
bantu (Andreas Fischer)
DavidMJ (David M.)
dhn (Dominik Dröscher)
kellanved (Henry Sudhof)
naderman (Nils Adermann)
Terrafrost (Jim Wigginton)
ToonArmy (Chris Smith)
Contributions by : leviatan21 (Gabriel Vazquez)
nickvergessen (Joas Schilling)
Raimon (Raimon Meuldijk)
rxu (Ruslan Uzdenov)
Xore (Robert Hetzler)
-- Previous Contributors --
phpBB Project Manager : theFinn (James Atkinson) [Founder - 04/2007]
SHS` (Jonathan Stanley)
phpBB Project Manager : theFinn (James Atkinson) [Founder - 04/2007]
SHS` (Jonathan Stanley)
phpBB Lead Developer : psoTFX (Paul S. Owen) [2001 - 09/2005]
phpBB Developers : Ashe (Ludovic Arnaud) [10/2002 - 11/2003, 06/2006 - 10/2006]
BartVB (Bart van Bragt) [11/2000 - 03/2006]
GrahamJE (Graham Eames) [09/2005 - 11/2006]
phpBB Lead Developer : psoTFX (Paul S. Owen) [2001 - 09/2005]
phpBB Developers : Ashe (Ludovic Arnaud) [10/2002 - 11/2003, 06/2006 - 10/2006]
BartVB (Bart van Bragt) [11/2000 - 03/2006]
GrahamJE (Graham Eames) [09/2005 - 11/2006]
Vic D'Elfant (Vic D'Elfant) [04/2007 - 04/2009]
-- Copyrights --
Visual Confirmation : Xore (Robert Hetzler)
Visual Confirmation : Xore (Robert Hetzler)
Original subSilver by subBlue Design, Tom Beddard, (c) 2001 phpBB Group
prosilver by subBlue Design, Tom Beddard, (c) 2004 phpBB Group

View file

@ -53,6 +53,7 @@
<ol>
<li><a href="#changelog">Changelog</a>
<ol style="list-style-type: lower-roman;">
<li><a href="#v305">Changes since 3.0.5</a></li>
<li><a href="#v304">Changes since 3.0.4</a></li>
<li><a href="#v303">Changes since 3.0.3</a></li>
<li><a href="#v302">Changes since 3.0.2</a></li>
@ -84,7 +85,223 @@
<div class="inner"><span class="corners-top"><span></span></span>
<div class="content">
<a name="v304"></a><h3>1.i. Changes since 3.0.4</h3>
<a name="v305"></a><h3>1.i. Changes since 3.0.5</h3>
<ul>
<li>[Fix] Allow whitespaces in avatar gallery names. (Bug #44955)</li>
<li>[Fix] Sorting by author or subject on viewtopic now preserves the order. (Bug #44875)</li>
<li>[Fix] Correctly determine writable status of files on Windows operating system. (Bug #39035)</li>
<li>[Fix] Show report button in prosilver for guests who are allowed to report posts. (Bug #45695 - Patch by bantu)</li>
<li>[Fix] Correctly show private message history (Bug #46065 - Patch by bantu)</li>
<li>[Fix] Various XHTML mistakes in prosilver, subsilver2 and the ACP. (Bugs #25545 - Patch by bantu, #26315, #38555, #45505 - Patch by Raimon, #45785, #45865, #47085 - Patch by Raimon)</li>
<li>[Fix] Fix some ACP style issues (Bug #45975 - Patch by leviatan21, Bug #16109 - Patch by prototech)</li>
<li>[Fix] Move post bump information markup to the template. (Bug #34295 - Patch by bantu)</li>
<li>[Fix] Show error in the ACP when template folder is not readable. (Bug #45705 - Patch by bantu)</li>
<li>[Fix] Adjust viewonline filename regular expression to be less strict. (Bug #46215 - Patch by bantu)</li>
<li>[Fix] Correctly apply the can change vote permission again. Regression introduced in r9470. (Bug #45895)</li>
<li>[Fix] Also remove data from friend/foe table when deleting user. (Bug #45345 - Patch by nickvergessen)</li>
<li>[Fix] Correctly hide skiplink in prosilver right-to-left mode. (Bug #45765 - Patch by prototech and bantu)</li>
<li>[Fix] Fix dynamic config update routine error if firebird is used (Bug #46315)</li>
<li>[Fix] Allow friends/foes to be added and removed at the same time. (Bug #46255 - Patch by bantu)</li>
<li>[Fix] Only change topic/post icon if icons are enabled and user is allowed to. (Bug #46355 - Patch by bantu)</li>
<li>[Fix] Fix saving custom profile fields in ACP if Oracle is used. (Bug #46015)</li>
<li>[Fix] Make view_log() more resilient to corrupt serialized data. (Bug #46545)</li>
<li>[Fix] Show error if hostname lookup doesn't return a valid IP address when banning. (Bug #45585 - Patch by bantu)</li>
<li>[Fix] Fix incorrect layout when loading private message draft. (Bug #38435 - Patch by nickvergessen)</li>
<li>[Fix] Show proper error message when trying to add bots to friends/foes list. (Bug #40205 - Patch by nickvergessen)</li>
<li>[Fix] Fix Oracle database backup (Bug #46715)</li>
<li>[Fix] Update attachments table when deleting user and retaining his posts. (Bug #40245 - Patch by rxu)</li>
<li>[Fix] Correctly detect files in subfolders when viewing cached template files. (Bug #46145 - Patch by nickvergessen)</li>
<li>[Fix] Display user's Jabber address in popup when Jabber functionality is disabled (Bug #20775 - Patch by nickvergessen)</li>
<li>[Fix] Correctly exclude forums from active topics list. (Bug #19135 - Patch by nickvergessen)</li>
<li>[Fix] Do not display birthdays of banned users (Bug #20625 - Patch by nickvergessen)</li>
<li>[Fix] Fix function to recalculate Nested Sets (Bug #41555 - Patch by EXreaction)</li>
<li>[Fix] Display but also highlight already used rank images when creating new ranks. (Bug #22665 - Patch by nickvergessen)</li>
<li>[Fix] Correctly orientate quoted text image on RTL languages (Bug #33745 - Patch by nickvergessen)</li>
<li>[Fix] Do not display &quot;View user notes&quot; and &quot;Warn user&quot; links in user profile if corresponding MCP modules are disabled. (Bug #10519 - Patch by rxu)</li>
<li>[Fix] Show proper error message when trying to create a private messages folder with an empty name. (Bug #39875 - Patch by nickvergessen)</li>
<li>[Fix] No longer state that it is possible to manage group leaders from the UCP. (Bug #19945 - Patch by nickvergessen)</li>
<li>[Fix] Do not throw an error when PDO is a shared module and not loaded preventing SQLite from being loaded.</li>
<li>[Fix] Fix censoring of unicode words. (Bug #16555 - Patches by rxu)</li>
<li>[Fix] Display coloured usernames in ACP groups management screens</li>
<li>[Fix] Correctly describe founder permissions on trace-information (Bug #37235 - Patch by nickvergessen)</li>
<li>[Fix] Correct the width value for poll_center.gif omitted in imageset.cfg for subsilver2. (Bug #43005 - Patch by rxu)</li>
<li>[Fix] Correctly load complex language variable using acp_language (Bug #45735 - Patch by leviatan21)</li>
<li>[Fix] Fix reapply_sid() to correctly strip session id in certain circumstances (Bug #43125 - Patch by leviatan21)</li>
<li>[Fix] Correctly state why one language pack is marked with an asterisk in the ACP. (Bug #37565 - Patch by bantu)</li>
<li>[Fix] Correctly check if install directory is still present. (Bug #46965 - Patch by rxu)</li>
<li>[Fix] Correct banned user behaviour when &quot;force password change&quot; is enabled (Bug #47145 - Patch by nickvergessen and leviatan21)</li>
<li>[Fix] Correctly display ACP logs options, without permission to clear logs. (Bug #24155 - Patch by leviatan21)</li>
<li>[Fix] Display topic icons in MCP forum view again (only prosilver).</li>
<li>[Fix] Properly display post status messages in topic when post is reported and unapproved (Bug #44455 - Patch by leviatan21)</li>
<li>[Fix] Do not remove recipients when loading private message draft. (Bug #38395 - Patch by nickvergessen)</li>
<li>[Fix] Add author name to moderator log when deleting post/topic. (Bug #46225 - Patch by nickvergessen)</li>
<li>[Fix] Fix broken &quot;Report details&quot; link in the MCP. (Bug #46975 - Patch by nickvergessen)</li>
<li>[Fix] Resolve accesskey conflicts in prosilver. (Bug #44685 - Patch by bantu)</li>
<li>[Fix] Check if template file is empty before trying to read from it. (Bug #47345 - Patch by bantu)</li>
<li>[Fix] Correct descriptions of the permissions to use BBCode, smilies, images and flash to be more relevant. (Bug #36065 - Patch by rxu)</li>
<li>[Fix] Fix style issues in print mode. (Bug #26375 - Patch by leviatan21)</li>
<li>[Fix] Fix minor issue with L_QUOTE language string missing in several PM composing modes. (Bug #39625 - Patch by rxu)</li>
<li>[Fix] Also fetch posts of guests and deleted or deactivated users when searching for author names. (Bug #36565, #47765 - Patch by nickvergessen)</li>
<li>[Fix] Show end of ban in MCP and ACP when user is banned by duration. (Bug #47815 - Patch by Pyramide)</li>
<li>[Fix] Correctly count posts awaiting approval in the MCP. (Bug #47685 - Patch by nickvergessen)</li>
<li>[Fix] Display user's posts count in private message when it is equal to 0 (prosilver). (Bug #40155 - Patch by rxu)</li>
<li>[Fix] Only allow users to disable word censor if globally allowed. (Bug #47575 - Patch by 00mohgta7)</li>
<li>[Fix] Fix database updater and db tools to support multiple column changes/additions/removals with SQLite</li>
<li>[Fix] Correctly detect GZIP status in debug mode. (Bug #24075 - Patch by rxu)</li>
<li>[Fix] Posting smilies in view more smilies now work again in IE (Bug #46025 - Patch by leviatan21)</li>
<li>[Fix] Properly convert and show filesize information. (Bug #47775 - Patch by bantu)</li>
<li>[Fix] Add ability to prune users who never logged in. (Bug #44295 - Patch by rxu)</li>
<li>[Fix] Show smilies and images in topic print view. (Bug #47265 - Patch by nickvergessen)</li>
<li>[Fix] Force full date in private message print view. (Patch by nickvergessen)</li>
<li>[Fix] Fix &quot;Always show a scrollbar for short pages&quot; for IE8 and Firefox 3.5 (Bug #47865 - Patch by stokerpiller)</li>
<li>[Fix] Do not allow setting group as default group for pending users. (Bug #45675 - Patch by nickvergessen)</li>
<li>[Fix] Fail gracefully if store folder is not writable during update. (Bugs #46615, #46945)</li>
<li>[Fix] Hide profile-icon from viewtopic-page if user has no permissions (subsilver2 only) (Bug #37635 - Patch by leviatan21)</li>
<li>[Fix] Correct escaping/unescaping in the LDAP authentication plugin. (Bug #48175)</li>
<li>[Fix] Add hard limit for smilies.</li>
<li>[Fix] Remove redundant SQL query from ucp.php. (Bug #40305)</li>
<li>[Fix] Reorder frame order of animated subsilver2 topic icons to be useful when animation is disabled. (Bug #29385 - Patch by prototech)</li>
<li>[Fix] Ensure user errors are displayed regardless of PHP settings. (Bug #47505)</li>
<li>[Fix] Permit null values for non-required integer custom profile fields and ensure zero complies with the range limits. (Bug #40925)</li>
<li>[Fix] Allow changing forum from select box under certain circumstances. (Bug #37525)</li>
<li>[Fix] Display required fields notice on registration above the custom profile fields. (Bug #39665)</li>
<li>[Fix] Copy poll options properly when copying topic. (Bug #39065)</li>
<li>[Fix] Fix error with disapproval of topics having several queued posts only. (Bug #47705 - Patch by rxu)</li>
<li>[Fix] Preserve newlines in template files (one newline had been always dropped after a template variable due to PHP's handling of closing tags)</li>
<li>[Fix] Be less strict with FTP daemons when getting directory filelists. (Bug #46295)</li>
<li>[Fix] Fix set_custom_template for database-stored styles (Bug #40515 - Patch by nickvergessen)</li>
<li>[Fix] Banning an already banned user states to be successful, but has no effect (Bug #47825 - Patch by Pyramide)</li>
<li>[Fix] Do not add style-parameter to URL again, after admin re-authentification (Bug #18005 - Patch by leviatan21)</li>
<li>[Fix] Do not cut post-message in between HTML-Entities on search.php (Bug #31505 - Patch by leviatan21)</li>
<li>[Fix] Correctly set attachment flag for topics, posts and pms after deleting attachments (Bug #48265 - Patch by MarcoDM and nickvergessen)</li>
<li>[Fix] Display &quot;Locked&quot; button instead of &quot;Reply&quot; one for locked forum in viewtopic (prosilver). (Bug #38055 - Patch by Raimon)</li>
<li>[Fix] Correctly propagate umlauts over search result pages (Bug #33755)</li>
<li>[Fix] Preserve post options when refusing to save the post as a draft. (Bug #39115)</li>
<li>[Fix] Do not send private message back to sender if sender is in the same group the private message was sent to.</li>
<li>[Fix] Correctly add user to a group making it a default one. (Bug #48345 - Patch by rxu)</li>
<li>[Fix] Add log entry when copying forum permissions.</li>
<li>[Fix] Min/max characters per posts no longer affects poll options (Bug #47295 - Patch by nickvergessen)</li>
<li>[Fix] Correctly log action when users request to join a group (Bug #37585 - Patch by nickvergessen)</li>
<li>[Fix] Do not try to create thumbnails for images we cannot open properly. (Bug #48695)</li>
<li>[Fix] Apply locale-independent basename() to attachment filenames. New function added: utf8_basename(). (Bug #43335 - Patch by ocean=Yohsuke)</li>
<li>[Fix] Adjust build_url() to not prepend $phpbb_root_path if path returned from redirect() is an URL. This fixes redirect issues with some installations and bridges. (Bug #47535)</li>
<li>[Fix] Do not mark global announcements as read if all topics in a forum become read (Bug #15729).</li>
<li>[Fix] Fix general error while registration, through undefined variable $config in validate_referer (Bug #49035 - Patch by wjvriend)</li>
<li>[Fix] Correctly extract column default value when exporting PostgreSQL tables. (Bug #48955)</li>
<li>[Fix] Allow updater to work correctly with PHP filename extensions other than &quot;.php&quot;. (Bugs #15809, #49215)</li>
<li>[Fix] Update search index if only post subject changed. (Bug #49435)</li>
<li>[Fix] Fix who is online displaying incorrect data. (Bug #49485, thanks Brainy)</li>
<li>[Fix] Fixed incorrect &quot;topic does not exist&quot; when unapproved posts were visited without global moderator permissions. (Bug #47795)</li>
<li>[Fix] Prevent style switcher from blocking the tab key. (Bug #49335)</li>
<li>[Fix] Correctly redirect on MCP main page after posts approval/disapproval from it. (Bug #49625)</li>
<li>[Fix] Do not display topic approval status image for shadow topic if a user is not a moderator in the forum the topic has been moved to. (Bug #43295)</li>
<li>[Fix] Fix email problems on servers with PHP installations not accepting RFC-compliant subject string passed to the the mail()-function. (Bug #46725)</li>
<li>[Fix] Correctly orientate Control-Panel-Navigation background-image on RTL languages. (Bug #49945)</li>
<li>[Fix] Sort private messages by message time and not message id. (Bug #50015)</li>
<li>[Fix] Make sure only logs for existing users are displayed and user-specific logs removed on user deletion. (Bug #49855)</li>
<li>[Fix] Only show &quot;Add friend&quot; and &quot;Add foe&quot; links if the specific module is enabled. (Bug #50475)</li>
<li>[Fix] Correctly display list items in forum description in prosilver and administration. (Bug #48055 - Patch by leviatan21)</li>
<li>[Fix] Fix handling of bookmarks and subscriptions on &quot;split topics&quot;, &quot;merge topics&quot; and &quot;merge posts&quot;. (Bug #50035)</li>
<li>[Fix] Only embed cron.php if there is no cron lock present to reduce overhead. (Bug #45725 - Patch by TerryE)</li>
<li>[Fix] Add header gradient back into subsilver2 but keep site logo easily replaceable with smaller and bigger ones. (Bug #11142 - Patch by dark/Rain and Raimon)</li>
<li>[Fix] Send activation email when activating user from user settings. (Bug #43145)</li>
<li>[Fix] Do not show resend activation email link when using admin activation. (Bug #44375 - Patch by bbrunnrman)</li>
<li>[Fix] Do not display links to user/post search if search is disabled. (Bug #50685 - Patch by HardStyle)</li>
<li>[Fix] Fix icon alignment for forums with large descriptions in subsilver2. (Bug #50445)</li>
<li>[Fix] Correctly display underlined links placed in last line in viewtopic. (Bug #14811 - Patch by primehalo)</li>
<li>[Change] submit_post() now accepts force_approved_state key passed to $data to indicate new posts being approved (true) or unapproved (false).</li>
<li>[Change] Change the data format of the default file ACM to be more secure from tampering and have better performance.</li>
<li>[Change] Add index on log_time to the log table to prevent slowdown on boards with many log entries. (Bug #44665 - Patch by bantu)</li>
<li>[Change] Template engine now permits to a limited extent variable includes.</li>
<li>[Change] Quote BBCode no longer requires the f_reply permission. (Bug #16079)</li>
<li>[Change] Banning/unbanning users now generates an entry in their user notes (Bug #21825 - Patch by nickvergessen)</li>
<li>[Change] Smilies no longer require the f_bbcode permission. (Bug #26545)</li>
<li>[Change] Ability to define column split in FAQ/BBCode help (Bug #31405)</li>
<li>[Change] Changed behaviour of group_create() function to support specifying additional group columns</li>
<li>[Change] Hide avatar when avatar-type is not allowed (Bug #46785 - Patch by cYbercOsmOnauT and nickvergessen)</li>
<li>[Change] INCLUDEPHP not depending on phpbb_root_path (Bug #45805 - Patch by nickvergessen)</li>
<li>[Change] Ability to fetch moderators with get_moderators() even if load_moderators setting is off. (Bug #35955)</li>
<li>[Change] &quot;Post details&quot; links with image in MCP. (Bug #39845 - Patch by leviatan21)</li>
<li>[Change] PM history now only shows PMs of users you currently reply to. (Bug #39505 - Patch by nickvergessen)</li>
<li>[Change] Show quote button for own PMs in PM history. (Bug #37285 - Patch by nickvergessen)</li>
<li>[Change] Fetch requested cookie variables directly from cookie super global. (Bug #47785)</li>
<li>[Change] Add confirmation for deactivating styles (Bug #14304 - Patch by leviatan21)</li>
<li>[Change] Add confirmation for deactivating language packs (Patch by leviatan21)</li>
<li>[Change] Add confirm-box when deleting permissions (Bug #13673 - Patch by nickvergessen)</li>
<li>[Change] Add pagination for icons and smilies in the ACP and smilies in the smiley popup</li>
<li>[Change] Cache get_username_string() function calls on viewtopic.</li>
<li>[Change] Cache version check.</li>
<li>[Change] When creating a new forum without copying permissions, ask again.</li>
<li>[Change] Parse multiline url title for [url] BBCode tag. (Bug #1309)</li>
<li>[Change] Introduce new parameter to page_header() for forum specific who is online listings.</li>
<li>[Change] Lifted minimum requirement for Firebird DBMS from 2.0+ to 2.1+.</li>
<li>[Change] Unapproved topics can no longer be replied to (Bug #44005, #47675, #23605)</li>
<li>[Change] Require user to be registered and logged in to search for unread posts if topic read tracking is disabled for guests (Bug #49525)</li>
<li>[Change] Allow three-digit hex notation in Color BBcode. (Bug #39965 - Patch by m0rpha)</li>
<li>[Change] Simplified login_box() and redirection after login. S_LOGIN_ACTION can now be used on every page. (Bug #50285)</li>
<li>[Change] Do not take edit post time into account for determining permission to delete last post in topic. (Bug #48615)</li>
<li>[Change] Resize oversized Topic icons (Bug #44415)</li>
<li>[Change] Banned IPs are now sorted (Bug #43045 - Patch by DavidIQ)</li>
<li>[Change] phpBB updater now skips sole whitespace changes. This reduces the chance of conflicts tremendously.</li>
<li>[Feature] Add language selection on the registration terms page (Bug #15085 - Patch by leviatan21)</li>
<li>[Feature] Backported 3.2 captcha plugins.
<ul>
<li>Classic and GD CAPTCHA</li>
<li>reCaptcha (based on API from recaptcha.net by Mike Crawford and Ben Maurer)</li>
<li>Q&amp;A CAPTCHA</li>
<li>3D Wave (by Robert &quot;Xore&quot; Hetzler)</li>
</ul>
</li>
<li>[Feature] Introduced new ACM plugins:
<ul>
<li>null</li>
<li><a href="http://pecl.php.net/package/memcache">memcache</a></li>
<li><a href="http://pecl.php.net/package/APC">APC</a></li>
<li><a href="http://xcache.lighttpd.net/">XCache</a></li>
<li><a href="http://eaccelerator.net/">eAccelerator</a></li>
</ul>
</li>
<li>[Feature] ATOM Feeds (Idea and diversed from RSS Feed 2.0 MOD (Version 1.0.8/9) by leviatan21)</li>
<li>[Feature] New groups option to excempt group leaders from group permissions</li>
<li>[Feature] New &quot;Newly Registered Users&quot; group for assigning permissions to newly registered users. They will be removed from this group once they reach a defineable amount of posts.</li>
<li>[Feature] Ability to define if the &quot;Newly Registered Users&quot; group will be assigned as the default group to newly registered users.</li>
<li>[Feature] Add new option to disable avatars board-wide (Bug #46785 - Patch by cYbercOsmOnauT and nickvergessen)</li>
<li>[Feature] Enhance obtain_users_online_string to be able to return user-lists for other session-items (Bug #31975 - Patch by nickvergessen)</li>
<li>[Feature] Add unapproved topic icon for moderators on forum list (Bug #46865 - Patch by nickvergessen)</li>
<li>[Feature] Ability to define minimum number of characters for posts/pms</li>
<li>[Feature] Store signature configuration options in database (Bug #45115 - Patch by rxu)</li>
<li>[Feature] Add bare-bones quick-reply editor to viewtopic.</li>
<li>[Feature] Detect when a post has been altered by someone else while editing. (Patch by bantu)</li>
<li>[Feature] Add unread posts quick search option (Bug #46765 - Patch by rxu)</li>
<li>[Feature] Add option to disable avatar uploads from remote locations. (Bug #45375 - Patch by nickvergessen)</li>
<li>[Feature] Ability to delete warnings and keep warnings permanently (Bug #43375 - Patch by nickvergessen)</li>
<li>[Feature] Ability to empty a user's outbox from the user ACP quick tools.</li>
<li>[Feature] Ability to search ACP / MCP logs</li>
<li>[Feature] Users can report PMs to moderators which are then visible in a new MCP module</li>
<li>[Feature] Parse email text files with the template engine.</li>
<li>[Feature] Use email-style quoting when bbcodes are disabled.</li>
<li>[Feature] Added new functionality to inactive users module:
<ul>
<li>Ability to set users per page.</li>
<li>Ability to sort by posts/number of reminders/last reminded date.</li>
<li>Show number of posts and ability to search posts.</li>
<li>Show number of reminders sent to user.</li>
<li>Show date of last reminder sent to user.</li>
</ul>
</li>
<li>[Feature] Display version check on ACP main page.</li>
<li>[Feature] Ability to copy permissions from one forum to several other forums.</li>
<li>[Feature] Ability to control the display of custom profile fields on viewtopic (Bug #48985).</li>
<li>[Feature] Fallback options for missing language files. (Bug #38575 - Patch by EXreaction)</li>
<li>[Feature] Separate PM Reply and PM Reply to all in prosilver.</li>
<li>[Feature] Place debug notices during captcha rendering in the error log - useful for debugging output already started errors.</li>
<li>[Feature] Ability to define constant PHPBB_USE_BOARD_URL_PATH to use board url for images/avatars/ranks/imageset...</li>
<li>[Feature] Added function to generate Email hash. (Bug #49195)</li>
<li>[Feature] Style authors are now able to define the default submit button used for form submission on ENTER keypress on forms using more than one. Prosilver uses this for the posting page(s) and registration screen.</li>
<li>[Feature] Ability to specify amount of time user is able to delete his last post in topic.</li>
</ul>
<a name="v304"></a><h3>1.ii. Changes since 3.0.4</h3>
<ul>
<li>[Fix] Delete user entry from ban list table upon user deletion (Bug #40015 - Patch by TerraFrost)</li>
@ -101,7 +318,7 @@
<li>[Fix] Changed the success message when requesting a new password to be more accurate. (Bug #41405)</li>
<li>[Fix] Add missing anti-abuse email headers to acp_inactive.php and ucp_resend.php.</li>
<li>[Fix] Only remind users in the correct inactive states depending on the board account activation level.</li>
<li>[Fix] Various XHTML mistakes in prosilver, subsilver2 and the ACP. (Bugs #41745, #42265 - Patch by nickvergessen, #38465, #43015)</li>
<li>[Fix] Various XHTML mistakes in prosilver, subsilver2 and the ACP. (Bugs #41745, #42265 - Patch by nickvergessen, #38465, #43015, #46585 - Patch by Raimon)</li>
<li>[Fix] Log password changes via password reset function. (Bug #41365)</li>
<li>[Fix] Poll, negative durations generate error (Bug #41295 - Patch by TerraFrost)</li>
<li>[Fix] Visibility of custom field on registration is incorrectly controlled by setting &quot;display&quot; (Bug #41385 - Patch by Eelke and fade2gray)</li>
@ -173,7 +390,7 @@
<li>[Sec] Only use forum id supplied for posting if global announcement detected. (Reported by nickvergessen)</li>
</ul>
<a name="v303"></a><h3>1.ii. Changes since 3.0.3</h3>
<a name="v303"></a><h3>1.iii. Changes since 3.0.3</h3>
<ul>
<li>[Fix] Allow mixed-case template directories to be inherited (Bug #36725)</li>
@ -205,7 +422,7 @@
<li>[Sec] Ask for forum password if post within passworded forum quoted in private message. (Reported by nickvergessen)</li>
</ul>
<a name="v302"></a><h3>1.iii. Changes since 3.0.2</h3>
<a name="v302"></a><h3>1.iv. Changes since 3.0.2</h3>
<ul>
<li>[Fix] Correctly set topic starter if first post in topic removed (Bug #30575 - Patch by blueray2048)</li>
@ -304,7 +521,7 @@
<li>[Sec Precaution] Stricter validation of the HTTP_HOST header (Thanks to Techie-Micheal et al for pointing out possible issues in derived code)</li>
</ul>
<a name="v301"></a><h3>1.iv. Changes since 3.0.1</h3>
<a name="v301"></a><h3>1.v. Changes since 3.0.1</h3>
<ul>
<li>[Fix] Ability to set permissions on non-mysql dbms (Bug #24955)</li>
@ -352,7 +569,7 @@
<li>[Sec] Only allow urls gone through redirect() being used within login_box(). (thanks nookieman)</li>
</ul>
<a name="v300"></a><h3>1.v. Changes since 3.0.0</h3>
<a name="v300"></a><h3>1.vi Changes since 3.0.0</h3>
<ul>
<li>[Change] Validate birthdays (Bug #15004)</li>
@ -423,7 +640,7 @@
<li>[Fix] Find and display colliding usernames correctly when converting from one database to another (Bug #23925)</li>
</ul>
<a name="v30rc8"></a><h3>1.vi. Changes since 3.0.RC8</h3>
<a name="v30rc8"></a><h3>1.vii. Changes since 3.0.RC8</h3>
<ul>
<li>[Fix] Cleaned usernames contain only single spaces, so &quot;a_name&quot; and &quot;a__name&quot; are treated as the same name (Bug #15634)</li>
@ -432,7 +649,7 @@
<li>[Fix] Call garbage_collection() within database updater to correctly close connections (affects Oracle for example)</li>
</ul>
<a name="v30rc7"></a><h3>1.vii. Changes since 3.0.RC7</h3>
<a name="v30rc7"></a><h3>1.viii. Changes since 3.0.RC7</h3>
<ul>
<li>[Fix] Fixed MSSQL related bug in the update system</li>
@ -467,7 +684,7 @@
<li>[Fix] No duplication of active topics (Bug #15474)</li>
</ul>
<a name="v30rc6"></a><h3>1.viii. Changes since 3.0.RC6</h3>
<a name="v30rc6"></a><h3>1.ix. Changes since 3.0.RC6</h3>
<ul>
<li>[Fix] Submitting language changes using acp_language (Bug #14736)</li>
@ -477,7 +694,7 @@
<li>[Fix] Able to request new password (Bug #14743)</li>
</ul>
<a name="v30rc5"></a><h3>1.ix. Changes since 3.0.RC5</h3>
<a name="v30rc5"></a><h3>1.x. Changes since 3.0.RC5</h3>
<ul>
<li>[Feature] Removing constant PHPBB_EMBEDDED in favor of using an exit_handler(); the constant was meant to achive this more or less.</li>
@ -540,7 +757,7 @@
<li>[Sec] New password hashing mechanism for storing passwords (#i42)</li>
</ul>
<a name="v30rc4"></a><h3>1.x. Changes since 3.0.RC4</h3>
<a name="v30rc4"></a><h3>1.xi. Changes since 3.0.RC4</h3>
<ul>
<li>[Fix] MySQL, PostgreSQL and SQLite related database fixes (Bug #13862)</li>
@ -591,7 +808,7 @@
<li>[Fix] odbc_autocommit causing existing result sets to be dropped (Bug #14182)</li>
</ul>
<a name="v30rc3"></a><h3>1.xi. Changes since 3.0.RC3</h3>
<a name="v30rc3"></a><h3>1.xii. Changes since 3.0.RC3</h3>
<ul>
<li>[Fix] Fixing some subsilver2 and prosilver style issues</li>
@ -700,7 +917,7 @@
</ul>
<a name="v30rc2"></a><h3>1.xii. Changes since 3.0.RC2</h3>
<a name="v30rc2"></a><h3>1.xiii. Changes since 3.0.RC2</h3>
<ul>
<li>[Fix] Re-allow searching within the memberlist</li>
@ -746,7 +963,7 @@
</ul>
<a name="v30rc1"></a><h3>1.xiii. Changes since 3.0.RC1</h3>
<a name="v30rc1"></a><h3>1.xiv. Changes since 3.0.RC1</h3>
<ul>
<li>[Fix] (X)HTML issues within the templates (Bug #11255, #11255)</li>
@ -902,4 +1119,4 @@
</div>
</body>
</html>
</html>

View file

@ -139,7 +139,7 @@
<li>MySQL 3.23 or above (MySQLi supported)</li>
<li>PostgreSQL 7.3+</li>
<li>SQLite 2.8.2+</li>
<li>Firebird 2.0+</li>
<li>Firebird 2.1+</li>
<li>MS SQL Server 2000 or above (directly or via ODBC)</li>
<li>Oracle</li>
</ul>
@ -273,7 +273,7 @@
<p>This package is meant for those wanting to only replace changed files from a previous version to the latest version. This package normally contains the changed files from up to five previous versions.</p>
<p>This package contains a number of archives, each contains the files changed from a given release to the latest version. You should select the appropriate archive for your current version, e.g. if you currently have <samp>3.0.4</samp> you should select the phpBB-3.0.4_to_3.0.5.zip/tar.gz file.</p>
<p>This package contains a number of archives, each contains the files changed from a given release to the latest version. You should select the appropriate archive for your current version, e.g. if you currently have <samp>3.0.5</samp> you should select the phpBB-3.0.5_to_3.0.6.zip/tar.gz file.</p>
<p>The directory structure has been preserved enabling you (if you wish) to simply upload the contents of the archive to the appropriate location on your server, i.e. simply overwrite the existing files with the new versions. Do not forget that if you have installed any MODs these files will overwrite the originals possibly destroying them in the process. You will need to re-add MODs to any affected file before uploading.</p>
@ -283,9 +283,9 @@
<p>The patch file package is for those wanting to update through the patch application, and being comfortable with it.</p>
<p>The patch file is one solution for those with many Modifications (MODs) or other changes who do not want to re-add them back to all the changed files if they use the method explained above. To use this you will need command line access to a standard UNIX type <strong>patch</strong> application. If you do not have access to such an application but still want to use this update approach, we strongly recommend the <a href="#update_auto">Automatic update package</a> explained below. It is also the preferred update method.</p>
<p>The patch file is one solution for those with many Modifications (MODs) or other changes who do not want to re-add them back to all the changed files if they use the method explained above. To use this you will need command line access to a standard UNIX type <strong>patch</strong> application. If you do not have access to such an application but still want to use this update approach, we strongly recommend the <a href="#update_auto">Automatic update package</a> explained below. It is also the recommended update method.</p>
<p>A number of patch files are provided to allow you to update from previous stable releases. Select the correct patch, e.g. if your current version is 3.0.4 you need the phpBB-3.0.4_to_3.0.5.patch file. Place the correct patch in the parent directory containing the phpBB3 core files (i.e. index.php, viewforum.php, etc.). With this done you should run the following command: <strong>patch -cl -d [PHPBB DIRECTORY] -p1 &lt; [PATCH NAME]</strong> (where PHPBB DIRECTORY is the directory name your phpBB Installation resides in, for example phpBB3, and where PATCH NAME is the relevant filename of the selected patch file). This should complete quickly, hopefully without any HUNK FAILED comments.</p>
<p>A number of patch files are provided to allow you to update from previous stable releases. Select the correct patch, e.g. if your current version is 3.0.5 you need the phpBB-3.0.5_to_3.0.6.patch file. Place the correct patch in the parent directory containing the phpBB3 core files (i.e. index.php, viewforum.php, etc.). With this done you should run the following command: <strong>patch -cl -d [PHPBB DIRECTORY] -p1 &lt; [PATCH NAME]</strong> (where PHPBB DIRECTORY is the directory name your phpBB Installation resides in, for example phpBB3, and where PATCH NAME is the relevant filename of the selected patch file). This should complete quickly, hopefully without any HUNK FAILED comments.</p>
<p>If you do get failures you should look at using the <a href="#update_files">Changed files only</a> package to replace the files which failed to patch, please note that you will need to manually re-add any Modifications (MODs) to these particular files. Alternatively if you know how you can examine the .rej files to determine what failed where and make manual adjustments to the relevant source.</p>
@ -293,7 +293,7 @@
<a name="update_auto"></a><h3>4.iv. Automatic update package</h3>
<p>This update method is the preferred method for updating. This package allows detecting changed files automatically and merges changes if needed.</p>
<p>This update method is the recommended method for updating. This package allows detecting changed files automatically and merges changes if needed.</p>
<p>The automatic update package contains - contrary to the others - only the information required to update the previous release version to the latest available version. These packages are meant for use with the automatic update tool.</p>

View file

@ -57,6 +57,7 @@
<li><a href="#editorsettings">Editor Settings</a></li>
<li><a href="#fileheader">File Header</a></li>
<li><a href="#locations">File Locations</a></li>
<li><a href="#constants">Special Constants</a></li>
</ol>
</li>
<li><a href="#code">Code Layout/Guidelines</a>
@ -86,6 +87,12 @@
<li><a href="#writingstyle">Writing Style</a></li>
</ol>
</li>
<li><a href="#vcs">VCS Guidelines</a>
<ol style="list-style-type: lower-roman;">
<li><a href="#repostruct">Repository structure</a></li>
<li><a href="#commitmessage">Commit messages</a></li>
</ol>
</li>
<li><a href="#changes">Guidelines Changelog</a></li>
<li><a href="#disclaimer">Copyright and disclaimer</a></li>
</ol>
@ -217,6 +224,54 @@ class ...
<li><strong>styles</strong><br /><code>/styles</code>, <code>style.php</code><br />phpBB Styles/Templates/Themes/Imagesets</li>
</ul>
<a name="constants"></a></h3>1.iv. Special Constants</h3>
<p>There are some special constants application developers are able to utilize to bend some of phpBB's internal functionality to suit their needs.</p>
<div class="codebox"><pre>
PHPBB_MSG_HANDLER (overwrite message handler)
PHPBB_DB_NEW_LINK (overwrite new_link parameter for sql_connect)
PHPBB_ROOT_PATH (overwrite $phpbb_root_path)
PHPBB_ADMIN_PATH (overwrite $phpbb_admin_path)
PHPBB_USE_BOARD_URL_PATH (use generate_board_url() for image paths instead of $phpbb_root_path)
PHPBB_DISABLE_ACP_EDITOR (disable ACP style editor for templates)
PHPBB_DISABLE_CONFIG_CHECK (disable ACP config.php writeable check)
PHPBB_ACM_MEMCACHE_PORT (overwrite memcached port, default is 11211)
PHPBB_ACM_MEMCACHE_COMPRESS (overwrite memcached compress setting, default is disabled)
PHPBB_ACM_MEMCACHE_HOST (overwrite memcached host name, default is localhost)
PHPBB_QA (Set board to QA-Mode, which means the updater also checks for RC-releases)
</pre></div>
<h4>PHPBB_USE_BOARD_URL_PATH</h4>
<p>If the <code>PHPBB_USE_BOARD_URL_PATH</code> constant is set to true, phpBB uses generate_board_url() (this will return the boards url with the script path included) on all instances where web-accessible images are loaded. The exact locations are:</p>
<ul>
<li>/includes/session.php - user::img()</li>
<li>/includes/functions_content.php - smiley_text()</li>
</ul>
<p>Path locations for the following template variables are affected by this too:</p>
<ul>
<li>{T_THEME_PATH} - styles/xxx/theme</li>
<li>{T_TEMPLATE_PATH} - styles/xxx/template</li>
<li>{T_SUPER_TEMPLATE_PATH} - styles/xxx/template</li>
<li>{T_IMAGESET_PATH} - styles/xxx/imageset</li>
<li>{T_IMAGESET_LANG_PATH} - styles/xxx/imageset/yy</li>
<li>{T_IMAGES_PATH} - images/</li>
<li>{T_SMILIES_PATH} - $config['smilies_path']/</li>
<li>{T_AVATAR_PATH} - $config['avatar_path']/</li>
<li>{T_AVATAR_GALLERY_PATH} - $config['avatar_gallery_path']/</li>
<li>{T_ICONS_PATH} - $config['icons_path']/</li>
<li>{T_RANKS_PATH} - $config['ranks_path']/</li>
<li>{T_UPLOAD_PATH} - $config['upload_path']/</li>
<li>{T_STYLESHEET_LINK} - styles/xxx/theme/stylesheet.css (or link to style.php if css is parsed dynamically)</li>
<li>New template variable {BOARD_URL} for the board url + script path.</li>
</ul>
</div>
<div class="back2top"><a href="#wrap" class="top">Back to Top</a></div>
@ -1110,6 +1165,29 @@ append_sid(&quot;{$phpbb_root_path}memberlist.$phpEx&quot;, 'mode=group&amp;amp;
<p>You will note in the 3.0 templates the major sources start with <code>&lt;!-- INCLUDE overall_header.html --&gt;</code> or <code>&lt;!-- INCLUDE simple_header.html --&gt;</code>, etc. In 2.0.x control of &quot;which&quot; header to use was defined entirely within the code. In 3.0.x the template designer can output what they like. Note that you can introduce new templates (i.e. other than those in the default set) using this system and include them as you wish ... perhaps useful for a common &quot;menu&quot; bar or some such. No need to modify loads of files as with 2.0.x.</p>
<p>Added in <strong>3.0.6</strong> is the ability to include a file using a template variable to specify the file, this functionality only works for root variables (i.e. not block variables).</p>
<div class="codebox"><pre>
<span class="comment">&lt;!-- INCLUDE {FILE_VAR} --&gt;</span>
</pre></div>
<p>Template defined variables can also be utilised.
<div class="codebox"><pre>
<span class="comment">&lt;!-- DEFINE $SOME_VAR = 'my_file.html' --&gt;</span>
<span class="comment">&lt;!-- INCLUDE {$SOME_VAR} --&gt;</span>
</pre></div>
<!-- no longer added in 3.0.6
<p>Also added in <strong>3.0.6</strong> is the ability to increment or decrement a variable on use. This can be used for instances like tabindexes, where the amount of entries is not statically known.
The INC (for incrementing) and DEC (for decrementing) commands will print the <strong>current</strong> state of a defined var and then increment/decrement it by one (postincrement/postdecrement).</p>
<div class="codebox"><pre>
<span class="comment">&lt;!-- DEFINE $SOME_VAR = 1 --&gt;</span>
<span class="comment">&lt;!-- INC $SOME_VAR --&gt;</span>
Result: 1<br />
<span class="comment">{$SOME_VAR}</span>
Result: 2<br />
</pre></div>
//-->
<h4>PHP</h4>
<p>A contentious decision has seen the ability to include PHP within the template introduced. This is achieved by enclosing the PHP within relevant tags:</p>
@ -2252,12 +2330,71 @@ if (utf8_case_fold_nfc($string1) == utf8_case_fold_nfc($string2))
<hr />
<a name="changes"></a><h2>7. Guidelines Changelog</h2>
<a name="vcs"></a><h2>7. VCS Guidelines</h2>
<div class="paragraph">
<div class="inner"><span class="corners-top"><span></span></span>
<div class="content">
<p>The version control system for phpBB3 is subversion. The repository is available at <a href="http://code.phpbb.com/svn/phpbb" title="repository">http://code.phpbb.com/svn/phpbb</a>.
<a name="repostruct"></a><h3>7.i. Repository Structure</h3>
<ul>
<li><strong>trunk</strong><br />The latest unstable development version with new features etc. Contains the actual board in <code>/trunk/phpBB</code></li>
<li><strong>branches</strong><br />Development branches of stable phpBB releases. Copied from <code>/trunk</code> at the time of release.
<ul>
<li><strong>phpBB3.0</strong><code>/branches/phpBB-3_0_0/phpBB</code><br />Development branch of the stable 3.0 line. Bug fixes are applied here.</li>
<li><strong>phpBB2</strong><code>/branches/phpBB-2_0_0/phpBB</code><br />Old phpBB2 development branch.</li>
</ul>
</li>
<li><strong>tags</strong><br />Released versions. Copies of trunk or the respective branch, made at the time of release.
<ul>
<li><code>/tags/release_3_0_BX</code><br />Beta release X of the 3.0 line.</li>
<li><code>/tags/release_3_0_RCX</code><br />Release candidate X of the 3.0 line.</li>
<li><code>/tags/release_3_0_X-RCY</code><br />Release candidate Y of the stable 3.0.X release.</li>
<li><code>/tags/release_3_0_X</code><br />Stable <strong>3.0.X</strong> release.</li>
<li><code>/tags/release_2_0_X</code><br />Old stable 2.0.X release.</li>
</ul>
</li>
</ul>
<a name="commitmessage"></a><h3>7.ii. Commit Messages</h3>
<p>The commit message should contain a brief explanation of all changes made within the commit. Often identical to the changelog entry. A bug ticket can be referenced by specifying the ticket ID with a hash, e.g. #12345. A reference to another revision should simply be prefixed with r, e.g. r12345.</p>
<p>Junior Developers need to have their patches approved by a development team member first. The commit message must end in a line with the following format:</p>
<div class="codebox"><pre>
Authorised by: developer1[, developer2[, ...]]
</pre></div>
</div>
<div class="back2top"><a href="#wrap" class="top">Back to Top</a></div>
<span class="corners-bottom"><span></span></span></div>
</div>
<hr />
<a name="changes"></a><h2>8. Guidelines Changelog</h2>
<div class="paragraph">
<div class="inner"><span class="corners-top"><span></span></span>
<div class="content">
<h3>Revision 10007</h3>
<ul>
<li>Added <a href="#constants">Special Constants</a> section.</li>
</ul>
<h3>Revision 9817</h3>
<ul>
<li>Added VCS section.</li>
</ul>
<h3>Revision 8732</h3>
@ -2330,7 +2467,7 @@ if (utf8_case_fold_nfc($string1) == utf8_case_fold_nfc($string2))
<hr />
<a name="disclaimer"></a><h2>8. Copyright and disclaimer</h2>
<a name="disclaimer"></a><h2>9. Copyright and disclaimer</h2>
<div class="paragraph">
<div class="inner"><span class="corners-top"><span></span></span>

View file

@ -104,14 +104,14 @@ h3 {
border-top: 1px solid #ccc;
}
code {
color: #006600;
font-weight: normal;
font-family: 'Courier New', monospace;
border-color: #D1D7DC;
border-width: 1px;
border-style: solid;
background-color: #FAFAFA;
code {
color: #006600;
font-weight: normal;
font-family: 'Courier New', monospace;
border-color: #D1D7DC;
border-width: 1px;
border-style: solid;
background-color: #FAFAFA;
}
#wrap {
@ -387,8 +387,36 @@ PHPBB_MSG_HANDLER (overwrite message handler)
PHPBB_DB_NEW_LINK (overwrite new_link parameter for sql_connect)
PHPBB_ROOT_PATH (overwrite $phpbb_root_path)
PHPBB_ADMIN_PATH (overwrite $phpbb_admin_path)
PHPBB_USE_BOARD_URL_PATH (use generate_board_url() for image paths instead of $phpbb_root_path)
</pre></div>
<p>If the <code>PHPBB_USE_BOARD_URL_PATH</code> constant is set to true, phpBB uses generate_board_url() (this will return the boards url with the script path included) on all instances where web-accessible images are loaded. The exact locations are:</p>
<ul>
<li>/includes/session.php - user::img()</li>
<li>/includes/functions_content.php - smiley_text()</li>
</ul>
<p>Path locations for the following template variables are affected by this too:</p>
<ul>
<li>{T_THEME_PATH} - styles/xxx/theme</li>
<li>{T_TEMPLATE_PATH} - styles/xxx/template</li>
<li>{T_SUPER_TEMPLATE_PATH} - styles/xxx/template</li>
<li>{T_IMAGESET_PATH} - styles/xxx/imageset</li>
<li>{T_IMAGESET_LANG_PATH} - styles/xxx/imageset/yy</li>
<li>{T_IMAGES_PATH} - images/</li>
<li>{T_SMILIES_PATH} - $config['smilies_path']/</li>
<li>{T_AVATAR_PATH} - $config['avatar_path']/</li>
<li>{T_AVATAR_GALLERY_PATH} - $config['avatar_gallery_path']/</li>
<li>{T_ICONS_PATH} - $config['icons_path']/</li>
<li>{T_RANKS_PATH} - $config['ranks_path']/</li>
<li>{T_UPLOAD_PATH} - $config['upload_path']/</li>
<li>{T_STYLESHEET_LINK} - styles/xxx/theme/stylesheet.css (or link to style.php if css is parsed dynamically)</li>
<li>New template variable {BOARD_URL} for the board url + script path.</li>
</ul>
</div>
<div class="back2top"><a href="#wrap" class="top">Back to Top</a></div>
@ -616,7 +644,7 @@ echo $second_object-&gt;hook_me('first', 'second') . '&lt;br /&gt;';
<div class="codebox"><pre>
not hooked
hooked
hooked
</pre></div>
<p>A different possibility would be using a function variable (which could be left out on passing the function variables to the hook):</p>
@ -670,7 +698,7 @@ echo $second_object-&gt;hook_me('first', 'second') . '&lt;br /&gt;';
<div class="codebox"><pre>
not hooked
hooked
hooked
</pre></div>
</div>

View file

@ -249,7 +249,7 @@ if (!$attachment)
trigger_error('ERROR_NO_ATTACHMENT');
}
$attachment['physical_filename'] = basename($attachment['physical_filename']);
$attachment['physical_filename'] = utf8_basename($attachment['physical_filename']);
$display_cat = $extensions[$attachment['extension']]['display_cat'];
if (($display_cat == ATTACHMENT_CATEGORY_IMAGE || $display_cat == ATTACHMENT_CATEGORY_THUMB) && !$user->optionget('viewimg'))

View file

@ -38,15 +38,28 @@ switch ($mode)
}
// Pull the array data from the lang pack
$switch_column = $found_switch = false;
$help_blocks = array();
foreach ($user->help as $help_ary)
{
if ($help_ary[0] == '--')
{
$template->assign_block_vars('faq_block', array(
'BLOCK_TITLE' => $help_ary[1])
);
if ($help_ary[1] == '--')
{
$switch_column = true;
$found_switch = true;
continue;
}
$template->assign_block_vars('faq_block', array(
'BLOCK_TITLE' => $help_ary[1],
'SWITCH_COLUMN' => $switch_column,
));
if ($switch_column)
{
$switch_column = false;
}
continue;
}
@ -58,11 +71,13 @@ foreach ($user->help as $help_ary)
// Lets build a page ...
$template->assign_vars(array(
'L_FAQ_TITLE' => $l_title,
'L_BACK_TO_TOP' => $user->lang['BACK_TO_TOP'])
);
'L_FAQ_TITLE' => $l_title,
'L_BACK_TO_TOP' => $user->lang['BACK_TO_TOP'],
page_header($l_title);
'SWITCH_COLUMN_MANUALLY' => (!$found_switch) ? true : false,
));
page_header($l_title, false);
$template->set_filenames(array(
'body' => 'faq_body.html')

1064
phpBB/feed.php Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,84 @@
<?php
/**
*
* @package acm
* @version $Id$
* @copyright (c) 2005, 2009 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
// Include the abstract base
if (!class_exists('acm_memory'))
{
require("{$phpbb_root_path}includes/acm/acm_memory.$phpEx");
}
/**
* ACM for APC
* @package acm
*/
class acm extends acm_memory
{
var $extension = 'apc';
/**
* Purge cache data
*
* @return void
*/
function purge()
{
apc_clear_cache('user');
parent::purge();
}
/**
* Fetch an item from the cache
*
* @access protected
* @param string $var Cache key
* @return mixed Cached data
*/
function _read($var)
{
return apc_fetch($this->key_prefix . $var);
}
/**
* Store data in the cache
*
* @access protected
* @param string $var Cache key
* @param mixed $data Data to store
* @param int $ttl Time-to-live of cached data
* @return bool True if the operation succeeded
*/
function _write($var, $data, $ttl = 2592000)
{
return apc_store($this->key_prefix . $var, $data, $ttl);
}
/**
* Remove an item from the cache
*
* @access protected
* @param string $var Cache key
* @return bool True if the operation succeeded
*/
function _delete($var)
{
return apc_delete($this->key_prefix . $var);
}
}
?>

View file

@ -0,0 +1,120 @@
<?php
/**
*
* @package acm
* @version $Id$
* @copyright (c) 2005, 2009 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
// Include the abstract base
if (!class_exists('acm_memory'))
{
require("{$phpbb_root_path}includes/acm/acm_memory.$phpEx");
}
/**
* ACM for eAccelerator
* @package acm
* @todo Missing locks from destroy() talk with David
*/
class acm extends acm_memory
{
var $extension = 'eaccelerator';
var $serialize_header = '#phpbb-serialized#';
/**
* Purge cache data
*
* @return void
*/
function purge()
{
foreach (eaccelerator_list_keys() as $var)
{
// @todo Check why the substr()
// @todo Only unset vars matching $this->key_prefix
eaccelerator_rm(substr($var['name'], 1));
}
parent::purge();
}
/**
* Perform cache garbage collection
*
* @return void
*/
function tidy()
{
eaccelerator_gc();
set_config('cache_last_gc', time(), true);
}
/**
* Fetch an item from the cache
*
* @access protected
* @param string $var Cache key
* @return mixed Cached data
*/
function _read($var)
{
$result = eaccelerator_get($this->key_prefix . $var);
if ($result === null)
{
return false;
}
// Handle serialized objects
if (is_string($result) && strpos($result, $this->serialize_header . 'O:') === 0)
{
$result = unserialize(substr($result, strlen($this->serialize_header)));
}
return $result;
}
/**
* Store data in the cache
*
* @access protected
* @param string $var Cache key
* @param mixed $data Data to store
* @param int $ttl Time-to-live of cached data
* @return bool True if the operation succeeded
*/
function _write($var, $data, $ttl = 2592000)
{
// Serialize objects and make them easy to detect
$data = (is_object($data)) ? $this->serialize_header . serialize($data) : $data;
return eaccelerator_put($this->key_prefix . $var, $data, $ttl);
}
/**
* Remove an item from the cache
*
* @access protected
* @param string $var Cache key
* @return bool True if the operation succeeded
*/
function _delete($var)
{
return eaccelerator_rm($this->key_prefix . $var);
}
}
?>

View file

@ -3,7 +3,7 @@
*
* @package acm
* @version $Id$
* @copyright (c) 2005 phpBB Group
* @copyright (c) 2005, 2009 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*
*/
@ -44,17 +44,7 @@ class acm
*/
function load()
{
global $phpEx;
if (file_exists($this->cache_dir . 'data_global.' . $phpEx))
{
@include($this->cache_dir . 'data_global.' . $phpEx);
}
else
{
return false;
}
return true;
return $this->_read('data_global');
}
/**
@ -86,22 +76,7 @@ class acm
global $phpEx;
if ($fp = @fopen($this->cache_dir . 'data_global.' . $phpEx, 'wb'))
{
@flock($fp, LOCK_EX);
fwrite($fp, "<?php\nif (!defined('IN_PHPBB')) exit;\n\$this->vars = " . var_export($this->vars, true) . ";\n\n\$this->var_expires = " . var_export($this->var_expires, true) . "\n?>");
@flock($fp, LOCK_UN);
fclose($fp);
if (!function_exists('phpbb_chmod'))
{
global $phpbb_root_path;
include($phpbb_root_path . 'includes/functions.' . $phpEx);
}
phpbb_chmod($this->cache_dir . 'data_global.' . $phpEx, CHMOD_READ | CHMOD_WRITE);
}
else
if (!$this->_write('data_global'))
{
// Now, this occurred how often? ... phew, just tell the user then...
if (!@is_writable($this->cache_dir))
@ -132,6 +107,8 @@ class acm
return;
}
$time = time();
while (($entry = readdir($dir)) !== false)
{
if (!preg_match('/^(sql_|data_(?!global))/', $entry))
@ -139,9 +116,20 @@ class acm
continue;
}
$expired = true;
@include($this->cache_dir . $entry);
if ($expired)
if (!($handle = @fopen($this->cache_dir . $entry, 'rb')))
{
continue;
}
// Skip the PHP header
fgets($handle);
// Skip expiration
$expires = (int) fgets($handle);
fclose($handle);
if ($time >= $expires)
{
$this->remove_file($this->cache_dir . $entry);
}
@ -157,7 +145,7 @@ class acm
foreach ($this->var_expires as $var_name => $expires)
{
if (time() > $expires)
if ($time >= $expires)
{
$this->destroy($var_name);
}
@ -181,8 +169,7 @@ class acm
return false;
}
@include($this->cache_dir . "data{$var_name}.$phpEx");
return (isset($data)) ? $data : false;
return $this->_read('data' . $var_name);
}
else
{
@ -197,23 +184,7 @@ class acm
{
if ($var_name[0] == '_')
{
global $phpEx;
if ($fp = @fopen($this->cache_dir . "data{$var_name}.$phpEx", 'wb'))
{
@flock($fp, LOCK_EX);
fwrite($fp, "<?php\nif (!defined('IN_PHPBB')) exit;\n\$expired = (time() > " . (time() + $ttl) . ") ? true : false;\nif (\$expired) { return; }\n\n\$data = " . (sizeof($var) ? "unserialize(" . var_export(serialize($var), true) . ");" : 'array();') . "\n\n?>");
@flock($fp, LOCK_UN);
fclose($fp);
if (!function_exists('phpbb_chmod'))
{
global $phpbb_root_path;
include($phpbb_root_path . 'includes/functions.' . $phpEx);
}
phpbb_chmod($this->cache_dir . "data{$var_name}.$phpEx", CHMOD_READ | CHMOD_WRITE);
}
$this->_write('data' . $var_name, $var, time() + $ttl);
}
else
{
@ -288,32 +259,31 @@ class acm
continue;
}
// The following method is more failproof than simply assuming the query is on line 3 (which it should be)
$check_line = @file_get_contents($this->cache_dir . $entry);
if (empty($check_line))
if (!($handle = @fopen($this->cache_dir . $entry, 'rb')))
{
continue;
}
// Now get the contents between /* and */
$check_line = substr($check_line, strpos($check_line, '/* ') + 3, strpos($check_line, ' */') - strpos($check_line, '/* ') - 3);
// Skip the PHP header
fgets($handle);
// Skip expiration
fgets($handle);
// Grab the query, remove the LF
$query = substr(fgets($handle), 0, -1);
fclose($handle);
$found = false;
foreach ($table as $check_table)
{
// Better catch partial table names than no table names. ;)
if (strpos($check_line, $check_table) !== false)
if (strpos($query, $check_table) !== false)
{
$found = true;
$this->remove_file($this->cache_dir . $entry);
break;
}
}
if ($found)
{
$this->remove_file($this->cache_dir . $entry);
}
}
closedir($dir);
@ -371,29 +341,16 @@ class acm
*/
function sql_load($query)
{
global $phpEx;
// Remove extra spaces and tabs
$query = preg_replace('/[\n\r\s\t]+/', ' ', $query);
if (($rowset = $this->_read('sql_' . md5($query))) === false)
{
return false;
}
$query_id = sizeof($this->sql_rowset);
if (!file_exists($this->cache_dir . 'sql_' . md5($query) . ".$phpEx"))
{
return false;
}
@include($this->cache_dir . 'sql_' . md5($query) . ".$phpEx");
if (!isset($expired))
{
return false;
}
else if ($expired)
{
$this->remove_file($this->cache_dir . 'sql_' . md5($query) . ".$phpEx", true);
return false;
}
$this->sql_rowset[$query_id] = $rowset;
$this->sql_row_pointer[$query_id] = 0;
return $query_id;
@ -404,41 +361,23 @@ class acm
*/
function sql_save($query, &$query_result, $ttl)
{
global $db, $phpEx;
global $db;
// Remove extra spaces and tabs
$query = preg_replace('/[\n\r\s\t]+/', ' ', $query);
$filename = $this->cache_dir . 'sql_' . md5($query) . '.' . $phpEx;
if ($fp = @fopen($filename, 'wb'))
$query_id = sizeof($this->sql_rowset);
$this->sql_rowset[$query_id] = array();
$this->sql_row_pointer[$query_id] = 0;
while ($row = $db->sql_fetchrow($query_result))
{
@flock($fp, LOCK_EX);
$query_id = sizeof($this->sql_rowset);
$this->sql_rowset[$query_id] = array();
$this->sql_row_pointer[$query_id] = 0;
while ($row = $db->sql_fetchrow($query_result))
{
$this->sql_rowset[$query_id][] = $row;
}
$db->sql_freeresult($query_result);
$file = "<?php\nif (!defined('IN_PHPBB')) exit;\n\n/* " . str_replace('*/', '*\/', $query) . " */\n";
$file .= "\n\$expired = (time() > " . (time() + $ttl) . ") ? true : false;\nif (\$expired) { return; }\n";
fwrite($fp, $file . "\n\$this->sql_rowset[\$query_id] = " . (sizeof($this->sql_rowset[$query_id]) ? "unserialize(" . var_export(serialize($this->sql_rowset[$query_id]), true) . ");" : 'array();') . "\n\n?>");
@flock($fp, LOCK_UN);
fclose($fp);
if (!function_exists('phpbb_chmod'))
{
global $phpbb_root_path;
include($phpbb_root_path . 'includes/functions.' . $phpEx);
}
phpbb_chmod($filename, CHMOD_READ | CHMOD_WRITE);
$this->sql_rowset[$query_id][] = $row;
}
$db->sql_freeresult($query_result);
if ($this->_write('sql_' . md5($query), $this->sql_rowset[$query_id], $ttl + time(), $query))
{
$query_result = $query_id;
}
}
@ -507,6 +446,262 @@ class acm
return true;
}
/**
* Read cached data from a specified file
*
* @access private
* @param string $filename Filename to write
* @return mixed False if an error was encountered, otherwise the data type of the cached data
*/
function _read($filename)
{
global $phpEx;
$file = "{$this->cache_dir}$filename.$phpEx";
$type = substr($filename, 0, strpos($filename, '_'));
if (!file_exists($file))
{
return false;
}
if (!($handle = @fopen($file, 'rb')))
{
return false;
}
// Skip the PHP header
fgets($handle);
if ($filename == 'data_global')
{
$this->vars = $this->var_expires = array();
$time = time();
while (($expires = (int) fgets($handle)) && !feof($handle))
{
// Number of bytes of data
$bytes = substr(fgets($handle), 0, -1);
if (!is_numeric($bytes) || ($bytes = (int) $bytes) === 0)
{
// We cannot process the file without a valid number of bytes
// so we discard it
fclose($handle);
$this->vars = $this->var_expires = array();
$this->is_modified = false;
$this->remove_file($file);
return false;
}
if ($time >= $expires)
{
fseek($handle, $bytes, SEEK_CUR);
continue;
}
$var_name = substr(fgets($handle), 0, -1);
// Read the length of bytes that consists of data.
$data = fread($handle, $bytes - strlen($var_name));
$data = @unserialize($data);
// Don't use the data if it was invalid
if ($data !== false)
{
$this->vars[$var_name] = $data;
$this->var_expires[$var_name] = $expires;
}
// Absorb the LF
fgets($handle);
}
fclose($handle);
$this->is_modified = false;
return true;
}
else
{
$data = false;
$line = 0;
while (($buffer = fgets($handle)) && !feof($handle))
{
$buffer = substr($buffer, 0, -1); // Remove the LF
// $buffer is only used to read integers
// if it is non numeric we have an invalid
// cache file, which we will now remove.
if (!is_numeric($buffer))
{
break;
}
if ($line == 0)
{
$expires = (int) $buffer;
if (time() >= $expires)
{
break;
}
if ($type == 'sql')
{
// Skip the query
fgets($handle);
}
}
else if ($line == 1)
{
$bytes = (int) $buffer;
// Never should have 0 bytes
if (!$bytes)
{
break;
}
// Grab the serialized data
$data = fread($handle, $bytes);
// Read 1 byte, to trigger EOF
fread($handle, 1);
if (!feof($handle))
{
// Somebody tampered with our data
$data = false;
}
break;
}
else
{
// Something went wrong
break;
}
$line++;
}
fclose($handle);
// unserialize if we got some data
$data = ($data !== false) ? @unserialize($data) : $data;
if ($data === false)
{
$this->remove_file($file);
return false;
}
return $data;
}
}
/**
* Write cache data to a specified file
*
* 'data_global' is a special case and the generated format is different for this file:
* <code>
* <?php exit; ?>
* (expiration)
* (length of var and serialised data)
* (var)
* (serialised data)
* ... (repeat)
* </code>
*
* The other files have a similar format:
* <code>
* <?php exit; ?>
* (expiration)
* (query) [SQL files only]
* (length of serialised data)
* (serialised data)
* </code>
*
* @access private
* @param string $filename Filename to write
* @param mixed $data Data to store
* @param int $expires Timestamp when the data expires
* @param string $query Query when caching SQL queries
* @return bool True if the file was successfully created, otherwise false
*/
function _write($filename, $data = null, $expires = 0, $query = '')
{
global $phpEx;
$file = "{$this->cache_dir}$filename.$phpEx";
if ($handle = @fopen($file, 'wb'))
{
@flock($handle, LOCK_EX);
// File header
fwrite($handle, '<' . '?php exit; ?' . '>');
if ($filename == 'data_global')
{
// Global data is a different format
foreach ($this->vars as $var => $data)
{
if (strpos($var, "\r") !== false || strpos($var, "\n") !== false)
{
// CR/LF would cause fgets() to read the cache file incorrectly
// do not cache test entries, they probably won't be read back
// the cache keys should really be alphanumeric with a few symbols.
continue;
}
$data = serialize($data);
// Write out the expiration time
fwrite($handle, "\n" . $this->var_expires[$var] . "\n");
// Length of the remaining data for this var (ignoring two LF's)
fwrite($handle, strlen($data . $var) . "\n");
fwrite($handle, $var . "\n");
fwrite($handle, $data);
}
}
else
{
fwrite($handle, "\n" . $expires . "\n");
if (strpos($filename, 'sql_') === 0)
{
fwrite($handle, $query . "\n");
}
$data = serialize($data);
fwrite($handle, strlen($data) . "\n");
fwrite($handle, $data);
}
@flock($handle, LOCK_UN);
fclose($handle);
if (!function_exists('phpbb_chmod'))
{
global $phpbb_root_path;
include($phpbb_root_path . 'includes/functions.' . $phpEx);
}
phpbb_chmod($file, CHMOD_READ | CHMOD_WRITE);
return true;
}
return false;
}
/**
* Removes/unlinks file
*/

View file

@ -0,0 +1,124 @@
<?php
/**
*
* @package acm
* @version $Id$
* @copyright (c) 2005, 2009 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
// Include the abstract base
if (!class_exists('acm_memory'))
{
require("{$phpbb_root_path}includes/acm/acm_memory.$phpEx");
}
if (!defined('PHPBB_ACM_MEMCACHE_PORT'))
{
define('PHPBB_ACM_MEMCACHE_PORT', 11211);
}
if (!defined('PHPBB_ACM_MEMCACHE_COMPRESS'))
{
define('PHPBB_ACM_MEMCACHE_COMPRESS', false);
}
if (!defined('PHPBB_ACM_MEMCACHE_HOST'))
{
define('PHPBB_ACM_MEMCACHE_HOST', 'localhost');
}
/**
* ACM for Memcached
* @package acm
*/
class acm extends acm_memory
{
var $extension = 'memcache';
var $memcache;
var $flags = 0;
function acm()
{
// Call the parent constructor
parent::acm_memory();
$this->memcache = new Memcache;
$this->memcache->connect(PHPBB_ACM_MEMCACHE_HOST, PHPBB_ACM_MEMCACHE_PORT);
$this->flags = (PHPBB_ACM_MEMCACHE_COMPRESS) ? MEMCACHE_COMPRESSED : 0;
}
/**
* Unload the cache resources
*
* @return void
*/
function unload()
{
parent::unload();
$this->memcache->close();
}
/**
* Purge cache data
*
* @return void
*/
function purge()
{
$this->memcache->flush();
parent::purge();
}
/**
* Fetch an item from the cache
*
* @access protected
* @param string $var Cache key
* @return mixed Cached data
*/
function _read($var)
{
return $this->memcache->get($this->key_prefix . $var);
}
/**
* Store data in the cache
*
* @access protected
* @param string $var Cache key
* @param mixed $data Data to store
* @param int $ttl Time-to-live of cached data
* @return bool True if the operation succeeded
*/
function _write($var, $data, $ttl = 2592000)
{
return $this->memcache->set($this->key_prefix . $var, $data, $this->flags, $ttl);
}
/**
* Remove an item from the cache
*
* @access protected
* @param string $var Cache key
* @return bool True if the operation succeeded
*/
function _delete($var)
{
return $this->memcache->delete($this->key_prefix . $var);
}
}
?>

View file

@ -0,0 +1,426 @@
<?php
/**
*
* @package acm
* @version $Id$
* @copyright (c) 2005 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* ACM Abstract Memory Class
* @package acm
*/
class acm_memory
{
var $key_prefix;
var $vars = array();
var $is_modified = false;
var $sql_rowset = array();
var $sql_row_pointer = array();
var $cache_dir = '';
/**
* Set cache path
*/
function acm_memory()
{
global $phpbb_root_path, $dbname, $table_prefix;
$this->cache_dir = $phpbb_root_path . 'cache/';
$this->key_prefix = substr(md5($dbname . $table_prefix), 0, 8) . '_';
if (!isset($this->extension) || !extension_loaded($this->extension))
{
global $acm_type;
trigger_error("Could not find required extension [{$this->extension}] for the ACM module $acm_type.", E_USER_ERROR);
}
}
/**
* Load global cache
*/
function load()
{
// grab the global cache
$this->vars = $this->_read('global');
if ($this->vars !== false)
{
return true;
}
return false;
}
/**
* Unload cache object
*/
function unload()
{
$this->save();
unset($this->vars);
unset($this->sql_rowset);
unset($this->sql_row_pointer);
$this->vars = array();
$this->sql_rowset = array();
$this->sql_row_pointer = array();
}
/**
* Save modified objects
*/
function save()
{
if (!$this->is_modified)
{
return;
}
$this->_write('global', $this->vars, 2592000);
$this->is_modified = false;
}
/**
* Tidy cache
*/
function tidy()
{
// cache has auto GC, no need to have any code here :)
set_config('cache_last_gc', time(), true);
}
/**
* Get saved cache object
*/
function get($var_name)
{
if ($var_name[0] == '_')
{
if (!$this->_exists($var_name))
{
return false;
}
return $this->_read($var_name);
}
else
{
return ($this->_exists($var_name)) ? $this->vars[$var_name] : false;
}
}
/**
* Put data into cache
*/
function put($var_name, $var, $ttl = 2592000)
{
if ($var_name[0] == '_')
{
$this->_write($var_name, $var, $ttl);
}
else
{
$this->vars[$var_name] = $var;
$this->is_modified = true;
}
}
/**
* Purge cache data
*/
function purge()
{
// Purge all phpbb cache files
$dir = @opendir($this->cache_dir);
if (!$dir)
{
return;
}
while (($entry = readdir($dir)) !== false)
{
if (strpos($entry, 'sql_') !== 0 && strpos($entry, 'data_') !== 0 && strpos($entry, 'ctpl_') !== 0 && strpos($entry, 'tpl_') !== 0)
{
continue;
}
$this->remove_file($this->cache_dir . $entry);
}
closedir($dir);
unset($this->vars);
unset($this->sql_rowset);
unset($this->sql_row_pointer);
$this->vars = array();
$this->sql_rowset = array();
$this->sql_row_pointer = array();
$this->is_modified = false;
}
/**
* Destroy cache data
*/
function destroy($var_name, $table = '')
{
if ($var_name == 'sql' && !empty($table))
{
if (!is_array($table))
{
$table = array($table);
}
foreach ($table as $table_name)
{
// gives us the md5s that we want
$temp = $this->_read('sql_' . $table_name);
if ($temp === false)
{
continue;
}
// delete each query ref
foreach ($temp as $md5_id => $void)
{
$this->_delete('sql_' . $md5_id);
}
// delete the table ref
$this->_delete('sql_' . $table_name);
}
return;
}
if (!$this->_exists($var_name))
{
return;
}
if ($var_name[0] == '_')
{
$this->_delete($var_name);
}
else if (isset($this->vars[$var_name]))
{
$this->is_modified = true;
unset($this->vars[$var_name]);
// We save here to let the following cache hits succeed
$this->save();
}
}
/**
* Check if a given cache entry exist
*/
function _exists($var_name)
{
if ($var_name[0] == '_')
{
return $this->_isset($var_name);
}
else
{
if (!sizeof($this->vars))
{
$this->load();
}
return isset($this->vars[$var_name]);
}
}
/**
* Load cached sql query
*/
function sql_load($query)
{
// Remove extra spaces and tabs
$query = preg_replace('/[\n\r\s\t]+/', ' ', $query);
$query_id = sizeof($this->sql_rowset);
if (($result = $this->_read('sql_' . md5($query))) === false)
{
return false;
}
$this->sql_rowset[$query_id] = $result;
$this->sql_row_pointer[$query_id] = 0;
return $query_id;
}
/**
* Save sql query
*/
function sql_save($query, &$query_result, $ttl)
{
global $db;
// Remove extra spaces and tabs
$query = preg_replace('/[\n\r\s\t]+/', ' ', $query);
$hash = md5($query);
// determine which tables this query belongs to
// Some queries use backticks, namely the get_database_size() query
// don't check for conformity, the SQL would error and not reach here.
if (!preg_match('/FROM \\(?(`?\\w+`?(?: \\w+)?(?:, ?`?\\w+`?(?: \\w+)?)*)\\)?/', $query, $regs))
{
// Bail out if the match fails.
return;
}
$tables = array_map('trim', explode(',', $regs[1]));
foreach ($tables as $table_name)
{
// Remove backticks
$table_name = ($table_name[0] == '`') ? substr($table_name, 1, -1) : $table_name;
if (($pos = strpos($table_name, ' ')) !== false)
{
$table_name = substr($table_name, 0, $pos);
}
$temp = $this->_read('sql_' . $table_name);
if ($temp === false)
{
$temp = array();
}
$temp[$hash] = true;
// This must never expire
$this->_write('sql_' . $table_name, $temp, 0);
}
// store them in the right place
$query_id = sizeof($this->sql_rowset);
$this->sql_rowset[$query_id] = array();
$this->sql_row_pointer[$query_id] = 0;
while ($row = $db->sql_fetchrow($query_result))
{
$this->sql_rowset[$query_id][] = $row;
}
$db->sql_freeresult($query_result);
$this->_write('sql_' . $hash, $this->sql_rowset[$query_id], $ttl);
$query_result = $query_id;
}
/**
* Ceck if a given sql query exist in cache
*/
function sql_exists($query_id)
{
return isset($this->sql_rowset[$query_id]);
}
/**
* Fetch row from cache (database)
*/
function sql_fetchrow($query_id)
{
if ($this->sql_row_pointer[$query_id] < sizeof($this->sql_rowset[$query_id]))
{
return $this->sql_rowset[$query_id][$this->sql_row_pointer[$query_id]++];
}
return false;
}
/**
* Fetch a field from the current row of a cached database result (database)
*/
function sql_fetchfield($query_id, $field)
{
if ($this->sql_row_pointer[$query_id] < sizeof($this->sql_rowset[$query_id]))
{
return (isset($this->sql_rowset[$query_id][$this->sql_row_pointer[$query_id]][$field])) ? $this->sql_rowset[$query_id][$this->sql_row_pointer[$query_id]][$field] : false;
}
return false;
}
/**
* Seek a specific row in an a cached database result (database)
*/
function sql_rowseek($rownum, $query_id)
{
if ($rownum >= sizeof($this->sql_rowset[$query_id]))
{
return false;
}
$this->sql_row_pointer[$query_id] = $rownum;
return true;
}
/**
* Free memory used for a cached database result (database)
*/
function sql_freeresult($query_id)
{
if (!isset($this->sql_rowset[$query_id]))
{
return false;
}
unset($this->sql_rowset[$query_id]);
unset($this->sql_row_pointer[$query_id]);
return true;
}
/**
* Removes/unlinks file
*/
function remove_file($filename, $check = false)
{
if ($check && !@is_writable($this->cache_dir))
{
// E_USER_ERROR - not using language entry - intended.
trigger_error('Unable to remove files within ' . $this->cache_dir . '. Please check directory permissions.', E_USER_ERROR);
}
return @unlink($filename);
}
/**
* Check if a cache var exists
*
* @access protected
* @param string $var Cache key
* @return bool True if it exists, otherwise false
*/
function _isset($var)
{
// Most caches don't need to check
return true;
}
}
?>

View file

@ -0,0 +1,156 @@
<?php
/**
*
* @package acm
* @version $Id$
* @copyright (c) 2005, 2009 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* ACM Null Caching
* @package acm
*/
class acm
{
/**
* Set cache path
*/
function acm()
{
}
/**
* Load global cache
*/
function load()
{
return true;
}
/**
* Unload cache object
*/
function unload()
{
}
/**
* Save modified objects
*/
function save()
{
}
/**
* Tidy cache
*/
function tidy()
{
// This cache always has a tidy room.
set_config('cache_last_gc', time(), true);
}
/**
* Get saved cache object
*/
function get($var_name)
{
return false;
}
/**
* Put data into cache
*/
function put($var_name, $var, $ttl = 0)
{
}
/**
* Purge cache data
*/
function purge()
{
}
/**
* Destroy cache data
*/
function destroy($var_name, $table = '')
{
}
/**
* Check if a given cache entry exist
*/
function _exists($var_name)
{
return false;
}
/**
* Load cached sql query
*/
function sql_load($query)
{
return false;
}
/**
* Save sql query
*/
function sql_save($query, &$query_result, $ttl)
{
}
/**
* Ceck if a given sql query exist in cache
*/
function sql_exists($query_id)
{
return false;
}
/**
* Fetch row from cache (database)
*/
function sql_fetchrow($query_id)
{
return false;
}
/**
* Fetch a field from the current row of a cached database result (database)
*/
function sql_fetchfield($query_id, $field)
{
return false;
}
/**
* Seek a specific row in an a cached database result (database)
*/
function sql_rowseek($rownum, $query_id)
{
return false;
}
/**
* Free memory used for a cached database result (database)
*/
function sql_freeresult($query_id)
{
return false;
}
}
?>

View file

@ -0,0 +1,121 @@
<?php
/**
*
* @package acm
* @version $Id$
* @copyright (c) 2005, 2009 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
// Include the abstract base
if (!class_exists('acm_memory'))
{
require("{$phpbb_root_path}includes/acm/acm_memory.$phpEx");
}
/**
* ACM for XCache
* @package acm
*
* To use this module you need ini_get() enabled and the following INI settings configured as follows:
* - xcache.var_size > 0
* - xcache.admin.enable_auth = off (or xcache.admin.user and xcache.admin.password set)
*
*/
class acm extends acm_memory
{
var $extension = 'XCache';
function acm()
{
parent::acm_memory();
if (!function_exists('ini_get') || (int) ini_get('xcache.var_size') <= 0)
{
trigger_error('Increase xcache.var_size setting above 0 or enable ini_get() to use this ACM module.', E_USER_ERROR);
}
}
/**
* Purge cache data
*
* @return void
*/
function purge()
{
// Run before for XCache, if admin functions are disabled it will terminate execution
parent::purge();
// If the admin authentication is enabled but not set up, this will cause a nasty error.
// Not much we can do about it though.
$n = xcache_count(XC_TYPE_VAR);
for ($i = 0; $i < $n; $i++)
{
xcache_clear_cache(XC_TYPE_VAR, $i);
}
}
/**
* Fetch an item from the cache
*
* @access protected
* @param string $var Cache key
* @return mixed Cached data
*/
function _read($var)
{
$result = xcache_get($this->key_prefix . $var);
return ($result !== null) ? $result : false;
}
/**
* Store data in the cache
*
* @access protected
* @param string $var Cache key
* @param mixed $data Data to store
* @param int $ttl Time-to-live of cached data
* @return bool True if the operation succeeded
*/
function _write($var, $data, $ttl = 2592000)
{
return xcache_set($this->key_prefix . $var, $data, $ttl);
}
/**
* Remove an item from the cache
*
* @access protected
* @param string $var Cache key
* @return bool True if the operation succeeded
*/
function _delete($var)
{
return xcache_unset($this->key_prefix . $var);
}
/**
* Check if a cache var exists
*
* @access protected
* @param string $var Cache key
* @return bool True if it exists, otherwise false
*/
function _isset($var)
{
return xcache_isset($this->key_prefix . $var);
}
}
?>

View file

@ -684,8 +684,9 @@ class acp_attachments
$ext_group_row['max_filesize'] = (int) $config['max_filesize'];
}
$size_format = ($ext_group_row['max_filesize'] >= 1048576) ? 'mb' : (($ext_group_row['max_filesize'] >= 1024) ? 'kb' : 'b');
$ext_group_row['max_filesize'] = get_formatted_filesize($ext_group_row['max_filesize'], false);
$max_filesize = get_formatted_filesize($ext_group_row['max_filesize'], false, array('mb', 'kb', 'b'));
$size_format = $max_filesize['si_identifier'];
$ext_group_row['max_filesize'] = $max_filesize['value'];
$img_path = $config['upload_icons_path'];
@ -694,7 +695,7 @@ class acp_attachments
$imglist = filelist($phpbb_root_path . $img_path);
if (sizeof($imglist))
if (!empty($imglist['']))
{
$imglist = array_values($imglist);
$imglist = $imglist[0];
@ -1026,8 +1027,8 @@ class acp_attachments
$template->assign_block_vars('orphan', array(
'FILESIZE' => get_formatted_filesize($row['filesize']),
'FILETIME' => $user->format_date($row['filetime']),
'REAL_FILENAME' => basename($row['real_filename']),
'PHYSICAL_FILENAME' => basename($row['physical_filename']),
'REAL_FILENAME' => utf8_basename($row['real_filename']),
'PHYSICAL_FILENAME' => utf8_basename($row['physical_filename']),
'ATTACH_ID' => $row['attach_id'],
'POST_IDS' => (!empty($post_ids[$row['attach_id']])) ? $post_ids[$row['attach_id']] : '',
'U_FILE' => append_sid($phpbb_root_path . 'download/file.' . $phpEx, 'mode=view&amp;id=' . $row['attach_id']))
@ -1429,8 +1430,9 @@ class acp_attachments
function max_filesize($value, $key = '')
{
// Determine size var and adjust the value accordingly
$size_var = ($value >= 1048576) ? 'mb' : (($value >= 1024) ? 'kb' : 'b');
$value = get_formatted_filesize($value, false);
$filesize = get_formatted_filesize($value, false, array('mb', 'kb', 'b'));
$size_var = $filesize['si_identifier'];
$value = $filesize['value'];
return '<input type="text" id="' . $key . '" size="8" maxlength="15" name="config[' . $key . ']" value="' . $value . '" /> <select name="' . $key . '">' . size_select_options($size_var) . '</select>';
}

View file

@ -156,7 +156,8 @@ class acp_ban
FROM ' . BANLIST_TABLE . '
WHERE (ban_end >= ' . time() . "
OR ban_end = 0)
AND ban_ip <> ''";
AND ban_ip <> ''
ORDER BY ban_ip";
break;
case 'email':
@ -168,7 +169,8 @@ class acp_ban
FROM ' . BANLIST_TABLE . '
WHERE (ban_end >= ' . time() . "
OR ban_end = 0)
AND ban_email <> ''";
AND ban_email <> ''
ORDER BY ban_email";
break;
}
$result = $db->sql_query($sql);
@ -181,7 +183,22 @@ class acp_ban
$banned_options .= '<option' . (($row['ban_exclude']) ? ' class="sep"' : '') . ' value="' . $row['ban_id'] . '">' . $row[$field] . '</option>';
$time_length = ($row['ban_end']) ? ($row['ban_end'] - $row['ban_start']) / 60 : 0;
$ban_length[$row['ban_id']] = (isset($ban_end_text[$time_length])) ? $ban_end_text[$time_length] : $user->lang['UNTIL'] . ' -> ' . $user->format_date($row['ban_end']);
if ($time_length == 0)
{
// Banned permanently
$ban_length[$row['ban_id']] = $user->lang['PERMANENT'];
}
else if (isset($ban_end_text[$time_length]))
{
// Banned for a given duration
$ban_length[$row['ban_id']] = sprintf($user->lang['BANNED_UNTIL_DURATION'], $ban_end_text[$time_length], $user->format_date($row['ban_end'], false, true));
}
else
{
// Banned until given date
$ban_length[$row['ban_id']] = sprintf($user->lang['BANNED_UNTIL_DATE'], $user->format_date($row['ban_end'], false, true));
}
$ban_reasons[$row['ban_id']] = $row['ban_reason'];
$ban_give_reasons[$row['ban_id']] = $row['ban_give_reason'];

View file

@ -64,6 +64,8 @@ class acp_board
'legend2' => 'WARNINGS',
'warnings_expire_days' => array('lang' => 'WARNINGS_EXPIRE', 'validate' => 'int', 'type' => 'text:3:4', 'explain' => true, 'append' => ' ' . $user->lang['DAYS']),
'legend3' => 'ACP_SUBMIT_CHANGES',
)
);
break;
@ -79,12 +81,14 @@ class acp_board
'allow_namechange' => array('lang' => 'ALLOW_NAME_CHANGE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
'allow_attachments' => array('lang' => 'ALLOW_ATTACHMENTS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
'allow_pm_attach' => array('lang' => 'ALLOW_PM_ATTACHMENTS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
'allow_pm_report' => array('lang' => 'ALLOW_PM_REPORT', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'allow_bbcode' => array('lang' => 'ALLOW_BBCODE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
'allow_smilies' => array('lang' => 'ALLOW_SMILIES', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
'allow_sig' => array('lang' => 'ALLOW_SIG', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
'allow_nocensors' => array('lang' => 'ALLOW_NO_CENSORS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'allow_bookmarks' => array('lang' => 'ALLOW_BOOKMARKS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'allow_birthdays' => array('lang' => 'ALLOW_BIRTHDAYS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'allow_quick_reply' => array('lang' => 'ALLOW_QUICK_REPLY', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'legend2' => 'ACP_LOAD_SETTINGS',
'load_birthdays' => array('lang' => 'YES_BIRTHDAYS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
@ -93,6 +97,8 @@ class acp_board
'load_cpf_memberlist' => array('lang' => 'LOAD_CPF_MEMBERLIST', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
'load_cpf_viewprofile' => array('lang' => 'LOAD_CPF_VIEWPROFILE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
'load_cpf_viewtopic' => array('lang' => 'LOAD_CPF_VIEWTOPIC', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
'legend3' => 'ACP_SUBMIT_CHANGES',
)
);
break;
@ -108,9 +114,11 @@ class acp_board
'avatar_max_width' => array('lang' => 'MAX_AVATAR_SIZE', 'validate' => 'int:0', 'type' => false, 'method' => false, 'explain' => false,),
'avatar_max_height' => array('lang' => 'MAX_AVATAR_SIZE', 'validate' => 'int:0', 'type' => false, 'method' => false, 'explain' => false,),
'allow_avatar' => array('lang' => 'ALLOW_AVATARS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'allow_avatar_local' => array('lang' => 'ALLOW_LOCAL', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
'allow_avatar_remote' => array('lang' => 'ALLOW_REMOTE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'allow_avatar_upload' => array('lang' => 'ALLOW_UPLOAD', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
'allow_avatar_remote_upload'=> array('lang' => 'ALLOW_REMOTE_UPLOAD', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'avatar_filesize' => array('lang' => 'MAX_FILESIZE', 'validate' => 'int:0', 'type' => 'text:4:10', 'explain' => true, 'append' => ' ' . $user->lang['BYTES']),
'avatar_min' => array('lang' => 'MIN_AVATAR_SIZE', 'validate' => 'int:0', 'type' => 'dimension:3:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']),
'avatar_max' => array('lang' => 'MAX_AVATAR_SIZE', 'validate' => 'int:0', 'type' => 'dimension:3:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']),
@ -143,7 +151,9 @@ class acp_board
'forward_pm' => array('lang' => 'ALLOW_FORWARD_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
'auth_img_pm' => array('lang' => 'ALLOW_IMG_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
'auth_flash_pm' => array('lang' => 'ALLOW_FLASH_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'enable_pm_icons' => array('lang' => 'ENABLE_PM_ICONS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false)
'enable_pm_icons' => array('lang' => 'ENABLE_PM_ICONS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
'legend3' => 'ACP_SUBMIT_CHANGES',
)
);
break;
@ -162,26 +172,30 @@ class acp_board
'allow_nocensors' => array('lang' => 'ALLOW_NO_CENSORS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'allow_bookmarks' => array('lang' => 'ALLOW_BOOKMARKS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'enable_post_confirm' => array('lang' => 'VISUAL_CONFIRM_POST', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'allow_quick_reply' => array('lang' => 'ALLOW_QUICK_REPLY', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'legend2' => 'POSTING',
'enable_queue_trigger' => array('lang' => 'ENABLE_QUEUE_TRIGGER', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'queue_trigger_posts' => array('lang' => 'QUEUE_TRIGGER_POSTS', 'validate' => 'int:0:250', 'type' => 'text:4:4', 'explain' => true),
'bump_type' => false,
'edit_time' => array('lang' => 'EDIT_TIME', 'validate' => 'int:0', 'type' => 'text:5:5', 'explain' => true, 'append' => ' ' . $user->lang['MINUTES']),
'delete_time' => array('lang' => 'DELETE_TIME', 'validate' => 'int:0', 'type' => 'text:5:5', 'explain' => true, 'append' => ' ' . $user->lang['MINUTES']),
'display_last_edited' => array('lang' => 'DISPLAY_LAST_EDITED', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'flood_interval' => array('lang' => 'FLOOD_INTERVAL', 'validate' => 'int:0', 'type' => 'text:3:10', 'explain' => true, 'append' => ' ' . $user->lang['SECONDS']),
'bump_interval' => array('lang' => 'BUMP_INTERVAL', 'validate' => 'int:0', 'type' => 'custom', 'method' => 'bump_interval', 'explain' => true),
'topics_per_page' => array('lang' => 'TOPICS_PER_PAGE', 'validate' => 'int:1', 'type' => 'text:3:4', 'explain' => false),
'posts_per_page' => array('lang' => 'POSTS_PER_PAGE', 'validate' => 'int:1', 'type' => 'text:3:4', 'explain' => false),
'smilies_per_page' => array('lang' => 'SMILIES_PER_PAGE', 'validate' => 'int:1', 'type' => 'text:3:4', 'explain' => false),
'hot_threshold' => array('lang' => 'HOT_THRESHOLD', 'validate' => 'int:0', 'type' => 'text:3:4', 'explain' => true),
'max_poll_options' => array('lang' => 'MAX_POLL_OPTIONS', 'validate' => 'int:2:127', 'type' => 'text:4:4', 'explain' => false),
'max_post_chars' => array('lang' => 'CHAR_LIMIT', 'validate' => 'int:0', 'type' => 'text:4:6', 'explain' => true),
'min_post_chars' => array('lang' => 'MIN_CHAR_LIMIT', 'validate' => 'int:0', 'type' => 'text:4:6', 'explain' => true),
'max_post_smilies' => array('lang' => 'SMILIES_LIMIT', 'validate' => 'int:0', 'type' => 'text:4:4', 'explain' => true),
'max_post_urls' => array('lang' => 'MAX_POST_URLS', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true),
'max_post_font_size' => array('lang' => 'MAX_POST_FONT_SIZE', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true, 'append' => ' %'),
'max_quote_depth' => array('lang' => 'QUOTE_DEPTH_LIMIT', 'validate' => 'int:0', 'type' => 'text:4:4', 'explain' => true),
'max_post_img_width' => array('lang' => 'MAX_POST_IMG_WIDTH', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']),
'max_post_img_height' => array('lang' => 'MAX_POST_IMG_HEIGHT', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']),
'legend3' => 'ACP_SUBMIT_CHANGES',
)
);
break;
@ -205,6 +219,8 @@ class acp_board
'max_sig_smilies' => array('lang' => 'MAX_SIG_SMILIES', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true),
'max_sig_img_width' => array('lang' => 'MAX_SIG_IMG_WIDTH', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']),
'max_sig_img_height' => array('lang' => 'MAX_SIG_IMG_HEIGHT', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']),
'legend3' => 'ACP_SUBMIT_CHANGES',
)
);
break;
@ -218,6 +234,8 @@ class acp_board
'max_pass_chars' => array('lang' => 'PASSWORD_LENGTH', 'validate' => 'int:8:255', 'type' => false, 'method' => false, 'explain' => false,),
'require_activation' => array('lang' => 'ACC_ACTIVATION', 'validate' => 'int', 'type' => 'custom', 'method' => 'select_acc_activation', 'explain' => true),
'new_member_post_limit' => array('lang' => 'NEW_MEMBER_POST_LIMIT', 'validate' => 'int:0:255', 'type' => 'text:4:4', 'explain' => true, 'append' => ' ' . $user->lang['POSTS']),
'new_member_group_default'=> array('lang' => 'NEW_MEMBER_GROUP_DEFAULT', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'min_name_chars' => array('lang' => 'USERNAME_LENGTH', 'validate' => 'int:1', 'type' => 'custom:5:180', 'method' => 'username_length', 'explain' => true),
'min_pass_chars' => array('lang' => 'PASSWORD_LENGTH', 'validate' => 'int:1', 'type' => 'custom', 'method' => 'password_length', 'explain' => true),
'allow_name_chars' => array('lang' => 'USERNAME_CHARS', 'validate' => 'string', 'type' => 'select', 'method' => 'select_username_chars', 'explain' => true),
@ -235,6 +253,28 @@ class acp_board
'coppa_enable' => array('lang' => 'ENABLE_COPPA', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'coppa_mail' => array('lang' => 'COPPA_MAIL', 'validate' => 'string', 'type' => 'textarea:5:40', 'explain' => true),
'coppa_fax' => array('lang' => 'COPPA_FAX', 'validate' => 'string', 'type' => 'text:25:100', 'explain' => false),
'legend4' => 'ACP_SUBMIT_CHANGES',
)
);
break;
case 'feed':
$display_vars = array(
'title' => 'ACP_FEED_MANAGEMENT',
'vars' => array(
'legend1' => 'ACP_FEED_GENERAL',
'feed_enable' => array('lang' => 'ACP_FEED_ENABLE', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true ),
'feed_item_statistics' => array('lang' => 'ACP_FEED_ITEM_STATISTICS', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true),
'feed_limit' => array('lang' => 'ACP_FEED_LIMIT', 'validate' => 'int:5', 'type' => 'text:3:4', 'explain' => true),
'feed_overall_forums' => array('lang' => 'ACP_FEED_OVERALL_FORUMS', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true ),
'feed_overall_forums_limit' => array('lang' => 'ACP_FEED_OVERALL_FORUMS_LIMIT', 'validate' => 'int:5', 'type' => 'text:3:4', 'explain' => false),
'feed_overall_topics' => array('lang' => 'ACP_FEED_OVERALL_TOPIC', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true ),
'feed_overall_topics_limit' => array('lang' => 'ACP_FEED_OVERALL_TOPIC_LIMIT', 'validate' => 'int:5', 'type' => 'text:3:4', 'explain' => false),
'feed_forum' => array('lang' => 'ACP_FEED_FORUM', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true ),
'feed_topic' => array('lang' => 'ACP_FEED_TOPIC', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true ),
'feed_news_id' => array('lang' => 'ACP_FEED_NEWS', 'validate' => 'string', 'type' => 'custom', 'method' => 'select_news_forums', 'explain' => true),
'feed_exclude_id' => array('lang' => 'ACP_FEED_EXCLUDE_ID', 'validate' => 'string', 'type' => 'custom', 'method' => 'select_exclude_forums', 'explain' => true),
)
);
break;
@ -279,6 +319,8 @@ class acp_board
'load_cpf_memberlist' => array('lang' => 'LOAD_CPF_MEMBERLIST', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
'load_cpf_viewprofile' => array('lang' => 'LOAD_CPF_VIEWPROFILE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
'load_cpf_viewtopic' => array('lang' => 'LOAD_CPF_VIEWTOPIC', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
'legend4' => 'ACP_SUBMIT_CHANGES',
)
);
break;
@ -312,6 +354,8 @@ class acp_board
'server_name' => array('lang' => 'SERVER_NAME', 'validate' => 'string', 'type' => 'text:40:255', 'explain' => true),
'server_port' => array('lang' => 'SERVER_PORT', 'validate' => 'int:0', 'type' => 'text:5:5', 'explain' => true),
'script_path' => array('lang' => 'SCRIPT_PATH', 'validate' => 'script_path', 'type' => 'text::255', 'explain' => true),
'legend4' => 'ACP_SUBMIT_CHANGES',
)
);
break;
@ -360,7 +404,9 @@ class acp_board
'smtp_port' => array('lang' => 'SMTP_PORT', 'validate' => 'int:0', 'type' => 'text:4:5', 'explain' => true),
'smtp_auth_method' => array('lang' => 'SMTP_AUTH_METHOD', 'validate' => 'string', 'type' => 'select', 'method' => 'mail_auth_select', 'explain' => true),
'smtp_username' => array('lang' => 'SMTP_USERNAME', 'validate' => 'string', 'type' => 'text:25:255', 'explain' => true),
'smtp_password' => array('lang' => 'SMTP_PASSWORD', 'validate' => 'string', 'type' => 'password:25:255', 'explain' => true)
'smtp_password' => array('lang' => 'SMTP_PASSWORD', 'validate' => 'string', 'type' => 'password:25:255', 'explain' => true),
'legend3' => 'ACP_SUBMIT_CHANGES',
)
);
break;
@ -400,7 +446,7 @@ class acp_board
continue;
}
if ($config_name == 'auth_method')
if ($config_name == 'auth_method' || $config_name == 'feed_news_id' || $config_name == 'feed_exclude_id')
{
continue;
}
@ -420,6 +466,13 @@ class acp_board
}
}
// Store news and exclude ids
if ($mode == 'feed' && $submit)
{
$this->store_feed_forums(FORUM_OPTION_FEED_NEWS, 'feed_news_id');
$this->store_feed_forums(FORUM_OPTION_FEED_EXCLUDE, 'feed_exclude_id');
}
if ($mode == 'auth')
{
// Retrieve a list of auth plugins and check their config values
@ -830,6 +883,75 @@ class acp_board
return "<select name=\"dateoptions\" id=\"dateoptions\" onchange=\"if (this.value == 'custom') { document.getElementById('" . addslashes($key) . "').value = '" . addslashes($value) . "'; } else { document.getElementById('" . addslashes($key) . "').value = this.value; }\">$dateformat_options</select>
<input type=\"text\" name=\"config[$key]\" id=\"$key\" value=\"$value\" maxlength=\"30\" />";
}
/**
* Select multiple forums
*/
function select_news_forums($value, $key)
{
global $user, $config;
$forum_list = make_forum_select(false, false, true, true, true, false, true);
// Build forum options
$s_forum_options = '<select id="' . $key . '" name="' . $key . '[]" multiple="multiple">';
foreach ($forum_list as $f_id => $f_row)
{
$f_row['selected'] = phpbb_optionget(FORUM_OPTION_FEED_NEWS, $f_row['forum_options']);
$s_forum_options .= '<option value="' . $f_id . '"' . (($f_row['selected']) ? ' selected="selected"' : '') . (($f_row['disabled']) ? ' disabled="disabled" class="disabled-option"' : '') . '>' . $f_row['padding'] . $f_row['forum_name'] . '</option>';
}
$s_forum_options .= '</select>';
return $s_forum_options;
}
function select_exclude_forums($value, $key)
{
global $user, $config;
$forum_list = make_forum_select(false, false, true, false, false, false, true);
// Build forum options
$s_forum_options = '<select id="' . $key . '" name="' . $key . '[]" multiple="multiple">';
foreach ($forum_list as $f_id => $f_row)
{
$f_row['selected'] = phpbb_optionget(FORUM_OPTION_FEED_EXCLUDE, $f_row['forum_options']);
$s_forum_options .= '<option value="' . $f_id . '"' . (($f_row['selected']) ? ' selected="selected"' : '') . (($f_row['disabled']) ? ' disabled="disabled" class="disabled-option"' : '') . '>' . $f_row['padding'] . $f_row['forum_name'] . '</option>';
}
$s_forum_options .= '</select>';
return $s_forum_options;
}
function store_feed_forums($option, $key)
{
global $db, $cache;
// Get key
$values = request_var($key, array(0 => 0));
// Empty option bit for all forums
$sql = 'UPDATE ' . FORUMS_TABLE . '
SET forum_options = forum_options - ' . (1 << $option) . '
WHERE ' . $db->sql_bit_and('forum_options', $option, '<> 0');
$db->sql_query($sql);
// Already emptied for all...
if (sizeof($values))
{
// Set for selected forums
$sql = 'UPDATE ' . FORUMS_TABLE . '
SET forum_options = forum_options + ' . (1 << $option) . '
WHERE ' . $db->sql_in_set('forum_id', $values);
$db->sql_query($sql);
}
// Empty sql cache for forums table because options changed
$cache->destroy('sql', FORUMS_TABLE);
}
}
?>

View file

@ -28,108 +28,120 @@ class acp_captcha
global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;
$user->add_lang('acp/board');
$captcha_vars = array(
'captcha_gd_x_grid' => 'CAPTCHA_GD_X_GRID',
'captcha_gd_y_grid' => 'CAPTCHA_GD_Y_GRID',
'captcha_gd_foreground_noise' => 'CAPTCHA_GD_FOREGROUND_NOISE',
'captcha_gd' => 'CAPTCHA_GD_PREVIEWED',
'captcha_gd_wave' => 'CAPTCHA_GD_WAVE',
'captcha_gd_3d_noise' => 'CAPTCHA_GD_3D_NOISE',
'captcha_gd_fonts' => 'CAPTCHA_GD_FONTS',
);
include($phpbb_root_path . 'includes/captcha/captcha_factory.' . $phpEx);
if (isset($_GET['demo']))
$selected = request_var('select_captcha', $config['captcha_plugin']);
$configure = request_var('configure', false);
// Oh, they are just here for the view
if (isset($_GET['captcha_demo']))
{
$captcha_vars = array_keys($captcha_vars);
foreach ($captcha_vars as $captcha_var)
{
$config[$captcha_var] = (isset($_REQUEST[$captcha_var])) ? request_var($captcha_var, 0) : $config[$captcha_var];
}
if ($config['captcha_gd'])
{
include($phpbb_root_path . 'includes/captcha/captcha_gd.' . $phpEx);
}
else
{
include($phpbb_root_path . 'includes/captcha/captcha_non_gd.' . $phpEx);
}
$captcha = new captcha();
$captcha->execute(gen_rand_string(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS)), time());
exit;
$this->deliver_demo($selected);
}
$config_vars = array(
'enable_confirm' => 'REG_ENABLE',
'enable_post_confirm' => 'POST_ENABLE',
'confirm_refresh' => 'CONFIRM_REFRESH',
'captcha_gd' => 'CAPTCHA_GD',
);
$this->tpl_name = 'acp_captcha';
$this->page_title = 'ACP_VC_SETTINGS';
$form_key = 'acp_captcha';
add_form_key($form_key);
$submit = request_var('submit', '');
if ($submit && check_form_key($form_key))
// Delegate
if ($configure)
{
$config_vars = array_keys($config_vars);
foreach ($config_vars as $config_var)
{
set_config($config_var, request_var($config_var, ''));
}
$captcha_vars = array_keys($captcha_vars);
foreach ($captcha_vars as $captcha_var)
{
$value = request_var($captcha_var, 0);
if ($value >= 0)
{
set_config($captcha_var, $value);
}
}
$config_captcha =& phpbb_captcha_factory::get_instance($selected);
$config_captcha->acp_page($id, $this);
add_log('admin', 'LOG_CONFIG_VISUAL');
trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($this->u_action));
}
else if ($submit)
{
trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action));
}
else
{
$preview_image_src = append_sid(append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&amp;demo=demo"));
$captchas = phpbb_captcha_factory::get_captcha_types();
if (@extension_loaded('gd'))
$config_vars = array(
'enable_confirm' => array('tpl' => 'REG_ENABLE', 'default' => false),
'enable_post_confirm' => array('tpl' => 'POST_ENABLE', 'default' => false),
'confirm_refresh' => array('tpl' => 'CONFIRM_REFRESH', 'default' => false),
'max_reg_attempts' => array('tpl' => 'REG_LIMIT', 'default' => 0),
);
$this->tpl_name = 'acp_captcha';
$this->page_title = 'ACP_VC_SETTINGS';
$form_key = 'acp_captcha';
add_form_key($form_key);
$submit = request_var('main_submit', false);
if ($submit && check_form_key($form_key))
{
$template->assign_var('GD', true);
}
foreach ($config_vars as $config_var => $options)
{
set_config($config_var, request_var($config_var, $options['default']));
}
foreach ($config_vars as $config_var => $template_var)
if ($selected !== $config['captcha_plugin'])
{
// sanity check
if (isset($captchas['available'][$selected]))
{
$old_captcha =& phpbb_captcha_factory::get_instance($config['captcha_plugin']);
$old_captcha->uninstall();
set_config('captcha_plugin', $selected);
$new_captcha =& phpbb_captcha_factory::get_instance($config['captcha_plugin']);
$new_captcha->install();
add_log('admin', 'LOG_CONFIG_VISUAL');
}
else
{
trigger_error($user->lang['CAPTCHA_UNAVAILABLE'] . adm_back_link($this->u_action));
}
}
trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($this->u_action));
}
else if ($submit)
{
$template->assign_var($template_var, (isset($_REQUEST[$config_var])) ? request_var($config_var, '') : $config[$config_var]) ;
trigger_error($user->lang['FORM_INVALID'] . adm_back_link());
}
foreach ($captcha_vars as $captcha_var => $template_var)
else
{
$var = (isset($_REQUEST[$captcha_var])) ? request_var($captcha_var, 0) : $config[$captcha_var];
$template->assign_var($template_var, $var);
$preview_image_src .= "&amp;$captcha_var=" . $var;
}
$captcha_select = '';
foreach ($captchas['available'] as $value => $title)
{
$current = ($selected !== false && $value == $selected) ? ' selected="selected"' : '';
$captcha_select .= '<option value="' . $value . '"' . $current . '>' . $user->lang[$title] . '</option>';
}
$template->assign_vars(array(
'CAPTCHA_PREVIEW' => $preview_image_src,
'PREVIEW' => isset($_POST['preview']),
));
foreach ($captchas['unavailable'] as $value => $title)
{
$current = ($selected !== false && $value == $selected) ? ' selected="selected"' : '';
$captcha_select .= '<option value="' . $value . '"' . $current . ' class="disabled-option">' . $user->lang[$title] . '</option>';
}
$demo_captcha =& phpbb_captcha_factory::get_instance($selected);
foreach ($config_vars as $config_var => $options)
{
$template->assign_var($options['tpl'], (isset($_POST[$config_var])) ? request_var($config_var, $options['default']) : $config[$config_var]) ;
}
$template->assign_vars(array(
'CAPTCHA_PREVIEW_TPL' => $demo_captcha->get_demo_template($id),
'S_CAPTCHA_HAS_CONFIG' => $demo_captcha->has_config(),
'CAPTCHA_SELECT' => $captcha_select,
));
}
}
}
/**
* Entry point for delivering image CAPTCHAs in the ACP.
*/
function deliver_demo($selected)
{
global $db, $user, $config;
$captcha =& phpbb_captcha_factory::get_instance($selected);
$captcha->init(CONFIRM_REG);
$captcha->execute_demo();
garbage_collection();
exit_handler();
}
}
?>

View file

@ -548,7 +548,7 @@ class base_extractor
if (!$this->fp)
{
trigger_error('Unable to write temporary file to storage folder', E_USER_ERROR);
trigger_error('FILE_WRITE_FAIL', E_USER_ERROR);
}
}
}
@ -1157,16 +1157,17 @@ class postgres_extractor extends base_extractor
AND (c.oid = d.adrelid)
AND d.adnum = " . $row['attnum'];
$def_res = $db->sql_query($sql_get_default);
$def_row = $db->sql_fetchrow($def_res);
$db->sql_freeresult($def_res);
if (!$def_res)
if (empty($def_row))
{
unset($row['rowdefault']);
}
else
{
$row['rowdefault'] = $db->sql_fetchfield('rowdefault', false, $def_res);
$row['rowdefault'] = $def_row['rowdefault'];
}
$db->sql_freeresult($def_res);
if ($row['type'] == 'bpchar')
{
@ -1854,7 +1855,8 @@ class oracle_extractor extends base_extractor
// Build the SQL statement to recreate the data.
for ($i = 0; $i < $i_num_fields; $i++)
{
$str_val = $row[$ary_name[$i]];
// Oracle uses uppercase - we use lowercase
$str_val = $row[strtolower($ary_name[$i])];
if (preg_match('#char|text|bool|raw#i', $ary_type[$i]))
{
@ -1885,7 +1887,7 @@ class oracle_extractor extends base_extractor
}
$schema_vals[$i] = $str_quote . $str_val . $str_quote;
$schema_fields[$i] = '"' . $ary_name[$i] . "'";
$schema_fields[$i] = '"' . $ary_name[$i] . '"';
}
// Take the ordered fields and their associated data and build it

View file

@ -75,6 +75,13 @@ class acp_forums
trigger_error($user->lang['NO_PERMISSION_FORUM_ADD'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
}
case 'copy_perm':
if (!(($auth->acl_get('a_fauth') && $auth->acl_get('a_authusers') && $auth->acl_get('a_authgroups') && $auth->acl_get('a_mauth'))))
{
trigger_error($user->lang['NO_PERMISSION_COPY'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
}
break;
}
@ -118,6 +125,7 @@ class acp_forums
'type_action' => request_var('type_action', ''),
'forum_status' => request_var('forum_status', ITEM_UNLOCKED),
'forum_parents' => '',
'forum_options' => 0,
'forum_name' => utf8_normalize_nfc(request_var('forum_name', '', true)),
'forum_link' => request_var('forum_link', ''),
'forum_link_track' => request_var('forum_link_track', false),
@ -139,6 +147,7 @@ class acp_forums
'enable_icons' => request_var('enable_icons', false),
'enable_prune' => request_var('enable_prune', false),
'enable_post_review' => request_var('enable_post_review', true),
'enable_quick_reply' => request_var('enable_quick_reply', false),
'prune_days' => request_var('prune_days', 7),
'prune_viewed' => request_var('prune_viewed', 7),
'prune_freq' => request_var('prune_freq', 1),
@ -181,73 +190,22 @@ class acp_forums
if (!sizeof($errors))
{
$forum_perm_from = request_var('forum_perm_from', 0);
$cache->destroy('sql', FORUMS_TABLE);
// Copy permissions?
if (!empty($forum_perm_from) && $forum_perm_from != $forum_data['forum_id'] &&
(($action != 'edit') || empty($forum_id) || ($auth->acl_get('a_fauth') && $auth->acl_get('a_authusers') && $auth->acl_get('a_authgroups') && $auth->acl_get('a_mauth'))))
{
// if we edit a forum delete current permissions first
if ($action == 'edit')
{
$sql = 'DELETE FROM ' . ACL_USERS_TABLE . '
WHERE forum_id = ' . (int) $forum_data['forum_id'];
$db->sql_query($sql);
$sql = 'DELETE FROM ' . ACL_GROUPS_TABLE . '
WHERE forum_id = ' . (int) $forum_data['forum_id'];
$db->sql_query($sql);
}
// From the mysql documentation:
// Prior to MySQL 4.0.14, the target table of the INSERT statement cannot appear in the FROM clause of the SELECT part of the query. This limitation is lifted in 4.0.14.
// Due to this we stay on the safe side if we do the insertion "the manual way"
// Copy permisisons from/to the acl users table (only forum_id gets changed)
$sql = 'SELECT user_id, auth_option_id, auth_role_id, auth_setting
FROM ' . ACL_USERS_TABLE . '
WHERE forum_id = ' . $forum_perm_from;
$result = $db->sql_query($sql);
$users_sql_ary = array();
while ($row = $db->sql_fetchrow($result))
{
$users_sql_ary[] = array(
'user_id' => (int) $row['user_id'],
'forum_id' => (int) $forum_data['forum_id'],
'auth_option_id' => (int) $row['auth_option_id'],
'auth_role_id' => (int) $row['auth_role_id'],
'auth_setting' => (int) $row['auth_setting']
);
}
$db->sql_freeresult($result);
// Copy permisisons from/to the acl groups table (only forum_id gets changed)
$sql = 'SELECT group_id, auth_option_id, auth_role_id, auth_setting
FROM ' . ACL_GROUPS_TABLE . '
WHERE forum_id = ' . $forum_perm_from;
$result = $db->sql_query($sql);
$groups_sql_ary = array();
while ($row = $db->sql_fetchrow($result))
{
$groups_sql_ary[] = array(
'group_id' => (int) $row['group_id'],
'forum_id' => (int) $forum_data['forum_id'],
'auth_option_id' => (int) $row['auth_option_id'],
'auth_role_id' => (int) $row['auth_role_id'],
'auth_setting' => (int) $row['auth_setting']
);
}
$db->sql_freeresult($result);
// Now insert the data
$db->sql_multi_insert(ACL_USERS_TABLE, $users_sql_ary);
$db->sql_multi_insert(ACL_GROUPS_TABLE, $groups_sql_ary);
copy_forum_permissions($forum_perm_from, $forum_data['forum_id'], ($action == 'edit') ? true : false);
cache_moderators();
}
else if (($action != 'edit') && $auth->acl_get('a_fauth') && $auth->acl_get('a_authusers') && $auth->acl_get('a_authgroups') && $auth->acl_get('a_mauth'))
{
$this->copy_permission_page($forum_data);
return;
}
$auth->acl_clear_prefetch();
$cache->destroy('sql', FORUMS_TABLE);
$acl_url = '&amp;mode=setting_forum_local&amp;forum_id[]=' . $forum_data['forum_id'];
@ -423,6 +381,7 @@ class acp_forums
$forum_data['forum_flags'] += (request_var('prune_sticky', false)) ? FORUM_FLAG_PRUNE_STICKY : 0;
$forum_data['forum_flags'] += ($forum_data['show_active']) ? FORUM_FLAG_ACTIVE_TOPICS : 0;
$forum_data['forum_flags'] += (request_var('enable_post_review', true)) ? FORUM_FLAG_POST_REVIEW : 0;
$forum_data['forum_flags'] += (request_var('enable_quick_reply', false)) ? FORUM_FLAG_QUICK_REPLY : 0;
}
// Show form to create/modify a forum
@ -485,6 +444,7 @@ class acp_forums
'prune_viewed' => 7,
'prune_freq' => 1,
'forum_flags' => FORUM_FLAG_POST_REVIEW,
'forum_options' => 0,
'forum_password' => '',
'forum_password_confirm'=> '',
);
@ -682,6 +642,7 @@ class acp_forums
'S_PRUNE_STICKY' => ($forum_data['forum_flags'] & FORUM_FLAG_PRUNE_STICKY) ? true : false,
'S_DISPLAY_ACTIVE_TOPICS' => ($forum_data['forum_flags'] & FORUM_FLAG_ACTIVE_TOPICS) ? true : false,
'S_ENABLE_POST_REVIEW' => ($forum_data['forum_flags'] & FORUM_FLAG_POST_REVIEW) ? true : false,
'S_ENABLE_QUICK_REPLY' => ($forum_data['forum_flags'] & FORUM_FLAG_QUICK_REPLY) ? true : false,
'S_CAN_COPY_PERMISSIONS' => ($action != 'edit' || empty($forum_id) || ($auth->acl_get('a_fauth') && $auth->acl_get('a_authusers') && $auth->acl_get('a_authgroups') && $auth->acl_get('a_mauth'))) ? true : false,
));
@ -740,6 +701,32 @@ class acp_forums
return;
break;
case 'copy_perm':
$forum_perm_from = request_var('forum_perm_from', 0);
// Copy permissions?
if (!empty($forum_perm_from) && $forum_perm_from != $forum_id)
{
copy_forum_permissions($forum_perm_from, $forum_id, true);
cache_moderators();
$auth->acl_clear_prefetch();
$cache->destroy('sql', FORUMS_TABLE);
$acl_url = '&amp;mode=setting_forum_local&amp;forum_id[]=' . $forum_id;
$message = $user->lang['FORUM_UPDATED'];
// Redirect to permissions
if ($auth->acl_get('a_fauth'))
{
$message .= '<br /><br />' . sprintf($user->lang['REDIRECT_ACL'], '<a href="' . append_sid("{$phpbb_admin_path}index.$phpEx", 'i=permissions' . $acl_url) . '">', '</a>');
}
trigger_error($message . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id));
}
break;
}
// Default management page
@ -941,6 +928,7 @@ class acp_forums
$forum_data['forum_flags'] += ($forum_data['prune_sticky']) ? FORUM_FLAG_PRUNE_STICKY : 0;
$forum_data['forum_flags'] += ($forum_data['show_active']) ? FORUM_FLAG_ACTIVE_TOPICS : 0;
$forum_data['forum_flags'] += ($forum_data['enable_post_review']) ? FORUM_FLAG_POST_REVIEW : 0;
$forum_data['forum_flags'] += ($forum_data['enable_quick_reply']) ? FORUM_FLAG_QUICK_REPLY : 0;
// Unset data that are not database fields
$forum_data_sql = $forum_data;
@ -951,6 +939,7 @@ class acp_forums
unset($forum_data_sql['prune_sticky']);
unset($forum_data_sql['show_active']);
unset($forum_data_sql['enable_post_review']);
unset($forum_data_sql['enable_quick_reply']);
unset($forum_data_sql['forum_password_confirm']);
// What are we going to do tonight Brain? The same thing we do everynight,
@ -1927,6 +1916,30 @@ class acp_forums
adm_page_footer();
}
/**
* Display copy permission page
*/
function copy_permission_page($forum_data)
{
global $phpEx, $phpbb_admin_path, $template, $user;
$acl_url = '&amp;mode=setting_forum_local&amp;forum_id[]=' . $forum_data['forum_id'];
$action = append_sid($this->u_action . "&amp;parent_id={$this->parent_id}&amp;f={$forum_data['forum_id']}&amp;action=copy_perm");
$l_acl = sprintf($user->lang['COPY_TO_ACL'], '<a href="' . append_sid("{$phpbb_admin_path}index.$phpEx", 'i=permissions' . $acl_url) . '">', '</a>');
$this->tpl_name = 'acp_forums_copy_perm';
$template->assign_vars(array(
'U_ACL' => append_sid("{$phpbb_admin_path}index.$phpEx", 'i=permissions' . $acl_url),
'L_ACL_LINK' => $l_acl,
'L_BACK_LINK' => adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id),
'S_COPY_ACTION' => $action,
'S_FORUM_OPTIONS' => make_forum_select($forum_data['parent_id'], $forum_data['forum_id'], false, false, false),
));
}
}
?>

View file

@ -309,6 +309,7 @@ class acp_groups
'message_limit' => request_var('group_message_limit', 0),
'max_recipients' => request_var('group_max_recipients', 0),
'founder_manage' => 0,
'skip_auth' => request_var('group_skip_auth', 0),
);
if ($user->data['user_type'] == USER_FOUNDER)
@ -400,11 +401,26 @@ class acp_groups
// were made.
$group_attributes = array();
$test_variables = array('rank', 'colour', 'avatar', 'avatar_type', 'avatar_width', 'avatar_height', 'receive_pm', 'legend', 'message_limit', 'max_recipients', 'founder_manage');
foreach ($test_variables as $test)
$test_variables = array(
'rank' => 'int',
'colour' => 'string',
'avatar' => 'string',
'avatar_type' => 'int',
'avatar_width' => 'int',
'avatar_height' => 'int',
'receive_pm' => 'int',
'legend' => 'int',
'message_limit' => 'int',
'max_recipients'=> 'int',
'founder_manage'=> 'int',
'skip_auth' => 'int',
);
foreach ($test_variables as $test => $type)
{
if (isset($submit_ary[$test]) && ($action == 'add' || $group_row['group_' . $test] != $submit_ary[$test]))
{
settype($submit_ary[$test], $type);
$group_attributes['group_' . $test] = $group_row['group_' . $test] = $submit_ary[$test];
}
}
@ -562,7 +578,7 @@ class acp_groups
'GROUP_MESSAGE_LIMIT' => (isset($group_row['group_message_limit'])) ? $group_row['group_message_limit'] : 0,
'GROUP_MAX_RECIPIENTS' => (isset($group_row['group_max_recipients'])) ? $group_row['group_max_recipients'] : 0,
'GROUP_COLOUR' => (isset($group_row['group_colour'])) ? $group_row['group_colour'] : '',
'GROUP_SKIP_AUTH' => (!empty($group_row['group_skip_auth'])) ? ' checked="checked"' : '',
'S_DESC_BBCODE_CHECKED' => $group_desc_data['allow_bbcode'],
'S_DESC_URLS_CHECKED' => $group_desc_data['allow_urls'],
@ -591,8 +607,7 @@ class acp_groups
'U_SWATCH' => append_sid("{$phpbb_admin_path}swatch.$phpEx", 'form=settings&amp;name=group_colour'),
'U_ACTION' => "{$this->u_action}&amp;action=$action&amp;g=$group_id",
'L_AVATAR_EXPLAIN' => sprintf($user->lang['AVATAR_EXPLAIN'], $config['avatar_max_width'], $config['avatar_max_height'], round($config['avatar_filesize'] / 1024)),
)
);
));
return;
break;
@ -607,7 +622,7 @@ class acp_groups
$this->page_title = 'GROUP_MEMBERS';
// Grab the leaders - always, on every page...
$sql = 'SELECT u.user_id, u.username, u.username_clean, u.user_regdate, u.user_posts, u.group_id, ug.group_leader, ug.user_pending
$sql = 'SELECT u.user_id, u.username, u.username_clean, u.user_regdate, u.user_colour, u.user_posts, u.group_id, ug.group_leader, ug.user_pending
FROM ' . USERS_TABLE . ' u, ' . USER_GROUP_TABLE . " ug
WHERE ug.group_id = $group_id
AND u.user_id = ug.user_id
@ -621,11 +636,12 @@ class acp_groups
'U_USER_EDIT' => append_sid("{$phpbb_admin_path}index.$phpEx", "i=users&amp;action=edit&amp;u={$row['user_id']}"),
'USERNAME' => $row['username'],
'USERNAME_COLOUR' => $row['user_colour'],
'S_GROUP_DEFAULT' => ($row['group_id'] == $group_id) ? true : false,
'JOINED' => ($row['user_regdate']) ? $user->format_date($row['user_regdate']) : ' - ',
'USER_POSTS' => $row['user_posts'],
'USER_ID' => $row['user_id'])
);
'USER_ID' => $row['user_id'],
));
}
$db->sql_freeresult($result);
@ -662,7 +678,7 @@ class acp_groups
));
// Grab the members
$sql = 'SELECT u.user_id, u.username, u.username_clean, u.user_regdate, u.user_posts, u.group_id, ug.group_leader, ug.user_pending
$sql = 'SELECT u.user_id, u.username, u.username_clean, u.user_colour, u.user_regdate, u.user_posts, u.group_id, ug.group_leader, ug.user_pending
FROM ' . USERS_TABLE . ' u, ' . USER_GROUP_TABLE . " ug
WHERE ug.group_id = $group_id
AND u.user_id = ug.user_id
@ -687,6 +703,7 @@ class acp_groups
'U_USER_EDIT' => append_sid("{$phpbb_admin_path}index.$phpEx", "i=users&amp;action=edit&amp;u={$row['user_id']}"),
'USERNAME' => $row['username'],
'USERNAME_COLOUR' => $row['user_colour'],
'S_GROUP_DEFAULT' => ($row['group_id'] == $group_id) ? true : false,
'JOINED' => ($row['user_regdate']) ? $user->format_date($row['user_regdate']) : ' - ',
'USER_POSTS' => $row['user_posts'],
@ -763,8 +780,7 @@ class acp_groups
'GROUP_NAME' => $group_name,
'TOTAL_MEMBERS' => $row['total_members'],
)
);
));
}
}
}

View file

@ -89,6 +89,18 @@ class acp_icons
continue;
}
// adjust the width and height to be lower than 128px while perserving the aspect ratio
if ($img_size[0] > 127 && $img_size[0] > $img_size[1])
{
$img_size[1] = (int) ($img_size[1] * (127 / $img_size[0]));
$img_size[0] = 127;
}
else if ($img_size[1] > 127)
{
$img_size[0] = (int) ($img_size[0] * (127 / $img_size[1]));
$img_size[1] = 127;
}
$_images[$path . $img]['file'] = $path . $img;
$_images[$path . $img]['width'] = $img_size[0];
$_images[$path . $img]['height'] = $img_size[1];
@ -168,19 +180,19 @@ class acp_icons
}
}
}
$sql = "SELECT *
FROM $table
ORDER BY {$fields}_order " . (($icon_id || $action == 'add') ? 'DESC' : 'ASC');
$result = $db->sql_query($sql);
$data = array();
$after = false;
$display = 0;
$order_lists = array('', '');
$add_order_lists = array('', '');
$display_count = 0;
while ($row = $db->sql_fetchrow($result))
{
if ($action == 'add')
@ -231,15 +243,15 @@ class acp_icons
$data = $_images;
}
$colspan = (($mode == 'smilies') ? '7' : '5');
$colspan = (($mode == 'smilies') ? 7 : 5);
$colspan += ($icon_id) ? 1 : 0;
$colspan += ($action == 'add') ? 2 : 0;
$template->assign_vars(array(
'S_EDIT' => true,
'S_SMILIES' => ($mode == 'smilies') ? true : false,
'S_ADD' => ($action == 'add') ? true : false,
'S_ORDER_LIST_DISPLAY' => $order_list . $order_lists[1],
'S_ORDER_LIST_UNDISPLAY' => $order_list . $order_lists[0],
'S_ORDER_LIST_DISPLAY_COUNT' => $display_count + 1,
@ -286,10 +298,10 @@ class acp_icons
'S_ADD_CODE' => true,
'S_IMG_OPTIONS' => $smiley_options,
'S_ADD_ORDER_LIST_DISPLAY' => $add_order_list . $add_order_lists[1],
'S_ADD_ORDER_LIST_UNDISPLAY' => $add_order_list . $add_order_lists[0],
'IMG_SRC' => $phpbb_root_path . $img_path . '/' . $default_row['smiley_url'],
'IMG_PATH' => $img_path,
'PHPBB_ROOT_PATH' => $phpbb_root_path,
@ -303,7 +315,7 @@ class acp_icons
}
return;
break;
case 'create':
@ -311,7 +323,7 @@ class acp_icons
// Get items to create/modify
$images = (isset($_POST['image'])) ? array_keys(request_var('image', array('' => 0))) : array();
// Now really get the items
$image_id = (isset($_POST['id'])) ? request_var('id', array('' => 0)) : array();
$image_order = (isset($_POST['order'])) ? request_var('order', array('' => 0)) : array();
@ -348,6 +360,25 @@ class acp_icons
}
}
if ($mode == 'smilies' && $action == 'create')
{
$smiley_count = $this->item_count($table);
$addable_smileys_count = sizeof($images);
foreach ($images as $image)
{
if (!isset($image_add[$image]))
{
--$addable_smileys_count;
}
}
if ($smiley_count + $addable_smileys_count > SMILEY_LIMIT)
{
trigger_error(sprintf($user->lang['TOO_MANY_SMILIES'], SMILEY_LIMIT) . adm_back_link($this->u_action), E_USER_WARNING);
}
}
$icons_updated = 0;
$errors = array();
foreach ($images as $image)
@ -369,6 +400,17 @@ class acp_icons
$image_height[$image] = $img_size[1];
}
if ($image_width[$image] > 127 && $image_width[$image] > $image_height[$image])
{
$image_height[$image] = (int) ($image_height[$image] * (127 / $image_width[$image]));
$image_width[$image] = 127;
}
else if ($image_height[$image] > 127)
{
$image_width[$image] = (int) ($image_width[$image] * (127 / $image_height[$image]));
$image_height[$image] = 127;
}
$img_sql = array(
$fields . '_url' => $image,
$fields . '_width' => $image_width[$image],
@ -426,13 +468,13 @@ class acp_icons
$db->sql_query($sql);
$icons_updated++;
}
}
}
$cache->destroy('_icons');
$cache->destroy('sql', $table);
$level = E_USER_NOTICE;
switch ($icons_updated)
{
@ -440,11 +482,11 @@ class acp_icons
$suc_lang = "{$lang}_NONE";
$level = E_USER_WARNING;
break;
case 1:
$suc_lang = "{$lang}_ONE";
break;
default:
$suc_lang = $lang;
}
@ -495,7 +537,6 @@ class acp_icons
}
}
// The user has already selected a smilies_pak file
if ($current == 'delete')
{
@ -541,6 +582,15 @@ class acp_icons
$db->sql_freeresult($result);
}
if ($mode == 'smilies')
{
$smiley_count = $this->item_count($table);
if ($smiley_count + sizeof($pak_ary) > SMILEY_LIMIT)
{
trigger_error(sprintf($user->lang['TOO_MANY_SMILIES'], SMILEY_LIMIT) . adm_back_link($this->u_action), E_USER_WARNING);
}
}
foreach ($pak_ary as $pak_entry)
{
$data = array();
@ -835,11 +885,14 @@ class acp_icons
);
$spacer = false;
$pagination_start = request_var('start', 0);
$item_count = $this->item_count($table);
$sql = "SELECT *
FROM $table
ORDER BY {$fields}_order ASC";
$result = $db->sql_query($sql);
$result = $db->sql_query_limit($sql, $config['smilies_per_page'], $pagination_start);
while ($row = $db->sql_fetchrow($result))
{
@ -855,9 +908,9 @@ class acp_icons
'EMOTION' => (isset($row['emotion'])) ? $row['emotion'] : '',
'U_EDIT' => $this->u_action . '&amp;action=edit&amp;id=' . $row[$fields . '_id'],
'U_DELETE' => $this->u_action . '&amp;action=delete&amp;id=' . $row[$fields . '_id'],
'U_MOVE_UP' => $this->u_action . '&amp;action=move_up&amp;id=' . $row[$fields . '_id'],
'U_MOVE_DOWN' => $this->u_action . '&amp;action=move_down&amp;id=' . $row[$fields . '_id'])
);
'U_MOVE_UP' => $this->u_action . '&amp;action=move_up&amp;id=' . $row[$fields . '_id'] . '&amp;start=' . $pagination_start,
'U_MOVE_DOWN' => $this->u_action . '&amp;action=move_down&amp;id=' . $row[$fields . '_id'] . '&amp;start=' . $pagination_start,
));
if (!$spacer && !$row['display_on_posting'])
{
@ -865,6 +918,28 @@ class acp_icons
}
}
$db->sql_freeresult($result);
$template->assign_var('PAGINATION',
generate_pagination($this->u_action, $item_count, $config['smilies_per_page'], $pagination_start, true)
);
}
/**
* Returns the count of smilies or icons in the database
*
* @param string $table The table of items to count.
* @return int number of items
*/
/* private */ function item_count($table)
{
global $db;
$sql = "SELECT COUNT(*) AS count
FROM $table";
$result = $db->sql_query($sql);
$item_count = (int) $db->sql_fetchfield('count');
$db->sql_freeresult($result);
return $item_count;
}
}

View file

@ -51,6 +51,19 @@ class acp_inactive
$form_key = 'acp_inactive';
add_form_key($form_key);
// We build the sort key and per page settings here, because they may be needed later
// Number of entries to display
$per_page = request_var('users_per_page', (int) $config['topics_per_page']);
// Sorting
$limit_days = array(0 => $user->lang['ALL_ENTRIES'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']);
$sort_by_text = array('i' => $user->lang['SORT_INACTIVE'], 'j' => $user->lang['SORT_REG_DATE'], 'l' => $user->lang['SORT_LAST_VISIT'], 'd' => $user->lang['SORT_LAST_REMINDER'], 'r' => $user->lang['SORT_REASON'], 'u' => $user->lang['SORT_USERNAME'], 'p' => $user->lang['SORT_POSTS'], 'e' => $user->lang['SORT_REMINDER']);
$sort_by_sql = array('i' => 'user_inactive_time', 'j' => 'user_regdate', 'l' => 'user_lastvisit', 'd' => 'user_reminded_time', 'r' => 'user_inactive_reason', 'u' => 'username_clean', 'p' => 'user_posts', 'e' => 'user_reminded');
$s_limit_days = $s_sort_key = $s_sort_dir = $u_sort_param = '';
gen_sort_selects($limit_days, $sort_by_text, $sort_days, $sort_key, $sort_dir, $s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param);
if ($submit && sizeof($mark))
{
if ($action !== 'delete' && !check_form_key($form_key))
@ -67,7 +80,7 @@ class acp_inactive
FROM ' . USERS_TABLE . '
WHERE ' . $db->sql_in_set('user_id', $mark);
$result = $db->sql_query($sql);
$user_affected = array();
while ($row = $db->sql_fetchrow($result))
{
@ -100,7 +113,7 @@ class acp_inactive
{
include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
$messenger = new messenger();
$messenger = new messenger(false);
foreach ($inactive_users as $row)
{
@ -122,6 +135,12 @@ class acp_inactive
$messenger->save_queue();
}
// For activate we really need to redirect, else a refresh can result in users being deactivated again
$u_action = $this->u_action . "&amp;$u_sort_param&amp;start=$start";
$u_action .= ($per_page != $config['topics_per_page']) ? "&amp;users_per_page=$per_page" : '';
redirect($u_action);
}
else if ($action == 'delete')
{
@ -175,7 +194,7 @@ class acp_inactive
include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
$messenger = new messenger();
$usernames = array();
$usernames = $user_ids = array();
do
{
@ -198,28 +217,34 @@ class acp_inactive
$messenger->send($row['user_notify_type']);
$usernames[] = $row['username'];
$user_ids[] = (int) $row['user_id'];
}
while ($row = $db->sql_fetchrow($result));
$messenger->save_queue();
// Add the remind state to the database
$sql = 'UPDATE ' . USERS_TABLE . '
SET user_reminded = user_reminded + 1,
user_reminded_time = ' . time() . '
WHERE ' . $db->sql_in_set('user_id', $user_ids);
$db->sql_query($sql);
add_log('admin', 'LOG_INACTIVE_REMIND', implode(', ', $usernames));
unset($usernames);
}
$db->sql_freeresult($result);
// For remind we really need to redirect, else a refresh can result in more than one reminder
$u_action = $this->u_action . "&amp;$u_sort_param&amp;start=$start";
$u_action .= ($per_page != $config['topics_per_page']) ? "&amp;users_per_page=$per_page" : '';
redirect($u_action);
break;
}
}
// Sorting
$limit_days = array(0 => $user->lang['ALL_ENTRIES'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']);
$sort_by_text = array('i' => $user->lang['SORT_INACTIVE'], 'j' => $user->lang['SORT_REG_DATE'], 'l' => $user->lang['SORT_LAST_VISIT'], 'r' => $user->lang['SORT_REASON'], 'u' => $user->lang['SORT_USERNAME']);
$sort_by_sql = array('i' => 'user_inactive_time', 'j' => 'user_regdate', 'l' => 'user_lastvisit', 'r' => 'user_inactive_reason', 'u' => 'username_clean');
$s_limit_days = $s_sort_key = $s_sort_dir = $u_sort_param = '';
gen_sort_selects($limit_days, $sort_by_text, $sort_days, $sort_key, $sort_dir, $s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param);
// Define where and sort sql for use in displaying logs
$sql_where = ($sort_days) ? (time() - ($sort_days * 86400)) : 0;
$sql_sort = $sort_by_sql[$sort_key] . ' ' . (($sort_dir == 'd') ? 'DESC' : 'ASC');
@ -227,19 +252,30 @@ class acp_inactive
$inactive = array();
$inactive_count = 0;
$start = view_inactive_users($inactive, $inactive_count, $config['topics_per_page'], $start, $sql_where, $sql_sort);
$start = view_inactive_users($inactive, $inactive_count, $per_page, $start, $sql_where, $sql_sort);
foreach ($inactive as $row)
{
$template->assign_block_vars('inactive', array(
'INACTIVE_DATE' => $user->format_date($row['user_inactive_time']),
'REMINDED_DATE' => $user->format_date($row['user_reminded_time']),
'JOINED' => $user->format_date($row['user_regdate']),
'LAST_VISIT' => (!$row['user_lastvisit']) ? ' - ' : $user->format_date($row['user_lastvisit']),
'REASON' => $row['inactive_reason'],
'USER_ID' => $row['user_id'],
'USERNAME' => $row['username'],
'U_USER_ADMIN' => append_sid("{$phpbb_admin_path}index.$phpEx", "i=users&amp;mode=overview&amp;u={$row['user_id']}"))
);
'POSTS' => ($row['user_posts']) ? $row['user_posts'] : 0,
'REMINDED' => $row['user_reminded'],
'REMINDED_EXPLAIN' => $user->lang('USER_LAST_REMINDED', (int) $row['user_reminded'], $user->format_date($row['user_reminded_time'])),
'USERNAME_FULL' => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour'], false, append_sid("{$phpbb_admin_path}index.$phpEx", 'i=users&amp;mode=overview')),
'USERNAME' => get_username_string('username', $row['user_id'], $row['username'], $row['user_colour']),
'USER_COLOR' => get_username_string('colour', $row['user_id'], $row['username'], $row['user_colour']),
'U_USER_ADMIN' => append_sid("{$phpbb_admin_path}index.$phpEx", "i=users&amp;mode=overview&amp;u={$row['user_id']}"),
'U_SEARCH_USER' => ($auth->acl_get('u_search')) ? append_sid("{$phpbb_root_path}search.$phpEx", "author_id={$row['user_id']}&amp;sr=posts") : '',
));
}
$option_ary = array('activate' => 'ACTIVATE', 'delete' => 'DELETE');
@ -255,9 +291,10 @@ class acp_inactive
'S_LIMIT_DAYS' => $s_limit_days,
'S_SORT_KEY' => $s_sort_key,
'S_SORT_DIR' => $s_sort_dir,
'S_ON_PAGE' => on_page($inactive_count, $config['topics_per_page'], $start),
'PAGINATION' => generate_pagination($this->u_action . "&amp;$u_sort_param", $inactive_count, $config['topics_per_page'], $start, true),
'S_ON_PAGE' => on_page($inactive_count, $per_page, $start),
'PAGINATION' => generate_pagination($this->u_action . "&amp;$u_sort_param&amp;users_per_page=$per_page", $inactive_count, $per_page, $start, true),
'USERS_PER_PAGE' => $per_page,
'U_ACTION' => $this->u_action . '&amp;start=' . $start,
));

View file

@ -766,28 +766,41 @@ class acp_language
trigger_error($user->lang['NO_REMOVE_DEFAULT_LANG'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$db->sql_query('DELETE FROM ' . LANG_TABLE . ' WHERE lang_id = ' . $lang_id);
if (confirm_box(true))
{
$db->sql_query('DELETE FROM ' . LANG_TABLE . ' WHERE lang_id = ' . $lang_id);
$sql = 'UPDATE ' . USERS_TABLE . "
SET user_lang = '" . $db->sql_escape($config['default_lang']) . "'
WHERE user_lang = '" . $db->sql_escape($row['lang_iso']) . "'";
$db->sql_query($sql);
$sql = 'UPDATE ' . USERS_TABLE . "
SET user_lang = '" . $db->sql_escape($config['default_lang']) . "'
WHERE user_lang = '" . $db->sql_escape($row['lang_iso']) . "'";
$db->sql_query($sql);
// We also need to remove the translated entries for custom profile fields - we want clean tables, don't we?
$sql = 'DELETE FROM ' . PROFILE_LANG_TABLE . ' WHERE lang_id = ' . $lang_id;
$db->sql_query($sql);
// We also need to remove the translated entries for custom profile fields - we want clean tables, don't we?
$sql = 'DELETE FROM ' . PROFILE_LANG_TABLE . ' WHERE lang_id = ' . $lang_id;
$db->sql_query($sql);
$sql = 'DELETE FROM ' . PROFILE_FIELDS_LANG_TABLE . ' WHERE lang_id = ' . $lang_id;
$db->sql_query($sql);
$sql = 'DELETE FROM ' . PROFILE_FIELDS_LANG_TABLE . ' WHERE lang_id = ' . $lang_id;
$db->sql_query($sql);
$sql = 'DELETE FROM ' . STYLES_IMAGESET_DATA_TABLE . " WHERE image_lang = '" . $db->sql_escape($row['lang_iso']) . "'";
$result = $db->sql_query($sql);
$sql = 'DELETE FROM ' . STYLES_IMAGESET_DATA_TABLE . " WHERE image_lang = '" . $db->sql_escape($row['lang_iso']) . "'";
$result = $db->sql_query($sql);
$cache->destroy('sql', STYLES_IMAGESET_DATA_TABLE);
$cache->destroy('sql', STYLES_IMAGESET_DATA_TABLE);
add_log('admin', 'LOG_LANGUAGE_PACK_DELETED', $row['lang_english_name']);
add_log('admin', 'LOG_LANGUAGE_PACK_DELETED', $row['lang_english_name']);
trigger_error(sprintf($user->lang['LANGUAGE_PACK_DELETED'], $row['lang_english_name']) . adm_back_link($this->u_action));
trigger_error(sprintf($user->lang['LANGUAGE_PACK_DELETED'], $row['lang_english_name']) . adm_back_link($this->u_action));
}
else
{
$s_hidden_fields = array(
'i' => $id,
'mode' => $mode,
'action' => $action,
'id' => $lang_id,
);
confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields($s_hidden_fields));
}
break;
case 'install':
@ -1254,7 +1267,7 @@ $lang = array_merge($lang, array(
$keys = func_get_args();
$non_static = array_shift($keys);
$value = array_shift($keys);
$value = utf8_normalize_nfc(array_shift($keys));
if (!$non_static)
{

View file

@ -33,6 +33,7 @@ class acp_logs
// Set up general vars
$action = request_var('action', '');
$forum_id = request_var('f', 0);
$topic_id = request_var('t', 0);
$start = request_var('start', 0);
$deletemark = (!empty($_POST['delmarked'])) ? true : false;
$deleteall = (!empty($_POST['delall'])) ? true : false;
@ -104,6 +105,9 @@ class acp_logs
$sql_where = ($sort_days) ? (time() - ($sort_days * 86400)) : 0;
$sql_sort = $sort_by_sql[$sort_key] . ' ' . (($sort_dir == 'd') ? 'DESC' : 'ASC');
$keywords = utf8_normalize_nfc(request_var('keywords', '', true));
$keywords_param = !empty($keywords) ? '&amp;keywords=' . urlencode(htmlspecialchars_decode($keywords)) : '';
$l_title = $user->lang['ACP_' . strtoupper($mode) . '_LOGS'];
$l_title_explain = $user->lang['ACP_' . strtoupper($mode) . '_LOGS_EXPLAIN'];
@ -123,7 +127,7 @@ class acp_logs
// Grab log data
$log_data = array();
$log_count = 0;
view_log($mode, $log_data, $log_count, $config['topics_per_page'], $start, $forum_id, 0, 0, $sql_where, $sql_sort);
view_log($mode, $log_data, $log_count, $config['topics_per_page'], $start, $forum_id, 0, 0, $sql_where, $sql_sort, $keywords);
$template->assign_vars(array(
'L_TITLE' => $l_title,
@ -131,12 +135,13 @@ class acp_logs
'U_ACTION' => $this->u_action,
'S_ON_PAGE' => on_page($log_count, $config['topics_per_page'], $start),
'PAGINATION' => generate_pagination($this->u_action . "&amp;$u_sort_param", $log_count, $config['topics_per_page'], $start, true),
'PAGINATION' => generate_pagination($this->u_action . "&amp;$u_sort_param$keywords_param", $log_count, $config['topics_per_page'], $start, true),
'S_LIMIT_DAYS' => $s_limit_days,
'S_SORT_KEY' => $s_sort_key,
'S_SORT_DIR' => $s_sort_dir,
'S_CLEARLOGS' => $auth->acl_get('a_clearlogs'),
'S_KEYWORDS' => $keywords,
)
);

View file

@ -97,6 +97,10 @@ class acp_main
$confirm = true;
$confirm_lang = 'PURGE_CACHE_CONFIRM';
break;
case 'purge_sessions':
$confirm = true;
$confirm_lang = 'PURGE_SESSIONS_CONFIRM';
break;
default:
$confirm = true;
@ -341,10 +345,76 @@ class acp_main
add_log('admin', 'LOG_PURGE_CACHE');
break;
case 'purge_sessions':
if ((int) $user->data['user_type'] !== USER_FOUNDER)
{
trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$tables = array(CONFIRM_TABLE, SESSIONS_TABLE);
foreach ($tables as $table)
{
switch ($db->sql_layer)
{
case 'sqlite':
case 'firebird':
$db->sql_query("DELETE FROM $table");
break;
default:
$db->sql_query("TRUNCATE TABLE $table");
break;
}
}
// let's restore the admin session
$reinsert_ary = array(
'session_id' => (string) $user->session_id,
'session_page' => (string) substr($user->page['page'], 0, 199),
'session_forum_id' => $user->page['forum'],
'session_user_id' => (int) $user->data['user_id'],
'session_start' => (int) $user->data['session_start'],
'session_last_visit' => (int) $user->data['session_last_visit'],
'session_time' => (int) $user->time_now,
'session_browser' => (string) trim(substr($user->browser, 0, 149)),
'session_forwarded_for' => (string) $user->forwarded_for,
'session_ip' => (string) $user->ip,
'session_autologin' => (int) $user->data['session_autologin'],
'session_admin' => 1,
'session_viewonline' => (int) $user->data['session_viewonline'],
);
$sql = 'INSERT INTO ' . SESSIONS_TABLE . ' ' . $db->sql_build_array('INSERT', $reinsert_ary);
$db->sql_query($sql);
add_log('admin', 'LOG_PURGE_SESSIONS');
break;
}
}
}
// Version check
$user->add_lang('install');
$latest_version_info = false;
if (($latest_version_info = obtain_latest_version_info(request_var('versioncheck_force', false))) === false)
{
$template->assign_var('S_VERSIONCHECK_FAIL', true);
}
else
{
$latest_version_info = explode("\n", $latest_version_info);
$latest_version = str_replace('rc', 'RC', strtolower(trim($latest_version_info[0])));
$current_version = str_replace('rc', 'RC', strtolower($config['version']));
$template->assign_vars(array(
'S_VERSION_UP_TO_DATE' => version_compare($current_version, $latest_version, '<') ? false : true,
));
}
// Get forum statistics
$total_posts = $config['num_posts'];
$total_topics = $config['num_topics'];
@ -435,13 +505,15 @@ class acp_main
'UPLOAD_DIR_SIZE' => $upload_dir_size,
'TOTAL_ORPHAN' => $total_orphan,
'S_TOTAL_ORPHAN' => ($total_orphan === false) ? false : true,
'GZIP_COMPRESSION' => ($config['gzip_compress']) ? $user->lang['ON'] : $user->lang['OFF'],
'GZIP_COMPRESSION' => ($config['gzip_compress'] && @extension_loaded('zlib')) ? $user->lang['ON'] : $user->lang['OFF'],
'DATABASE_INFO' => $db->sql_server_info(),
'BOARD_VERSION' => $config['version'],
'U_ACTION' => $this->u_action,
'U_ADMIN_LOG' => append_sid("{$phpbb_admin_path}index.$phpEx", 'i=logs&amp;mode=admin'),
'U_INACTIVE_USERS' => append_sid("{$phpbb_admin_path}index.$phpEx", 'i=inactive&amp;mode=list'),
'U_VERSIONCHECK' => append_sid("{$phpbb_admin_path}index.$phpEx", 'i=update&amp;mode=version_check'),
'U_VERSIONCHECK_FORCE' => append_sid("{$phpbb_admin_path}index.$phpEx", 'i=1&amp;versioncheck_force=1'),
'S_ACTION_OPTIONS' => ($auth->acl_get('a_board')) ? true : false,
'S_FOUNDER' => ($user->data['user_type'] == USER_FOUNDER) ? true : false,
@ -468,6 +540,8 @@ class acp_main
if ($auth->acl_get('a_user'))
{
$user->add_lang('memberlist');
$inactive = array();
$inactive_count = 0;
@ -477,13 +551,24 @@ class acp_main
{
$template->assign_block_vars('inactive', array(
'INACTIVE_DATE' => $user->format_date($row['user_inactive_time']),
'REMINDED_DATE' => $user->format_date($row['user_reminded_time']),
'JOINED' => $user->format_date($row['user_regdate']),
'LAST_VISIT' => (!$row['user_lastvisit']) ? ' - ' : $user->format_date($row['user_lastvisit']),
'REASON' => $row['inactive_reason'],
'USER_ID' => $row['user_id'],
'USERNAME' => $row['username'],
'U_USER_ADMIN' => append_sid("{$phpbb_admin_path}index.$phpEx", "i=users&amp;mode=overview&amp;u={$row['user_id']}"))
);
'POSTS' => ($row['user_posts']) ? $row['user_posts'] : 0,
'REMINDED' => $row['user_reminded'],
'REMINDED_EXPLAIN' => $user->lang('USER_LAST_REMINDED', (int) $row['user_reminded'], $user->format_date($row['user_reminded_time'])),
'USERNAME_FULL' => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour'], false, append_sid("{$phpbb_admin_path}index.$phpEx", 'i=users&amp;mode=overview')),
'USERNAME' => get_username_string('username', $row['user_id'], $row['username'], $row['user_colour']),
'USER_COLOR' => get_username_string('colour', $row['user_id'], $row['username'], $row['user_colour']),
'U_USER_ADMIN' => append_sid("{$phpbb_admin_path}index.$phpEx", "i=users&amp;mode=overview&amp;u={$row['user_id']}"),
'U_SEARCH_USER' => ($auth->acl_get('u_search')) ? append_sid("{$phpbb_root_path}search.$phpEx", "author_id={$row['user_id']}&amp;sr=posts") : '',
));
}
$option_ary = array('activate' => 'ACTIVATE', 'delete' => 'DELETE');
@ -499,12 +584,12 @@ class acp_main
}
// Warn if install is still present
if (file_exists($phpbb_root_path . 'install'))
if (file_exists($phpbb_root_path . 'install') && !is_file($phpbb_root_path . 'install'))
{
$template->assign_var('S_REMOVE_INSTALL', true);
}
if (!defined('PHPBB_DISABLE_CONFIG_CHECK') && file_exists($phpbb_root_path . 'config.' . $phpEx) && is_writable($phpbb_root_path . 'config.' . $phpEx))
if (!defined('PHPBB_DISABLE_CONFIG_CHECK') && file_exists($phpbb_root_path . 'config.' . $phpEx) && phpbb_is_writable($phpbb_root_path . 'config.' . $phpEx))
{
// World-Writable? (000x)
$template->assign_var('S_WRITABLE_CONFIG', (bool) (@fileperms($phpbb_root_path . 'config.' . $phpEx) & 0x0002));

View file

@ -57,6 +57,21 @@ class acp_permissions
trigger_error('NO_MODE', E_USER_ERROR);
}
// Copy forum permissions
if ($mode == 'setting_forum_copy')
{
$this->tpl_name = 'permission_forum_copy';
if ($auth->acl_get('a_fauth') && $auth->acl_get('a_authusers') && $auth->acl_get('a_authgroups') && $auth->acl_get('a_mauth'))
{
$this->page_title = 'ACP_FORUM_PERMISSIONS_COPY';
$this->copy_forum_permissions();
return;
}
trigger_error('NO_MODE', E_USER_ERROR);
}
// Set some vars
$action = request_var('action', array('' => 0));
$action = key($action);
@ -217,43 +232,71 @@ class acp_permissions
trigger_error($user->lang['WRONG_PERMISSION_TYPE'] . adm_back_link($this->u_action), E_USER_WARNING);
}
// Handle actions
if (strpos($mode, 'setting_') === 0 && $action)
{
switch ($action)
{
case 'delete':
if (!check_form_key($form_name))
if (confirm_box(true))
{
trigger_error($user->lang['FORM_INVALID']. adm_back_link($this->u_action), E_USER_WARNING);
}
// All users/groups selected?
$all_users = (isset($_POST['all_users'])) ? true : false;
$all_groups = (isset($_POST['all_groups'])) ? true : false;
// All users/groups selected?
$all_users = (isset($_POST['all_users'])) ? true : false;
$all_groups = (isset($_POST['all_groups'])) ? true : false;
if ($all_users || $all_groups)
{
$items = $this->retrieve_defined_user_groups($permission_scope, $forum_id, $permission_type);
if ($all_users && sizeof($items['user_ids']))
if ($all_users || $all_groups)
{
$user_id = $items['user_ids'];
}
else if ($all_groups && sizeof($items['group_ids']))
{
$group_id = $items['group_ids'];
}
}
$items = $this->retrieve_defined_user_groups($permission_scope, $forum_id, $permission_type);
if (sizeof($user_id) || sizeof($group_id))
{
$this->remove_permissions($mode, $permission_type, $auth_admin, $user_id, $group_id, $forum_id);
if ($all_users && sizeof($items['user_ids']))
{
$user_id = $items['user_ids'];
}
else if ($all_groups && sizeof($items['group_ids']))
{
$group_id = $items['group_ids'];
}
}
if (sizeof($user_id) || sizeof($group_id))
{
$this->remove_permissions($mode, $permission_type, $auth_admin, $user_id, $group_id, $forum_id);
}
else
{
trigger_error($user->lang['NO_USER_GROUP_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING);
}
}
else
{
trigger_error($user->lang['NO_USER_GROUP_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING);
if (isset($_POST['cancel']))
{
$u_redirect = $this->u_action . '&amp;type=' . $permission_type;
foreach ($forum_id as $fid)
{
$u_redirect .= '&amp;forum_id[]=' . $fid;
}
redirect($u_redirect);
}
$s_hidden_fields = array(
'i' => $id,
'mode' => $mode,
'action' => array($action => 1),
'user_id' => $user_id,
'group_id' => $group_id,
'forum_id' => $forum_id,
'type' => $permission_type,
);
if (isset($_POST['all_users']))
{
$s_hidden_fields['all_users'] = 1;
}
if (isset($_POST['all_groups']))
{
$s_hidden_fields['all_groups'] = 1;
}
confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields($s_hidden_fields));
}
break;
@ -963,6 +1006,7 @@ class acp_permissions
LEFT JOIN ' . USER_GROUP_TABLE . ' ug ON (ug.group_id = g.group_id)
WHERE ug.user_id = ' . $user_id . '
AND ug.user_pending = 0
AND NOT (ug.group_leader = 1 AND g.group_skip_auth = 1)
ORDER BY g.group_type DESC, g.group_id DESC';
$result = $db->sql_query($sql);
@ -1123,6 +1167,57 @@ class acp_permissions
));
}
/**
* Handles copying permissions from one forum to others
*/
function copy_forum_permissions()
{
global $auth, $cache, $template, $user;
$user->add_lang('acp/forums');
$submit = isset($_POST['submit']) ? true : false;
if ($submit)
{
$src = request_var('src_forum_id', 0);
$dest = request_var('dest_forum_ids', array(0));
if (confirm_box(true))
{
if (copy_forum_permissions($src, $dest))
{
cache_moderators();
$auth->acl_clear_prefetch();
$cache->destroy('sql', FORUMS_TABLE);
trigger_error($user->lang['AUTH_UPDATED'] . adm_back_link($this->u_action));
}
else
{
trigger_error($user->lang['SELECTED_FORUM_NOT_EXIST'] . adm_back_link($this->u_action), E_USER_WARNING);
}
}
else
{
$s_hidden_fields = array(
'submit' => $submit,
'src_forum_id' => $src,
'dest_forum_ids' => $dest,
);
$s_hidden_fields = build_hidden_fields($s_hidden_fields);
confirm_box(false, $user->lang['COPY_PERMISSIONS_CONFIRM'], $s_hidden_fields);
}
}
$template->assign_vars(array(
'S_FORUM_OPTIONS' => make_forum_select(false, false, false, false, false),
));
}
/**
* Get already assigned users/groups
*/

View file

@ -369,6 +369,7 @@ class acp_profile
'field_show_profile'=> 0,
'field_no_view' => 0,
'field_show_on_reg' => 0,
'field_show_on_vt' => 0,
'lang_name' => utf8_normalize_nfc(request_var('field_ident', '', true)),
'lang_explain' => '',
'lang_default_value'=> '')
@ -379,7 +380,7 @@ class acp_profile
// $exclude contains the data we gather in each step
$exclude = array(
1 => array('field_ident', 'lang_name', 'lang_explain', 'field_option_none', 'field_show_on_reg', 'field_required', 'field_hide', 'field_show_profile', 'field_no_view'),
1 => array('field_ident', 'lang_name', 'lang_explain', 'field_option_none', 'field_show_on_reg', 'field_show_on_vt', 'field_required', 'field_hide', 'field_show_profile', 'field_no_view'),
2 => array('field_length', 'field_maxlen', 'field_minlen', 'field_validation', 'field_novalue', 'field_default_value'),
3 => array('l_lang_name', 'l_lang_explain', 'l_lang_default_value', 'l_lang_options')
);
@ -405,6 +406,7 @@ class acp_profile
$visibility_ary = array(
'field_required',
'field_show_on_reg',
'field_show_on_vt',
'field_show_profile',
'field_hide',
);
@ -721,6 +723,7 @@ class acp_profile
'S_STEP_ONE' => true,
'S_FIELD_REQUIRED' => ($cp->vars['field_required']) ? true : false,
'S_SHOW_ON_REG' => ($cp->vars['field_show_on_reg']) ? true : false,
'S_SHOW_ON_VT' => ($cp->vars['field_show_on_vt']) ? true : false,
'S_FIELD_HIDE' => ($cp->vars['field_hide']) ? true : false,
'S_SHOW_PROFILE' => ($cp->vars['field_show_profile']) ? true : false,
'S_FIELD_NO_VIEW' => ($cp->vars['field_no_view']) ? true : false,
@ -1036,6 +1039,7 @@ class acp_profile
'field_validation' => $cp->vars['field_validation'],
'field_required' => $cp->vars['field_required'],
'field_show_on_reg' => $cp->vars['field_show_on_reg'],
'field_show_on_vt' => $cp->vars['field_show_on_vt'],
'field_hide' => $cp->vars['field_hide'],
'field_show_profile' => $cp->vars['field_show_profile'],
'field_no_view' => $cp->vars['field_no_view']

View file

@ -406,7 +406,12 @@ class acp_prune
$where_sql .= (sizeof($joined)) ? " AND user_regdate " . $key_match[$joined_select] . ' ' . gmmktime(0, 0, 0, (int) $joined[1], (int) $joined[2], (int) $joined[0]) : '';
$where_sql .= ($count !== '') ? " AND user_posts " . $key_match[$count_select] . ' ' . (int) $count . ' ' : '';
if (sizeof($active) && $active_select != 'lt')
// First handle pruning of users who never logged in, last active date is 0000-00-00
if (sizeof($active) && (int) $active[0] == 0 && (int) $active[1] == 0 && (int) $active[2] == 0)
{
$where_sql .= ' AND user_lastvisit = 0';
}
else if (sizeof($active) && $active_select != 'lt')
{
$where_sql .= ' AND user_lastvisit ' . $key_match[$active_select] . ' ' . gmmktime(0, 0, 0, (int) $active[1], (int) $active[2], (int) $active[0]);
}

View file

@ -39,7 +39,7 @@ class acp_ranks
$this->tpl_name = 'acp_ranks';
$this->page_title = 'ACP_MANAGE_RANKS';
$form_name = 'acp_prune';
$form_name = 'acp_ranks';
add_form_key($form_name);
switch ($action)
@ -168,25 +168,22 @@ class acp_ranks
{
$img = $path . $img;
if (!in_array($img, $existing_imgs) || $action == 'edit')
if ($ranks && $img == $ranks['rank_image'])
{
if ($ranks && $img == $ranks['rank_image'])
{
$selected = ' selected="selected"';
$edit_img = $img;
}
else
{
$selected = '';
}
if (strlen($img) > 255)
{
continue;
}
$filename_list .= '<option value="' . htmlspecialchars($img) . '"' . $selected . '>' . $img . '</option>';
$selected = ' selected="selected"';
$edit_img = $img;
}
else
{
$selected = '';
}
if (strlen($img) > 255)
{
continue;
}
$filename_list .= '<option value="' . htmlspecialchars($img) . '"' . $selected . '>' . $img . ((in_array($img, $existing_imgs)) ? ' ' . $user->lang['RANK_IMAGE_IN_USE'] : '') . '</option>';
}
}

View file

@ -0,0 +1,90 @@
<?php
/**
*
* @package acp
* @version $Id$
* @copyright (c) 2005 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
include($phpbb_root_path . 'includes/questionnaire/questionnaire.' . $phpEx);
/**
* @package acp
*/
class acp_send_statistics
{
var $u_action;
function main($id, $mode)
{
global $config, $template, $phpbb_admin_path, $phpEx;
$collect_url = "http://www.phpbb.com/stats/receive_stats.php";
$this->tpl_name = 'acp_send_statistics';
$this->page_title = 'ACP_SEND_STATISTICS';
// generate a unique id if necessary
if (!isset($config['questionnaire_unique_id']))
{
$install_id = unique_id();
set_config('questionnaire_unique_id', $install_id);
}
else
{
$install_id = $config['questionnaire_unique_id'];
}
$collector = new phpbb_questionnaire_data_collector($install_id);
// Add data provider
$collector->add_data_provider(new phpbb_questionnaire_php_data_provider());
$collector->add_data_provider(new phpbb_questionnaire_system_data_provider());
$collector->add_data_provider(new phpbb_questionnaire_phpbb_data_provider($config));
$template->assign_vars(array(
'U_COLLECT_STATS' => $collect_url,
'RAW_DATA' => $collector->get_data_for_form(),
'U_ACP_MAIN' => append_sid("{$phpbb_admin_path}index.$phpEx"),
));
$raw = $collector->get_data_raw();
foreach ($raw as $provider => $data)
{
if ($provider == 'install_id')
{
$data = array($provider => $data);
}
$template->assign_block_vars('providers', array(
'NAME' => htmlspecialchars($provider),
));
foreach ($data as $key => $value)
{
if (is_array($value))
{
$value = utf8_wordwrap(serialize($value), 75, "\n", true);
}
$template->assign_block_vars('providers.values', array(
'KEY' => utf8_htmlspecialchars($key),
'VALUE' => utf8_htmlspecialchars($value),
));
}
}
}
}
?>

View file

@ -210,23 +210,36 @@ parse_css_file = {PARSE_CSS_FILE}
trigger_error($user->lang['DEACTIVATE_DEFAULT'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$sql = 'UPDATE ' . STYLES_TABLE . '
SET style_active = ' . (($action == 'activate') ? 1 : 0) . '
WHERE style_id = ' . $style_id;
$db->sql_query($sql);
// Set style to default for any member using deactivated style
if ($action == 'deactivate')
if (($action == 'deactivate' && confirm_box(true)) || $action == 'activate')
{
$sql = 'UPDATE ' . USERS_TABLE . '
SET user_style = ' . $config['default_style'] . "
WHERE user_style = $style_id";
$sql = 'UPDATE ' . STYLES_TABLE . '
SET style_active = ' . (($action == 'activate') ? 1 : 0) . '
WHERE style_id = ' . $style_id;
$db->sql_query($sql);
$sql = 'UPDATE ' . FORUMS_TABLE . '
SET forum_style = 0
WHERE forum_style = ' . $style_id;
$db->sql_query($sql);
// Set style to default for any member using deactivated style
if ($action == 'deactivate')
{
$sql = 'UPDATE ' . USERS_TABLE . '
SET user_style = ' . $config['default_style'] . "
WHERE user_style = $style_id";
$db->sql_query($sql);
$sql = 'UPDATE ' . FORUMS_TABLE . '
SET forum_style = 0
WHERE forum_style = ' . $style_id;
$db->sql_query($sql);
}
}
else if ($action == 'deactivate')
{
$s_hidden_fields = array(
'i' => $id,
'mode' => $mode,
'action' => $action,
'style_id' => $style_id,
);
confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields($s_hidden_fields));
}
break;
}
@ -734,7 +747,8 @@ parse_css_file = {PARSE_CSS_FILE}
{
if (!($fp = @fopen($file, 'wb')))
{
trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING);
// File exists and is writeable, but still not able to be written to
trigger_error(sprintf($user->lang['TEMPLATE_FILE_NOT_WRITABLE'], htmlspecialchars($template_file)) . adm_back_link($this->u_action), E_USER_WARNING);
}
fwrite($fp, $template_data);
fclose($fp);
@ -827,6 +841,11 @@ parse_css_file = {PARSE_CSS_FILE}
unset($file_info);
}
if (empty($filelist['']))
{
trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING);
}
// Now create the categories
$filelist_cats[''] = array();
foreach ($filelist as $pathfile => $file_ary)
@ -1024,12 +1043,12 @@ parse_css_file = {PARSE_CSS_FILE}
foreach ($file_ary as $file)
{
$file = str_replace('/', '.', $file);
$file = str_replace('/', '.', $file);
// perform some dirty guessing to get the path right.
// We assume that three dots in a row were '../'
$tpl_file = str_replace('.', '/', $file);
$tpl_file = str_replace('///', '../', $tpl_file);
$tpl_file = str_replace('.', '/', $file);
$tpl_file = str_replace('///', '../', $tpl_file);
$filename = "{$cache_prefix}_$file.html.$phpEx";
@ -1061,6 +1080,11 @@ parse_css_file = {PARSE_CSS_FILE}
}
}
// Correct the filename if it is stored in database and the file is in a subfolder.
if ($template_row['template_storedb'])
{
$file = str_replace('.', '/', $file);
}
$template->assign_block_vars('file', array(
'U_VIEWSOURCE' => $this->u_action . "&amp;action=cache&amp;id=$template_id&amp;source=$file",
@ -1068,7 +1092,7 @@ parse_css_file = {PARSE_CSS_FILE}
'CACHED' => $user->format_date(filemtime("{$phpbb_root_path}cache/$filename")),
'FILENAME' => $file,
'FILENAME_PATH' => $file_tpl,
'FILESIZE' => sprintf('%.1f ' . $user->lang['KIB'], filesize("{$phpbb_root_path}cache/$filename") / 1024),
'FILESIZE' => get_formatted_filesize(filesize("{$phpbb_root_path}cache/$filename")),
'MODIFIED' => $user->format_date((!$template_row['template_storedb']) ? filemtime($file_tpl) : $filemtime[$file . '.html']))
);
}
@ -1266,7 +1290,6 @@ parse_css_file = {PARSE_CSS_FILE}
);
}
/**
* Edit imagesets
*
@ -2404,7 +2427,6 @@ parse_css_file = {PARSE_CSS_FILE}
}
}
if ($mode == 'template')
{
$super = array();
@ -2535,9 +2557,22 @@ parse_css_file = {PARSE_CSS_FILE}
{
trigger_error("Could not open {$phpbb_root_path}styles/$template_path$pathfile$file", E_USER_ERROR);
}
$template_data = fread($fp, filesize("{$phpbb_root_path}styles/$template_path$pathfile$file"));
$filesize = filesize("{$phpbb_root_path}styles/$template_path$pathfile$file");
if ($filesize)
{
$template_data = fread($fp, $filesize);
}
fclose($fp);
if (!$filesize)
{
// File is empty
continue;
}
if (preg_match_all('#<!-- INCLUDE (.*?\.html) -->#is', $template_data, $matches))
{
foreach ($matches[1] as $match)
@ -3204,7 +3239,6 @@ parse_css_file = {PARSE_CSS_FILE}
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
if ($row)
{
// If it exist, we just use the style on installation
@ -3255,7 +3289,6 @@ parse_css_file = {PARSE_CSS_FILE}
$inherit_bf = false;
}
if (sizeof($error))
{
return false;
@ -3525,7 +3558,6 @@ parse_css_file = {PARSE_CSS_FILE}
break;
}
$sql = "SELECT {$mode}_inherits_id
FROM $sql_from
WHERE {$mode}_id = " . (int) $id;

View file

@ -37,12 +37,7 @@ class acp_update
$errstr = '';
$errno = 0;
$info = get_remote_file('www.phpbb.com', '/updatecheck', ((defined('PHPBB_QA')) ? '30x_qa.txt' : '30x.txt'), $errstr, $errno);
if ($info === false)
{
trigger_error($errstr, E_USER_WARNING);
}
$info = obtain_latest_version_info(request_var('versioncheck_force', false), true);
$info = explode("\n", $info);
$latest_version = trim($info[0]);
@ -68,6 +63,7 @@ class acp_update
'S_UP_TO_DATE_AUTO' => $up_to_date_automatic,
'S_VERSION_CHECK' => true,
'U_ACTION' => $this->u_action,
'U_VERSIONCHECK_FORCE' => append_sid($this->u_action . '&amp;versioncheck_force=1'),
'LATEST_VERSION' => $latest_version,
'CURRENT_VERSION' => $config['version'],

View file

@ -385,6 +385,31 @@ class acp_users
user_active_flip('flip', $user_id);
if ($user_row['user_type'] == USER_INACTIVE)
{
if ($config['require_activation'] == USER_ACTIVATION_ADMIN)
{
include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
$messenger = new messenger(false);
$messenger->template('admin_welcome_activated', $user_row['user_lang']);
$messenger->to($user_row['user_email'], $user_row['username']);
$messenger->headers('X-AntiAbuse: Board servername - ' . $config['server_name']);
$messenger->headers('X-AntiAbuse: User_id - ' . $user->data['user_id']);
$messenger->headers('X-AntiAbuse: Username - ' . $user->data['username']);
$messenger->headers('X-AntiAbuse: User IP - ' . $user->ip);
$messenger->assign_vars(array(
'USERNAME' => htmlspecialchars_decode($user_row['username']))
);
$messenger->send(NOTIFY_EMAIL);
}
}
$message = ($user_row['user_type'] == USER_INACTIVE) ? 'USER_ADMIN_ACTIVATED' : 'USER_ADMIN_DEACTIVED';
$log = ($user_row['user_type'] == USER_INACTIVE) ? 'LOG_USER_ACTIVE' : 'LOG_USER_INACTIVE';
@ -495,6 +520,56 @@ class acp_users
break;
case 'deloutbox':
if (confirm_box(true))
{
$msg_ids = array();
$lang = 'EMPTY';
$sql = 'SELECT msg_id
FROM ' . PRIVMSGS_TO_TABLE . "
WHERE author_id = $user_id
AND folder_id = " . PRIVMSGS_OUTBOX;
$result = $db->sql_query($sql);
if ($row = $db->sql_fetchrow($result))
{
if (!function_exists('delete_pm'))
{
include($phpbb_root_path . 'includes/functions_privmsgs.' . $phpEx);
}
do
{
$msg_ids[] = (int) $row['msg_id'];
}
while ($row = $db->sql_fetchrow($result));
$db->sql_freeresult($result);
delete_pm($user_id, $msg_ids, PRIVMSGS_OUTBOX);
add_log('admin', 'LOG_USER_DEL_OUTBOX', $user_row['username']);
$lang = 'EMPTIED';
}
$db->sql_freeresult($result);
trigger_error($user->lang['USER_OUTBOX_' . $lang] . adm_back_link($this->u_action . '&amp;u=' . $user_id));
}
else
{
confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array(
'u' => $user_id,
'i' => $id,
'mode' => $mode,
'action' => $action,
'update' => true))
);
}
break;
case 'moveposts':
if (!check_form_key($form_name))
@ -650,6 +725,28 @@ class acp_users
trigger_error($user->lang['USER_POSTS_MOVED'] . adm_back_link($this->u_action . '&amp;u=' . $user_id));
break;
case 'leave_nr':
if (confirm_box(true))
{
remove_newly_registered($user_id, $user_row);
add_log('admin', 'LOG_USER_REMOVED_NR', $user_row['username']);
trigger_error($user->lang['USER_LIFTED_NR'] . adm_back_link($this->u_action . '&amp;u=' . $user_id));
}
else
{
confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array(
'u' => $user_id,
'i' => $id,
'mode' => $mode,
'action' => $action,
'update' => true))
);
}
break;
}
// Handle registration info updates
@ -775,7 +872,7 @@ class acp_users
{
$sql_ary += array(
'user_email' => $update_email,
'user_email_hash' => crc32($update_email) . strlen($update_email)
'user_email_hash' => phpbb_email_hash($update_email),
);
add_log('user', $user_id, 'LOG_USER_UPDATE_EMAIL', $user_row['username'], $user_row['user_email'], $update_email);
@ -820,7 +917,11 @@ class acp_users
if ($user_id == $user->data['user_id'])
{
$quick_tool_ary = array('delsig' => 'DEL_SIG', 'delavatar' => 'DEL_AVATAR', 'moveposts' => 'MOVE_POSTS', 'delposts' => 'DEL_POSTS', 'delattach' => 'DEL_ATTACH');
$quick_tool_ary = array('delsig' => 'DEL_SIG', 'delavatar' => 'DEL_AVATAR', 'moveposts' => 'MOVE_POSTS', 'delposts' => 'DEL_POSTS', 'delattach' => 'DEL_ATTACH', 'deloutbox' => 'DEL_OUTBOX');
if ($user_row['user_new'])
{
$quick_tool_ary['leave_nr'] = 'LEAVE_NR';
}
}
else
{
@ -836,12 +937,17 @@ class acp_users
$quick_tool_ary += array('active' => (($user_row['user_type'] == USER_INACTIVE) ? 'ACTIVATE' : 'DEACTIVATE'));
}
$quick_tool_ary += array('delsig' => 'DEL_SIG', 'delavatar' => 'DEL_AVATAR', 'moveposts' => 'MOVE_POSTS', 'delposts' => 'DEL_POSTS', 'delattach' => 'DEL_ATTACH');
$quick_tool_ary += array('delsig' => 'DEL_SIG', 'delavatar' => 'DEL_AVATAR', 'moveposts' => 'MOVE_POSTS', 'delposts' => 'DEL_POSTS', 'delattach' => 'DEL_ATTACH', 'deloutbox' => 'DEL_OUTBOX');
if ($config['email_enable'] && ($user_row['user_type'] == USER_NORMAL || $user_row['user_type'] == USER_INACTIVE))
{
$quick_tool_ary['reactivate'] = 'FORCE';
}
if ($user_row['user_new'])
{
$quick_tool_ary['leave_nr'] = 'LEAVE_NR';
}
}
$s_action_options = '<option class="sep" value="">' . $user->lang['SELECT_OPTION'] . '</option>';
@ -1035,6 +1141,161 @@ class acp_users
break;
case 'warnings':
$user->add_lang('mcp');
// Set up general vars
$start = request_var('start', 0);
$deletemark = (isset($_POST['delmarked'])) ? true : false;
$deleteall = (isset($_POST['delall'])) ? true : false;
$confirm = (isset($_POST['confirm'])) ? true : false;
$marked = request_var('mark', array(0));
$message = utf8_normalize_nfc(request_var('message', '', true));
// Sort keys
$sort_days = request_var('st', 0);
$sort_key = request_var('sk', 't');
$sort_dir = request_var('sd', 'd');
// Delete entries if requested and able
if ($deletemark || $deleteall || $confirm)
{
if (confirm_box(true))
{
$where_sql = '';
$deletemark = request_var('delmarked', 0);
$deleteall = request_var('delall', 0);
if ($deletemark && $marked)
{
$sql_in = array();
foreach ($marked as $mark)
{
$sql_in[] = $mark;
}
$where_sql = ' AND ' . $db->sql_in_set('warning_id', $sql_in);
unset($sql_in);
}
if ($where_sql || $deleteall)
{
$sql = 'DELETE FROM ' . WARNINGS_TABLE . "
WHERE user_id = $user_id
$where_sql";
$db->sql_query($sql);
if ($deleteall)
{
$log_warnings = $deleted_warnings = 0;
}
else
{
$num_warnings = (int) $db->sql_affectedrows();
$deleted_warnings = ' user_warnings - ' . $num_warnings;
$log_warnings = ($num_warnings > 2) ? 2 : $num_warnings;
}
$sql = 'UPDATE ' . USERS_TABLE . "
SET user_warnings = $deleted_warnings
WHERE user_id = $user_id";
$db->sql_query($sql);
switch ($log_warnings)
{
case 2:
add_log('admin', 'LOG_WARNINGS_DELETED', $user_row['username'], $num_warnings);
break;
case 1:
add_log('admin', 'LOG_WARNING_DELETED', $user_row['username']);
break;
default:
add_log('admin', 'LOG_WARNINGS_DELETED_ALL', $user_row['username']);
break;
}
}
}
else
{
$s_hidden_fields = array(
'i' => $id,
'mode' => $mode,
'u' => $user_id,
'mark' => $marked,
);
if (isset($_POST['delmarked']))
{
$s_hidden_fields['delmarked'] = 1;
}
if (isset($_POST['delall']))
{
$s_hidden_fields['delall'] = 1;
}
if (isset($_POST['delall']) || (isset($_POST['delmarked']) && sizeof($marked)))
{
confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields($s_hidden_fields));
}
}
}
$sql = 'SELECT w.warning_id, w.warning_time, w.post_id, l.log_operation, l.log_data, l.user_id AS mod_user_id, m.username AS mod_username, m.user_colour AS mod_user_colour
FROM ' . WARNINGS_TABLE . ' w
LEFT JOIN ' . LOG_TABLE . ' l
ON (w.log_id = l.log_id)
LEFT JOIN ' . USERS_TABLE . ' m
ON (l.user_id = m.user_id)
WHERE w.user_id = ' . $user_id . '
ORDER BY w.warning_time DESC';
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
{
if (!$row['log_operation'])
{
// We do not have a log-entry anymore, so there is no data available
$row['action'] = $user->lang['USER_WARNING_LOG_DELETED'];
}
else
{
$row['action'] = (isset($user->lang[$row['log_operation']])) ? $user->lang[$row['log_operation']] : '{' . ucfirst(str_replace('_', ' ', $row['log_operation'])) . '}';
if (!empty($row['log_data']))
{
$log_data_ary = @unserialize($row['log_data']);
$log_data_ary = ($log_data_ary === false) ? array() : $log_data_ary;
if (isset($user->lang[$row['log_operation']]))
{
// Check if there are more occurrences of % than arguments, if there are we fill out the arguments array
// It doesn't matter if we add more arguments than placeholders
if ((substr_count($row['action'], '%') - sizeof($log_data_ary)) > 0)
{
$log_data_ary = array_merge($log_data_ary, array_fill(0, substr_count($row['action'], '%') - sizeof($log_data_ary), ''));
}
$row['action'] = vsprintf($row['action'], $log_data_ary);
$row['action'] = bbcode_nl2br(censor_text($row['action']));
}
else if (!empty($log_data_ary))
{
$row['action'] .= '<br />' . implode('', $log_data_ary);
}
}
}
$template->assign_block_vars('warn', array(
'ID' => $row['warning_id'],
'USERNAME' => ($row['log_operation']) ? get_username_string('full', $row['mod_user_id'], $row['mod_username'], $row['mod_user_colour']) : '-',
'ACTION' => make_clickable($row['action']),
'DATE' => $user->format_date($row['warning_time']),
));
}
$db->sql_freeresult($result);
$template->assign_vars(array(
'S_WARNINGS' => true,
'S_CLEARLOGS' => $auth->acl_get('a_clearlogs'),
));
break;
case 'profile':
include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
@ -1136,54 +1397,7 @@ class acp_users
$db->sql_query($sql);
// Update Custom Fields
if (sizeof($cp_data))
{
switch ($db->sql_layer)
{
case 'oracle':
case 'firebird':
case 'postgres':
$right_delim = $left_delim = '"';
break;
case 'sqlite':
case 'mssql':
case 'mssql_odbc':
$right_delim = ']';
$left_delim = '[';
break;
case 'mysql':
case 'mysql4':
case 'mysqli':
$right_delim = $left_delim = '`';
break;
}
foreach ($cp_data as $key => $value)
{
// Firebird is case sensitive with delimiter
$cp_data[$left_delim . (($db->sql_layer == 'firebird') ? strtoupper($key) : $key) . $right_delim] = $value;
unset($cp_data[$key]);
}
$sql = 'UPDATE ' . PROFILE_FIELDS_DATA_TABLE . '
SET ' . $db->sql_build_array('UPDATE', $cp_data) . "
WHERE user_id = $user_id";
$db->sql_query($sql);
if (!$db->sql_affectedrows())
{
$cp_data['user_id'] = (int) $user_id;
$db->sql_return_on_error(true);
$sql = 'INSERT INTO ' . PROFILE_FIELDS_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $cp_data);
$db->sql_query($sql);
$db->sql_return_on_error(false);
}
}
$cp->update_profile_field_data($user_id, $cp_data);
trigger_error($user->lang['USER_PROFILE_UPDATED'] . adm_back_link($this->u_action . '&amp;u=' . $user_id));
}
@ -1476,8 +1690,19 @@ class acp_users
$error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error);
}
if (!$config['allow_avatar'] && $user_row['user_avatar_type'])
{
$error[] = $user->lang['USER_AVATAR_NOT_ALLOWED'];
}
else if ((($user_row['user_avatar_type'] == AVATAR_UPLOAD) && !$config['allow_avatar_upload']) ||
(($user_row['user_avatar_type'] == AVATAR_REMOTE) && !$config['allow_avatar_remote']) ||
(($user_row['user_avatar_type'] == AVATAR_GALLERY) && !$config['allow_avatar_local']))
{
$error[] = $user->lang['USER_AVATAR_TYPE_NOT_ALLOWED'];
}
// Generate users avatar
$avatar_img = ($user_row['user_avatar']) ? get_user_avatar($user_row['user_avatar'], $user_row['user_avatar_type'], $user_row['user_avatar_width'], $user_row['user_avatar_height']) : '<img src="' . $phpbb_admin_path . 'images/no_avatar.gif" alt="" />';
$avatar_img = ($user_row['user_avatar']) ? get_user_avatar($user_row['user_avatar'], $user_row['user_avatar_type'], $user_row['user_avatar_width'], $user_row['user_avatar_height'], 'USER_AVATAR', true) : '<img src="' . $phpbb_admin_path . 'images/no_avatar.gif" alt="" />';
$display_gallery = (isset($_POST['display_gallery'])) ? true : false;
$avatar_select = basename(request_var('avatar_select', ''));
@ -1490,10 +1715,11 @@ class acp_users
$template->assign_vars(array(
'S_AVATAR' => true,
'S_CAN_UPLOAD' => ($can_upload && $config['allow_avatar_upload']) ? true : false,
'S_ALLOW_REMOTE' => ($config['allow_avatar_remote']) ? true : false,
'S_DISPLAY_GALLERY' => ($config['allow_avatar_local'] && !$display_gallery) ? true : false,
'S_IN_GALLERY' => ($config['allow_avatar_local'] && $display_gallery) ? true : false,
'S_UPLOAD_FILE' => ($config['allow_avatar'] && $can_upload && $config['allow_avatar_upload']) ? true : false,
'S_REMOTE_UPLOAD' => ($config['allow_avatar'] && $can_upload && $config['allow_avatar_remote_upload']) ? true : false,
'S_ALLOW_REMOTE' => ($config['allow_avatar'] && $config['allow_avatar_remote']) ? true : false,
'S_DISPLAY_GALLERY' => ($config['allow_avatar'] && $config['allow_avatar_local'] && !$display_gallery) ? true : false,
'S_IN_GALLERY' => ($config['allow_avatar'] && $config['allow_avatar_local'] && $display_gallery) ? true : false,
'AVATAR_IMAGE' => $avatar_img,
'AVATAR_MAX_FILESIZE' => $config['avatar_filesize'],
@ -1551,9 +1777,9 @@ class acp_users
include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx);
include_once($phpbb_root_path . 'includes/functions_display.' . $phpEx);
$enable_bbcode = ($config['allow_sig_bbcode']) ? ((request_var('disable_bbcode', !$user->optionget('bbcode'))) ? false : true) : false;
$enable_smilies = ($config['allow_sig_smilies']) ? ((request_var('disable_smilies', !$user->optionget('smilies'))) ? false : true) : false;
$enable_urls = ($config['allow_sig_links']) ? ((request_var('disable_magic_url', false)) ? false : true) : false;
$enable_bbcode = ($config['allow_sig_bbcode']) ? (bool) $this->optionget($user_row, 'sig_bbcode') : false;
$enable_smilies = ($config['allow_sig_smilies']) ? (bool) $this->optionget($user_row, 'sig_smilies') : false;
$enable_urls = ($config['allow_sig_links']) ? (bool) $this->optionget($user_row, 'sig_links') : false;
$signature = utf8_normalize_nfc(request_var('signature', (string) $user_row['user_sig'], true));
$preview = (isset($_POST['preview'])) ? true : false;
@ -1562,6 +1788,10 @@ class acp_users
{
include_once($phpbb_root_path . 'includes/message_parser.' . $phpEx);
$enable_bbcode = ($config['allow_sig_bbcode']) ? ((request_var('disable_bbcode', false)) ? false : true) : false;
$enable_smilies = ($config['allow_sig_smilies']) ? ((request_var('disable_smilies', false)) ? false : true) : false;
$enable_urls = ($config['allow_sig_links']) ? ((request_var('disable_magic_url', false)) ? false : true) : false;
$message_parser = new parse_message($signature);
// Allowing Quote BBCode
@ -1579,8 +1809,13 @@ class acp_users
if (!sizeof($error) && $submit)
{
$this->optionset($user_row, 'sig_bbcode', $enable_bbcode);
$this->optionset($user_row, 'sig_smilies', $enable_smilies);
$this->optionset($user_row, 'sig_links', $enable_urls);
$sql_ary = array(
'user_sig' => (string) $message_parser->message,
'user_options' => $user_row['user_options'],
'user_sig_bbcode_uid' => (string) $message_parser->bbcode_uid,
'user_sig_bbcode_bitfield' => (string) $message_parser->bbcode_bitfield
);
@ -1871,6 +2106,29 @@ class acp_users
}
break;
case 'approve':
if (confirm_box(true))
{
if (!$group_id)
{
trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action . '&amp;u=' . $user_id), E_USER_WARNING);
}
group_user_attributes($action, $group_id, $user_id);
}
else
{
confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array(
'u' => $user_id,
'i' => $id,
'mode' => $mode,
'action' => $action,
'g' => $group_id))
);
}
break;
}
// Add user to group?
@ -1963,10 +2221,12 @@ class acp_users
'U_DEFAULT' => $this->u_action . "&amp;action=default&amp;u=$user_id&amp;g=" . $data['group_id'],
'U_DEMOTE_PROMOTE' => $this->u_action . '&amp;action=' . (($data['group_leader']) ? 'demote' : 'promote') . "&amp;u=$user_id&amp;g=" . $data['group_id'],
'U_DELETE' => $this->u_action . "&amp;action=delete&amp;u=$user_id&amp;g=" . $data['group_id'],
'U_APPROVE' => ($group_type == 'pending') ? $this->u_action . "&amp;action=approve&amp;u=$user_id&amp;g=" . $data['group_id'] : '',
'GROUP_NAME' => ($group_type == 'special') ? $user->lang['G_' . $data['group_name']] : $data['group_name'],
'L_DEMOTE_PROMOTE' => ($data['group_leader']) ? $user->lang['GROUP_DEMOTE'] : $user->lang['GROUP_PROMOTE'],
'S_IS_MEMBER' => ($group_type != 'pending') ? true : false,
'S_NO_DEFAULT' => ($user_row['group_id'] != $data['group_id']) ? true : false,
'S_SPECIAL_GROUP' => ($group_type == 'special') ? true : false,
)

View file

@ -23,7 +23,7 @@ if (!defined('IN_PHPBB'))
class acp_words
{
var $u_action;
function main($id, $mode)
{
global $db, $user, $auth, $template, $cache;
@ -47,8 +47,9 @@ class acp_words
switch ($action)
{
case 'edit':
$word_id = request_var('id', 0);
if (!$word_id)
{
trigger_error($user->lang['NO_WORD'] . adm_back_link($this->u_action), E_USER_WARNING);
@ -73,7 +74,7 @@ class acp_words
'REPLACEMENT' => (isset($word_info['replacement'])) ? $word_info['replacement'] : '',
'S_HIDDEN_FIELDS' => $s_hidden_fields)
);
return;
break;
@ -84,11 +85,12 @@ class acp_words
{
trigger_error($user->lang['FORM_INVALID']. adm_back_link($this->u_action), E_USER_WARNING);
}
$word_id = request_var('id', 0);
$word = utf8_normalize_nfc(request_var('word', '', true));
$replacement = utf8_normalize_nfc(request_var('replacement', '', true));
if (!$word || !$replacement)
if ($word === '' || $replacement === '')
{
trigger_error($user->lang['ENTER_WORD'] . adm_back_link($this->u_action), E_USER_WARNING);
}

View file

@ -26,6 +26,7 @@ class acp_board_info
'message' => array('title' => 'ACP_MESSAGE_SETTINGS', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION', 'ACP_MESSAGES')),
'post' => array('title' => 'ACP_POST_SETTINGS', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION')),
'signature' => array('title' => 'ACP_SIGNATURE_SETTINGS', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION')),
'feed' => array('title' => 'ACP_FEED_SETTINGS', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION')),
'registration' => array('title' => 'ACP_REGISTER_SETTINGS', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION')),
'auth' => array('title' => 'ACP_AUTH_SETTINGS', 'auth' => 'acl_a_server', 'cat' => array('ACP_CLIENT_COMMUNICATION')),

View file

@ -24,6 +24,7 @@ class acp_permissions_info
'trace' => array('title' => 'ACP_PERMISSION_TRACE', 'auth' => 'acl_a_viewauth', 'display' => false, 'cat' => array('ACP_PERMISSION_MASKS')),
'setting_forum_local' => array('title' => 'ACP_FORUM_PERMISSIONS', 'auth' => 'acl_a_fauth && (acl_a_authusers || acl_a_authgroups)', 'cat' => array('ACP_FORUM_BASED_PERMISSIONS')),
'setting_forum_copy' => array('title' => 'ACP_FORUM_PERMISSIONS_COPY', 'auth' => 'acl_a_fauth && acl_a_authusers && acl_a_authgroups && acl_a_mauth', 'cat' => array('ACP_FORUM_BASED_PERMISSIONS')),
'setting_mod_local' => array('title' => 'ACP_FORUM_MODERATORS', 'auth' => 'acl_a_mauth && (acl_a_authusers || acl_a_authgroups)', 'cat' => array('ACP_FORUM_BASED_PERMISSIONS')),
'setting_user_global' => array('title' => 'ACP_USERS_PERMISSIONS', 'auth' => 'acl_a_authusers && (acl_a_aauth || acl_a_mauth || acl_a_uauth)', 'cat' => array('ACP_GLOBAL_PERMISSIONS', 'ACP_CAT_USERS')),
'setting_user_local' => array('title' => 'ACP_USERS_FORUM_PERMISSIONS', 'auth' => 'acl_a_authusers && (acl_a_mauth || acl_a_fauth)', 'cat' => array('ACP_FORUM_BASED_PERMISSIONS', 'ACP_CAT_USERS')),

View file

@ -0,0 +1,37 @@
<?php
/**
*
* @package acp
* @version $Id$
* @copyright (c) 2005 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*
*/
/**
* @package module_install
*/
class acp_send_statistics_info
{
function module()
{
return array(
'filename' => 'acp_send_statistics',
'title' => 'ACP_SEND_STATISTICS',
'version' => '1.0.0',
'modes' => array(
'send_statistics' => array('title' => 'ACP_SEND_STATISTICS', 'auth' => 'acl_a_server', 'cat' => array('ACP_SERVER_CONFIGURATION')),
),
);
}
function install()
{
}
function uninstall()
{
}
}
?>

View file

@ -22,6 +22,7 @@ class acp_users_info
'modes' => array(
'overview' => array('title' => 'ACP_MANAGE_USERS', 'auth' => 'acl_a_user', 'cat' => array('ACP_CAT_USERS')),
'feedback' => array('title' => 'ACP_USER_FEEDBACK', 'auth' => 'acl_a_user', 'display' => false, 'cat' => array('ACP_CAT_USERS')),
'warnings' => array('title' => 'ACP_USER_WARNINGS', 'auth' => 'acl_a_user', 'display' => false, 'cat' => array('ACP_CAT_USERS')),
'profile' => array('title' => 'ACP_USER_PROFILE', 'auth' => 'acl_a_user', 'display' => false, 'cat' => array('ACP_CAT_USERS')),
'prefs' => array('title' => 'ACP_USER_PREFS', 'auth' => 'acl_a_user', 'display' => false, 'cat' => array('ACP_CAT_USERS')),
'avatar' => array('title' => 'ACP_USER_AVATAR', 'auth' => 'acl_a_user', 'display' => false, 'cat' => array('ACP_CAT_USERS')),

View file

@ -64,9 +64,9 @@ class auth
$db->sql_freeresult($result);
$cache->put('_acl_options', $this->acl_options);
$this->acl_cache($userdata);
}
else if (!trim($userdata['user_permissions']))
if (!trim($userdata['user_permissions']))
{
$this->acl_cache($userdata);
}
@ -608,22 +608,26 @@ class auth
// Now grab group settings - non-role specific...
$sql_ary[] = 'SELECT ug.user_id, a.forum_id, a.auth_setting, a.auth_option_id' . $sql_opts_select . '
FROM ' . ACL_GROUPS_TABLE . ' a, ' . USER_GROUP_TABLE . ' ug' . $sql_opts_from . '
FROM ' . ACL_GROUPS_TABLE . ' a, ' . USER_GROUP_TABLE . ' ug, ' . GROUPS_TABLE . ' g' . $sql_opts_from . '
WHERE a.auth_role_id = 0 ' .
(($sql_opts_from) ? 'AND a.auth_option_id = ao.auth_option_id ' : '') . '
AND a.group_id = ug.group_id
AND g.group_id = ug.group_id
AND ug.user_pending = 0
AND NOT (ug.group_leader = 1 AND g.group_skip_auth = 1)
' . (($sql_user) ? 'AND ug.' . $sql_user : '') . "
$sql_forum
$sql_opts";
// Now grab group settings - role specific...
$sql_ary[] = 'SELECT ug.user_id, a.forum_id, r.auth_setting, r.auth_option_id' . $sql_opts_select . '
FROM ' . ACL_GROUPS_TABLE . ' a, ' . USER_GROUP_TABLE . ' ug, ' . ACL_ROLES_DATA_TABLE . ' r' . $sql_opts_from . '
FROM ' . ACL_GROUPS_TABLE . ' a, ' . USER_GROUP_TABLE . ' ug, ' . GROUPS_TABLE . ' g, ' . ACL_ROLES_DATA_TABLE . ' r' . $sql_opts_from . '
WHERE a.auth_role_id = r.role_id ' .
(($sql_opts_from) ? 'AND r.auth_option_id = ao.auth_option_id ' : '') . '
AND a.group_id = ug.group_id
AND g.group_id = ug.group_id
AND ug.user_pending = 0
AND NOT (ug.group_leader = 1 AND g.group_skip_auth = 1)
' . (($sql_user) ? 'AND ug.' . $sql_user : '') . "
$sql_forum
$sql_opts";
@ -825,9 +829,11 @@ class auth
// Now grab group-specific permission settings
$sql = 'SELECT a.forum_id, a.auth_option_id, a.auth_role_id, a.auth_setting
FROM ' . ACL_GROUPS_TABLE . ' a, ' . USER_GROUP_TABLE . ' ug
FROM ' . ACL_GROUPS_TABLE . ' a, ' . USER_GROUP_TABLE . ' ug, ' . GROUPS_TABLE . ' g
WHERE a.group_id = ug.group_id
AND g.group_id = ug.group_id
AND ug.user_pending = 0
AND NOT (ug.group_leader = 1 AND g.group_skip_auth = 1)
AND ug.user_id = ' . $user_id;
$result = $db->sql_query($sql);

View file

@ -217,6 +217,7 @@ function user_row_apache($username, $password)
'group_id' => (int) $row['group_id'],
'user_type' => USER_NORMAL,
'user_ip' => $user->ip,
'user_new' => ($config['new_member_post_limit']) ? 1 : 0,
);
}

View file

@ -68,7 +68,6 @@ function login_db(&$username, &$password)
if ($config['max_login_attempts'] && $row['user_login_attempts'] >= $config['max_login_attempts'])
{
$confirm_id = request_var('confirm_id', '');
$confirm_code = request_var('confirm_code', '');
// Visual Confirmation handling
if (!$confirm_id)
@ -81,41 +80,15 @@ function login_db(&$username, &$password)
}
else
{
global $user;
$captcha =& phpbb_captcha_factory::get_instance($config['captcha_plugin']);
$captcha->init(CONFIRM_LOGIN);
$vc_response = $captcha->validate();
$sql = 'SELECT code
FROM ' . CONFIRM_TABLE . "
WHERE confirm_id = '" . $db->sql_escape($confirm_id) . "'
AND session_id = '" . $db->sql_escape($user->session_id) . "'
AND confirm_type = " . CONFIRM_LOGIN;
$result = $db->sql_query($sql);
$confirm_row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
if ($confirm_row)
{
if (strcasecmp($confirm_row['code'], $confirm_code) === 0)
{
$sql = 'DELETE FROM ' . CONFIRM_TABLE . "
WHERE confirm_id = '" . $db->sql_escape($confirm_id) . "'
AND session_id = '" . $db->sql_escape($user->session_id) . "'
AND confirm_type = " . CONFIRM_LOGIN;
$db->sql_query($sql);
}
else
{
return array(
'status' => LOGIN_ERROR_ATTEMPTS,
'error_msg' => 'CONFIRM_CODE_WRONG',
'user_row' => $row,
);
}
}
else
if ($vc_response)
{
return array(
'status' => LOGIN_ERROR_ATTEMPTS,
'error_msg' => 'CONFIRM_CODE_WRONG',
'error_msg' => 'LOGIN_ERROR_ATTEMPTS',
'user_row' => $row,
);
}
@ -157,7 +130,7 @@ function login_db(&$username, &$password)
$row['user_pass_convert'] = 0;
$row['user_password'] = $hash;
}
else
else
{
// Although we weren't able to convert this password we have to
// increase login attempt count to make sure this cannot be exploited

View file

@ -63,9 +63,11 @@ function init_ldap()
// ldap_connect only checks whether the specified server is valid, so the connection might still fail
$search = @ldap_search(
$ldap,
$config['ldap_base_dn'],
htmlspecialchars_decode($config['ldap_base_dn']),
ldap_user_filter($user->data['username']),
(empty($config['ldap_email'])) ? array($config['ldap_uid']) : array($config['ldap_uid'], $config['ldap_email']),
(empty($config['ldap_email'])) ?
array(htmlspecialchars_decode($config['ldap_uid'])) :
array(htmlspecialchars_decode($config['ldap_uid']), htmlspecialchars_decode($config['ldap_email'])),
0,
1
);
@ -85,7 +87,7 @@ function init_ldap()
return sprintf($user->lang['LDAP_NO_IDENTITY'], $user->data['username']);
}
if (!empty($config['ldap_email']) && !isset($result[0][$config['ldap_email']]))
if (!empty($config['ldap_email']) && !isset($result[0][htmlspecialchars_decode($config['ldap_email'])]))
{
return $user->lang['LDAP_NO_EMAIL'];
}
@ -152,7 +154,7 @@ function login_ldap(&$username, &$password)
if ($config['ldap_user'] || $config['ldap_password'])
{
if (!@ldap_bind($ldap, $config['ldap_user'], htmlspecialchars_decode($config['ldap_password'])))
if (!@ldap_bind($ldap, htmlspecialchars_decode($config['ldap_user']), htmlspecialchars_decode($config['ldap_password'])))
{
return $user->lang['LDAP_NO_SERVER_CONNECTION'];
}
@ -160,9 +162,11 @@ function login_ldap(&$username, &$password)
$search = @ldap_search(
$ldap,
$config['ldap_base_dn'],
htmlspecialchars_decode($config['ldap_base_dn']),
ldap_user_filter($username),
(empty($config['ldap_email'])) ? array($config['ldap_uid']) : array($config['ldap_uid'], $config['ldap_email']),
(empty($config['ldap_email'])) ?
array(htmlspecialchars_decode($config['ldap_uid'])) :
array(htmlspecialchars_decode($config['ldap_uid']), htmlspecialchars_decode($config['ldap_email'])),
0,
1
);
@ -223,10 +227,11 @@ function login_ldap(&$username, &$password)
$ldap_user_row = array(
'username' => $username,
'user_password' => phpbb_hash($password),
'user_email' => (!empty($config['ldap_email'])) ? $ldap_result[0][$config['ldap_email']][0] : '',
'user_email' => (!empty($config['ldap_email'])) ? utf8_htmlspecialchars($ldap_result[0][htmlspecialchars_decode($config['ldap_email'])][0]) : '',
'group_id' => (int) $row['group_id'],
'user_type' => USER_NORMAL,
'user_ip' => $user->ip,
'user_new' => ($config['new_member_post_limit']) ? 1 : 0,
);
unset($ldap_result);
@ -276,7 +281,8 @@ function ldap_user_filter($username)
$filter = '(' . $config['ldap_uid'] . '=' . ldap_escape(htmlspecialchars_decode($username)) . ')';
if ($config['ldap_user_filter'])
{
$filter = "(&$filter({$config['ldap_user_filter']}))";
$_filter = ($config['ldap_user_filter'][0] == '(' && substr($config['ldap_user_filter'], -1) == ')') ? $config['ldap_user_filter'] : "({$config['ldap_user_filter']})";
$filter = "(&{$filter}{$_filter})";
}
return $filter;
}

View file

@ -265,7 +265,7 @@ class bbcode
case 6:
$this->bbcode_cache[$bbcode_id] = array(
'preg' => array(
'!\[color=(#[0-9a-f]{6}|[a-z\-]+):$uid\](.*?)\[/color:$uid\]!is' => $this->bbcode_tpl('color', $bbcode_id),
'!\[color=(#[0-9a-f]{3}|#[0-9a-f]{6}|[a-z\-]+):$uid\](.*?)\[/color:$uid\]!is' => $this->bbcode_tpl('color', $bbcode_id),
)
);
break;

View file

@ -84,7 +84,15 @@ class cache extends acm
$censors = array();
while ($row = $db->sql_fetchrow($result))
{
$censors['match'][] = '#(?<!\w)(' . str_replace('\*', '\w*?', preg_quote($row['word'], '#')) . ')(?!\w)#i';
if ((version_compare(PHP_VERSION, '5.1.0', '>=') || (version_compare(PHP_VERSION, '5.0.0-dev', '<=') && version_compare(PHP_VERSION, '4.4.0', '>='))) && @preg_match('/\p{L}/u', 'a') !== false)
{
$censors['match'][] = '#(?<![\p{Nd}\p{L}_])(' . str_replace('\*', '[\p{Nd}\p{L}_]*?', preg_quote($row['word'], '#')) . ')(?![\p{Nd}\p{L}_])#u';
}
else
{
$censors['match'][] = '#(?<!\S)(' . str_replace('\*', '\S*?', preg_quote($row['word'], '#')) . ')(?!\S)#iu';
}
$censors['replace'][] = $row['replacement'];
}
$db->sql_freeresult($result);

View file

@ -0,0 +1,100 @@
<?php
/**
*
* @package VC
* @version $Id$
* @copyright (c) 2008 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* A small class for 3.0.x (no autoloader in 3.0.x)
*
* @package VC
*/
class phpbb_captcha_factory
{
/**
* return an instance of class $name in file $name_plugin.php
*/
function &get_instance($name)
{
global $phpbb_root_path, $phpEx;
$name = basename($name);
if (!class_exists($name))
{
include($phpbb_root_path . "includes/captcha/plugins/{$name}_plugin." . $phpEx);
}
$instance =& call_user_func(array($name, 'get_instance'));
return $instance;
}
/**
* Call the garbage collector
*/
function garbage_collect($name)
{
global $phpbb_root_path, $phpEx;
$name = basename($name);
if (!class_exists($name))
{
include($phpbb_root_path . "includes/captcha/plugins/{$name}_plugin." . $phpEx);
}
call_user_func(array($name, 'garbage_collect'), 0);
}
/**
* return a list of all discovered CAPTCHA plugins
*/
function get_captcha_types()
{
global $phpbb_root_path, $phpEx;
$captchas = array(
'available' => array(),
'unavailable' => array(),
);
$dp = @opendir($phpbb_root_path . 'includes/captcha/plugins');
if ($dp)
{
while (($file = readdir($dp)) !== false)
{
if ((preg_match('#_plugin\.' . $phpEx . '$#', $file)))
{
$name = preg_replace('#^(.*?)_plugin\.' . $phpEx . '$#', '\1', $file);
if (!class_exists($name))
{
include($phpbb_root_path . "includes/captcha/plugins/$file");
}
if (call_user_func(array($name, 'is_available')))
{
$captchas['available'][$name] = call_user_func(array($name, 'get_name'));
}
else
{
$captchas['unavailable'][$name] = call_user_func(array($name, 'get_name'));
}
}
}
closedir($dp);
}
return $captchas;
}
}
?>

View file

@ -34,8 +34,8 @@ class captcha
function execute($code, $seed)
{
global $config;
srand($seed);
//mt_srand($seed);
mt_srand($seed);
// Create image
$img = imagecreatetruecolor($this->width, $this->height);
@ -108,7 +108,7 @@ class captcha
if ($config['captcha_gd_3d_noise'])
{
$xoffset = rand(0,9);
$xoffset = mt_rand(0,9);
$noise_bitmaps = $this->captcha_noise_bg_bitmaps();
for ($i = 0; $i < $code_len; ++$i)
{

View file

@ -0,0 +1,845 @@
<?php
/**
*
* @package VC
* @version $Id$
* @copyright (c) 2006 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*
*/
/**
* Wave3D CAPTCHA
*
* @author Robert Hetzler
* @package VC
*/
class captcha
{
var $width = 360;
var $height = 96;
function execute($code, $seed)
{
global $starttime;
// seed the random generator
mt_srand($seed);
// set height and width
$img_x = $this->width;
$img_y = $this->height;
// Generate image
$img = imagecreatetruecolor($img_x, $img_y);
$x_grid = mt_rand(6, 10);
$y_grid = mt_rand(6, 10);
// Ok, so lets cut to the chase. We could accurately represent this in 3d and
// do all the appropriate linear transforms. my questions is... why bother?
// The computational overhead is unnecessary when you consider the simple fact:
// we're not here to accurately represent a model, but to just show off some random-ish
// polygons
// Conceive of 3 spaces.
// 1) planar-space (discrete "pixel" grid)
// 2) 3-space. (planar-space with z/height aspect)
// 3) image space (pixels on the screen)
// resolution of the planar-space we're embedding the text code in
$plane_x = 100;
$plane_y = 30;
$subdivision_factor = 3;
// $box is the 4 points in img_space that correspond to the corners of the plane in 3-space
$box = array(
'upper_left' => array(
'x' => mt_rand(5, 15),
'y' => mt_rand(10, 15)
),
'upper_right' => array(
'x' => mt_rand($img_x - 35, $img_x - 19),
'y' => mt_rand(10, 17)
),
'lower_left' => array(
'x' => mt_rand($img_x - 5, $img_x - 45),
'y' => mt_rand($img_y - 0, $img_y - 15)
),
);
$box['lower_right'] = array(
'x' => $box['lower_left']['x'] + $box['upper_left']['x'] - $box['upper_right']['x'],
'y' => $box['lower_left']['y'] + $box['upper_left']['y'] - $box['upper_right']['y'],
);
// TODO
$background = imagecolorallocate($img, mt_rand(155, 255), mt_rand(155, 255), mt_rand(155, 255));
imagefill($img, 0, 0, $background);
$black = imagecolorallocate($img, 0, 0, 0);
$random = array();
$fontcolors = array();
for ($i = 0; $i < 15; ++$i)
{
$random[$i] = imagecolorallocate($img, mt_rand(120, 255), mt_rand(120, 255), mt_rand(120, 255));
}
$fontcolors[0] = imagecolorallocate($img, mt_rand(0, 120), mt_rand(0, 120), mt_rand(0, 120));
$colors = array();
$minr = mt_rand(20, 30);
$ming = mt_rand(20, 30);
$minb = mt_rand(20, 30);
$maxr = mt_rand(150, 230);
$maxg = mt_rand(150, 230);
$maxb = mt_rand(150, 230);
for ($i = -30; $i <= 30; ++$i)
{
$coeff1 = ($i + 12) / 45;
$coeff2 = 1 - $coeff1;
$colors[$i] = imagecolorallocate($img, ($coeff2 * $maxr) + ($coeff1 * $minr), ($coeff2 * $maxg) + ($coeff1 * $ming), ($coeff2 * $maxb) + ($coeff1 * $minb));
}
// $img_buffer is the last row of 3-space positions (converted to img-space), cached
// (using this means we don't need to recalculate all 4 positions for each new polygon,
// merely the newest point that we're adding, which is then cached.
$img_buffer = array(array(), array());
// In image-space, the x- and y-offset necessary to move one unit in the x-direction in planar-space
$dxx = ($box['upper_right']['x'] - $box['upper_left']['x']) / ($subdivision_factor * $plane_x);
$dxy = ($box['upper_right']['y'] - $box['upper_left']['y']) / ($subdivision_factor * $plane_x);
// In image-space, the x- and y-offset necessary to move one unit in the y-direction in planar-space
$dyx = ($box['lower_right']['x'] - $box['upper_left']['x']) / ($subdivision_factor * $plane_y);
$dyy = ($box['lower_right']['y'] - $box['upper_left']['y']) / ($subdivision_factor * $plane_y);
// Initial captcha-letter offset in planar-space
$plane_offset_x = mt_rand(3, 8);
$plane_offset_y = mt_rand( 12, 15);
// character map
$map = $this->captcha_bitmaps();
// matrix
$plane = array();
// for each character, we'll silkscreen it into our boolean pixel plane
for ($c = 0, $code_num = strlen($code); $c < $code_num; ++$c)
{
$letter = $code[$c];
for ($x = $map['width'] - 1; $x >= 0; --$x)
{
for ($y = $map['height'] - 1; $y >= 0; --$y)
{
if ($map['data'][$letter][$y][$x])
{
$plane[$y + $plane_offset_y + (($c & 1) ? 1 : -1)][$x + $plane_offset_x] = true;
}
}
}
$plane_offset_x += 11;
}
// calculate our first buffer, we can't actually draw polys with these yet
// img_pos_prev == screen x,y location to our immediate left.
// img_pos_cur == current screen x,y location
// we calculate screen position of our
// current cell based on the difference from the previous cell
// rather than recalculating from absolute coordinates
// What we cache into the $img_buffer contains the raised text coordinates.
$img_pos_prev = $img_buffer[0][0] = array($box['upper_left']['x'], $box['upper_left']['y']);
$cur_height = $prev_height = $this->wave_height(0, 0, $subdivision_factor);
$full_x = $plane_x * $subdivision_factor;
$full_y = $plane_y * $subdivision_factor;
for ($x = 1; $x <= $full_x; ++$x)
{
$cur_height = $this->wave_height($x, 0, $subdivision_factor);
$offset = $cur_height - $prev_height;
$img_pos_cur = array($img_pos_prev[0] + $dxx, $img_pos_prev[1] + $dxy + $offset);
$img_buffer[0][$x] = $img_pos_cur;
$img_pos_prev = $img_pos_cur;
$prev_height = $cur_height;
}
for ($y = 1; $y <= $full_y; ++$y)
{
// swap buffers
$buffer_cur = $y & 1;
$buffer_prev = 1 - $buffer_cur;
$prev_height = $this->wave_height(0, $y, $subdivision_factor);
$offset = $prev_height - $this->wave_height(0, $y - 1, $subdivision_factor);
$img_pos_cur = array($img_buffer[$buffer_prev][0][0] + $dyx, min($img_buffer[$buffer_prev][0][1] + $dyy + $offset, $img_y - 1));
// make sure we don't try to write off the page
$img_pos_prev = $img_pos_cur;
$img_buffer[$buffer_cur][0] = $img_pos_cur;
for ($x = 1; $x <= $full_x; ++$x)
{
$cur_height = $this->wave_height($x, $y, $subdivision_factor) + $this->grid_height($x, $y, 1, $x_grid, $y_grid);
// height is a z-factor, not a y-factor
$offset = $cur_height - $prev_height;
$img_pos_cur = array($img_pos_prev[0] + $dxx, $img_pos_prev[1] + $dxy + $offset);
// height is float, index it to an int, get closest color
$color = $colors[intval($cur_height)];
$img_pos_prev = $img_pos_cur;
$prev_height = $cur_height;
$y_index_old = intval(($y - 1) / $subdivision_factor);
$y_index_new = intval($y / $subdivision_factor);
$x_index_old = intval(($x - 1) / $subdivision_factor);
$x_index_new = intval($x / $subdivision_factor);
if (!empty($plane[$y_index_new][$x_index_new]))
{
$img_pos_cur[1] += $this->wave_height($x, $y, $subdivision_factor, 1) - 30 - $cur_height;
$color = $colors[20];
}
$img_pos_cur[1] = min($img_pos_cur[1], $img_y - 1);
$img_buffer[$buffer_cur][$x] = $img_pos_cur;
// Smooth the edges as much as possible by having not more than one low<->high traingle per square
// Otherwise, just
$diag_down = (empty($plane[$y_index_old][$x_index_old]) == empty($plane[$y_index_new][$x_index_new]));
$diag_up = (empty($plane[$y_index_old][$x_index_new]) == empty($plane[$y_index_new][$x_index_old]));
// natural switching
$mode = ($x + $y) & 1;
// override if it requires it
if ($diag_down != $diag_up)
{
$mode = $diag_up;
}
if ($mode)
{
// +-/ /
// 1 |/ 2 /|
// / /-+
$poly1 = array_merge($img_buffer[$buffer_cur][$x - 1], $img_buffer[$buffer_prev][$x - 1], $img_buffer[$buffer_prev][$x]);
$poly2 = array_merge($img_buffer[$buffer_cur][$x - 1], $img_buffer[$buffer_cur][$x], $img_buffer[$buffer_prev][$x]);
}
else
{
// \ \-+
// 1 |\ 2 \|
// +-\ \
$poly1 = array_merge($img_buffer[$buffer_cur][$x - 1], $img_buffer[$buffer_prev][$x - 1], $img_buffer[$buffer_cur][$x]);
$poly2 = array_merge($img_buffer[$buffer_prev][$x - 1], $img_buffer[$buffer_prev][$x], $img_buffer[$buffer_cur][$x]);
}
imagefilledpolygon($img, $poly1, 3, $color);
imagefilledpolygon($img, $poly2, 3, $color);
}
}
// Output image
header('Content-Type: image/png');
header('Cache-control: no-cache, no-store');
//$mtime = explode(' ', microtime());
//$totaltime = $mtime[0] + $mtime[1] - $starttime;
//echo $totaltime . "<br />\n";
//echo memory_get_usage() - $tmp;
imagepng($img);
imagedestroy($img);
}
function wave_height($x, $y, $factor = 1, $tweak = 0.7)
{
// stretch the wave. TODO: pretty it up
$x = $x/5 + 180;
$y = $y/4;
return ((sin($x / (3 * $factor)) + sin($y / (3 * $factor))) * 10 * $tweak);
}
function grid_height($x, $y, $factor = 1, $x_grid, $y_grid)
{
return ((!($x % ($x_grid * $factor)) || !($y % ($y_grid * $factor))) ? 3 : 0);
}
function captcha_bitmaps()
{
return array(
'width' => 9,
'height' => 13,
'data' => array(
'A' => array(
array(0,0,1,1,1,1,0,0,0),
array(0,1,0,0,0,0,1,0,0),
array(1,0,0,0,0,0,0,1,0),
array(1,0,0,0,0,0,0,1,0),
array(1,0,0,0,0,0,0,1,0),
array(1,0,0,0,0,0,0,1,0),
array(1,0,0,0,0,0,0,1,0),
array(1,1,1,1,1,1,1,1,0),
array(1,0,0,0,0,0,0,1,0),
array(1,0,0,0,0,0,0,1,0),
array(1,0,0,0,0,0,0,1,0),
array(1,0,0,0,0,0,0,1,0),
array(1,0,0,0,0,0,0,1,0),
array(0,0,0,0,0,0,0,0,0),
),
'B' => array(
array(1,1,1,1,1,1,0,0,0),
array(1,0,0,0,0,0,1,0,0),
array(1,0,0,0,0,0,0,1,0),
array(1,0,0,0,0,0,0,1,0),
array(1,0,0,0,0,0,0,1,0),
array(1,0,0,0,0,0,1,0,0),
array(1,1,1,1,1,1,0,0,0),
array(1,0,0,0,0,0,1,0,0),
array(1,0,0,0,0,0,0,1,0),
array(1,0,0,0,0,0,0,1,0),
array(1,0,0,0,0,0,0,1,0),
array(1,0,0,0,0,0,1,0,0),
array(1,1,1,1,1,1,0,0,0),
array(0,0,0,0,0,0,0,0,0),
),
'C' => array(
array(0,0,1,1,1,1,1,0,0),
array(0,1,0,0,0,0,0,1,0),
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,1),
array(0,1,0,0,0,0,0,1,0),
array(0,0,1,1,1,1,1,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
),
'D' => array(
array(1,1,1,1,1,1,1,0,0),
array(1,0,0,0,0,0,0,1,0),
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,1,0),
array(1,1,1,1,1,1,1,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
),
'E' => array(
array(0,0,1,1,1,1,1,1,1),
array(0,1,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(1,1,1,1,1,1,1,0,0),
array(1,0,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(0,1,0,0,0,0,0,0,0),
array(0,0,1,1,1,1,1,1,1),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
),
'F' => array(
array(0,0,1,1,1,1,1,1,0),
array(0,1,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(1,1,1,1,1,1,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
),
'G' => array(
array(0,0,1,1,1,1,1,0,0),
array(0,1,0,0,0,0,0,1,0),
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,1,1),
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(0,1,0,0,0,0,0,1,0),
array(0,0,1,1,1,1,1,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
),
'H' => array(
array(1,0,0,0,0,0,1,0,0),
array(1,0,0,0,0,0,1,0,0),
array(1,0,0,0,0,0,1,0,0),
array(1,0,0,0,0,0,1,0,0),
array(1,0,0,0,0,0,1,0,0),
array(1,1,1,1,1,1,1,0,0),
array(1,0,0,0,0,0,1,0,0),
array(1,0,0,0,0,0,1,0,0),
array(1,0,0,0,0,0,1,0,0),
array(1,0,0,0,0,0,1,0,0),
array(1,0,0,0,0,0,1,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
),
'I' => array(
array(0,1,1,1,1,1,1,1,0),
array(0,0,0,0,1,0,0,0,0),
array(0,0,0,0,1,0,0,0,0),
array(0,0,0,0,1,0,0,0,0),
array(0,0,0,0,1,0,0,0,0),
array(0,0,0,0,1,0,0,0,0),
array(0,0,0,0,1,0,0,0,0),
array(0,0,0,0,1,0,0,0,0),
array(0,0,0,0,1,0,0,0,0),
array(0,1,1,1,1,1,1,1,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
),
'J' => array(
array(0,0,0,0,0,0,1,1,1),
array(0,0,0,0,0,0,0,0,1),
array(0,0,0,0,0,0,0,0,1),
array(0,0,0,0,0,0,0,0,1),
array(0,0,0,0,0,0,0,0,1),
array(0,0,0,0,0,0,0,0,1),
array(0,0,0,0,0,0,0,0,1),
array(0,1,0,0,0,0,0,0,1),
array(0,1,0,0,0,0,0,0,1),
array(0,0,1,0,0,0,0,1,0),
array(0,0,0,1,1,1,1,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
),
'K' => array(
array(1,0,0,0,0,0,1,0,0),
array(1,0,0,0,0,1,0,0,0),
array(1,0,0,0,1,0,0,0,0),
array(1,0,0,1,0,0,0,0,0),
array(1,0,1,0,0,0,0,0,0),
array(1,1,0,0,0,0,0,0,0),
array(1,0,1,0,0,0,0,0,0),
array(1,0,0,1,0,0,0,0,0),
array(1,0,0,0,1,0,0,0,0),
array(1,0,0,0,0,1,0,0,0),
array(1,0,0,0,0,0,1,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
),
'L' => array(
array(1,0,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(0,1,0,0,0,0,0,0,0),
array(0,0,1,1,1,1,0,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
),
'M' => array(
array(0,1,0,0,0,0,0,1,0),
array(0,1,1,0,0,0,1,1,0),
array(0,1,0,1,0,1,0,1,0),
array(0,1,0,0,1,0,0,1,0),
array(0,1,0,0,0,0,0,1,0),
array(0,1,0,0,0,0,0,1,0),
array(0,1,0,0,0,0,0,1,0),
array(0,1,0,0,0,0,0,1,0),
array(0,1,0,0,0,0,0,1,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
),
'N' => array(
array(1,0,0,0,0,0,0,0,1),
array(1,1,0,0,0,0,0,0,1),
array(1,0,1,0,0,0,0,0,1),
array(1,0,0,1,0,0,0,0,1),
array(1,0,0,0,1,0,0,0,1),
array(1,0,0,0,0,1,0,0,1),
array(1,0,0,0,0,0,1,0,1),
array(1,0,0,0,0,0,0,1,1),
array(1,0,0,0,0,0,0,0,1),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
),
'O' => array(
array(0,0,0,1,1,1,0,0,0),
array(0,0,1,0,0,0,1,0,0),
array(0,1,0,0,0,0,0,1,0),
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(0,1,0,0,0,0,0,1,0),
array(0,0,1,0,0,0,1,0,0),
array(0,0,0,1,1,1,0,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
),
'P' => array(
array(1,1,1,1,1,1,0,0,0),
array(1,0,0,0,0,0,1,0,0),
array(1,0,0,0,0,0,0,1,0),
array(1,0,0,0,0,0,0,1,0),
array(1,0,0,0,0,0,0,1,0),
array(1,0,0,0,0,0,0,1,0),
array(1,0,0,0,0,0,1,0,0),
array(1,1,1,1,1,1,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
),
'Q' => array(
array(0,0,1,1,1,1,0,0,0),
array(0,1,0,0,0,0,1,0,0),
array(1,0,0,0,0,0,0,1,0),
array(1,0,0,0,0,0,0,1,0),
array(1,0,0,0,0,0,0,1,0),
array(1,0,0,0,0,0,0,1,0),
array(1,0,0,0,1,0,0,1,0),
array(1,0,0,0,0,1,0,1,0),
array(0,1,0,0,0,0,1,0,0),
array(0,0,1,1,1,1,0,1,0),
array(0,0,0,0,0,0,0,0,1),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
),
'R' => array(
array(1,1,1,1,1,1,0,0,0),
array(1,0,0,0,0,0,1,0,0),
array(1,0,0,0,0,0,0,1,0),
array(1,0,0,0,0,0,0,1,0),
array(1,0,0,0,0,0,0,1,0),
array(1,0,0,0,0,0,1,0,0),
array(1,1,1,1,1,1,0,0,0),
array(1,0,1,0,0,0,0,0,0),
array(1,0,0,1,0,0,0,0,0),
array(1,0,0,0,1,0,0,0,0),
array(1,0,0,0,0,1,0,0,0),
array(1,0,0,0,0,0,1,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
),
'S' => array(
array(0,0,1,1,1,1,1,1,1),
array(0,1,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(0,1,0,0,0,0,0,0,0),
array(0,0,1,1,1,1,1,0,0),
array(0,0,0,0,0,0,0,1,0),
array(0,0,0,0,0,0,0,0,1),
array(0,0,0,0,0,0,0,0,1),
array(0,0,0,0,0,0,0,1,0),
array(1,1,1,1,1,1,1,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
),
'T' => array(
array(1,1,1,1,1,1,1,1,1),
array(0,0,0,0,1,0,0,0,0),
array(0,0,0,0,1,0,0,0,0),
array(0,0,0,0,1,0,0,0,0),
array(0,0,0,0,1,0,0,0,0),
array(0,0,0,0,1,0,0,0,0),
array(0,0,0,0,1,0,0,0,0),
array(0,0,0,0,1,0,0,0,0),
array(0,0,0,0,1,0,0,0,0),
array(0,0,0,0,1,0,0,0,0),
array(0,0,0,0,1,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
),
'U' => array(
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(0,1,0,0,0,0,0,1,0),
array(0,0,1,1,1,1,1,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
),
'V' => array(
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(0,1,0,0,0,0,0,1,0),
array(0,0,1,0,0,0,1,0,0),
array(0,0,0,1,0,1,0,0,0),
array(0,0,0,0,1,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
),
'W' => array(
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,1,0,0,0,1),
array(1,0,0,1,0,1,0,0,1),
array(1,0,1,0,0,0,1,0,1),
array(1,1,0,0,0,0,0,1,1),
array(1,0,0,0,0,0,0,0,1),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
),
'X' => array(
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(0,1,0,0,0,0,0,1,0),
array(0,0,1,0,0,0,1,0,0),
array(0,0,0,1,0,1,0,0,0),
array(0,0,0,0,1,0,0,0,0),
array(0,0,0,1,0,1,0,0,0),
array(0,0,1,0,0,0,1,0,0),
array(0,1,0,0,0,0,0,1,0),
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
),
'Y' => array(
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(0,1,0,0,0,0,0,1,0),
array(0,0,1,0,0,0,1,0,0),
array(0,0,0,1,0,1,0,0,0),
array(0,0,0,0,1,0,0,0,0),
array(0,0,0,0,1,0,0,0,0),
array(0,0,0,0,1,0,0,0,0),
array(0,0,0,0,1,0,0,0,0),
array(0,0,0,0,1,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
),
'Z' => array(
array(1,1,1,1,1,1,1,1,1),
array(1,0,0,0,0,0,0,0,1),
array(0,0,0,0,0,0,0,1,0),
array(0,0,0,0,0,0,1,0,0),
array(0,0,0,0,0,1,0,0,0),
array(0,0,0,0,1,0,0,0,0),
array(0,0,0,1,0,0,0,0,0),
array(0,0,1,0,0,0,0,0,0),
array(0,1,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,1),
array(1,1,1,1,1,1,1,1,1),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
),
'1' => array(
array(0,0,0,0,1,0,0,0,0),
array(0,0,0,1,1,0,0,0,0),
array(0,0,1,0,1,0,0,0,0),
array(0,1,0,0,1,0,0,0,0),
array(0,0,0,0,1,0,0,0,0),
array(0,0,0,0,1,0,0,0,0),
array(0,0,0,0,1,0,0,0,0),
array(0,0,0,0,1,0,0,0,0),
array(0,0,0,0,1,0,0,0,0),
array(0,0,0,0,1,0,0,0,0),
array(0,0,0,0,1,0,0,0,0),
array(0,1,1,1,1,1,1,1,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
),
'2' => array(
array(0,0,0,1,1,1,0,0,0),
array(0,0,1,0,0,0,1,0,0),
array(0,1,0,0,0,0,0,1,0),
array(0,0,0,0,0,0,0,0,1),
array(0,0,0,0,0,0,0,0,1),
array(0,0,0,0,0,0,0,0,1),
array(0,0,0,0,0,0,0,1,0),
array(0,0,0,0,0,0,1,0,0),
array(0,0,0,0,0,1,0,0,0),
array(0,0,0,0,1,0,0,0,0),
array(0,0,0,1,0,0,0,0,0),
array(0,0,1,0,0,0,0,0,0),
array(0,1,1,1,1,1,1,1,1),
array(0,0,0,0,0,0,0,0,0),
),
'3' => array(
array(0,0,0,1,1,1,1,0,0),
array(0,0,1,0,0,0,0,1,0),
array(0,1,0,0,0,0,0,0,1),
array(0,0,0,0,0,0,0,0,1),
array(0,0,0,0,0,0,0,0,1),
array(0,0,0,0,0,0,0,1,0),
array(0,0,0,0,0,1,1,0,0),
array(0,0,0,0,0,0,0,1,0),
array(0,0,0,0,0,0,0,0,1),
array(0,0,0,0,0,0,0,0,1),
array(0,1,0,0,0,0,0,0,1),
array(0,0,1,0,0,0,0,1,0),
array(0,0,0,1,1,1,1,0,0),
array(0,0,0,0,0,0,0,0,0),
),
'4' => array(
array(0,0,0,0,0,0,0,1,0),
array(0,0,0,0,0,0,1,1,0),
array(0,0,0,0,0,1,0,1,0),
array(0,0,0,0,1,0,0,1,0),
array(0,0,0,1,0,0,0,1,0),
array(0,0,1,0,0,0,0,1,0),
array(0,1,1,1,1,1,1,1,1),
array(0,0,0,0,0,0,0,1,0),
array(0,0,0,0,0,0,0,1,0),
array(0,0,0,0,0,0,0,1,0),
array(0,0,0,0,0,0,0,1,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
),
'5' => array(
array(1,1,1,1,1,1,1,1,1),
array(1,0,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(0,1,0,0,0,0,0,0,0),
array(0,0,1,1,1,1,1,0,0),
array(0,0,0,0,0,0,0,1,0),
array(0,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(0,1,0,0,0,0,0,1,0),
array(0,0,1,1,1,1,1,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
),
'6' => array(
array(0,0,1,1,1,1,1,0,0),
array(0,1,0,0,0,0,0,1,0),
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,0),
array(1,0,0,0,0,0,0,0,0),
array(1,0,0,1,1,1,1,0,0),
array(1,0,1,0,0,0,0,1,0),
array(1,1,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(0,1,0,0,0,0,0,1,0),
array(0,0,1,1,1,1,1,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
),
'7' => array(
array(1,1,1,1,1,1,1,1,1),
array(1,0,0,0,0,0,0,0,1),
array(0,0,0,0,0,0,0,1,0),
array(0,0,0,0,0,0,1,0,0),
array(0,0,0,0,0,1,0,0,0),
array(0,0,0,0,1,0,0,0,0),
array(0,0,0,0,1,0,0,0,0),
array(0,0,0,0,1,0,0,0,0),
array(0,0,0,0,1,0,0,0,0),
array(0,0,0,0,1,0,0,0,0),
array(0,0,0,0,1,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
),
'8' => array(
array(0,0,1,1,1,1,1,0,0),
array(0,1,0,0,0,0,0,1,0),
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(0,1,0,0,0,0,0,1,0),
array(0,0,1,1,1,1,1,0,0),
array(0,1,0,0,0,0,0,1,0),
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(1,0,0,0,0,0,0,0,1),
array(0,1,0,0,0,0,0,1,0),
array(0,0,1,1,1,1,1,0,0),
array(0,0,0,0,0,0,0,0,0),
),
'9' => array(
array(0,0,0,1,1,1,1,0,0),
array(0,0,1,0,0,0,0,1,0),
array(0,1,0,0,0,0,0,0,1),
array(0,1,0,0,0,0,0,0,1),
array(0,1,0,0,0,0,0,0,1),
array(0,1,0,0,0,0,0,1,1),
array(0,0,1,1,1,1,1,0,1),
array(0,0,0,0,0,0,0,0,1),
array(0,0,0,0,0,0,0,0,1),
array(0,1,0,0,0,0,0,0,1),
array(0,0,1,0,0,0,0,1,0),
array(0,0,0,1,1,1,1,0,0),
array(0,0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0,0),
),
)
);
}
}
?>

View file

@ -0,0 +1,375 @@
<?php
/**
*
* @package VC
* @version $Id$
* @copyright (c) 2006, 2008 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* This class holds the code shared by the two default 3.0.x CAPTCHAs.
*
* @package VC
*/
class phpbb_default_captcha
{
var $confirm_id;
var $confirm_code;
var $code;
var $seed;
var $attempts = 0;
var $type;
var $solved = 0;
var $captcha_vars = false;
function init($type)
{
global $config, $db, $user;
// read input
$this->confirm_id = request_var('confirm_id', '');
$this->confirm_code = request_var('confirm_code', '');
$refresh = request_var('refresh_vc', false) && $config['confirm_refresh'];
$this->type = (int) $type;
if (!strlen($this->confirm_id) || !$this->load_code())
{
// we have no confirm ID, better get ready to display something
$this->generate_code();
}
else if ($refresh)
{
$this->regenerate_code();
}
}
function execute_demo()
{
global $user;
$this->code = gen_rand_string(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS));
$this->seed = hexdec(substr(unique_id(), 4, 10));
// compute $seed % 0x7fffffff
$this->seed -= 0x7fffffff * floor($this->seed / 0x7fffffff);
$captcha = new captcha();
define('IMAGE_OUTPUT', 1);
$captcha->execute($this->code, $this->seed);
}
function execute()
{
if (empty($this->code))
{
if (!$this->load_code())
{
// invalid request, bail out
return false;
}
}
$captcha = new captcha();
define('IMAGE_OUTPUT', 1);
$captcha->execute($this->code, $this->seed);
}
function get_template()
{
global $config, $user, $template, $phpEx, $phpbb_root_path;
if ($this->is_solved())
{
return false;
}
else
{
$link = append_sid($phpbb_root_path . 'ucp.' . $phpEx, 'mode=confirm&amp;confirm_id=' . $this->confirm_id . '&amp;type=' . $this->type);
$explain = $user->lang(($this->type != CONFIRM_POST) ? 'CONFIRM_EXPLAIN' : 'POST_CONFIRM_EXPLAIN', '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">', '</a>');
$template->assign_vars(array(
'CONFIRM_IMAGE_LINK' => $link,
'CONFIRM_IMAGE' => '<img src="' . $link . '" />',
'CONFIRM_IMG' => '<img src="' . $link . '" />',
'CONFIRM_ID' => $this->confirm_id,
'S_CONFIRM_CODE' => true,
'S_TYPE' => $this->type,
'S_CONFIRM_REFRESH' => ($config['enable_confirm'] && $config['confirm_refresh'] && $this->type == CONFIRM_REG) ? true : false,
'L_CONFIRM_EXPLAIN' => $explain,
));
return 'captcha_default.html';
}
}
function get_demo_template($id)
{
global $config, $user, $template, $phpbb_admin_path, $phpEx;
$variables = '';
if (is_array($this->captcha_vars))
{
foreach ($this->captcha_vars as $captcha_var => $template_var)
{
$variables .= '&amp;' . rawurlencode($captcha_var) . '=' . request_var($captcha_var, (int) $config[$captcha_var]);
}
}
// acp_captcha has a delivery function; let's use it
$template->assign_vars(array(
'CONFIRM_IMAGE' => append_sid($phpbb_admin_path . 'index.' . $phpEx, 'captcha_demo=1&amp;mode=visual&amp;i=' . $id . '&amp;select_captcha=' . $this->get_class_name()) . $variables,
'CONFIRM_ID' => $this->confirm_id,
));
return 'captcha_default_acp_demo.html';
}
function get_hidden_fields()
{
$hidden_fields = array();
// this is required for posting.php - otherwise we would forget about the captcha being already solved
if ($this->solved)
{
$hidden_fields['confirm_code'] = $this->confirm_code;
}
$hidden_fields['confirm_id'] = $this->confirm_id;
return $hidden_fields;
}
function garbage_collect($type)
{
global $db, $config;
$sql = 'SELECT DISTINCT c.session_id
FROM ' . CONFIRM_TABLE . ' c
LEFT JOIN ' . SESSIONS_TABLE . ' s ON (c.session_id = s.session_id)
WHERE s.session_id IS NULL' .
((empty($type)) ? '' : ' AND c.confirm_type = ' . (int) $type);
$result = $db->sql_query($sql);
if ($row = $db->sql_fetchrow($result))
{
$sql_in = array();
do
{
$sql_in[] = (string) $row['session_id'];
}
while ($row = $db->sql_fetchrow($result));
if (sizeof($sql_in))
{
$sql = 'DELETE FROM ' . CONFIRM_TABLE . '
WHERE ' . $db->sql_in_set('session_id', $sql_in);
$db->sql_query($sql);
}
}
$db->sql_freeresult($result);
}
function uninstall()
{
$this->garbage_collect(0);
}
function install()
{
return;
}
function validate()
{
global $config, $db, $user;
$error = '';
if (!$this->confirm_id)
{
$error = $user->lang['CONFIRM_CODE_WRONG'];
}
else
{
if ($this->check_code())
{
// $this->delete_code(); commented out to allow posting.php to repeat the question
$this->solved = true;
}
else
{
$error = $user->lang['CONFIRM_CODE_WRONG'];
}
}
if (strlen($error))
{
// okay, incorrect answer. Let's ask a new question.
$this->new_attempt();
return $error;
}
else
{
return false;
}
}
/**
* The old way to generate code, suitable for GD and non-GD. Resets the internal state.
*/
function generate_code()
{
global $db, $user;
$this->code = gen_rand_string(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS));
$this->confirm_id = md5(unique_id($user->ip));
$this->seed = hexdec(substr(unique_id(), 4, 10));
$this->solved = 0;
// compute $seed % 0x7fffffff
$this->seed -= 0x7fffffff * floor($this->seed / 0x7fffffff);
$sql = 'INSERT INTO ' . CONFIRM_TABLE . ' ' . $db->sql_build_array('INSERT', array(
'confirm_id' => (string) $this->confirm_id,
'session_id' => (string) $user->session_id,
'confirm_type' => (int) $this->type,
'code' => (string) $this->code,
'seed' => (int) $this->seed)
);
$db->sql_query($sql);
}
/**
* New Question, if desired.
*/
function regenerate_code()
{
global $db, $user;
$this->code = gen_rand_string(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS));
$this->seed = hexdec(substr(unique_id(), 4, 10));
$this->solved = 0;
// compute $seed % 0x7fffffff
$this->seed -= 0x7fffffff * floor($this->seed / 0x7fffffff);
$sql = 'UPDATE ' . CONFIRM_TABLE . ' SET ' . $db->sql_build_array('UPDATE', array(
'code' => (string) $this->code,
'seed' => (int) $this->seed)) . '
WHERE
confirm_id = \'' . $db->sql_escape($this->confirm_id) . '\'
AND session_id = \'' . $db->sql_escape($user->session_id) . '\'';
$db->sql_query($sql);
}
/**
* New Question, if desired.
*/
function new_attempt()
{
global $db, $user;
$this->code = gen_rand_string(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS));
$this->seed = hexdec(substr(unique_id(), 4, 10));
$this->solved = 0;
// compute $seed % 0x7fffffff
$this->seed -= 0x7fffffff * floor($this->seed / 0x7fffffff);
$sql = 'UPDATE ' . CONFIRM_TABLE . ' SET ' . $db->sql_build_array('UPDATE', array(
'code' => (string) $this->code,
'seed' => (int) $this->seed)) . '
, attempts = attempts + 1
WHERE
confirm_id = \'' . $db->sql_escape($this->confirm_id) . '\'
AND session_id = \'' . $db->sql_escape($user->session_id) . '\'';
$db->sql_query($sql);
}
/**
* Look up everything we need for painting&checking.
*/
function load_code()
{
global $db, $user;
$sql = 'SELECT code, seed, attempts
FROM ' . CONFIRM_TABLE . "
WHERE confirm_id = '" . $db->sql_escape($this->confirm_id) . "'
AND session_id = '" . $db->sql_escape($user->session_id) . "'
AND confirm_type = " . $this->type;
$result = $db->sql_query($sql);
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
if ($row)
{
$this->code = $row['code'];
$this->seed = $row['seed'];
$this->attempts = $row['attempts'];
return true;
}
return false;
}
function check_code()
{
return (strcasecmp($this->code, $this->confirm_code) === 0);
}
function delete_code()
{
global $db, $user;
$sql = 'DELETE FROM ' . CONFIRM_TABLE . "
WHERE confirm_id = '" . $db->sql_escape($confirm_id) . "'
AND session_id = '" . $db->sql_escape($user->session_id) . "'
AND confirm_type = " . $this->type;
$db->sql_query($sql);
}
function get_attempt_count()
{
return $this->attempts;
}
function reset()
{
global $db, $user;
$sql = 'DELETE FROM ' . CONFIRM_TABLE . "
WHERE session_id = '" . $db->sql_escape($user->session_id) . "'
AND confirm_type = " . (int) $this->type;
$db->sql_query($sql);
// we leave the class usable by generating a new question
$this->generate_code();
}
function is_solved()
{
if (request_var('confirm_code', false) && $this->solved === 0)
{
$this->validate();
}
return (bool) $this->solved;
}
/**
* API function
*/
function has_config()
{
return false;
}
}
?>

View file

@ -0,0 +1,163 @@
<?php
/**
*
* @package VC
* @version $Id$
* @copyright (c) 2006, 2008 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Placeholder for autoload
*/
if (!class_exists('phpbb_default_captcha'))
{
include($phpbb_root_path . 'includes/captcha/plugins/captcha_abstract.' . $phpEx);
}
/**
* @package VC
*/
class phpbb_captcha_gd extends phpbb_default_captcha
{
var $captcha_vars = array(
'captcha_gd_x_grid' => 'CAPTCHA_GD_X_GRID',
'captcha_gd_y_grid' => 'CAPTCHA_GD_Y_GRID',
'captcha_gd_foreground_noise' => 'CAPTCHA_GD_FOREGROUND_NOISE',
// 'captcha_gd' => 'CAPTCHA_GD_PREVIEWED',
'captcha_gd_wave' => 'CAPTCHA_GD_WAVE',
'captcha_gd_3d_noise' => 'CAPTCHA_GD_3D_NOISE',
'captcha_gd_fonts' => 'CAPTCHA_GD_FONTS',
);
function phpbb_captcha_gd()
{
global $phpbb_root_path, $phpEx;
if (!class_exists('captcha'))
{
include($phpbb_root_path . 'includes/captcha/captcha_gd.' . $phpEx);
}
}
function &get_instance()
{
$instance =& new phpbb_captcha_gd();
return $instance;
}
function is_available()
{
global $phpbb_root_path, $phpEx;
if (@extension_loaded('gd'))
{
return true;
}
if (!function_exists('can_load_dll'))
{
include($phpbb_root_path . 'includes/functions_install.' . $phpEx);
}
return can_load_dll('gd');
}
/**
* API function
*/
function has_config()
{
return true;
}
function get_name()
{
return 'CAPTCHA_GD';
}
function get_class_name()
{
return 'phpbb_captcha_gd';
}
function acp_page($id, &$module)
{
global $db, $user, $auth, $template;
global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;
$user->add_lang('acp/board');
$config_vars = array(
'enable_confirm' => 'REG_ENABLE',
'enable_post_confirm' => 'POST_ENABLE',
'confirm_refresh' => 'CONFIRM_REFRESH',
'captcha_gd' => 'CAPTCHA_GD',
);
$module->tpl_name = 'captcha_gd_acp';
$module->page_title = 'ACP_VC_SETTINGS';
$form_key = 'acp_captcha';
add_form_key($form_key);
$submit = request_var('submit', '');
if ($submit && check_form_key($form_key))
{
$captcha_vars = array_keys($this->captcha_vars);
foreach ($captcha_vars as $captcha_var)
{
$value = request_var($captcha_var, 0);
if ($value >= 0)
{
set_config($captcha_var, $value);
}
}
trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($module->u_action));
}
else if ($submit)
{
trigger_error($user->lang['FORM_INVALID'] . adm_back_link($module->u_action));
}
else
{
foreach ($this->captcha_vars as $captcha_var => $template_var)
{
$var = (isset($_REQUEST[$captcha_var])) ? request_var($captcha_var, 0) : $config[$captcha_var];
$template->assign_var($template_var, $var);
}
$template->assign_vars(array(
'CAPTCHA_PREVIEW' => $this->get_demo_template($id),
'CAPTCHA_NAME' => $this->get_class_name(),
'U_ACTION' => $module->u_action,
));
}
}
function execute_demo()
{
global $config;
$config_old = $config;
foreach ($this->captcha_vars as $captcha_var => $template_var)
{
$config[$captcha_var] = request_var($captcha_var, (int) $config[$captcha_var]);
}
parent::execute_demo();
$config = $config_old;
}
}
?>

View file

@ -0,0 +1,83 @@
<?php
/**
*
* @package VC
* @version $Id$
* @copyright (c) 2006, 2008 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Placeholder for autoload
*/
if (!class_exists('phpbb_default_captcha'))
{
include($phpbb_root_path . 'includes/captcha/plugins/captcha_abstract.' . $phpEx);
}
/**
* @package VC
*/
class phpbb_captcha_gd_wave extends phpbb_default_captcha
{
function phpbb_captcha_gd_wave()
{
global $phpbb_root_path, $phpEx;
if (!class_exists('captcha'))
{
include_once($phpbb_root_path . 'includes/captcha/captcha_gd_wave.' . $phpEx);
}
}
function get_instance()
{
return new phpbb_captcha_gd_wave();
}
function is_available()
{
global $phpbb_root_path, $phpEx;
if (@extension_loaded('gd'))
{
return true;
}
if (!function_exists('can_load_dll'))
{
include($phpbb_root_path . 'includes/functions_install.' . $phpEx);
}
return can_load_dll('gd');
}
function get_name()
{
return 'CAPTCHA_GD_3D';
}
function get_class_name()
{
return 'phpbb_captcha_gd_wave';
}
function acp_page($id, &$module)
{
global $config, $db, $template, $user;
trigger_error($user->lang['CAPTCHA_NO_OPTIONS'] . adm_back_link($module->u_action));
}
}
?>

View file

@ -0,0 +1,72 @@
<?php
/**
*
* @package VC
* @version $Id$
* @copyright (c) 2006, 2008 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Placeholder for autoload
*/
if (!class_exists('phpbb_default_captcha'))
{
include($phpbb_root_path . 'includes/captcha/plugins/captcha_abstract.' . $phpEx);
}
/**
* @package VC
*/
class phpbb_captcha_nogd extends phpbb_default_captcha
{
function phpbb_captcha_nogd()
{
global $phpbb_root_path, $phpEx;
if (!class_exists('captcha'))
{
include_once($phpbb_root_path . 'includes/captcha/captcha_non_gd.' . $phpEx);
}
}
function &get_instance()
{
$instance =& new phpbb_captcha_nogd();
return $instance;
}
function is_available()
{
return true;
}
function get_name()
{
return 'CAPTCHA_NO_GD';
}
function get_class_name()
{
return 'phpbb_captcha_nogd';
}
function acp_page($id, &$module)
{
global $user;
trigger_error($user->lang['CAPTCHA_NO_OPTIONS'] . adm_back_link($module->u_action));
}
}
?>

View file

@ -0,0 +1,924 @@
<?php
/**
*
* @package VC
* @version $Id$
* @copyright (c) 2006, 2008 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
global $table_prefix;
define('CAPTCHA_QUESTIONS_TABLE', $table_prefix . 'captcha_questions');
define('CAPTCHA_ANSWERS_TABLE', $table_prefix . 'captcha_answers');
define('CAPTCHA_QA_CONFIRM_TABLE', $table_prefix . 'qa_confirm');
/**
* And now to something completely different. Let's make a captcha without extending the abstract class.
* QA CAPTCHA sample implementation
*
* @package VC
*/
class phpbb_captcha_qa
{
var $confirm_id;
var $answer;
var $question_ids;
var $question_text;
var $question_lang;
var $question_strict;
var $attempts = 0;
var $type;
// dirty trick: 0 is false, but can still encode that the captcha is not yet validated
var $solved = 0;
/**
* @param int $type as per the CAPTCHA API docs, the type
*/
function init($type)
{
global $config, $db, $user;
// load our language file
$user->add_lang('captcha_qa');
// read input
$this->confirm_id = request_var('qa_confirm_id', '');
$this->answer = request_var('qa_answer', '', true);
$this->type = (int) $type;
$this->question_lang = $user->data['user_lang'];
// we need all defined questions - shouldn't be too many, so we can just grab them
// try the user's lang first
$sql = 'SELECT question_id
FROM ' . CAPTCHA_QUESTIONS_TABLE . "
WHERE lang_iso = '" . $db->sql_escape($user->data['user_lang']) . "'";
$result = $db->sql_query($sql, 3600);
while ($row = $db->sql_fetchrow($result))
{
$this->question_ids[$row['question_id']] = $row['question_id'];
}
$db->sql_freeresult($result);
// fallback to the board default lang
if (!sizeof($this->question_ids))
{
$this->question_lang = $config['default_lang'];
$sql = 'SELECT question_id
FROM ' . CAPTCHA_QUESTIONS_TABLE . "
WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "'";
$result = $db->sql_query($sql, 7200);
while ($row = $db->sql_fetchrow($result))
{
$this->question_ids[$row['question_id']] = $row['question_id'];
}
$db->sql_freeresult($result);
}
// okay, if there is a confirm_id, we try to load that confirm's state
if (!strlen($this->confirm_id) || !$this->load_answer())
{
// we have no valid confirm ID, better get ready to ask something
$this->select_question();
}
}
/**
* API function
*/
function &get_instance()
{
$instance =& new phpbb_captcha_qa();
return $instance;
}
/**
* See if the captcha has created its tables.
*/
function is_installed()
{
global $db, $phpbb_root_path, $phpEx;
if (!class_exists('phpbb_db_tools'))
{
include("$phpbb_root_path/includes/db/db_tools.$phpEx");
}
$db_tool = new phpbb_db_tools($db);
return $db_tool->sql_table_exists(CAPTCHA_QUESTIONS_TABLE);
}
/**
* API function - for the captcha to be available, it must have installed itself and there has to be at least one question in the board's default lang
*/
function is_available()
{
global $config, $db, $phpbb_root_path, $phpEx, $user;
// load language file for pretty display in the ACP dropdown
$user->add_lang('captcha_qa');
if (!phpbb_captcha_qa::is_installed())
{
return false;
}
$sql = 'SELECT COUNT(question_id) as count
FROM ' . CAPTCHA_QUESTIONS_TABLE . "
WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "'";
$result = $db->sql_query($sql);
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
return ((bool) $row['count']);
}
/**
* API function
*/
function has_config()
{
return true;
}
/**
* API function
*/
function get_name()
{
return 'CAPTCHA_QA';
}
/**
* API function
*/
function get_class_name()
{
return 'phpbb_captcha_qa';
}
/**
* API function - not needed as we don't display an image
*/
function execute_demo()
{
}
/**
* API function - not needed as we don't display an image
*/
function execute()
{
}
/**
* API function - send the question to the template
*/
function get_template()
{
global $template;
if ($this->is_solved())
{
return false;
}
else
{
$template->assign_vars(array(
'QA_CONFIRM_QUESTION' => $this->question_text,
'QA_CONFIRM_ID' => $this->confirm_id,
'S_CONFIRM_CODE' => true,
'S_TYPE' => $this->type,
));
return 'captcha_qa.html';
}
}
/**
* API function - we just display a mockup so that the captcha doesn't need to be installed
*/
function get_demo_template()
{
return 'captcha_qa_acp_demo.html';
}
/**
* API function
*/
function get_hidden_fields()
{
$hidden_fields = array();
// this is required - otherwise we would forget about the captcha being already solved
if ($this->solved)
{
$hidden_fields['qa_answer'] = $this->answer;
}
$hidden_fields['qa_confirm_id'] = $this->confirm_id;
return $hidden_fields;
}
/**
* API function
*/
function garbage_collect($type)
{
global $db, $config;
$sql = 'SELECT DISTINCT c.session_id
FROM ' . CAPTCHA_QA_CONFIRM_TABLE . ' c
LEFT JOIN ' . SESSIONS_TABLE . ' s
ON (c.session_id = s.session_id)
WHERE s.session_id IS NULL' .
((empty($type)) ? '' : ' AND c.confirm_type = ' . (int) $type);
$result = $db->sql_query($sql);
if ($row = $db->sql_fetchrow($result))
{
$sql_in = array();
do
{
$sql_in[] = (string) $row['session_id'];
}
while ($row = $db->sql_fetchrow($result));
if (sizeof($sql_in))
{
$sql = 'DELETE FROM ' . CAPTCHA_QA_CONFIRM_TABLE . '
WHERE ' . $db->sql_in_set('session_id', $sql_in);
$db->sql_query($sql);
}
}
$db->sql_freeresult($result);
}
/**
* API function - we don't drop the tables here, as that would cause the loss of all entered questions.
*/
function uninstall()
{
$this->garbage_collect(0);
}
/**
* API function - set up shop
*/
function install()
{
global $db, $phpbb_root_path, $phpEx;
if (!class_exists('phpbb_db_tools'))
{
include("$phpbb_root_path/includes/db/db_tools.$phpEx");
}
$db_tool = new phpbb_db_tools($db);
$tables = array(CAPTCHA_QUESTIONS_TABLE, CAPTCHA_ANSWERS_TABLE, CAPTCHA_QA_CONFIRM_TABLE);
$schemas = array(
CAPTCHA_QUESTIONS_TABLE => array (
'COLUMNS' => array(
'question_id' => array('UINT', Null, 'auto_increment'),
'strict' => array('BOOL', 0),
'lang_id' => array('UINT', 0),
'lang_iso' => array('VCHAR:30', ''),
'question_text' => array('TEXT_UNI', ''),
),
'PRIMARY_KEY' => 'question_id',
'KEYS' => array(
'lang_iso' => array('INDEX', 'lang_iso'),
),
),
CAPTCHA_ANSWERS_TABLE => array (
'COLUMNS' => array(
'question_id' => array('UINT', 0),
'answer_text' => array('STEXT_UNI', ''),
),
'KEYS' => array(
'question_id' => array('INDEX', 'question_id'),
),
),
CAPTCHA_QA_CONFIRM_TABLE => array (
'COLUMNS' => array(
'session_id' => array('CHAR:32', ''),
'confirm_id' => array('CHAR:32', ''),
'lang_iso' => array('VCHAR:30', ''),
'question_id' => array('UINT', 0),
'attempts' => array('UINT', 0),
'confirm_type' => array('USINT', 0),
),
'KEYS' => array(
'session_id' => array('INDEX', 'session_id'),
'lookup' => array('INDEX', array('confirm_id', 'session_id', 'lang_iso')),
),
'PRIMARY_KEY' => 'confirm_id',
),
);
foreach($schemas as $table => $schema)
{
if (!$db_tool->sql_table_exists($table))
{
$db_tool->sql_create_table($table, $schema);
}
}
}
/**
* API function - see what has to be done to validate
*/
function validate()
{
global $config, $db, $user;
$error = '';
if (!$this->confirm_id)
{
$error = $user->lang['CONFIRM_QUESTION_WRONG'];
}
else
{
if ($this->check_answer())
{
// $this->delete_code(); commented out to allow posting.php to repeat the question
$this->solved = true;
}
else
{
$error = $user->lang['CONFIRM_QUESTION_WRONG'];
}
}
if (strlen($error))
{
// okay, incorrect answer. Let's ask a new question.
$this->new_attempt();
$this->solved = false;
return $error;
}
else
{
return false;
}
}
/**
* Select a question
*/
function select_question()
{
global $db, $user;
$this->confirm_id = md5(unique_id($user->ip));
$this->question = (int) array_rand($this->question_ids);
$sql = 'INSERT INTO ' . CAPTCHA_QA_CONFIRM_TABLE . ' ' . $db->sql_build_array('INSERT', array(
'confirm_id' => (string) $this->confirm_id,
'session_id' => (string) $user->session_id,
'lang_iso' => (string) $this->question_lang,
'confirm_type' => (int) $this->type,
'question_id' => (int) $this->question,
));
$db->sql_query($sql);
$this->load_answer();
}
/**
* New Question, if desired.
*/
function reselect_question()
{
global $db, $user;
$this->question = (int) array_rand($this->question_ids);
$this->solved = 0;
$sql = 'UPDATE ' . CAPTCHA_QA_CONFIRM_TABLE . '
SET question_id = ' . (int) $this->question . "
WHERE confirm_id = '" . $db->sql_escape($this->confirm_id) . "'
AND session_id = '" . $db->sql_escape($user->session_id) . "'";
$db->sql_query($sql);
$this->load_answer();
}
/**
* Wrong answer, so we increase the attempts and use a different question.
*/
function new_attempt()
{
global $db, $user;
// yah, I would prefer a stronger rand, but this should work
$this->question = (int) array_rand($this->question_ids);
$this->solved = 0;
$sql = 'UPDATE ' . CAPTCHA_QA_CONFIRM_TABLE . '
SET question_id = ' . (int) $this->question . ",
attempts = attempts + 1
WHERE confirm_id = '" . $db->sql_escape($this->confirm_id) . "'
AND session_id = '" . $db->sql_escape($user->session_id) . "'";
$db->sql_query($sql);
$this->load_answer();
}
/**
* Look up everything we need and populate the instance variables.
*/
function load_answer()
{
global $db, $user;
$sql = 'SELECT con.question_id, attempts, question_text, strict
FROM ' . CAPTCHA_QA_CONFIRM_TABLE . ' con, ' . CAPTCHA_QUESTIONS_TABLE . " qes
WHERE con.question_id = qes.question_id
AND confirm_id = '" . $db->sql_escape($this->confirm_id) . "'
AND session_id = '" . $db->sql_escape($user->session_id) . "'
AND qes.lang_iso = '" . $db->sql_escape($this->question_lang) . "'
AND confirm_type = " . $this->type;
$result = $db->sql_query($sql);
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
if ($row)
{
$this->question = $row['question_id'];
$this->attempts = $row['attempts'];
$this->question_strict = $row['strict'];
$this->question_text = $row['question_text'];
return true;
}
return false;
}
/**
* The actual validation
*/
function check_answer()
{
global $db;
$answer = ($this->question_strict) ? request_var('qa_answer', '', true) : utf8_clean_string(request_var('qa_answer', '', true));
$sql = 'SELECT answer_text
FROM ' . CAPTCHA_ANSWERS_TABLE . '
WHERE question_id = ' . (int) $this->question;
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
{
$solution = ($this->question_strict) ? $row['answer_text'] : utf8_clean_string($row['answer_text']);
if ($solution === $answer)
{
$this->solved = true;
break;
}
}
$db->sql_freeresult($result);
return $this->solved;
}
/**
* API function - clean the entry
*/
function delete_code()
{
global $db, $user;
$sql = 'DELETE FROM ' . CAPTCHA_QA_CONFIRM_TABLE . "
WHERE confirm_id = '" . $db->sql_escape($confirm_id) . "'
AND session_id = '" . $db->sql_escape($user->session_id) . "'
AND confirm_type = " . $this->type;
$db->sql_query($sql);
}
/**
* API function
*/
function get_attempt_count()
{
return $this->attempts;
}
/**
* API function
*/
function reset()
{
global $db, $user;
$sql = 'DELETE FROM ' . CAPTCHA_QA_CONFIRM_TABLE . "
WHERE session_id = '" . $db->sql_escape($user->session_id) . "'
AND confirm_type = " . (int) $this->type;
$db->sql_query($sql);
// we leave the class usable by generating a new question
$this->select_question();
}
/**
* API function
*/
function is_solved()
{
if (request_var('qa_answer', false) && $this->solved === 0)
{
$this->validate();
}
return (bool) $this->solved;
}
/**
* API function - The ACP backend, this marks the end of the easy methods
*/
function acp_page($id, &$module)
{
global $db, $user, $auth, $template;
global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;
$user->add_lang('acp/board');
$user->add_lang('captcha_qa');
if (!$this->is_installed())
{
$this->install();
}
$module->tpl_name = 'captcha_qa_acp';
$module->page_title = 'ACP_VC_SETTINGS';
$form_key = 'acp_captcha';
add_form_key($form_key);
$submit = request_var('submit', false);
$question_id = request_var('question_id', 0);
$action = request_var('action', '');
// we have two pages, so users might want to navigate from one to the other
$list_url = $module->u_action . "&amp;configure=1&amp;select_captcha=" . $this->get_class_name();
$template->assign_vars(array(
'U_ACTION' => $module->u_action,
'QUESTION_ID' => $question_id ,
'CLASS' => $this->get_class_name(),
));
// show the list?
if (!$question_id && $action != 'add')
{
$this->acp_question_list($module);
}
else if ($question_id && $action == 'delete')
{
if (confirm_box(true))
{
$this->acp_delete_question($question_id);
trigger_error($user->lang['QUESTION_DELETED'] . adm_back_link($list_url));
}
else
{
confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array(
'question_id' => $question_id,
'action' => $action,
'configure' => 1,
'select_captcha' => $this->get_class_name(),
))
);
}
}
else
{
// okay, show the editor
$error = false;
$input_question = request_var('question_text', '', true);
$input_answers = request_var('answers', '', true);
$input_lang = request_var('lang_iso', '', true);
$input_strict = request_var('strict', false);
$langs = $this->get_languages();
foreach ($langs as $lang => $entry)
{
$template->assign_block_vars('langs', array(
'ISO' => $lang,
'NAME' => $entry['name'],
));
}
$template->assign_vars(array(
'U_LIST' => $list_url,
));
if ($question_id)
{
if ($question = $this->acp_get_question_data($question_id))
{
$answers = (isset($input_answers[$lang])) ? $input_answers[$lang] : implode("\n", $question['answers']);
$template->assign_vars(array(
'QUESTION_TEXT' => ($input_question) ? $input_question : $question['question_text'],
'LANG_ISO' => ($input_lang) ? $input_lang : $question['lang_iso'],
'STRICT' => (isset($_REQUEST['strict'])) ? $input_strict : $question['strict'],
'ANSWERS' => $answers,
));
}
else
{
trigger_error($user->lang['FORM_INVALID'] . adm_back_link($list_url));
}
}
else
{
$template->assign_vars(array(
'QUESTION_TEXT' => $input_question,
'LANG_ISO' => $input_lang,
'STRICT' => $input_strict,
'ANSWERS' => $input_answers,
));
}
if ($submit && check_form_key($form_key))
{
$data = $this->acp_get_question_input();
if (!$this->validate_input($data))
{
$template->assign_vars(array(
'S_ERROR' => true,
));
}
else
{
if ($question_id)
{
$this->acp_update_question($data, $question_id);
}
else
{
$this->acp_add_question($data);
}
trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($list_url));
}
}
else if ($submit)
{
trigger_error($user->lang['FORM_INVALID'] . adm_back_link($list_url));
}
}
}
/**
* This handles the list overview
*/
function acp_question_list(&$module)
{
global $db, $template;
$sql = 'SELECT *
FROM ' . CAPTCHA_QUESTIONS_TABLE;
$result = $db->sql_query($sql);
$template->assign_vars(array(
'S_LIST' => true,
));
while ($row = $db->sql_fetchrow($result))
{
$url = $module->u_action . "&amp;question_id={$row['question_id']}&amp;configure=1&amp;select_captcha=" . $this->get_class_name() . '&amp;';
$template->assign_block_vars('questions', array(
'QUESTION_TEXT' => $row['question_text'],
'QUESTION_ID' => $row['question_id'],
'QUESTION_LANG' => $row['lang_iso'],
'U_DELETE' => "{$url}action=delete",
'U_EDIT' => "{$url}action=edit",
));
}
$db->sql_freeresult($result);
}
/**
* Grab a question and bring it into a format the editor understands
*/
function acp_get_question_data($question_id)
{
global $db;
if ($question_id)
{
$sql = 'SELECT *
FROM ' . CAPTCHA_QUESTIONS_TABLE . '
WHERE question_id = ' . $question_id;
$result = $db->sql_query($sql);
$question = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
if (!$question)
{
return false;
}
$question['answers'] = array();
$sql = 'SELECT *
FROM ' . CAPTCHA_ANSWERS_TABLE . '
WHERE question_id = ' . $question_id;
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
{
$question['answers'][] = $row['answer_text'];
}
$db->sql_freeresult($result);
return $question;
}
}
/**
* Grab a question from input and bring it into a format the editor understands
*/
function acp_get_question_input()
{
$question = array(
'question_text' => request_var('question_text', '', true),
'strict' => request_var('strict', false),
'lang_iso' => request_var('lang_iso', ''),
'answers' => explode("\n", request_var('answers', '', true)),
);
return $question;
}
/**
* Update a question.
* param mixed $data : an array as created from acp_get_question_input or acp_get_question_data
*/
function acp_update_question($data, $question_id)
{
global $db, $cache;
// easier to delete all answers than to figure out which to update
$sql = 'DELETE FROM ' . CAPTCHA_ANSWERS_TABLE . " WHERE question_id = $question_id";
$db->sql_query($sql);
$langs = $this->get_languages();
$question_ary = $data;
$question_ary['lang_id'] = $langs[$question_ary['lang_iso']]['id'];
unset($question_ary['answers']);
$sql = 'UPDATE ' . CAPTCHA_QUESTIONS_TABLE . '
SET ' . $db->sql_build_array('UPDATE', $question_ary) . "
WHERE question_id = $question_id";
$db->sql_query($sql);
$this->acp_insert_answers($data, $question_id);
$cache->destroy('sql', CAPTCHA_QUESTIONS_TABLE);
}
/**
* Insert a question.
* param mixed $data : an array as created from acp_get_question_input or acp_get_question_data
*/
function acp_add_question($data)
{
global $db, $cache;
$langs = $this->get_languages();
$question_ary = $data;
$question_ary['lang_id'] = $langs[$data['lang_iso']]['id'];
unset($question_ary['answers']);
$sql = 'INSERT INTO ' . CAPTCHA_QUESTIONS_TABLE . ' ' . $db->sql_build_array('INSERT', $question_ary);
$db->sql_query($sql);
$question_id = $db->sql_nextid();
$this->acp_insert_answers($data, $question_id);
$cache->destroy('sql', CAPTCHA_QUESTIONS_TABLE);
}
/**
* Insert the answers.
* param mixed $data : an array as created from acp_get_question_input or acp_get_question_data
*/
function acp_insert_answers($data, $question_id)
{
global $db, $cache;
foreach ($data['answers'] as $answer)
{
$answer_ary = array(
'question_id' => $question_id,
'answer_text' => $answer,
);
$sql = 'INSERT INTO ' . CAPTCHA_ANSWERS_TABLE . ' ' . $db->sql_build_array('INSERT', $answer_ary);
$db->sql_query($sql);
}
$cache->destroy('sql', CAPTCHA_ANSWERS_TABLE);
}
/**
* Delete a question.
*/
function acp_delete_question($question_id)
{
global $db, $cache;
$tables = array(CAPTCHA_QUESTIONS_TABLE, CAPTCHA_ANSWERS_TABLE);
foreach ($tables as $table)
{
$sql = "DELETE FROM $table
WHERE question_id = $question_id";
$db->sql_query($sql);
}
$cache->destroy('sql', $tables);
}
/**
* Check if the entered data can be inserted/used
* param mixed $data : an array as created from acp_get_question_input or acp_get_question_data
*/
function validate_input($question_data)
{
$langs = $this->get_languages();
if (!isset($question_data['lang_iso']) ||
!isset($question_data['question_text']) ||
!isset($question_data['strict']) ||
!isset($question_data['answers']))
{
return false;
}
if (!isset($langs[$question_data['lang_iso']]) ||
!$question_data['question_text'] ||
!sizeof($question_data['answers']))
{
return false;
}
return true;
}
/**
* List the installed language packs
*/
function get_languages()
{
global $db;
$sql = 'SELECT *
FROM ' . LANG_TABLE;
$result = $db->sql_query($sql);
$langs = array();
while ($row = $db->sql_fetchrow($result))
{
$langs[$row['lang_iso']] = array(
'name' => $row['lang_local_name'],
'id' => (int) $row['lang_id'],
);
}
$db->sql_freeresult($result);
return $langs;
}
}
?>

View file

@ -0,0 +1,334 @@
<?php
/**
*
* @package VC
* @version $Id$
* @copyright (c) 2006, 2008 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
if (!class_exists('phpbb_default_captcha'))
{
// we need the classic captcha code for tracking solutions and attempts
include($phpbb_root_path . 'includes/captcha/plugins/captcha_abstract.' . $phpEx);
}
/**
* @package VC
*/
class phpbb_recaptcha extends phpbb_default_captcha
{
var $recaptcha_server = 'http://api.recaptcha.net';
var $recaptcha_verify_server = 'api-verify.recaptcha.net';
var $challenge;
var $response;
function init($type)
{
global $config, $db, $user;
$user->add_lang('captcha_recaptcha');
parent::init($type);
$this->challenge = request_var('recaptcha_challenge_field', '');
$this->response = request_var('recaptcha_response_field', '');
}
function &get_instance()
{
$instance =& new phpbb_recaptcha();
return $instance;
}
function is_available()
{
global $config, $user;
$user->add_lang('captcha_recaptcha');
return (isset($config['recaptcha_pubkey']) && !empty($config['recaptcha_pubkey']));
}
/**
* API function
*/
function has_config()
{
return true;
}
function get_name()
{
return 'CAPTCHA_RECAPTCHA';
}
function get_class_name()
{
return 'phpbb_recaptcha';
}
function acp_page($id, &$module)
{
global $config, $db, $template, $user;
$captcha_vars = array(
'recaptcha_pubkey' => 'RECAPTCHA_PUBKEY',
'recaptcha_privkey' => 'RECAPTCHA_PRIVKEY',
);
$module->tpl_name = 'captcha_recaptcha_acp';
$module->page_title = 'ACP_VC_SETTINGS';
$form_key = 'acp_captcha';
add_form_key($form_key);
$submit = request_var('submit', '');
if ($submit && check_form_key($form_key))
{
$captcha_vars = array_keys($captcha_vars);
foreach ($captcha_vars as $captcha_var)
{
$value = request_var($captcha_var, '');
if ($value)
{
set_config($captcha_var, $value);
}
}
trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($module->u_action));
}
else if ($submit)
{
trigger_error($user->lang['FORM_INVALID'] . adm_back_link($module->u_action));
}
else
{
foreach ($captcha_vars as $captcha_var => $template_var)
{
$var = (isset($_REQUEST[$captcha_var])) ? request_var($captcha_var, '') : ((isset($config[$captcha_var])) ? $config[$captcha_var] : '');
$template->assign_var($template_var, $var);
}
$template->assign_vars(array(
'CAPTCHA_PREVIEW' => $this->get_demo_template($id),
'CAPTCHA_NAME' => $this->get_class_name(),
'U_ACTION' => $module->u_action,
));
}
}
// not needed
function execute_demo()
{
}
// not needed
function execute()
{
}
function get_template()
{
global $config, $user, $template;
if ($this->is_solved())
{
return false;
}
else
{
$explain = $user->lang(($this->type != CONFIRM_POST) ? 'CONFIRM_EXPLAIN' : 'POST_CONFIRM_EXPLAIN', '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">', '</a>');
$template->assign_vars(array(
'RECAPTCHA_SERVER' => $this->recaptcha_server,
'RECAPTCHA_PUBKEY' => isset($config['recaptcha_pubkey']) ? $config['recaptcha_pubkey'] : '',
'RECAPTCHA_ERRORGET' => '',
'S_RECAPTCHA_AVAILABLE' => $this->is_available(),
'S_CONFIRM_CODE' => true,
'S_TYPE' => $this->type,
'L_CONFIRM_EXPLAIN' => $explain,
));
return 'captcha_recaptcha.html';
}
}
function get_demo_template($id)
{
return $this->get_template();
}
function get_hidden_fields()
{
$hidden_fields = array();
// this is required for posting.php - otherwise we would forget about the captcha being already solved
if ($this->solved)
{
$hidden_fields['confirm_code'] = $this->code;
}
$hidden_fields['confirm_id'] = $this->confirm_id;
return $hidden_fields;
}
function uninstall()
{
$this->garbage_collect(0);
}
function install()
{
return;
}
function validate()
{
if (!parent::validate())
{
return false;
}
else
{
return $this->recaptcha_check_answer();
}
}
// Code from here on is based on recaptchalib.php
/*
* This is a PHP library that handles calling reCAPTCHA.
* - Documentation and latest version
* http://recaptcha.net/plugins/php/
* - Get a reCAPTCHA API Key
* http://recaptcha.net/api/getkey
* - Discussion group
* http://groups.google.com/group/recaptcha
*
* Copyright (c) 2007 reCAPTCHA -- http://recaptcha.net
* AUTHORS:
* Mike Crawford
* Ben Maurer
*
* 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.
*/
/**
* 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/phpBB\r\n";
$http_request .= "\r\n";
$http_request .= $req;
$response = '';
if (false == ($fs = @fsockopen($host, $port, $errno, $errstr, 10)))
{
trigger_error('Could not open socket', E_USER_ERROR);
}
fwrite($fs, $http_request);
while (!feof($fs))
{
// One TCP-IP packet
$response .= fgets($fs, 1160);
}
fclose($fs);
$response = explode("\r\n\r\n", $response, 2);
return $response;
}
/**
* Calls an HTTP POST function to verify if the user's guess was correct
* @param array $extra_params an array of extra variables to post to the server
* @return ReCaptchaResponse
*/
function recaptcha_check_answer($extra_params = array())
{
global $config, $user;
//discard spam submissions
if ($this->challenge == null || strlen($this->challenge) == 0 || $this->response == null || strlen($this->response) == 0)
{
return $user->lang['RECAPTCHA_INCORRECT'];
}
$response = $this->_recaptcha_http_post($this->recaptcha_verify_server, '/verify',
array(
'privatekey' => $config['recaptcha_privkey'],
'remoteip' => $user->ip,
'challenge' => $this->challenge,
'response' => $this->response
) + $extra_params
);
$answers = explode("\n", $response[1]);
if (trim($answers[0]) === 'true')
{
$this->solved = true;
return false;
}
else
{
if ($answers[1] === 'incorrect-captcha-sol')
{
return $user->lang['RECAPTCHA_INCORRECT'];
}
}
}
/**
* 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;
}
}
?>

View file

@ -25,7 +25,7 @@ if (!defined('IN_PHPBB'))
*/
// phpBB Version
define('PHPBB_VERSION', '3.0.5');
define('PHPBB_VERSION', '3.0.6-RC1');
// QA-related
// define('PHPBB_QA', 1);
@ -91,6 +91,11 @@ define('FORUM_FLAG_PRUNE_ANNOUNCE', 4);
define('FORUM_FLAG_PRUNE_STICKY', 8);
define('FORUM_FLAG_ACTIVE_TOPICS', 16);
define('FORUM_FLAG_POST_REVIEW', 32);
define('FORUM_FLAG_QUICK_REPLY', 64);
// Forum Options... sequential order. Modifications should begin at number 10 (number 29 is maximum)
define('FORUM_OPTION_FEED_NEWS', 1);
define('FORUM_OPTION_FEED_EXCLUDE', 2);
// Optional text flags
define('OPTION_FLAG_BBCODE', 1);
@ -160,6 +165,9 @@ define('BBCODE_UID_LEN', 8);
// Number of core BBCodes
define('NUM_CORE_BBCODES', 12);
// Smiley hard limit
define('SMILEY_LIMIT', 1000);
// Magic url types
define('MAGIC_URL_EMAIL', 1);
define('MAGIC_URL_FULL', 2);

View file

@ -347,6 +347,11 @@ class phpbb_db_tools
// holds the DDL for a column
$columns = $statements = array();
if ($this->sql_table_exists($table_name))
{
return $this->_sql_run_sql($statements);
}
// Begin transaction
$statements[] = 'begin';
@ -580,6 +585,14 @@ class phpbb_db_tools
}
$statements = array();
$sqlite = false;
// For SQLite we need to perform the schema changes in a much more different way
if ($this->db->sql_layer == 'sqlite' && $this->return_statements)
{
$sqlite_data = array();
$sqlite = true;
}
// Change columns?
if (!empty($schema_changes['change_columns']))
@ -589,16 +602,27 @@ class phpbb_db_tools
foreach ($columns as $column_name => $column_data)
{
// If the column exists we change it, else we add it ;)
if ($this->sql_column_exists($table, $column_name))
if ($column_exists = $this->sql_column_exists($table, $column_name))
{
$result = $this->sql_column_change($table, $column_name, $column_data);
$result = $this->sql_column_change($table, $column_name, $column_data, true);
}
else
{
$result = $this->sql_column_add($table, $column_name, $column_data);
$result = $this->sql_column_add($table, $column_name, $column_data, true);
}
if ($this->return_statements)
if ($sqlite)
{
if ($column_exists)
{
$sqlite_data[$table]['change_columns'][] = $result;
}
else
{
$sqlite_data[$table]['add_columns'][] = $result;
}
}
else if ($this->return_statements)
{
$statements = array_merge($statements, $result);
}
@ -614,16 +638,27 @@ class phpbb_db_tools
foreach ($columns as $column_name => $column_data)
{
// Only add the column if it does not exist yet, else change it (to be consistent)
if ($this->sql_column_exists($table, $column_name))
if ($column_exists = $this->sql_column_exists($table, $column_name))
{
$result = $this->sql_column_change($table, $column_name, $column_data);
$result = $this->sql_column_change($table, $column_name, $column_data, true);
}
else
{
$result = $this->sql_column_add($table, $column_name, $column_data);
$result = $this->sql_column_add($table, $column_name, $column_data, true);
}
if ($this->return_statements)
if ($sqlite)
{
if ($column_exists)
{
$sqlite_data[$table]['change_columns'][] = $result;
}
else
{
$sqlite_data[$table]['add_columns'][] = $result;
}
}
else if ($this->return_statements)
{
$statements = array_merge($statements, $result);
}
@ -658,9 +693,13 @@ class phpbb_db_tools
// Only remove the column if it exists...
if ($this->sql_column_exists($table, $column))
{
$result = $this->sql_column_remove($table, $column);
$result = $this->sql_column_remove($table, $column, true);
if ($this->return_statements)
if ($sqlite)
{
$sqlite_data[$table]['drop_columns'][] = $result;
}
else if ($this->return_statements)
{
$statements = array_merge($statements, $result);
}
@ -674,9 +713,13 @@ class phpbb_db_tools
{
foreach ($schema_changes['add_primary_keys'] as $table => $columns)
{
$result = $this->sql_create_primary_key($table, $columns);
$result = $this->sql_create_primary_key($table, $columns, true);
if ($this->return_statements)
if ($sqlite)
{
$sqlite_data[$table]['primary_key'] = $result;
}
else if ($this->return_statements)
{
$statements = array_merge($statements, $result);
}
@ -717,6 +760,147 @@ class phpbb_db_tools
}
}
if ($sqlite)
{
foreach ($sqlite_data as $table_name => $sql_schema_changes)
{
// Create temporary table with original data
$statements[] = 'begin';
$sql = "SELECT sql
FROM sqlite_master
WHERE type = 'table'
AND name = '{$table_name}'
ORDER BY type DESC, name;";
$result = $this->db->sql_query($sql);
if (!$result)
{
continue;
}
$row = $this->db->sql_fetchrow($result);
$this->db->sql_freeresult($result);
// Create a backup table and populate it, destroy the existing one
$statements[] = preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $row['sql']);
$statements[] = 'INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name;
$statements[] = 'DROP TABLE ' . $table_name;
// Get the columns...
preg_match('#\((.*)\)#s', $row['sql'], $matches);
$plain_table_cols = trim($matches[1]);
$new_table_cols = preg_split('/,(?![\s\w]+\))/m', $plain_table_cols);
$column_list = array();
foreach ($new_table_cols as $declaration)
{
$entities = preg_split('#\s+#', trim($declaration));
if ($entities[0] == 'PRIMARY')
{
continue;
}
$column_list[] = $entities[0];
}
// note down the primary key notation because sqlite only supports adding it to the end for the new table
$primary_key = false;
$_new_cols = array();
foreach ($new_table_cols as $key => $declaration)
{
$entities = preg_split('#\s+#', trim($declaration));
if ($entities[0] == 'PRIMARY')
{
$primary_key = $declaration;
continue;
}
$_new_cols[] = $declaration;
}
$new_table_cols = $_new_cols;
// First of all... change columns
if (!empty($sql_schema_changes['change_columns']))
{
foreach ($sql_schema_changes['change_columns'] as $column_sql)
{
foreach ($new_table_cols as $key => $declaration)
{
$entities = preg_split('#\s+#', trim($declaration));
if (strpos($column_sql, $entities[0] . ' ') === 0)
{
$new_table_cols[$key] = $column_sql;
}
}
}
}
if (!empty($sql_schema_changes['add_columns']))
{
foreach ($sql_schema_changes['add_columns'] as $column_sql)
{
$new_table_cols[] = $column_sql;
}
}
// Now drop them...
if (!empty($sql_schema_changes['drop_columns']))
{
foreach ($sql_schema_changes['drop_columns'] as $column_name)
{
// Remove from column list...
$new_column_list = array();
foreach ($column_list as $key => $value)
{
if ($value === $column_name)
{
continue;
}
$new_column_list[] = $value;
}
$column_list = $new_column_list;
// Remove from table...
$_new_cols = array();
foreach ($new_table_cols as $key => $declaration)
{
$entities = preg_split('#\s+#', trim($declaration));
if (strpos($column_name . ' ', $entities[0] . ' ') === 0)
{
continue;
}
$_new_cols[] = $declaration;
}
$new_table_cols = $_new_cols;
}
}
// Primary key...
if (!empty($sql_schema_changes['primary_key']))
{
$new_table_cols[] = 'PRIMARY KEY (' . implode(', ', $sql_schema_changes['primary_key']) . ')';
}
// Add a new one or the old primary key
else if ($primary_key !== false)
{
$new_table_cols[] = $primary_key;
}
$columns = implode(',', $column_list);
// create a new table and fill it up. destroy the temp one
$statements[] = 'CREATE TABLE ' . $table_name . ' (' . implode(',', $new_table_cols) . ');';
$statements[] = 'INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;';
$statements[] = 'DROP TABLE ' . $table_name . '_temp';
$statements[] = 'commit';
}
}
if ($this->return_statements)
{
return $statements;
@ -801,7 +985,7 @@ class phpbb_db_tools
case 'oracle':
$sql = "SELECT column_name
FROM user_tab_columns
WHERE table_name = '{$table}'";
WHERE LOWER(table_name) = '" . strtolower($table) . "'";
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
@ -819,7 +1003,7 @@ class phpbb_db_tools
case 'firebird':
$sql = "SELECT RDB\$FIELD_NAME as FNAME
FROM RDB\$RELATION_FIELDS
WHERE RDB\$RELATION_NAME = '{$table}'";
WHERE RDB\$RELATION_NAME = '" . strtoupper($table) . "'";
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
@ -972,10 +1156,12 @@ class phpbb_db_tools
{
case 'firebird':
$sql .= " {$column_type} ";
$return_array['column_type_sql_type'] = " {$column_type} ";
if (!is_null($column_data[1]))
{
$sql .= 'DEFAULT ' . ((is_numeric($column_data[1])) ? $column_data[1] : "'{$column_data[1]}'") . ' ';
$return_array['column_type_sql_default'] = ((is_numeric($column_data[1])) ? $column_data[1] : "'{$column_data[1]}'") . ' ';
}
$sql .= 'NOT NULL';
@ -1129,7 +1315,7 @@ class phpbb_db_tools
/**
* Add new column
*/
function sql_column_add($table_name, $column_name, $column_data)
function sql_column_add($table_name, $column_name, $column_data, $inline = false)
{
$column_data = $this->sql_prepare_column_data($table_name, $column_name, $column_data);
$statements = array();
@ -1158,6 +1344,12 @@ class phpbb_db_tools
break;
case 'sqlite':
if ($inline && $this->return_statements)
{
return $column_name . ' ' . $column_data['column_type_sql'];
}
if (version_compare(sqlite_libversion(), '3.0') == -1)
{
$sql = "SELECT sql
@ -1222,7 +1414,7 @@ class phpbb_db_tools
/**
* Drop column
*/
function sql_column_remove($table_name, $column_name)
function sql_column_remove($table_name, $column_name, $inline = false)
{
$statements = array();
@ -1250,6 +1442,12 @@ class phpbb_db_tools
break;
case 'sqlite':
if ($inline && $this->return_statements)
{
return $column_name;
}
if (version_compare(sqlite_libversion(), '3.0') == -1)
{
$sql = "SELECT sql
@ -1292,7 +1490,7 @@ class phpbb_db_tools
$columns = implode(',', $column_list);
$new_table_cols = $new_table_cols = preg_replace('/' . $column_name . '[^,]+(?:,|$)/m', '', $new_table_cols);
$new_table_cols = preg_replace('/' . $column_name . '[^,]+(?:,|$)/m', '', $new_table_cols);
// create a new table and fill it up. destroy the temp one
$statements[] = 'CREATE TABLE ' . $table_name . ' (' . $new_table_cols . ');';
@ -1347,6 +1545,11 @@ class phpbb_db_tools
{
$statements = array();
if (!$this->sql_table_exists($table_name))
{
return $this->_sql_run_sql($statements);
}
// the most basic operation, get rid of the table
$statements[] = 'DROP TABLE ' . $table_name;
@ -1405,7 +1608,7 @@ class phpbb_db_tools
/**
* Add primary key
*/
function sql_create_primary_key($table_name, $column)
function sql_create_primary_key($table_name, $column, $inline = false)
{
$statements = array();
@ -1432,6 +1635,12 @@ class phpbb_db_tools
break;
case 'sqlite':
if ($inline && $this->return_statements)
{
return $column;
}
$sql = "SELECT sql
FROM sqlite_master
WHERE type = 'table'
@ -1639,7 +1848,7 @@ class phpbb_db_tools
/**
* Change column type (not name!)
*/
function sql_column_change($table_name, $column_name, $column_data)
function sql_column_change($table_name, $column_name, $column_data, $inline = false)
{
$column_data = $this->sql_prepare_column_data($table_name, $column_name, $column_data);
$statements = array();
@ -1648,7 +1857,15 @@ class phpbb_db_tools
{
case 'firebird':
// Change type...
$statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN "' . strtoupper($column_name) . '" TYPE ' . ' ' . $column_data['column_type_sql'];
if (!empty($column_data['column_type_sql_default']))
{
$statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN "' . strtoupper($column_name) . '" TYPE ' . ' ' . $column_data['column_type_sql_type'];
$statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN "' . strtoupper($column_name) . '" SET DEFAULT ' . ' ' . $column_data['column_type_sql_default'];
}
else
{
$statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN "' . strtoupper($column_name) . '" TYPE ' . ' ' . $column_data['column_type_sql'];
}
break;
case 'mssql':
@ -1729,6 +1946,11 @@ class phpbb_db_tools
case 'sqlite':
if ($inline && $this->return_statements)
{
return $column_name . ' ' . $column_data['column_type_sql'];
}
$sql = "SELECT sql
FROM sqlite_master
WHERE type = 'table'

View file

@ -235,8 +235,8 @@ class dbal
*/
function sql_like_expression($expression)
{
$expression = str_replace(array('_', '%'), array("\_", "\%"), $expression);
$expression = str_replace(array(chr(0) . "\_", chr(0) . "\%"), array('_', '%'), $expression);
$expression = utf8_str_replace(array('_', '%'), array("\_", "\%"), $expression);
$expression = utf8_str_replace(array(chr(0) . "\_", chr(0) . "\%"), array('_', '%'), $expression);
return $this->_sql_like_expression('LIKE \'' . $this->sql_escape($expression) . '\'');
}
@ -411,6 +411,24 @@ class dbal
}
}
/**
* Run binary AND operator on DB column.
* Results in sql statement: "{$column_name} & (1 << {$bit}) {$compare}"
*
* @param string $column_name The column name to use
* @param int $bit The value to use for the AND operator, will be converted to (1 << $bit). Is used by options, using the number schema... 0, 1, 2...29
* @param string $compare Any custom SQL code after the check (for example "= 0")
*/
function sql_bit_and($column_name, $bit, $compare = '')
{
if (method_exists($this, '_sql_bit_and'))
{
return $this->_sql_bit_and($column_name, $bit, $compare);
}
return $column_name . ' & ' . (1 << $bit) . (($compare) ? ' ' . $compare : '');
}
/**
* Run more than one insert statement.
*
@ -435,8 +453,7 @@ class dbal
// If by accident the sql array is only one-dimensional we build a normal insert statement
if (!is_array($_sql_ary))
{
$this->sql_query('INSERT INTO ' . $table . ' ' . $this->sql_build_array('INSERT', $sql_ary));
return true;
return $this->sql_query('INSERT INTO ' . $table . ' ' . $this->sql_build_array('INSERT', $sql_ary));
}
$values = array();
@ -447,7 +464,7 @@ class dbal
$ary[] = '(' . implode(', ', $values) . ')';
}
$this->sql_query('INSERT INTO ' . $table . ' ' . ' (' . implode(', ', array_keys($sql_ary[0])) . ') VALUES ' . implode(', ', $ary));
return $this->sql_query('INSERT INTO ' . $table . ' ' . ' (' . implode(', ', array_keys($sql_ary[0])) . ') VALUES ' . implode(', ', $ary));
}
else
{
@ -458,7 +475,12 @@ class dbal
return false;
}
$this->sql_query('INSERT INTO ' . $table . ' ' . $this->sql_build_array('INSERT', $ary));
$result = $this->sql_query('INSERT INTO ' . $table . ' ' . $this->sql_build_array('INSERT', $ary));
if (!$result)
{
return false;
}
}
}

View file

@ -20,7 +20,7 @@ include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
/**
* Firebird/Interbase Database Abstraction Layer
* Minimum Requirement is Firebird 2.0
* Minimum Requirement is Firebird 2.1
* @package dbal
*/
class dbal_firebird extends dbal
@ -72,7 +72,7 @@ class dbal_firebird extends dbal
return @ibase_server_info($this->service_handle, IBASE_SVC_SERVER_VERSION);
}
return ($raw) ? '2.0' : 'Firebird/Interbase';
return ($raw) ? '2.1' : 'Firebird/Interbase';
}
/**
@ -446,6 +446,11 @@ class dbal_firebird extends dbal
return $data;
}
function _sql_bit_and($column_name, $bit, $compare = '')
{
return 'BIN_AND(' . $column_name . ', ' . (1 << $bit) . ')' . (($compare) ? ' ' . $compare : '');
}
/**
* return sql error array
* @access private

View file

@ -568,6 +568,11 @@ class dbal_oracle extends dbal
return $data;
}
function _sql_bit_and($column_name, $bit, $compare = '')
{
return 'BITAND(' . $column_name . ', ' . (1 << $bit) . ')' . (($compare) ? ' ' . $compare : '');
}
/**
* return sql error array
* @access private

View file

@ -49,6 +49,8 @@ if (!defined('IN_PHPBB'))
*/
class diff_engine
{
var $skip_whitespace_changes = true;
function diff(&$from_lines, &$to_lines, $preserve_cr = true)
{
// Remove empty lines...
@ -176,6 +178,20 @@ class diff_engine
$add[] = $to_lines[$yi++];
}
// Here we are a bit naughty. Naughty Boy... Naughty Boy...
// We check if delete and add is filled and only consist of one item
if ($this->skip_whitespace_changes && sizeof($delete) == 1 && sizeof($add) == 1)
{
// Now we simply trim the string and see if the lines are identical
// If they are identical we do not need to take them into account for the merge (less conflicts in phpBB)
if (trim($delete[0]) === trim($add[0]))
{
// This line ensures the line found here is correctly copied later (remember: we naughty boys like loops)
$xi--; $yi--; $this->xchanged[$xi] = $this->ychanged[$yi] = false;
$delete = $add = array();
}
}
if ($delete && $add)
{
$edits[] = new diff_op_change($delete, $add);

View file

@ -536,7 +536,7 @@ class diff_renderer_raw extends diff_renderer
*/
function get_diff_content($diff)
{
return '<textarea style="height: 290px;" class="full">' . htmlspecialchars($this->render($diff)) . '</textarea>';
return '<textarea style="height: 290px;" rows="15" cols="76" class="full">' . htmlspecialchars($this->render($diff)) . '</textarea>';
}
function _block_header($xbeg, $xlen, $ybeg, $ylen)

View file

@ -71,12 +71,13 @@ function request_var($var_name, $default, $multibyte = false, $cookie = false)
$_REQUEST[$var_name] = isset($_POST[$var_name]) ? $_POST[$var_name] : $_GET[$var_name];
}
if (!isset($_REQUEST[$var_name]) || (is_array($_REQUEST[$var_name]) && !is_array($default)) || (is_array($default) && !is_array($_REQUEST[$var_name])))
$super_global = ($cookie) ? '_COOKIE' : '_REQUEST';
if (!isset($GLOBALS[$super_global][$var_name]) || is_array($GLOBALS[$super_global][$var_name]) != is_array($default))
{
return (is_array($default)) ? array() : $default;
}
$var = $_REQUEST[$var_name];
$var = $GLOBALS[$super_global][$var_name];
if (!is_array($default))
{
$type = gettype($default);
@ -174,7 +175,7 @@ function set_config_count($config_name, $increment, $is_dynamic = false)
switch ($db->sql_layer)
{
case 'firebird':
$sql_update = 'CAST(CAST(config_value as integer) + ' . (int) $increment . ' as CHAR)';
$sql_update = 'CAST(CAST(config_value as integer) + ' . (int) $increment . ' as VARCHAR(255))';
break;
case 'postgres':
@ -231,27 +232,82 @@ function unique_id($extra = 'c')
/**
* Return formatted string for filesizes
*
* @param int $value filesize in bytes
* @param bool $string_only true if language string should be returned
* @param array $allowed_units only allow these units (data array indexes)
*
* @return mixed data array if $string_only is false
* @author bantu
*/
function get_formatted_filesize($bytes, $add_size_lang = true)
function get_formatted_filesize($value, $string_only = true, $allowed_units = false)
{
global $user;
if ($bytes >= pow(2, 30))
$available_units = array(
'gb' => array(
'min' => 1073741824, // pow(2, 30)
'index' => 3,
'si_unit' => 'GB',
'iec_unit' => 'GIB',
),
'mb' => array(
'min' => 1048576, // pow(2, 20)
'index' => 2,
'si_unit' => 'MB',
'iec_unit' => 'MIB',
),
'kb' => array(
'min' => 1024, // pow(2, 10)
'index' => 1,
'si_unit' => 'KB',
'iec_unit' => 'KIB',
),
'b' => array(
'min' => 0,
'index' => 0,
'si_unit' => 'BYTES', // Language index
'iec_unit' => 'BYTES', // Language index
),
);
foreach ($available_units as $si_identifier => $unit_info)
{
return ($add_size_lang) ? round($bytes / 1024 / 1024 / 1024, 2) . ' ' . $user->lang['GIB'] : round($bytes / 1024 / 1024 / 1024, 2);
if (!empty($allowed_units) && $si_identifier != 'b' && !in_array($si_identifier, $allowed_units))
{
continue;
}
if ($value >= $unit_info['min'])
{
$unit_info['si_identifier'] = $si_identifier;
break;
}
}
unset($available_units);
for ($i = 0; $i < $unit_info['index']; $i++)
{
$value /= 1024;
}
$value = round($value, 2);
// Lookup units in language dictionary
$unit_info['si_unit'] = (isset($user->lang[$unit_info['si_unit']])) ? $user->lang[$unit_info['si_unit']] : $unit_info['si_unit'];
$unit_info['iec_unit'] = (isset($user->lang[$unit_info['iec_unit']])) ? $user->lang[$unit_info['iec_unit']] : $unit_info['iec_unit'];
// Default to IEC
$unit_info['unit'] = $unit_info['iec_unit'];
if (!$string_only)
{
$unit_info['value'] = $value;
return $unit_info;
}
if ($bytes >= pow(2, 20))
{
return ($add_size_lang) ? round($bytes / 1024 / 1024, 2) . ' ' . $user->lang['MIB'] : round($bytes / 1024 / 1024, 2);
}
if ($bytes >= pow(2, 10))
{
return ($add_size_lang) ? round($bytes / 1024, 2) . ' ' . $user->lang['KIB'] : round($bytes / 1024, 2);
}
return ($add_size_lang) ? ($bytes) . ' ' . $user->lang['BYTES'] : ($bytes);
return $value . ' ' . $unit_info['unit'];
}
/**
@ -495,6 +551,18 @@ function _hash_crypt_private($password, $setting, &$itoa64)
return $output;
}
/**
* Hashes an email address to a big integer
*
* @param string $email Email address
*
* @return string Big Integer
*/
function phpbb_email_hash($email)
{
return crc32(strtolower($email)) . strlen($email);
}
/**
* Global function for chmodding directories and files for internal use
*
@ -669,6 +737,67 @@ function phpbb_chmod($filename, $perms = CHMOD_READ)
return $result;
}
/**
* Test if a file/directory is writable
*
* This function calls the native is_writable() when not running under
* Windows and it is not disabled.
*
* @param string $file Path to perform write test on
* @return bool True when the path is writable, otherwise false.
*/
function phpbb_is_writable($file)
{
if (strtolower(substr(PHP_OS, 0, 3)) === 'win' || !function_exists('is_writable'))
{
if (file_exists($file))
{
// Canonicalise path to absolute path
$file = phpbb_realpath($file);
if (is_dir($file))
{
// Test directory by creating a file inside the directory
$result = @tempnam($file, 'i_w');
if (is_string($result) && file_exists($result))
{
unlink($result);
// Ensure the file is actually in the directory (returned realpathed)
return (strpos($result, $file) === 0) ? true : false;
}
}
else
{
$handle = @fopen($file, 'r+');
if (is_resource($handle))
{
fclose($handle);
return true;
}
}
}
else
{
// file does not exist test if we can write to the directory
$dir = dirname($file);
if (file_exists($dir) && is_dir($dir) && phpbb_is_writable($dir))
{
return true;
}
}
return false;
}
else
{
return is_writable($file);
}
}
// Compatibility functions
if (!function_exists('array_combine'))
@ -1047,7 +1176,7 @@ function tz_select($default = '', $truncate = false)
if (is_numeric($offset))
{
$selected = ($offset == $default) ? ' selected="selected"' : '';
$tz_select .= '<option title="'.$zone.'" value="' . $offset . '"' . $selected . '>' . $zone_trunc . '</option>';
$tz_select .= '<option title="' . $zone . '" value="' . $offset . '"' . $selected . '>' . $zone_trunc . '</option>';
}
}
@ -1110,7 +1239,7 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $
}
// Add 0 to forums array to mark global announcements correctly
$forum_id[] = 0;
// $forum_id[] = 0;
if ($config['load_db_lastread'] && $user->data['is_registered'])
{
@ -1527,6 +1656,135 @@ function get_complete_topic_tracking($forum_id, $topic_ids, $global_announce_lis
return $last_read;
}
/**
* Get list of unread topics
*
* @param int $user_id User ID (or false for current user)
* @param string $sql_extra Extra WHERE SQL statement
* @param string $sql_sort ORDER BY SQL sorting statement
* @param string $sql_limit Limits the size of unread topics list, 0 for unlimited query
*
* @return array[int][int] Topic ids as keys, mark_time of topic as value
*/
function get_unread_topics($user_id = false, $sql_extra = '', $sql_sort = '', $sql_limit = 1001)
{
global $config, $db, $user;
$user_id = ($user_id === false) ? (int) $user->data['user_id'] : (int) $user_id;
// Data array we're going to return
$unread_topics = array();
if (empty($sql_sort))
{
$sql_sort = 'ORDER BY t.topic_last_post_time DESC';
}
if ($config['load_db_lastread'] && $user->data['is_registered'])
{
// Get list of the unread topics
$last_mark = $user->data['user_lastmark'];
$sql_array = array(
'SELECT' => 't.topic_id, t.topic_last_post_time, tt.mark_time as topic_mark_time, ft.mark_time as forum_mark_time',
'FROM' => array(TOPICS_TABLE => 't'),
'LEFT_JOIN' => array(
array(
'FROM' => array(TOPICS_TRACK_TABLE => 'tt'),
'ON' => "tt.user_id = $user_id AND t.topic_id = tt.topic_id AND tt.mark_time > $last_mark",
),
array(
'FROM' => array(FORUMS_TRACK_TABLE => 'ft'),
'ON' => "ft.user_id = $user_id AND t.forum_id = ft.forum_id AND ft.mark_time > $last_mark",
),
),
'WHERE' => "
(
(tt.mark_time IS NOT NULL AND t.topic_last_post_time > tt.mark_time) OR
(tt.mark_time IS NULL AND ft.mark_time IS NOT NULL AND t.topic_last_post_time > ft.mark_time) OR
(
((tt.mark_time IS NULL AND ft.mark_time IS NULL) OR (tt.mark_time < $last_mark AND ft.mark_time < $last_mark))
AND t.topic_last_post_time > $last_mark
)
)
$sql_extra
$sql_sort",
);
$sql = $db->sql_build_query('SELECT', $sql_array);
$result = $db->sql_query_limit($sql, $sql_limit);
while ($row = $db->sql_fetchrow($result))
{
$topic_id = (int) $row['topic_id'];
$unread_topics[$topic_id] = ($row['topic_mark_time']) ? (int) $row['topic_mark_time'] : (($row['forum_mark_time']) ? (int) $row['forum_mark_time'] : $last_mark);
}
$db->sql_freeresult($result);
}
else if ($config['load_anon_lastread'] || $user->data['is_registered'])
{
global $tracking_topics;
if (empty($tracking_topics))
{
$tracking_topics = request_var($config['cookie_name'] . '_track', '', false, true);
$tracking_topics = ($tracking_topics) ? tracking_unserialize($tracking_topics) : array();
}
if (!$user->data['is_registered'])
{
$user_lastmark = (isset($tracking_topics['l'])) ? base_convert($tracking_topics['l'], 36, 10) + $config['board_startdate'] : 0;
}
else
{
$user_lastmark = (int) $user->data['user_lastmark'];
}
$sql = 'SELECT t.topic_id, t.forum_id, t.topic_last_post_time
FROM ' . TOPICS_TABLE . ' t
WHERE t.topic_last_post_time > ' . $user_lastmark . "
$sql_extra
$sql_sort";
$result = $db->sql_query_limit($sql, $sql_limit);
while ($row = $db->sql_fetchrow($result))
{
$forum_id = (int) $row['forum_id'];
$topic_id = (int) $row['topic_id'];
$topic_id36 = base_convert($topic_id, 10, 36);
if (isset($tracking_topics['t'][$topic_id36]))
{
$last_read = base_convert($tracking_topics['t'][$topic_id36], 36, 10) + $config['board_startdate'];
if ($row['topic_last_post_time'] > $last_read)
{
$unread_topics[$topic_id] = $last_read;
}
}
else if (isset($tracking_topics['f'][$forum_id]))
{
$mark_time = base_convert($tracking_topics['f'][$forum_id], 36, 10) + $config['board_startdate'];
if ($row['topic_last_post_time'] > $mark_time)
{
$unread_topics[$topic_id] = $mark_time;
}
}
else
{
$unread_topics[$topic_id] = $user_lastmark;
}
}
$db->sql_freeresult($result);
}
return $unread_topics;
}
/**
* Check for read forums and update topic tracking info accordingly
*
@ -1777,7 +2035,7 @@ function generate_pagination($base_url, $num_items, $per_page, $start_item, $add
}
$on_page = floor($start_item / $per_page) + 1;
$url_delim = (strpos($base_url, '?') === false) ? '?' : '&amp;';
$url_delim = (strpos($base_url, '?') === false) ? '?' : ((strpos($base_url, '?') === strlen($base_url) - 1) ? '' : '&amp;');
$page_string = ($on_page == 1) ? '<strong>1</strong>' : '<a href="' . $base_url . '">1</a>';
@ -2056,7 +2314,7 @@ function redirect($url, $return = false, $disable_cd_check = false)
$url = str_replace('&amp;', '&', $url);
// Determine which type of redirect we need to handle...
$url_parts = parse_url($url);
$url_parts = @parse_url($url);
if ($url_parts === false)
{
@ -2200,17 +2458,12 @@ function reapply_sid($url)
}
// Remove previously added sid
if (strpos($url, '?sid=') !== false)
if (strpos($url, 'sid=') !== false)
{
$url = preg_replace('/(\?)sid=[a-z0-9]+(&amp;|&)?/', '\1', $url);
}
else if (strpos($url, '&sid=') !== false)
{
$url = preg_replace('/&sid=[a-z0-9]+(&)?/', '\1', $url);
}
else if (strpos($url, '&amp;sid=') !== false)
{
$url = preg_replace('/&amp;sid=[a-z0-9]+(&amp;)?/', '\1', $url);
// All kind of links
$url = preg_replace('/(\?)?(&amp;|&)?sid=[a-z0-9]+/', '', $url);
// if the sid was the first param, make the old second as first ones
$url = preg_replace("/$phpEx(&amp;|&)+?/", "$phpEx?", $url);
}
return append_sid($url);
@ -2274,6 +2527,18 @@ function build_url($strip_vars = false)
$redirect .= ($query) ? '?' . $query : '';
}
// We need to be cautious here.
// On some situations, the redirect path is an absolute URL, sometimes a relative path
// For a relative path, let's prefix it with $phpbb_root_path to point to the correct location,
// else we use the URL directly.
$url_parts = @parse_url($redirect);
// URL
if ($url_parts !== false && !empty($url_parts['scheme']) && !empty($url_parts['host']))
{
return str_replace('&', '&amp;', $redirect);
}
return $phpbb_root_path . str_replace('&', '&amp;', $redirect);
}
@ -2435,7 +2700,7 @@ function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_bo
if ($check && $confirm)
{
$user_id = request_var('user_id', 0);
$user_id = request_var('confirm_uid', 0);
$session_id = request_var('sess', '');
$confirm_key = request_var('confirm_key', '');
@ -2457,10 +2722,10 @@ function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_bo
}
$s_hidden_fields = build_hidden_fields(array(
'user_id' => $user->data['user_id'],
'sess' => $user->session_id,
'sid' => $user->session_id)
);
'confirm_uid' => $user->data['user_id'],
'sess' => $user->session_id,
'sid' => $user->session_id,
));
// generate activation key
$confirm_key = gen_rand_string(10);
@ -2471,7 +2736,7 @@ function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_bo
}
else
{
page_header((!isset($user->lang[$title])) ? $user->lang['CONFIRM'] : $user->lang[$title]);
page_header(((!isset($user->lang[$title])) ? $user->lang['CONFIRM'] : $user->lang[$title]), false);
}
$template->set_filenames(array(
@ -2520,6 +2785,11 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa
{
global $db, $user, $template, $auth, $phpEx, $phpbb_root_path, $config;
if (!class_exists('phpbb_captcha_factory'))
{
include($phpbb_root_path . 'includes/captcha/captcha_factory.' . $phpEx);
}
$err = '';
// Make sure user->setup() has been called
@ -2630,38 +2900,15 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa
{
case LOGIN_ERROR_ATTEMPTS:
// Show confirm image
$sql = 'DELETE FROM ' . CONFIRM_TABLE . "
WHERE session_id = '" . $db->sql_escape($user->session_id) . "'
AND confirm_type = " . CONFIRM_LOGIN;
$db->sql_query($sql);
// Generate code
$code = gen_rand_string(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS));
$confirm_id = md5(unique_id($user->ip));
$seed = hexdec(substr(unique_id(), 4, 10));
// compute $seed % 0x7fffffff
$seed -= 0x7fffffff * floor($seed / 0x7fffffff);
$sql = 'INSERT INTO ' . CONFIRM_TABLE . ' ' . $db->sql_build_array('INSERT', array(
'confirm_id' => (string) $confirm_id,
'session_id' => (string) $user->session_id,
'confirm_type' => (int) CONFIRM_LOGIN,
'code' => (string) $code,
'seed' => (int) $seed)
);
$db->sql_query($sql);
$captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']);
$captcha->init(CONFIRM_LOGIN);
// $captcha->reset();
$template->assign_vars(array(
'S_CONFIRM_CODE' => true,
'CONFIRM_ID' => $confirm_id,
'CONFIRM_IMAGE' => '<img src="' . append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=confirm&amp;id=' . $confirm_id . '&amp;type=' . CONFIRM_LOGIN) . '" alt="" title="" />',
'L_LOGIN_CONFIRM_EXPLAIN' => sprintf($user->lang['LOGIN_CONFIRM_EXPLAIN'], '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">', '</a>'),
'CAPTCHA_TEMPLATE' => $captcha->get_template(),
));
$err = $user->lang[$result['error_msg']];
break;
case LOGIN_ERROR_PASSWORD_CONVERT:
@ -2688,28 +2935,18 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa
}
}
if (!$redirect)
{
// We just use what the session code determined...
// If we are not within the admin directory we use the page dir...
$redirect = '';
if (!$admin)
{
$redirect .= ($user->page['page_dir']) ? $user->page['page_dir'] . '/' : '';
}
$redirect .= $user->page['page_name'] . (($user->page['query_string']) ? '?' . htmlspecialchars($user->page['query_string']) : '');
}
// Assign credential for username/password pair
$credential = ($admin) ? md5(unique_id()) : false;
$s_hidden_fields = array(
'redirect' => $redirect,
'sid' => $user->session_id,
);
if ($redirect)
{
$s_hidden_fields['redirect'] = $redirect;
}
if ($admin)
{
$s_hidden_fields['credential'] = $credential;
@ -2722,12 +2959,11 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa
'LOGIN_EXPLAIN' => $l_explain,
'U_SEND_PASSWORD' => ($config['email_enable']) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=sendpassword') : '',
'U_RESEND_ACTIVATION' => ($config['require_activation'] != USER_ACTIVATION_NONE && $config['email_enable']) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=resend_act') : '',
'U_RESEND_ACTIVATION' => ($config['require_activation'] == USER_ACTIVATION_SELF && $config['email_enable']) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=resend_act') : '',
'U_TERMS_USE' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=terms'),
'U_PRIVACY' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=privacy'),
'S_DISPLAY_FULL_LOGIN' => ($s_display) ? true : false,
'S_LOGIN_ACTION' => (!$admin) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=login') : append_sid("index.$phpEx", false, true, $user->session_id), // Needs to stay index.$phpEx because we are within the admin directory
'S_HIDDEN_FIELDS' => $s_hidden_fields,
'S_ADMIN_AUTH' => $admin,
@ -2811,7 +3047,7 @@ function login_forum_box($forum_data)
$template->assign_var('LOGIN_ERROR', $user->lang['WRONG_PASSWORD']);
}
page_header($user->lang['LOGIN']);
page_header($user->lang['LOGIN'], false);
$template->assign_vars(array(
'S_HIDDEN_FIELDS' => build_hidden_fields(array('f' => $forum_data['forum_id'])))
@ -2933,6 +3169,14 @@ function add_log()
{
global $db, $user;
// In phpBB 3.1.x i want to have logging in a class to be able to control it
// For now, we need a quite hakish approach to circumvent logging for some actions
// @todo implement cleanly
if (!empty($GLOBALS['skip_add_log']))
{
return false;
}
$args = func_get_args();
$mode = array_shift($args);
@ -3200,7 +3444,7 @@ function msg_handler($errno, $msg_text, $errfile, $errline)
global $phpEx, $phpbb_root_path, $msg_title, $msg_long_text;
// Do not display notices if we suppress them via @
if (error_reporting() == 0)
if (error_reporting() == 0 && $errno != E_USER_ERROR && $errno != E_USER_WARNING && $errno != E_USER_NOTICE)
{
return;
}
@ -3211,6 +3455,11 @@ function msg_handler($errno, $msg_text, $errfile, $errline)
$msg_text = $msg_long_text;
}
if (!defined('E_DEPRECATED'))
{
define('E_DEPRECATED', 8192);
}
switch ($errno)
{
case E_NOTICE:
@ -3243,8 +3492,13 @@ function msg_handler($errno, $msg_text, $errfile, $errline)
// remove complete path to installation, with the risk of changing backslashes meant to be there
$errfile = str_replace(array(phpbb_realpath($phpbb_root_path), '\\'), array('', '/'), $errfile);
$msg_text = str_replace(array(phpbb_realpath($phpbb_root_path), '\\'), array('', '/'), $msg_text);
echo '<b>[phpBB Debug] PHP Notice</b>: in file <b>' . $errfile . '</b> on line <b>' . $errline . '</b>: <b>' . $msg_text . '</b><br />' . "\n";
// we are writing an image - the user won't see the debug, so let's place it in the log
if (defined('IMAGE_OUTPUT') || defined('IN_CRON'))
{
add_log('critical', 'LOG_IMAGE_GENERATION_ERROR', $errfile, $errline, $msg_text);
}
// echo '<br /><br />BACKTRACE<br />' . get_backtrace() . '<br />' . "\n";
}
@ -3279,6 +3533,17 @@ function msg_handler($errno, $msg_text, $errfile, $errline)
}
}
if (defined('DEBUG') || defined('IN_CRON') || defined('IMAGE_OUTPUT'))
{
// let's avoid loops
$db->sql_return_on_error(true);
add_log('critical', 'LOG_GENERAL_ERROR', $msg_title, $msg_text);
$db->sql_return_on_error(false);
}
// Do not send 200 OK, but service unavailable on errors
header('HTTP/1.1 503 Service Unavailable');
garbage_collection();
// Try to not call the adm page data...
@ -3357,7 +3622,7 @@ function msg_handler($errno, $msg_text, $errfile, $errline)
}
else
{
page_header($msg_title);
page_header($msg_title, false);
}
}
@ -3386,6 +3651,11 @@ function msg_handler($errno, $msg_text, $errfile, $errline)
exit_handler();
break;
// PHP4 compatibility
case E_DEPRECATED:
return true;
break;
}
// If we notice an error not handled here we pass this back to PHP by returning false
@ -3395,16 +3665,17 @@ function msg_handler($errno, $msg_text, $errfile, $errline)
/**
* Queries the session table to get information about online guests
* @param int $forum_id Limits the search to the forum with this id
* @param int $item_id Limits the search to the item with this id
* @param string $item The name of the item which is stored in the session table as session_{$item}_id
* @return int The number of active distinct guest sessions
*/
function obtain_guest_count($forum_id = 0)
function obtain_guest_count($item_id = 0, $item = 'forum')
{
global $db, $config;
if ($forum_id)
if ($item_id)
{
$reading_sql = ' AND s.session_forum_id = ' . (int) $forum_id;
$reading_sql = ' AND s.session_' . $item . '_id = ' . (int) $item_id;
}
else
{
@ -3442,17 +3713,18 @@ function obtain_guest_count($forum_id = 0)
/**
* Queries the session table to get information about online users
* @param int $forum_id Limits the search to the forum with this id
* @param int $item_id Limits the search to the item with this id
* @param string $item The name of the item which is stored in the session table as session_{$item}_id
* @return array An array containing the ids of online, hidden and visible users, as well as statistical info
*/
function obtain_users_online($forum_id = 0)
function obtain_users_online($item_id = 0, $item = 'forum')
{
global $db, $config, $user;
$reading_sql = '';
if ($forum_id !== 0)
if ($item_id !== 0)
{
$reading_sql = ' AND s.session_forum_id = ' . (int) $forum_id;
$reading_sql = ' AND s.session_' . $item . '_id = ' . (int) $item_id;
}
$online_users = array(
@ -3466,7 +3738,7 @@ function obtain_users_online($forum_id = 0)
if ($config['load_online_guests'])
{
$online_users['guests_online'] = obtain_guest_count($forum_id);
$online_users['guests_online'] = obtain_guest_count($item_id, $item);
}
// a little discrete magic to cache this for 30 seconds
@ -3505,14 +3777,17 @@ function obtain_users_online($forum_id = 0)
/**
* Uses the result of obtain_users_online to generate a localized, readable representation.
* @param mixed $online_users result of obtain_users_online - array with user_id lists for total, hidden and visible users, and statistics
* @param int $forum_id Indicate that the data is limited to one forum and not global.
* @param int $item_id Indicate that the data is limited to one item and not global
* @param string $item The name of the item which is stored in the session table as session_{$item}_id
* @return array An array containing the string for output to the template
*/
function obtain_users_online_string($online_users, $forum_id = 0)
function obtain_users_online_string($online_users, $item_id = 0, $item = 'forum')
{
global $config, $db, $user, $auth;
$user_online_link = $online_userlist = '';
// Need caps version of $item for language-strings
$item_caps = strtoupper($item);
if (sizeof($online_users['online_users']))
{
@ -3547,18 +3822,18 @@ function obtain_users_online_string($online_users, $forum_id = 0)
$online_userlist = $user->lang['NO_ONLINE_USERS'];
}
if ($forum_id === 0)
if ($item_id === 0)
{
$online_userlist = $user->lang['REGISTERED_USERS'] . ' ' . $online_userlist;
}
else if ($config['load_online_guests'])
{
$l_online = ($online_users['guests_online'] === 1) ? $user->lang['BROWSING_FORUM_GUEST'] : $user->lang['BROWSING_FORUM_GUESTS'];
$l_online = ($online_users['guests_online'] === 1) ? $user->lang['BROWSING_' . $item_caps . '_GUEST'] : $user->lang['BROWSING_' . $item_caps . '_GUESTS'];
$online_userlist = sprintf($l_online, $online_userlist, $online_users['guests_online']);
}
else
{
$online_userlist = sprintf($user->lang['BROWSING_FORUM'], $online_userlist);
$online_userlist = sprintf($user->lang['BROWSING_' . $item_caps], $online_userlist);
}
// Build online listing
$vars_online = array(
@ -3612,11 +3887,45 @@ function obtain_users_online_string($online_users, $forum_id = 0)
);
}
/**
* Get option bitfield from custom data
*
* @param int $bit The bit/value to get
* @param int $data Current bitfield to check
* @return bool Returns true if value of constant is set in bitfield, else false
*/
function phpbb_optionget($bit, $data)
{
return ($data & 1 << (int) $bit) ? true : false;
}
/**
* Set option bitfield
*
* @param int $bit The bit/value to set/unset
* @param bool $set True if option should be set, false if option should be unset.
* @param int $data Current bitfield to change
*
* @return int The new bitfield
*/
function phpbb_optionset($bit, $set, $data)
{
if ($set && !($data & 1 << $bit))
{
$data += 1 << $bit;
}
else if (!$set && ($data & 1 << $bit))
{
$data -= 1 << $bit;
}
return $data;
}
/**
* Generate page header
*/
function page_header($page_title = '', $display_online_list = true)
function page_header($page_title = '', $display_online_list = true, $item_id = 0, $item = 'forum')
{
global $db, $config, $template, $SID, $_SID, $user, $auth, $phpEx, $phpbb_root_path;
@ -3656,10 +3965,14 @@ function page_header($page_title = '', $display_online_list = true)
if ($config['load_online'] && $config['load_online_time'] && $display_online_list)
{
$f = request_var('f', 0);
$f = max($f, 0);
$online_users = obtain_users_online($f);
$user_online_strings = obtain_users_online_string($online_users, $f);
/**
* Load online data:
* For obtaining another session column use $item and $item_id in the function-parameter, whereby the column is session_{$item}_id.
*/
$item_id = max($item_id, 0);
$online_users = obtain_users_online($item_id, $item);
$user_online_strings = obtain_users_online_string($online_users, $item_id, $item);
$l_online_users = $user_online_strings['l_online_users'];
$online_userlist = $user_online_strings['online_userlist'];
@ -3731,6 +4044,26 @@ function page_header($page_title = '', $display_online_list = true)
$user_lang = substr($user_lang, 0, strpos($user_lang, '-x-'));
}
$forum_id = request_var('f', 0);
$topic_id = request_var('t', 0);
$s_feed_news = false;
// Get option for news
if ($config['feed_enable'])
{
$sql = 'SELECT forum_id
FROM ' . FORUMS_TABLE . '
WHERE ' . $db->sql_bit_and('forum_options', FORUM_OPTION_FEED_NEWS, '<> 0');
$result = $db->sql_query_limit($sql, 1, 0, 600);
$s_feed_news = (int) $db->sql_fetchfield('forum_id');
$db->sql_freeresult($result);
}
// Determine board url - we may need it later
$board_url = generate_board_url() . '/';
$web_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? $board_url : $phpbb_root_path;
// The following assigns all _common_ variables that may be used at any point in a template.
$template->assign_vars(array(
'SITENAME' => $config['sitename'],
@ -3748,11 +4081,13 @@ function page_header($page_title = '', $display_online_list = true)
'S_USER_NEW_PRIVMSG' => $user->data['user_new_privmsg'],
'S_USER_UNREAD_PRIVMSG' => $user->data['user_unread_privmsg'],
'S_USER_NEW' => $user->data['user_new'],
'SID' => $SID,
'_SID' => $_SID,
'SESSION_ID' => $user->session_id,
'ROOT_PATH' => $phpbb_root_path,
'BOARD_URL' => $board_url,
'L_LOGIN_LOGOUT' => $l_login_logout,
'L_INDEX' => $user->lang['FORUM_INDEX'],
@ -3774,10 +4109,14 @@ function page_header($page_title = '', $display_online_list = true)
'U_SEARCH_SELF' => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=egosearch'),
'U_SEARCH_NEW' => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=newposts'),
'U_SEARCH_UNANSWERED' => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=unanswered'),
'U_SEARCH_UNREAD' => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=unreadposts'),
'U_SEARCH_ACTIVE_TOPICS'=> append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=active_topics'),
'U_DELETE_COOKIES' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=delete_cookies'),
'U_TEAM' => ($user->data['user_id'] != ANONYMOUS && !$auth->acl_get('u_viewprofile')) ? '' : append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=leaders'),
'U_TERMS_USE' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=terms'),
'U_PRIVACY' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=privacy'),
'U_RESTORE_PERMISSIONS' => ($user->data['user_perm_from'] && $auth->acl_get('a_switchperm')) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=restore_perm') : '',
'U_FEED' => generate_board_url() . "/feed.$phpEx",
'S_USER_LOGGED_IN' => ($user->data['user_id'] != ANONYMOUS) ? true : false,
'S_AUTOLOGIN_ENABLED' => ($config['allow_autologin']) ? true : false,
@ -3799,22 +4138,44 @@ function page_header($page_title = '', $display_online_list = true)
'S_DISPLAY_MEMBERLIST' => (isset($auth)) ? $auth->acl_get('u_viewprofile') : 0,
'S_NEW_PM' => ($s_privmsg_new) ? 1 : 0,
'S_REGISTER_ENABLED' => ($config['require_activation'] != USER_ACTIVATION_DISABLE) ? true : false,
'S_FORUM_ID' => $forum_id,
'S_TOPIC_ID' => $topic_id,
'T_THEME_PATH' => "{$phpbb_root_path}styles/" . $user->theme['theme_path'] . '/theme',
'T_TEMPLATE_PATH' => "{$phpbb_root_path}styles/" . $user->theme['template_path'] . '/template',
'T_SUPER_TEMPLATE_PATH' => (isset($user->theme['template_inherit_path']) && $user->theme['template_inherit_path']) ? "{$phpbb_root_path}styles/" . $user->theme['template_inherit_path'] . '/template' : "{$phpbb_root_path}styles/" . $user->theme['template_path'] . '/template',
'T_IMAGESET_PATH' => "{$phpbb_root_path}styles/" . $user->theme['imageset_path'] . '/imageset',
'T_IMAGESET_LANG_PATH' => "{$phpbb_root_path}styles/" . $user->theme['imageset_path'] . '/imageset/' . $user->data['user_lang'],
'T_IMAGES_PATH' => "{$phpbb_root_path}images/",
'T_SMILIES_PATH' => "{$phpbb_root_path}{$config['smilies_path']}/",
'T_AVATAR_PATH' => "{$phpbb_root_path}{$config['avatar_path']}/",
'T_AVATAR_GALLERY_PATH' => "{$phpbb_root_path}{$config['avatar_gallery_path']}/",
'T_ICONS_PATH' => "{$phpbb_root_path}{$config['icons_path']}/",
'T_RANKS_PATH' => "{$phpbb_root_path}{$config['ranks_path']}/",
'T_UPLOAD_PATH' => "{$phpbb_root_path}{$config['upload_path']}/",
'T_STYLESHEET_LINK' => (!$user->theme['theme_storedb']) ? "{$phpbb_root_path}styles/" . $user->theme['theme_path'] . '/theme/stylesheet.css' : "{$phpbb_root_path}style.$phpEx?sid=$user->session_id&amp;id=" . $user->theme['style_id'] . '&amp;lang=' . $user->data['user_lang'],
'S_LOGIN_ACTION' => (!defined('ADMIN_START')) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=login') . '&amp;redirect=' . urlencode(str_replace('&amp;', '&', build_url())) : append_sid("index.$phpEx", false, true, $user->session_id) . '&amp;redirect=' . urlencode(str_replace('&amp;', '&', build_url())),
'S_ENABLE_FEEDS' => ($config['feed_enable']) ? true : false,
'S_ENABLE_FEEDS_FORUMS' => ($config['feed_overall_forums']) ? true : false,
'S_ENABLE_FEEDS_TOPICS' => ($config['feed_overall_topics']) ? true : false,
'S_ENABLE_FEEDS_NEWS' => ($s_feed_news) ? true : false,
'T_THEME_PATH' => "{$web_path}styles/" . $user->theme['theme_path'] . '/theme',
'T_TEMPLATE_PATH' => "{$web_path}styles/" . $user->theme['template_path'] . '/template',
'T_SUPER_TEMPLATE_PATH' => (isset($user->theme['template_inherit_path']) && $user->theme['template_inherit_path']) ? "{$web_path}styles/" . $user->theme['template_inherit_path'] . '/template' : "{$web_path}styles/" . $user->theme['template_path'] . '/template',
'T_IMAGESET_PATH' => "{$web_path}styles/" . $user->theme['imageset_path'] . '/imageset',
'T_IMAGESET_LANG_PATH' => "{$web_path}styles/" . $user->theme['imageset_path'] . '/imageset/' . $user->data['user_lang'],
'T_IMAGES_PATH' => "{$web_path}images/",
'T_SMILIES_PATH' => "{$web_path}{$config['smilies_path']}/",
'T_AVATAR_PATH' => "{$web_path}{$config['avatar_path']}/",
'T_AVATAR_GALLERY_PATH' => "{$web_path}{$config['avatar_gallery_path']}/",
'T_ICONS_PATH' => "{$web_path}{$config['icons_path']}/",
'T_RANKS_PATH' => "{$web_path}{$config['ranks_path']}/",
'T_UPLOAD_PATH' => "{$web_path}{$config['upload_path']}/",
'T_STYLESHEET_LINK' => (!$user->theme['theme_storedb']) ? "{$web_path}styles/" . $user->theme['theme_path'] . '/theme/stylesheet.css' : append_sid("{$phpbb_root_path}style.$phpEx", 'id=' . $user->theme['style_id'] . '&amp;lang=' . $user->data['user_lang']),
'T_STYLESHEET_NAME' => $user->theme['theme_name'],
'T_THEME_NAME' => $user->theme['theme_path'],
'T_TEMPLATE_NAME' => $user->theme['template_path'],
'T_SUPER_TEMPLATE_NAME' => (isset($user->theme['template_inherit_path']) && $user->theme['template_inherit_path']) ? $user->theme['template_inherit_path'] : $user->theme['template_path'],
'T_IMAGESET_NAME' => $user->theme['imageset_path'],
'T_IMAGESET_LANG_NAME' => $user->data['user_lang'],
'T_IMAGES' => 'images',
'T_SMILIES' => $config['smilies_path'],
'T_AVATAR' => $config['avatar_path'],
'T_AVATAR_GALLERY' => $config['avatar_gallery_path'],
'T_ICONS' => $config['icons_path'],
'T_RANKS' => $config['ranks_path'],
'T_UPLOAD' => $config['upload_path'],
'SITE_LOGO_IMG' => $user->img('site_logo'),
'A_COOKIE_SETTINGS' => addslashes('; path=' . $config['cookie_path'] . ((!$config['cookie_domain'] || $config['cookie_domain'] == 'localhost' || $config['cookie_domain'] == '127.0.0.1') ? '' : '; domain=' . $config['cookie_domain']) . ((!$config['cookie_secure']) ? '' : '; secure')),
@ -3848,7 +4209,7 @@ function page_footer($run_cron = true)
$db->sql_report('display');
}
$debug_output = sprintf('Time : %.3fs | ' . $db->sql_num_queries() . ' Queries | GZIP : ' . (($config['gzip_compress']) ? 'On' : 'Off') . (($user->load) ? ' | Load : ' . $user->load : ''), $totaltime);
$debug_output = sprintf('Time : %.3fs | ' . $db->sql_num_queries() . ' Queries | GZIP : ' . (($config['gzip_compress'] && @extension_loaded('zlib')) ? 'On' : 'Off') . (($user->load) ? ' | Load : ' . $user->load : ''), $totaltime);
if ($auth->acl_get('a_') && defined('DEBUG_EXTRA'))
{
@ -3876,35 +4237,55 @@ function page_footer($run_cron = true)
);
// Call cron-type script
$call_cron = false;
if (!defined('IN_CRON') && $run_cron && !$config['board_disable'])
{
$call_cron = true;
$time_now = (!empty($user->time_now) && is_int($user->time_now)) ? $user->time_now : time();
// Any old lock present?
if (!empty($config['cron_lock']))
{
$cron_time = explode(' ', $config['cron_lock']);
// If 1 hour lock is present we do not call cron.php
if ($cron_time[0] + 3600 >= $time_now)
{
$call_cron = false;
}
}
}
// Call cron job?
if ($call_cron)
{
$cron_type = '';
if (time() - $config['queue_interval'] > $config['last_queue_run'] && !defined('IN_ADMIN') && file_exists($phpbb_root_path . 'cache/queue.' . $phpEx))
if ($time_now - $config['queue_interval'] > $config['last_queue_run'] && !defined('IN_ADMIN') && file_exists($phpbb_root_path . 'cache/queue.' . $phpEx))
{
// Process email queue
$cron_type = 'queue';
}
else if (method_exists($cache, 'tidy') && time() - $config['cache_gc'] > $config['cache_last_gc'])
else if (method_exists($cache, 'tidy') && $time_now - $config['cache_gc'] > $config['cache_last_gc'])
{
// Tidy the cache
$cron_type = 'tidy_cache';
}
else if (time() - $config['warnings_gc'] > $config['warnings_last_gc'])
else if ($config['warnings_expire_days'] && ($time_now - $config['warnings_gc'] > $config['warnings_last_gc']))
{
$cron_type = 'tidy_warnings';
}
else if (time() - $config['database_gc'] > $config['database_last_gc'])
else if ($time_now - $config['database_gc'] > $config['database_last_gc'])
{
// Tidy the database
$cron_type = 'tidy_database';
}
else if (time() - $config['search_gc'] > $config['search_last_gc'])
else if ($time_now - $config['search_gc'] > $config['search_last_gc'])
{
// Tidy the search
$cron_type = 'tidy_search';
}
else if (time() - $config['session_gc'] > $config['session_last_gc'])
else if ($time_now - $config['session_gc'] > $config['session_last_gc'])
{
$cron_type = 'tidy_sessions';
}

View file

@ -17,95 +17,47 @@ if (!defined('IN_PHPBB'))
}
/**
* Recalculate Binary Tree
function recalc_btree($sql_id, $sql_table, $module_class = '')
* Recalculate Nested Sets
*
* @param int $new_id first left_id (should start with 1)
* @param string $pkey primary key-column (containing the id for the parent_id of the children)
* @param string $table constant or fullname of the table
* @param int $parent_id parent_id of the current set (default = 0)
* @param array $where contains strings to compare closer on the where statement (additional)
*
* @author EXreaction
*/
function recalc_nested_sets(&$new_id, $pkey, $table, $parent_id = 0, $where = array())
{
global $db;
if (!$sql_id || !$sql_table)
{
return;
}
$sql_where = ($module_class) ? " WHERE module_class = '" . $db->sql_escape($module_class) . "'" : '';
// Reset to minimum possible left and right id
$sql = "SELECT MIN(left_id) as min_left_id, MIN(right_id) as min_right_id
FROM $sql_table
$sql_where";
$sql = 'SELECT *
FROM ' . $table . '
WHERE parent_id = ' . (int) $parent_id .
((!empty($where)) ? ' AND ' . implode(' AND ', $where) : '') . '
ORDER BY left_id ASC';
$result = $db->sql_query($sql);
$row = $db->sql_fetchrow($result);
while ($row = $db->sql_fetchrow($result))
{
// First we update the left_id for this module
if ($row['left_id'] != $new_id)
{
$db->sql_query('UPDATE ' . $table . ' SET ' . $db->sql_build_array('UPDATE', array('left_id' => $new_id)) . " WHERE $pkey = {$row[$pkey]}");
}
$new_id++;
// Then we go through any children and update their left/right id's
recalc_nested_sets($new_id, $pkey, $table, $row[$pkey], $where);
// Then we come back and update the right_id for this module
if ($row['right_id'] != $new_id)
{
$db->sql_query('UPDATE ' . $table . ' SET ' . $db->sql_build_array('UPDATE', array('right_id' => $new_id)) . " WHERE $pkey = {$row[$pkey]}");
}
$new_id++;
}
$db->sql_freeresult($result);
$substract = (int) (min($row['min_left_id'], $row['min_right_id']) - 1);
if ($substract > 0)
{
$sql = "UPDATE $sql_table
SET left_id = left_id - $substract, right_id = right_id - $substract
$sql_where";
$db->sql_query($sql);
}
$sql = "SELECT $sql_id, parent_id, left_id, right_id
FROM $sql_table
$sql_where
ORDER BY left_id ASC, parent_id ASC, $sql_id ASC";
$f_result = $db->sql_query($sql);
while ($item_data = $db->sql_fetchrow($f_result))
{
if ($item_data['parent_id'])
{
$sql = "SELECT left_id, right_id
FROM $sql_table
$sql_where " . (($sql_where) ? 'AND' : 'WHERE') . "
$sql_id = {$item_data['parent_id']}";
$result = $db->sql_query($sql);
if (!$row = $db->sql_fetchrow($result))
{
$sql = "UPDATE $sql_table SET parent_id = 0 WHERE $sql_id = " . $item_data[$sql_id];
$db->sql_query($sql);
}
$db->sql_freeresult($result);
$sql = "UPDATE $sql_table
SET left_id = left_id + 2, right_id = right_id + 2
$sql_where " . (($sql_where) ? 'AND' : 'WHERE') . "
left_id > {$row['right_id']}";
$db->sql_query($sql);
$sql = "UPDATE $sql_table
SET right_id = right_id + 2
$sql_where " . (($sql_where) ? 'AND' : 'WHERE') . "
{$row['left_id']} BETWEEN left_id AND right_id";
$db->sql_query($sql);
$item_data['left_id'] = $row['right_id'];
$item_data['right_id'] = $row['right_id'] + 1;
}
else
{
$sql = "SELECT MAX(right_id) AS right_id
FROM $sql_table
$sql_where";
$result = $db->sql_query($sql);
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
$item_data['left_id'] = $row['right_id'] + 1;
$item_data['right_id'] = $row['right_id'] + 2;
}
$sql = "UPDATE $sql_table
SET left_id = {$item_data['left_id']}, right_id = {$item_data['right_id']}
WHERE $sql_id = " . $item_data[$sql_id];
$db->sql_query($sql);
}
$db->sql_freeresult($f_result);
}
*/
/**
* Simple version of jumpbox, just lists authed forums
@ -117,7 +69,7 @@ function make_forum_select($select_id = false, $ignore_id = false, $ignore_acl =
$acl = ($ignore_acl) ? '' : (($only_acl_post) ? 'f_post' : array('f_list', 'a_forum', 'a_forumadd', 'a_forumdel'));
// This query is identical to the jumpbox one
$sql = 'SELECT forum_id, forum_name, parent_id, forum_type, left_id, right_id
$sql = 'SELECT forum_id, forum_name, parent_id, forum_type, forum_flags, forum_options, left_id, right_id
FROM ' . FORUMS_TABLE . '
ORDER BY left_id ASC';
$result = $db->sql_query($sql, 600);
@ -354,12 +306,157 @@ function get_forum_branch($forum_id, $type = 'all', $order = 'descending', $incl
return $rows;
}
/**
* Copies permissions from one forum to others
*
* @param int $src_forum_id The source forum we want to copy permissions from
* @param array $dest_forum_ids The destination forum(s) we want to copy to
* @param bool $clear_dest_perms True if destination permissions should be deleted
* @param bool $add_log True if log entry should be added
*
* @return bool False on error
*
* @author bantu
*/
function copy_forum_permissions($src_forum_id, $dest_forum_ids, $clear_dest_perms = true, $add_log = true)
{
global $db;
// Only one forum id specified
if (!is_array($dest_forum_ids))
{
$dest_forum_ids = array($dest_forum_ids);
}
// Make sure forum ids are integers
$src_forum_id = (int) $src_forum_id;
$dest_forum_ids = array_map('intval', $dest_forum_ids);
// No source forum or no destination forums specified
if (empty($src_forum_id) || empty($dest_forum_ids))
{
return false;
}
// Check if source forum exists
$sql = 'SELECT forum_name
FROM ' . FORUMS_TABLE . '
WHERE forum_id = ' . $src_forum_id;
$result = $db->sql_query($sql);
$src_forum_name = $db->sql_fetchfield('forum_name');
$db->sql_freeresult($result);
// Source forum doesn't exist
if (empty($src_forum_name))
{
return false;
}
// Check if destination forums exists
$sql = 'SELECT forum_id, forum_name
FROM ' . FORUMS_TABLE . '
WHERE ' . $db->sql_in_set('forum_id', $dest_forum_ids);
$result = $db->sql_query($sql);
$dest_forum_ids = $dest_forum_names = array();
while ($row = $db->sql_fetchrow($result))
{
$dest_forum_ids[] = (int) $row['forum_id'];
$dest_forum_names[] = $row['forum_name'];
}
$db->sql_freeresult($result);
// No destination forum exists
if (empty($dest_forum_ids))
{
return false;
}
// From the mysql documentation:
// Prior to MySQL 4.0.14, the target table of the INSERT statement cannot appear
// in the FROM clause of the SELECT part of the query. This limitation is lifted in 4.0.14.
// Due to this we stay on the safe side if we do the insertion "the manual way"
// Rowsets we're going to insert
$users_sql_ary = $groups_sql_ary = array();
// Query acl users table for source forum data
$sql = 'SELECT user_id, auth_option_id, auth_role_id, auth_setting
FROM ' . ACL_USERS_TABLE . '
WHERE forum_id = ' . $src_forum_id;
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
{
$row = array(
'user_id' => (int) $row['user_id'],
'auth_option_id' => (int) $row['auth_option_id'],
'auth_role_id' => (int) $row['auth_role_id'],
'auth_setting' => (int) $row['auth_setting'],
);
foreach ($dest_forum_ids as $dest_forum_id)
{
$users_sql_ary[] = $row + array('forum_id' => $dest_forum_id);
}
}
$db->sql_freeresult($result);
// Query acl groups table for source forum data
$sql = 'SELECT group_id, auth_option_id, auth_role_id, auth_setting
FROM ' . ACL_GROUPS_TABLE . '
WHERE forum_id = ' . $src_forum_id;
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
{
$row = array(
'group_id' => (int) $row['group_id'],
'auth_option_id' => (int) $row['auth_option_id'],
'auth_role_id' => (int) $row['auth_role_id'],
'auth_setting' => (int) $row['auth_setting'],
);
foreach ($dest_forum_ids as $dest_forum_id)
{
$groups_sql_ary[] = $row + array('forum_id' => $dest_forum_id);
}
}
$db->sql_freeresult($result);
$db->sql_transaction('begin');
// Clear current permissions of destination forums
if ($clear_dest_perms)
{
$sql = 'DELETE FROM ' . ACL_USERS_TABLE . '
WHERE ' . $db->sql_in_set('forum_id', $dest_forum_ids);
$db->sql_query($sql);
$sql = 'DELETE FROM ' . ACL_GROUPS_TABLE . '
WHERE ' . $db->sql_in_set('forum_id', $dest_forum_ids);
$db->sql_query($sql);
}
$db->sql_multi_insert(ACL_USERS_TABLE, $users_sql_ary);
$db->sql_multi_insert(ACL_GROUPS_TABLE, $groups_sql_ary);
if ($add_log)
{
add_log('admin', 'LOG_FORUM_COPIED_PERMISSIONS', $src_forum_name, implode(', ', $dest_forum_names));
}
$db->sql_transaction('commit');
return true;
}
/**
* Get physical file listing
*/
function filelist($rootdir, $dir = '', $type = 'gif|jpg|jpeg|png')
{
$matches = array();
$matches = array($dir => array());
// Remove initial / if present
$rootdir = (substr($rootdir, 0, 1) == '/') ? substr($rootdir, 1) : $rootdir;
@ -940,19 +1037,61 @@ function delete_attachments($mode, $ids, $resync = true)
// Update post indicators for posts now no longer having attachments
if (sizeof($post_ids))
{
$sql = 'UPDATE ' . POSTS_TABLE . '
SET post_attachment = 0
WHERE ' . $db->sql_in_set('post_id', $post_ids);
$db->sql_query($sql);
// Just check which posts are still having an assigned attachment not orphaned by querying the attachments table
$sql = 'SELECT post_msg_id
FROM ' . ATTACHMENTS_TABLE . '
WHERE ' . $db->sql_in_set('post_msg_id', $post_ids) . '
AND in_message = 0
AND is_orphan = 0';
$result = $db->sql_query($sql);
$remaining_ids = array();
while ($row = $db->sql_fetchrow($result))
{
$remaining_ids[] = $row['post_msg_id'];
}
$db->sql_freeresult($result);
// Now only unset those ids remaining
$post_ids = array_diff($post_ids, $remaining_ids);
if (sizeof($post_ids))
{
$sql = 'UPDATE ' . POSTS_TABLE . '
SET post_attachment = 0
WHERE ' . $db->sql_in_set('post_id', $post_ids);
$db->sql_query($sql);
}
}
// Update message table if messages are affected
if (sizeof($message_ids))
{
$sql = 'UPDATE ' . PRIVMSGS_TABLE . '
SET message_attachment = 0
WHERE ' . $db->sql_in_set('msg_id', $message_ids);
$db->sql_query($sql);
// Just check which messages are still having an assigned attachment not orphaned by querying the attachments table
$sql = 'SELECT post_msg_id
FROM ' . ATTACHMENTS_TABLE . '
WHERE ' . $db->sql_in_set('post_msg_id', $message_ids) . '
AND in_message = 1
AND is_orphan = 0';
$result = $db->sql_query($sql);
$remaining_ids = array();
while ($row = $db->sql_fetchrow($result))
{
$remaining_ids[] = $row['post_msg_id'];
}
$db->sql_freeresult($result);
// Now only unset those ids remaining
$message_ids = array_diff($message_ids, $remaining_ids);
if (sizeof($message_ids))
{
$sql = 'UPDATE ' . PRIVMSGS_TABLE . '
SET message_attachment = 0
WHERE ' . $db->sql_in_set('msg_id', $message_ids);
$db->sql_query($sql);
}
}
// Now update the topics. This is a bit trickier, because there could be posts still having attachments within the topic
@ -1098,7 +1237,7 @@ function phpbb_unlink($filename, $mode = 'file', $entry_removed = false)
// Because of copying topics or modifications a physical filename could be assigned more than once. If so, do not remove the file itself.
$sql = 'SELECT COUNT(attach_id) AS num_entries
FROM ' . ATTACHMENTS_TABLE . "
WHERE physical_filename = '" . $db->sql_escape(basename($filename)) . "'";
WHERE physical_filename = '" . $db->sql_escape(utf8_basename($filename)) . "'";
$result = $db->sql_query($sql);
$num_entries = (int) $db->sql_fetchfield('num_entries');
$db->sql_freeresult($result);
@ -1109,7 +1248,7 @@ function phpbb_unlink($filename, $mode = 'file', $entry_removed = false)
return false;
}
$filename = ($mode == 'thumbnail') ? 'thumb_' . basename($filename) : basename($filename);
$filename = ($mode == 'thumbnail') ? 'thumb_' . utf8_basename($filename) : utf8_basename($filename);
return @unlink($phpbb_root_path . $config['upload_path'] . '/' . $filename);
}
@ -1193,6 +1332,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
switch ($mode)
{
case 'topic_moved':
$db->sql_transaction('begin');
switch ($db->sql_layer)
{
case 'mysql4':
@ -1229,9 +1369,13 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
break;
}
break;
$db->sql_transaction('commit');
break;
case 'topic_approved':
$db->sql_transaction('begin');
switch ($db->sql_layer)
{
case 'mysql4':
@ -1267,11 +1411,15 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
$db->sql_query($sql);
break;
}
break;
$db->sql_transaction('commit');
break;
case 'post_reported':
$post_ids = $post_reported = array();
$db->sql_transaction('begin');
$sql = 'SELECT p.post_id, p.post_reported
FROM ' . POSTS_TABLE . " p
$where_sql
@ -1322,7 +1470,9 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
WHERE ' . $db->sql_in_set('post_id', $post_ids);
$db->sql_query($sql);
}
break;
$db->sql_transaction('commit');
break;
case 'topic_reported':
if ($sync_extra)
@ -1332,6 +1482,8 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
$topic_ids = $topic_reported = array();
$db->sql_transaction('begin');
$sql = 'SELECT DISTINCT(t.topic_id)
FROM ' . POSTS_TABLE . " t
$where_sql_and t.post_reported = 1";
@ -1364,11 +1516,15 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
WHERE ' . $db->sql_in_set('topic_id', $topic_ids);
$db->sql_query($sql);
}
break;
$db->sql_transaction('commit');
break;
case 'post_attachment':
$post_ids = $post_attachment = array();
$db->sql_transaction('begin');
$sql = 'SELECT p.post_id, p.post_attachment
FROM ' . POSTS_TABLE . " p
$where_sql
@ -1419,7 +1575,9 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
WHERE ' . $db->sql_in_set('post_id', $post_ids);
$db->sql_query($sql);
}
break;
$db->sql_transaction('commit');
break;
case 'topic_attachment':
if ($sync_extra)
@ -1429,6 +1587,8 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
$topic_ids = $topic_attachment = array();
$db->sql_transaction('begin');
$sql = 'SELECT DISTINCT(t.topic_id)
FROM ' . POSTS_TABLE . " t
$where_sql_and t.post_attachment = 1";
@ -1461,10 +1621,15 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
WHERE ' . $db->sql_in_set('topic_id', $topic_ids);
$db->sql_query($sql);
}
break;
$db->sql_transaction('commit');
break;
case 'forum':
$db->sql_transaction('begin');
// 1: Get the list of all forums
$sql = 'SELECT f.*
FROM ' . FORUMS_TABLE . " f
@ -1665,11 +1830,15 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
$db->sql_query($sql);
}
}
break;
$db->sql_transaction('commit');
break;
case 'topic':
$topic_data = $post_ids = $approved_unapproved_ids = $resync_forums = $delete_topics = $delete_posts = $moved_topics = array();
$db->sql_transaction('begin');
$sql = 'SELECT t.topic_id, t.forum_id, t.topic_moved_id, t.topic_approved, ' . (($sync_extra) ? 't.topic_attachment, t.topic_reported, ' : '') . 't.topic_poster, t.topic_time, t.topic_replies, t.topic_replies_real, t.topic_first_post_id, t.topic_first_poster_name, t.topic_first_poster_colour, t.topic_last_post_id, t.topic_last_post_subject, t.topic_last_poster_id, t.topic_last_poster_name, t.topic_last_poster_colour, t.topic_last_post_time
FROM ' . TOPICS_TABLE . " t
$where_sql";
@ -1992,6 +2161,8 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
}
unset($topic_data);
$db->sql_transaction('commit');
// if some topics have been resync'ed then resync parent forums
// except when we're only syncing a range, we don't want to sync forums during
// batch processing.
@ -1999,7 +2170,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
{
sync('forum', 'forum_id', array_values($resync_forums), true, true);
}
break;
break;
}
return;
@ -2185,12 +2356,13 @@ function cache_moderators()
// Remove users who have group memberships with DENY moderator permissions
$sql = $db->sql_build_query('SELECT', array(
'SELECT' => 'a.forum_id, ug.user_id',
'SELECT' => 'a.forum_id, ug.user_id, g.group_id',
'FROM' => array(
ACL_OPTIONS_TABLE => 'o',
USER_GROUP_TABLE => 'ug',
ACL_GROUPS_TABLE => 'a'
ACL_GROUPS_TABLE => 'a',
GROUPS_TABLE => 'g',
),
'LEFT_JOIN' => array(
@ -2204,6 +2376,8 @@ function cache_moderators()
AND ((a.auth_setting = ' . ACL_NEVER . ' AND r.auth_setting IS NULL)
OR r.auth_setting = ' . ACL_NEVER . ')
AND a.group_id = ug.group_id
AND g.group_id = ug.group_id
AND NOT (ug.group_leader = 1 AND g.group_skip_auth = 1)
AND ' . $db->sql_in_set('ug.user_id', $ug_id_ary) . "
AND ug.user_pending = 0
AND o.auth_option " . $db->sql_like_expression('m_' . $db->any_char),
@ -2323,7 +2497,7 @@ function cache_moderators()
/**
* View log
*/
function view_log($mode, &$log, &$log_count, $limit = 0, $offset = 0, $forum_id = 0, $topic_id = 0, $user_id = 0, $limit_days = 0, $sort_by = 'l.log_time DESC')
function view_log($mode, &$log, &$log_count, $limit = 0, $offset = 0, $forum_id = 0, $topic_id = 0, $user_id = 0, $limit_days = 0, $sort_by = 'l.log_time DESC', $keywords = '')
{
global $db, $user, $auth, $phpEx, $phpbb_root_path, $phpbb_admin_path;
@ -2343,15 +2517,15 @@ function view_log($mode, &$log, &$log_count, $limit = 0, $offset = 0, $forum_id
if ($topic_id)
{
$sql_forum = 'AND l.topic_id = ' . intval($topic_id);
$sql_forum = 'AND l.topic_id = ' . (int) $topic_id;
}
else if (is_array($forum_id))
{
$sql_forum = 'AND ' . $db->sql_in_set('l.forum_id', array_map('intval', $forum_id));
}
else
else if ($forum_id)
{
$sql_forum = ($forum_id) ? 'AND l.forum_id = ' . intval($forum_id) : '';
$sql_forum = 'AND l.forum_id = ' . (int) $forum_id;
}
break;
@ -2374,11 +2548,40 @@ function view_log($mode, &$log, &$log_count, $limit = 0, $offset = 0, $forum_id
return;
}
$keywords = preg_split('#[\s+\-|*()]+#u', utf8_strtolower(preg_quote($keywords, '#')), 0, PREG_SPLIT_NO_EMPTY);
$sql_keywords = '';
if (!empty($keywords))
{
$keywords_pattern = '#' . implode('|', $keywords) . '#ui';
for ($i = 0, $num_keywords = sizeof($keywords); $i < $num_keywords; $i++)
{
$keywords[$i] = $db->sql_like_expression($db->any_char . $keywords[$i] . $db->any_char);
}
$operations = array();
foreach ($user->lang as $key => $value)
{
if (substr($key, 0, 4) == 'LOG_' && preg_match($keywords_pattern, $value))
{
$operations[] = $key;
}
}
$sql_keywords = 'AND (';
if (!empty($operations))
{
$sql_keywords .= $db->sql_in_set('l.log_operation', $operations) . ' OR ';
}
$sql_keywords .= 'LOWER(l.log_data) ' . implode(' OR LOWER(l.log_data) ', $keywords) . ')';
}
$sql = "SELECT l.*, u.username, u.username_clean, u.user_colour
FROM " . LOG_TABLE . " l, " . USERS_TABLE . " u
WHERE l.log_type = $log_type
AND u.user_id = l.user_id
" . (($limit_days) ? "AND l.log_time >= $limit_days" : '') . "
$sql_keywords
$sql_forum
ORDER BY $sort_by";
$result = $db->sql_query_limit($sql, $limit, $offset);
@ -2419,7 +2622,8 @@ function view_log($mode, &$log, &$log_count, $limit = 0, $offset = 0, $forum_id
if (!empty($row['log_data']))
{
$log_data_ary = unserialize($row['log_data']);
$log_data_ary = @unserialize($row['log_data']);
$log_data_ary = ($log_data_ary === false) ? array() : $log_data_ary;
if (isset($user->lang[$row['log_operation']]))
{
@ -2442,7 +2646,7 @@ function view_log($mode, &$log, &$log_count, $limit = 0, $offset = 0, $forum_id
$log[$i]['action'] = bbcode_nl2br(censor_text($log[$i]['action']));
}
}
else
else if (!empty($log_data_ary))
{
$log[$i]['action'] .= '<br />' . implode('', $log_data_ary);
}
@ -2540,9 +2744,11 @@ function view_log($mode, &$log, &$log_count, $limit = 0, $offset = 0, $forum_id
}
$sql = 'SELECT COUNT(l.log_id) AS total_entries
FROM ' . LOG_TABLE . " l
FROM ' . LOG_TABLE . ' l, ' . USERS_TABLE . " u
WHERE l.log_type = $log_type
AND l.user_id = u.user_id
AND l.log_time >= $limit_days
$sql_keywords
$sql_forum";
$result = $db->sql_query($sql);
$log_count = (int) $db->sql_fetchfield('total_entries');
@ -2685,7 +2891,7 @@ function view_inactive_users(&$users, &$user_count, $limit = 0, $offset = 0, $li
$offset = ($offset - $limit < 0) ? 0 : $offset - $limit;
}
$sql = 'SELECT user_id, username, user_regdate, user_lastvisit, user_inactive_time, user_inactive_reason
$sql = 'SELECT *
FROM ' . USERS_TABLE . '
WHERE user_type = ' . USER_INACTIVE .
(($limit_days) ? " AND user_inactive_time >= $limit_days" : '') . "
@ -3054,4 +3260,43 @@ function add_permission_language()
return true;
}
/**
* Obtains the latest version information
*
* @param bool $force_update Ignores cached data. Defaults to false.
* @param bool $warn_fail Trigger a warning if obtaining the latest version information fails. Defaults to false.
* @param int $ttl Cache version information for $ttl seconds. Defaults to 86400 (24 hours).
*
* @return string | false Version info on success, false on failure.
*/
function obtain_latest_version_info($force_update = false, $warn_fail = false, $ttl = 86400)
{
global $cache;
$info = $cache->get('versioncheck');
if ($info === false || $force_update)
{
$errstr = '';
$errno = 0;
$info = get_remote_file('www.phpbb.com', '/updatecheck',
((defined('PHPBB_QA')) ? '30x_qa.txt' : '30x.txt'), $errstr, $errno);
if ($info === false)
{
$cache->destroy('versioncheck');
if ($warn_fail)
{
trigger_error($errstr, E_USER_WARNING);
}
return false;
}
$cache->put('versioncheck', $info, $ttl);
}
return $info;
}
?>

View file

@ -155,7 +155,12 @@ class compress_zip extends compress
*/
function compress_zip($mode, $file)
{
return $this->fp = @fopen($file, $mode . 'b');
$this->fp = @fopen($file, $mode . 'b');
if (!$this->fp)
{
trigger_error('Unable to open file ' . $file . ' [' . $mode . 'b]');
}
}
/**

View file

@ -250,6 +250,11 @@ function get_context($text, $words, $length = 400)
// first replace all whitespaces with single spaces
$text = preg_replace('/ +/', ' ', strtr($text, "\t\n\r\x0C ", ' '));
// we need to turn the entities back into their original form, to not cut the message in between them
$entities = array('&lt;', '&gt;', '&#91;', '&#93;', '&#46;', '&#58;', '&#058;');
$characters = array('<', '>', '[', ']', '.', ':', ':');
$text = str_replace($entities, $characters, $text);
$word_indizes = array();
if (sizeof($words))
{
@ -345,13 +350,13 @@ function get_context($text, $words, $length = 400)
}
}
}
return $final_text;
return str_replace($characters, $entities, $final_text);
}
}
if (!sizeof($words) || !sizeof($word_indizes))
{
return (utf8_strlen($text) >= $length + 3) ? utf8_substr($text, 0, $length) . '...' : $text;
return str_replace($characters, $entities, ((utf8_strlen($text) >= $length + 3) ? utf8_substr($text, 0, $length) . '...' : $text));
}
}
@ -680,6 +685,12 @@ function censor_text($text)
{
static $censors;
// Nothing to do?
if ($text === '')
{
return '';
}
// We moved the word censor checks in here because we call this function quite often - and then only need to do the check once
if (!isset($censors) || !is_array($censors))
{
@ -728,7 +739,8 @@ function smiley_text($text, $force_option = false)
}
else
{
return preg_replace('#<!\-\- s(.*?) \-\-><img src="\{SMILIES_PATH\}\/(.*?) \/><!\-\- s\1 \-\->#', '<img src="' . $phpbb_root_path . $config['smilies_path'] . '/\2 />', $text);
$root_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? generate_board_url() . '/' : $phpbb_root_path;
return preg_replace('#<!\-\- s(.*?) \-\-><img src="\{SMILIES_PATH\}\/(.*?) \/><!\-\- s\1 \-\->#', '<img src="' . $root_path . $config['smilies_path'] . '/\2 />', $text);
}
}
@ -836,8 +848,8 @@ function parse_attachments($forum_id, &$message, &$attachments, &$update_count,
// Some basics...
$attachment['extension'] = strtolower(trim($attachment['extension']));
$filename = $phpbb_root_path . $config['upload_path'] . '/' . basename($attachment['physical_filename']);
$thumbnail_filename = $phpbb_root_path . $config['upload_path'] . '/thumb_' . basename($attachment['physical_filename']);
$filename = $phpbb_root_path . $config['upload_path'] . '/' . utf8_basename($attachment['physical_filename']);
$thumbnail_filename = $phpbb_root_path . $config['upload_path'] . '/thumb_' . utf8_basename($attachment['physical_filename']);
$upload_icon = '';
@ -853,17 +865,15 @@ function parse_attachments($forum_id, &$message, &$attachments, &$update_count,
}
}
$filesize = $attachment['filesize'];
$size_lang = ($filesize >= 1048576) ? $user->lang['MIB'] : (($filesize >= 1024) ? $user->lang['KIB'] : $user->lang['BYTES']);
$filesize = get_formatted_filesize($filesize, false);
$filesize = get_formatted_filesize($attachment['filesize'], false);
$comment = bbcode_nl2br(censor_text($attachment['attach_comment']));
$block_array += array(
'UPLOAD_ICON' => $upload_icon,
'FILESIZE' => $filesize,
'SIZE_LANG' => $size_lang,
'DOWNLOAD_NAME' => basename($attachment['real_filename']),
'FILESIZE' => $filesize['value'],
'SIZE_LANG' => $filesize['unit'],
'DOWNLOAD_NAME' => utf8_basename($attachment['real_filename']),
'COMMENT' => $comment,
);

View file

@ -551,7 +551,7 @@ function _import_check($config_var, $source, $use_target)
);
// copy file will prepend $phpBB_root_path
$target = $config[$config_var] . '/' . basename(($use_target === false) ? $source : $use_target);
$target = $config[$config_var] . '/' . utf8_basename(($use_target === false) ? $source : $use_target);
if (!empty($convert->convertor[$config_var]) && strpos($source, $convert->convertor[$config_var]) !== 0)
{
@ -567,11 +567,11 @@ function _import_check($config_var, $source, $use_target)
if ($result['copied'])
{
$result['target'] = basename($target);
$result['target'] = utf8_basename($target);
}
else
{
$result['target'] = ($use_target !== false) ? $result['orig_source'] : basename($target);
$result['target'] = ($use_target !== false) ? $result['orig_source'] : utf8_basename($target);
}
return $result;
@ -600,7 +600,7 @@ function import_attachment($source, $use_target = false)
{
$thumb_dir = $convert->convertor['thumbnails'][0];
$thumb_prefix = $convert->convertor['thumbnails'][1];
$thumb_source = $thumb_dir . $thumb_prefix . basename($result['source']);
$thumb_source = $thumb_dir . $thumb_prefix . utf8_basename($result['source']);
if (strpos($thumb_source, $convert->convertor['upload_path']) !== 0)
{
@ -1698,7 +1698,8 @@ function add_default_groups()
'REGISTERED_COPPA' => array('', 0, 0),
'GLOBAL_MODERATORS' => array('00AA00', 1, 0),
'ADMINISTRATORS' => array('AA0000', 1, 1),
'BOTS' => array('9E8DA7', 0, 0)
'BOTS' => array('9E8DA7', 0, 0),
'NEWLY_REGISTERED' => array('', 0, 0),
);
$sql = 'SELECT *
@ -2256,7 +2257,7 @@ function copy_file($src, $trg, $overwrite = false, $die_on_failure = true, $sour
if (substr($trg, -1) == '/')
{
$trg .= basename($src);
$trg .= utf8_basename($src);
}
$src_path = relative_base($src, $source_relative_path, __LINE__, __FILE__);
$trg_path = $trg;

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