Уважаемые пользователи!
C 7 ноября 2020 года phpBB Group прекратила выпуск обновлений и завершила дальнейшее развитие phpBB версии 3.2.
С 1 августа 2024 года phpBB Group прекращает поддержку phpBB 3.2 на официальном сайте.
Сайт официальной русской поддержки phpBB Guru продолжит поддержку phpBB 3.2 до 31 декабря 2024 года.
С учетом этого, настоятельно рекомендуется обновить конференции до версии 3.3.

С чего начинался phpBB

Вопросы без привязки к версии. Установлена авточистка (2 года).
Правила форума
Местная Конституция | Шаблон запроса | Документация (phpBB3) | Переход на 3.0.6 и выше | FAQ | Как задавать вопросы | Как устанавливать расширения

Ваш вопрос может быть удален без объяснения причин, если на него есть ответы по приведённым ссылкам (а вы рискуете получить предупреждение ;) ).
Аватара пользователя
Nekstati
Поддержка
Поддержка
Сообщения: 3335
Стаж: 15 лет
Благодарил (а): 35 раз
Поблагодарили: 1434 раза

С чего начинался phpBB

Сообщение Nekstati »

В следующем году phpBB исполнится 20 лет. Каким он был тогда, в 2000 году?

Первая версия phpBB кардинально отличалась от последней... На самом деле нет. :) Она была очень похожа. Там были уже и модерация, и ББкоды, и смайлы, и личные сообщения, и email-уведомления, и банхаммер. В комплекте шло целых три темы, и по умолчанию стояла чёрная! Темы можно было легко редактировать через админку! Из базовых функций там не хватало только вложений и аватар.

Не поверите, но phpBB 1.0 был адаптивным и респонсивным. :D Там простая табличная вёрстка, которая вполне сносно отображается на мобильных.

Основателем phpBB был Джеймс Аткинсон aka theFinn, а вот его рассказ о том, как всё начиналось.

Вы можете сами попробовать phpBB 1.0 на своём локальном сервере. Вот дистрибутив, который я слегка исправила, чтобы работал на PHP 5.6 и MySQL 5.7.
  
phpBB-1.0.zip
(178.68 КБ) 102 скачивания
  
Устанавливается как обычно. Перед установкой подредактируйте некоторые значения в config.php:
$url_images, $url_phpbb, $url_admin - тут надо уточнить путь к папке с форумом, если он отличен от дефолтного пути /phpBB.
$cookiedomain, $cookiepath - тут указать реальный домен и путь к папке с форумом.

Список форумов
Список форумов
  
Топик
Топик
  
Редактирование темы в админке
Редактирование темы в админке
  
Светлая тема
Светлая тема
  
Мобильный вид: я лишь немного уменьшила картинку логотипа, и форум отлично уместился на мобильном экране
Мобильный вид: я лишь немного уменьшила картинку логотипа, и форум отлично уместился на мобильном экране
Аватара пользователя
TaLLeR43
phpBB 2.0.1
Сообщения: 274
Стаж: 6 лет 11 месяцев
Откуда: Кикнур
Благодарил (а): 50 раз
Поблагодарили: 22 раза
Контактная информация:

Re: С чего начинался phpBB

Сообщение TaLLeR43 »

;) хорошая статейка
Аватара пользователя
Sheer
Former team member
Сообщения: 12113
Стаж: 17 лет 1 месяц
Откуда: Калининград не Кенигсберг
Благодарил (а): 54 раза
Поблагодарили: 2752 раза
Контактная информация:

Re: С чего начинался phpBB

Сообщение Sheer »

Nekstati писал(а): 09.07.2019 0:22 Первая версия phpBB кардинально отличалась от последней... На самом деле нет
Самое главное, что и в последней версии исходный код остался чистым, прозрачным и понятным, чего не скажешь об используемым фреймворке. phpBB рулит 8-)
Изображение
Общие ошибки новичков (07.11.2005) & Как задавать вопросы
Мини FAQ
Если ничто другое не помогает, прочтите, наконец, инструкцию!
"Никакая инструкция не может перечислить всех обязанностей должностного лица, предусмотреть все отдельные случаи и дать вперёд соответствующие указания, а поэтому господа инженеры должны проявить инициативу и, руководствуясь знаниями своей специальности и пользой дела, принять все усилия для оправдания своего назначения".
Циркуляр Морского технического комитета №15 от 29.11.1910 г.
Аватара пользователя
Nekstati
Поддержка
Поддержка
Сообщения: 3335
Стаж: 15 лет
Благодарил (а): 35 раз
Поблагодарили: 1434 раза

Re: С чего начинался phpBB

Сообщение Nekstati »

Sheer,

2000 год   
2005 год

Код: Выделить всё

$_GET['page']
  
2015 год

Код: Выделить всё

use Symfony\Component\HttpFoundation\Request;
$request = Request::createFromGlobals();
$request->query->get('page');
Аватара пользователя
Sheer
Former team member
Сообщения: 12113
Стаж: 17 лет 1 месяц
Откуда: Калининград не Кенигсберг
Благодарил (а): 54 раза
Поблагодарили: 2752 раза
Контактная информация:

Re: С чего начинался phpBB

Сообщение Sheer »

2019

Код: Выделить всё

// Basic parameter data
$id = $request->variable('i', '');
Что тут непонятного?
Изображение
Общие ошибки новичков (07.11.2005) & Как задавать вопросы
Мини FAQ
Если ничто другое не помогает, прочтите, наконец, инструкцию!
"Никакая инструкция не может перечислить всех обязанностей должностного лица, предусмотреть все отдельные случаи и дать вперёд соответствующие указания, а поэтому господа инженеры должны проявить инициативу и, руководствуясь знаниями своей специальности и пользой дела, принять все усилия для оправдания своего назначения".
Циркуляр Морского технического комитета №15 от 29.11.1910 г.
Аватара пользователя
Татьяна5
Поддержка
Поддержка
Сообщения: 12372
Стаж: 12 лет 7 месяцев
Благодарил (а): 223 раза
Поблагодарили: 3517 раз
Контактная информация:

Re: С чего начинался phpBB

Сообщение Татьяна5 »

Nekstati писал(а): 09.07.2019 12:442005 год
Nekstati писал(а): 09.07.2019 12:442015 год
Посередине ещё было request_var('page, '')
И сейчас чаще всего всё сводится к $request->variable('page', '')
Аватара пользователя
Nekstati
Поддержка
Поддержка
Сообщения: 3335
Стаж: 15 лет
Благодарил (а): 35 раз
Поблагодарили: 1434 раза

Re: С чего начинался phpBB

Сообщение Nekstati »

Sheer, Татьяна5, я больше про php в целом, чем про phpBB. :)
Sheer писал(а): 09.07.2019 11:55 и в последней версии исходный код остался чистым, прозрачным и понятным
Функции по 2000 строк, а особенно свитч-кейсы по 1000 строк, не выделенные даже фигурными скобками, так что фиг найдёшь, где заканчивается кейс, - это понятный код? :?

Код: Выделить всё

		switch ($mode)
		{
			case 'overview':

				if (!function_exists('user_get_id_name'))
				{
					include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
				}

				$user->add_lang('acp/ban');

				$delete			= $request->variable('delete', 0);
				$delete_type	= $request->variable('delete_type', '');
				$ip				= $request->variable('ip', 'ip');

				/**
				 * Run code at beginning of ACP users overview
				 *
				 * @event core.acp_users_overview_before
				 * @var	array   user_row    Current user data
				 * @var	string  mode        Active module
				 * @var	string  action      Module that should be run
				 * @var	bool    submit      Do we display the form only
				 *                          or did the user press submit
				 * @var	array   error       Array holding error messages
				 * @since 3.1.3-RC1
				 */
				$vars = array('user_row', 'mode', 'action', 'submit', 'error');
				extract($phpbb_dispatcher->trigger_event('core.acp_users_overview_before', compact($vars)));

				if ($submit)
				{
					if ($delete)
					{
						if (!$auth->acl_get('a_userdel'))
						{
							send_status_line(403, 'Forbidden');
							trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING);
						}

						// Check if the user wants to remove himself or the guest user account
						if ($user_id == ANONYMOUS)
						{
							trigger_error($user->lang['CANNOT_REMOVE_ANONYMOUS'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING);
						}

						// Founders can not be deleted.
						if ($user_row['user_type'] == USER_FOUNDER)
						{
							trigger_error($user->lang['CANNOT_REMOVE_FOUNDER'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING);
						}

						if ($user_id == $user->data['user_id'])
						{
							trigger_error($user->lang['CANNOT_REMOVE_YOURSELF'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING);
						}

						if ($delete_type)
						{
							if (confirm_box(true))
							{
								user_delete($delete_type, $user_id, $user_row['username']);

								$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_DELETED', false, array($user_row['username']));
								trigger_error($user->lang['USER_DELETED'] . adm_back_link(
										(empty($redirect)) ? $this->u_action : $redirect_url
									)
								);
							}
							else
							{
								$delete_confirm_hidden_fields = array(
									'u'				=> $user_id,
									'i'				=> $id,
									'mode'			=> $mode,
									'action'		=> $action,
									'update'		=> true,
									'delete'		=> 1,
									'delete_type'	=> $delete_type,
								);

								// Checks if the redirection page is specified
								if (!empty($redirect))
								{
									$delete_confirm_hidden_fields['redirect'] = $redirect;
								}

								confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields($delete_confirm_hidden_fields));
							}
						}
						else
						{
							trigger_error($user->lang['NO_MODE'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING);
						}
					}

					// Handle quicktool actions
					switch ($action)
					{
						case 'banuser':
						case 'banemail':
						case 'banip':

							if ($user_id == $user->data['user_id'])
							{
								trigger_error($user->lang['CANNOT_BAN_YOURSELF'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING);
							}

							if ($user_id == ANONYMOUS)
							{
								trigger_error($user->lang['CANNOT_BAN_ANONYMOUS'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING);
							}

							if ($user_row['user_type'] == USER_FOUNDER)
							{
								trigger_error($user->lang['CANNOT_BAN_FOUNDER'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING);
							}

							if (!check_form_key($form_name))
							{
								trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING);
							}

							$ban = array();

							switch ($action)
							{
								case 'banuser':
									$ban[] = $user_row['username'];
									$reason = 'USER_ADMIN_BAN_NAME_REASON';
								break;

								case 'banemail':
									$ban[] = $user_row['user_email'];
									$reason = 'USER_ADMIN_BAN_EMAIL_REASON';
								break;

								case 'banip':
									$ban[] = $user_row['user_ip'];

									$sql = 'SELECT DISTINCT poster_ip
										FROM ' . POSTS_TABLE . "
										WHERE poster_id = $user_id";
									$result = $db->sql_query($sql);

									while ($row = $db->sql_fetchrow($result))
									{
										$ban[] = $row['poster_ip'];
									}
									$db->sql_freeresult($result);

									$reason = 'USER_ADMIN_BAN_IP_REASON';
								break;
							}

							$ban_reason = $request->variable('ban_reason', $user->lang[$reason], true);
							$ban_give_reason = $request->variable('ban_give_reason', '', true);

							// Log not used at the moment, we simply utilize the ban function.
							$result = user_ban(substr($action, 3), $ban, 0, 0, 0, $ban_reason, $ban_give_reason);

							trigger_error((($result === false) ? $user->lang['BAN_ALREADY_ENTERED'] : $user->lang['BAN_SUCCESSFUL']) . adm_back_link($this->u_action . '&u=' . $user_id));

						break;

						case 'reactivate':

							if ($user_id == $user->data['user_id'])
							{
								trigger_error($user->lang['CANNOT_FORCE_REACT_YOURSELF'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING);
							}

							if (!check_form_key($form_name))
							{
								trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING);
							}

							if ($user_row['user_type'] == USER_FOUNDER)
							{
								trigger_error($user->lang['CANNOT_FORCE_REACT_FOUNDER'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING);
							}

							if ($user_row['user_type'] == USER_IGNORE)
							{
								trigger_error($user->lang['CANNOT_FORCE_REACT_BOT'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING);
							}

							if ($config['email_enable'])
							{
								if (!class_exists('messenger'))
								{
									include($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
								}

								$server_url = generate_board_url();

								$user_actkey = gen_rand_string(mt_rand(6, 10));
								$email_template = ($user_row['user_type'] == USER_NORMAL) ? 'user_reactivate_account' : 'user_resend_inactive';

								if ($user_row['user_type'] == USER_NORMAL)
								{
									user_active_flip('deactivate', $user_id, INACTIVE_REMIND);
								}
								else
								{
									// Grabbing the last confirm key - we only send a reminder
									$sql = 'SELECT user_actkey
										FROM ' . USERS_TABLE . '
										WHERE user_id = ' . $user_id;
									$result = $db->sql_query($sql);
									$user_activation_key = (string) $db->sql_fetchfield('user_actkey');
									$db->sql_freeresult($result);

									$user_actkey = empty($user_activation_key) ? $user_actkey : $user_activation_key;
								}

								if ($user_row['user_type'] == USER_NORMAL || empty($user_activation_key))
								{
									$sql = 'UPDATE ' . USERS_TABLE . "
										SET user_actkey = '" . $db->sql_escape($user_actkey) . "'
										WHERE user_id = $user_id";
									$db->sql_query($sql);
								}

								$messenger = new messenger(false);

								$messenger->template($email_template, $user_row['user_lang']);

								$messenger->set_addresses($user_row);

								$messenger->anti_abuse_headers($config, $user);

								$messenger->assign_vars(array(
									'WELCOME_MSG'	=> htmlspecialchars_decode(sprintf($user->lang['WELCOME_SUBJECT'], $config['sitename'])),
									'USERNAME'		=> htmlspecialchars_decode($user_row['username']),
									'U_ACTIVATE'	=> "$server_url/ucp.$phpEx?mode=activate&u={$user_row['user_id']}&k=$user_actkey")
								);

								$messenger->send(NOTIFY_EMAIL);

								$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_REACTIVATE', false, array($user_row['username']));
								$phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_REACTIVATE_USER', false, array(
									'reportee_id' => $user_id
								));

								trigger_error($user->lang['FORCE_REACTIVATION_SUCCESS'] . adm_back_link($this->u_action . '&u=' . $user_id));
							}

						break;

						case 'active':

							if ($user_id == $user->data['user_id'])
							{
								// It is only deactivation since the user is already activated (else he would not have reached this page)
								trigger_error($user->lang['CANNOT_DEACTIVATE_YOURSELF'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING);
							}

							if (!check_form_key($form_name))
							{
								trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING);
							}

							if ($user_row['user_type'] == USER_FOUNDER)
							{
								trigger_error($user->lang['CANNOT_DEACTIVATE_FOUNDER'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING);
							}

							if ($user_row['user_type'] == USER_IGNORE)
							{
								trigger_error($user->lang['CANNOT_DEACTIVATE_BOT'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING);
							}

							user_active_flip('flip', $user_id);

							if ($user_row['user_type'] == USER_INACTIVE)
							{
								if ($config['require_activation'] == USER_ACTIVATION_ADMIN)
								{
									/* @var $phpbb_notifications \phpbb\notification\manager */
									$phpbb_notifications = $phpbb_container->get('notification_manager');
									$phpbb_notifications->delete_notifications('notification.type.admin_activate_user', $user_row['user_id']);

									if (!class_exists('messenger'))
									{
										include($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
									}

									$messenger = new messenger(false);

									$messenger->template('admin_welcome_activated', $user_row['user_lang']);

									$messenger->set_addresses($user_row);

									$messenger->anti_abuse_headers($config, $user);

									$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';

							$phpbb_log->add('admin', $user->data['user_id'], $user->ip, $log, false, array($user_row['username']));
							$phpbb_log->add('user', $user->data['user_id'], $user->ip, $log . '_USER', false, array(
								'reportee_id' => $user_id
							));

							trigger_error($user->lang[$message] . adm_back_link($this->u_action . '&u=' . $user_id));

						break;

						case 'delsig':

							if (!check_form_key($form_name))
							{
								trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING);
							}

							$sql_ary = array(
								'user_sig'					=> '',
								'user_sig_bbcode_uid'		=> '',
								'user_sig_bbcode_bitfield'	=> ''
							);

							$sql = 'UPDATE ' . USERS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . "
								WHERE user_id = $user_id";
							$db->sql_query($sql);

							$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_DEL_SIG', false, array($user_row['username']));
							$phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_DEL_SIG_USER', false, array(
								'reportee_id' => $user_id
							));

							trigger_error($user->lang['USER_ADMIN_SIG_REMOVED'] . adm_back_link($this->u_action . '&u=' . $user_id));

						break;

						case 'delavatar':

							if (!check_form_key($form_name))
							{
								trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING);
							}

							// Delete old avatar if present
							/* @var $phpbb_avatar_manager \phpbb\avatar\manager */
							$phpbb_avatar_manager = $phpbb_container->get('avatar.manager');
							$phpbb_avatar_manager->handle_avatar_delete($db, $user, $phpbb_avatar_manager->clean_row($user_row, 'user'), USERS_TABLE, 'user_');

							$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_DEL_AVATAR', false, array($user_row['username']));
							$phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_DEL_AVATAR_USER', false, array(
								'reportee_id' => $user_id
							));

							trigger_error($user->lang['USER_ADMIN_AVATAR_REMOVED'] . adm_back_link($this->u_action . '&u=' . $user_id));
						break;

						case 'delposts':

							if (confirm_box(true))
							{
								// Delete posts, attachments, etc.
								delete_posts('poster_id', $user_id);

								$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_DEL_POSTS', false, array($user_row['username']));
								trigger_error($user->lang['USER_POSTS_DELETED'] . adm_back_link($this->u_action . '&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 'delattach':

							if (confirm_box(true))
							{
								/** @var \phpbb\attachment\manager $attachment_manager */
								$attachment_manager = $phpbb_container->get('attachment.manager');
								$attachment_manager->delete('user', $user_id);
								unset($attachment_manager);

								$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_DEL_ATTACH', false, array($user_row['username']));
								trigger_error($user->lang['USER_ATTACHMENTS_REMOVED'] . adm_back_link($this->u_action . '&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 '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);

									$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_DEL_OUTBOX', false, array($user_row['username']));

									$lang = 'EMPTIED';
								}
								$db->sql_freeresult($result);

								trigger_error($user->lang['USER_OUTBOX_' . $lang] . adm_back_link($this->u_action . '&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))
							{
								trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING);
							}

							$user->add_lang('acp/forums');

							$new_forum_id = $request->variable('new_f', 0);

							if (!$new_forum_id)
							{
								$this->page_title = 'USER_ADMIN_MOVE_POSTS';

								$template->assign_vars(array(
									'S_SELECT_FORUM'		=> true,
									'U_ACTION'				=> $this->u_action . "&action=$action&u=$user_id",
									'U_BACK'				=> $this->u_action . "&u=$user_id",
									'S_FORUM_OPTIONS'		=> make_forum_select(false, false, false, true))
								);

								return;
							}

							// Is the new forum postable to?
							$sql = 'SELECT forum_name, forum_type
								FROM ' . FORUMS_TABLE . "
								WHERE forum_id = $new_forum_id";
							$result = $db->sql_query($sql);
							$forum_info = $db->sql_fetchrow($result);
							$db->sql_freeresult($result);

							if (!$forum_info)
							{
								trigger_error($user->lang['NO_FORUM'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING);
							}

							if ($forum_info['forum_type'] != FORUM_POST)
							{
								trigger_error($user->lang['MOVE_POSTS_NO_POSTABLE_FORUM'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING);
							}

							// Two stage?
							// Move topics comprising only posts from this user
							$topic_id_ary = $move_topic_ary = $move_post_ary = $new_topic_id_ary = array();
							$forum_id_ary = array($new_forum_id);

							$sql = 'SELECT topic_id, post_visibility, COUNT(post_id) AS total_posts
								FROM ' . POSTS_TABLE . "
								WHERE poster_id = $user_id
									AND forum_id <> $new_forum_id
								GROUP BY topic_id, post_visibility";
							$result = $db->sql_query($sql);

							while ($row = $db->sql_fetchrow($result))
							{
								$topic_id_ary[$row['topic_id']][$row['post_visibility']] = $row['total_posts'];
							}
							$db->sql_freeresult($result);

							if (count($topic_id_ary))
							{
								$sql = 'SELECT topic_id, forum_id, topic_title, topic_posts_approved, topic_posts_unapproved, topic_posts_softdeleted, topic_attachment
									FROM ' . TOPICS_TABLE . '
									WHERE ' . $db->sql_in_set('topic_id', array_keys($topic_id_ary));
								$result = $db->sql_query($sql);

								while ($row = $db->sql_fetchrow($result))
								{
									if ($topic_id_ary[$row['topic_id']][ITEM_APPROVED] == $row['topic_posts_approved']
										&& $topic_id_ary[$row['topic_id']][ITEM_UNAPPROVED] == $row['topic_posts_unapproved']
										&& $topic_id_ary[$row['topic_id']][ITEM_REAPPROVE] == $row['topic_posts_unapproved']
										&& $topic_id_ary[$row['topic_id']][ITEM_DELETED] == $row['topic_posts_softdeleted'])
									{
										$move_topic_ary[] = $row['topic_id'];
									}
									else
									{
										$move_post_ary[$row['topic_id']]['title'] = $row['topic_title'];
										$move_post_ary[$row['topic_id']]['attach'] = ($row['topic_attachment']) ? 1 : 0;
									}

									$forum_id_ary[] = $row['forum_id'];
								}
								$db->sql_freeresult($result);
							}

							// Entire topic comprises posts by this user, move these topics
							if (count($move_topic_ary))
							{
								move_topics($move_topic_ary, $new_forum_id, false);
							}

							if (count($move_post_ary))
							{
								// Create new topic
								// Update post_ids, report_ids, attachment_ids
								foreach ($move_post_ary as $topic_id => $post_ary)
								{
									// Create new topic
									$sql = 'INSERT INTO ' . TOPICS_TABLE . ' ' . $db->sql_build_array('INSERT', array(
										'topic_poster'				=> $user_id,
										'topic_time'				=> time(),
										'forum_id' 					=> $new_forum_id,
										'icon_id'					=> 0,
										'topic_visibility'			=> ITEM_APPROVED,
										'topic_title' 				=> $post_ary['title'],
										'topic_first_poster_name'	=> $user_row['username'],
										'topic_type'				=> POST_NORMAL,
										'topic_time_limit'			=> 0,
										'topic_attachment'			=> $post_ary['attach'])
									);
									$db->sql_query($sql);

									$new_topic_id = $db->sql_nextid();

									// Move posts
									$sql = 'UPDATE ' . POSTS_TABLE . "
										SET forum_id = $new_forum_id, topic_id = $new_topic_id
										WHERE topic_id = $topic_id
											AND poster_id = $user_id";
									$db->sql_query($sql);

									if ($post_ary['attach'])
									{
										$sql = 'UPDATE ' . ATTACHMENTS_TABLE . "
											SET topic_id = $new_topic_id
											WHERE topic_id = $topic_id
												AND poster_id = $user_id";
										$db->sql_query($sql);
									}

									$new_topic_id_ary[] = $new_topic_id;
								}
							}

							$forum_id_ary = array_unique($forum_id_ary);
							$topic_id_ary = array_unique(array_merge(array_keys($topic_id_ary), $new_topic_id_ary));

							if (count($topic_id_ary))
							{
								sync('topic_reported', 'topic_id', $topic_id_ary);
								sync('topic', 'topic_id', $topic_id_ary);
							}

							if (count($forum_id_ary))
							{
								sync('forum', 'forum_id', $forum_id_ary, false, true);
							}

							$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_MOVE_POSTS', false, array($user_row['username'], $forum_info['forum_name']));
							$phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_MOVE_POSTS_USER', false, array(
								'reportee_id' => $user_id,
								$forum_info['forum_name']
							));

							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);

								$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_REMOVED_NR', false, array($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;

						default:
							$u_action = $this->u_action;

							/**
							* Run custom quicktool code
							*
							* @event core.acp_users_overview_run_quicktool
							* @var	string	action		Quick tool that should be run
							* @var	array	user_row	Current user data
							* @var	string	u_action	The u_action link
							* @since 3.1.0-a1
							* @changed 3.2.2-RC1 Added u_action
							*/
							$vars = array('action', 'user_row', 'u_action');
							extract($phpbb_dispatcher->trigger_event('core.acp_users_overview_run_quicktool', compact($vars)));

							unset($u_action);
						break;
					}

					// Handle registration info updates
					$data = array(
						'username'			=> $request->variable('user', $user_row['username'], true),
						'user_founder'		=> $request->variable('user_founder', ($user_row['user_type'] == USER_FOUNDER) ? 1 : 0),
						'email'				=> strtolower($request->variable('user_email', $user_row['user_email'])),
						'new_password'		=> $request->variable('new_password', '', true),
						'password_confirm'	=> $request->variable('password_confirm', '', true),
					);

					// Validation data - we do not check the password complexity setting here
					$check_ary = array(
						'new_password'		=> array(
							array('string', true, $config['min_pass_chars'], $config['max_pass_chars']),
							array('password')),
						'password_confirm'	=> array('string', true, $config['min_pass_chars'], $config['max_pass_chars']),
					);

					// Check username if altered
					if ($data['username'] != $user_row['username'])
					{
						$check_ary += array(
							'username'			=> array(
								array('string', false, $config['min_name_chars'], $config['max_name_chars']),
								array('username', $user_row['username'])
							),
						);
					}

					// Check email if altered
					if ($data['email'] != $user_row['user_email'])
					{
						$check_ary += array(
							'email'				=> array(
								array('string', false, 6, 60),
								array('user_email', $user_row['user_email']),
							),
						);
					}

					$error = validate_data($data, $check_ary);

					if ($data['new_password'] && $data['password_confirm'] != $data['new_password'])
					{
						$error[] = 'NEW_PASSWORD_ERROR';
					}

					if (!check_form_key($form_name))
					{
						$error[] = 'FORM_INVALID';
					}

					// Instantiate passwords manager
					/* @var $passwords_manager \phpbb\passwords\manager */
					$passwords_manager = $phpbb_container->get('passwords.manager');

					// Which updates do we need to do?
					$update_username = ($user_row['username'] != $data['username']) ? $data['username'] : false;
					$update_password = $data['new_password'] && !$passwords_manager->check($data['new_password'], $user_row['user_password']);
					$update_email = ($data['email'] != $user_row['user_email']) ? $data['email'] : false;

					if (!count($error))
					{
						$sql_ary = array();

						if ($user_row['user_type'] != USER_FOUNDER || $user->data['user_type'] == USER_FOUNDER)
						{
							// Only allow founders updating the founder status...
							if ($user->data['user_type'] == USER_FOUNDER)
							{
								// Setting a normal member to be a founder
								if ($data['user_founder'] && $user_row['user_type'] != USER_FOUNDER)
								{
									// Make sure the user is not setting an Inactive or ignored user to be a founder
									if ($user_row['user_type'] == USER_IGNORE)
									{
										trigger_error($user->lang['CANNOT_SET_FOUNDER_IGNORED'] . adm_back_link($this->u_action . '&amp;u=' . $user_id), E_USER_WARNING);
									}

									if ($user_row['user_type'] == USER_INACTIVE)
									{
										trigger_error($user->lang['CANNOT_SET_FOUNDER_INACTIVE'] . adm_back_link($this->u_action . '&amp;u=' . $user_id), E_USER_WARNING);
									}

									$sql_ary['user_type'] = USER_FOUNDER;
								}
								else if (!$data['user_founder'] && $user_row['user_type'] == USER_FOUNDER)
								{
									// Check if at least one founder is present
									$sql = 'SELECT user_id
										FROM ' . USERS_TABLE . '
										WHERE user_type = ' . USER_FOUNDER . '
											AND user_id <> ' . $user_id;
									$result = $db->sql_query_limit($sql, 1);
									$row = $db->sql_fetchrow($result);
									$db->sql_freeresult($result);

									if ($row)
									{
										$sql_ary['user_type'] = USER_NORMAL;
									}
									else
									{
										trigger_error($user->lang['AT_LEAST_ONE_FOUNDER'] . adm_back_link($this->u_action . '&amp;u=' . $user_id), E_USER_WARNING);
									}
								}
							}
						}

						/**
						* Modify user data before we update it
						*
						* @event core.acp_users_overview_modify_data
						* @var	array	user_row	Current user data
						* @var	array	data		Submitted user data
						* @var	array	sql_ary		User data we udpate
						* @since 3.1.0-a1
						*/
						$vars = array('user_row', 'data', 'sql_ary');
						extract($phpbb_dispatcher->trigger_event('core.acp_users_overview_modify_data', compact($vars)));

						if ($update_username !== false)
						{
							$sql_ary['username'] = $update_username;
							$sql_ary['username_clean'] = utf8_clean_string($update_username);

							$phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_UPDATE_NAME', false, array(
								'reportee_id' => $user_id,
								$user_row['username'],
								$update_username
							));
						}

						if ($update_email !== false)
						{
							$sql_ary += array(
								'user_email'		=> $update_email,
								'user_email_hash'	=> phpbb_email_hash($update_email),
							);

							$phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_UPDATE_EMAIL', false, array(
								'reportee_id' => $user_id,
								$user_row['username'],
								$user_row['user_email'],
								$update_email
							));
						}

						if ($update_password)
						{
							$sql_ary += array(
								'user_password'		=> $passwords_manager->hash($data['new_password']),
								'user_passchg'		=> time(),
							);

							$user->reset_login_keys($user_id);

							$phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_NEW_PASSWORD', false, array(
								'reportee_id' => $user_id,
								$user_row['username']
							));
						}

						if (count($sql_ary))
						{
							$sql = 'UPDATE ' . USERS_TABLE . '
								SET ' . $db->sql_build_array('UPDATE', $sql_ary) . '
								WHERE user_id = ' . $user_id;
							$db->sql_query($sql);
						}

						if ($update_username)
						{
							user_update_name($user_row['username'], $update_username);
						}

						// Let the users permissions being updated
						$auth->acl_clear_prefetch($user_id);

						$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_USER_UPDATE', false, array($data['username']));

						trigger_error($user->lang['USER_OVERVIEW_UPDATED'] . adm_back_link($this->u_action . '&amp;u=' . $user_id));
					}

					// Replace "error" strings with their real, localised form
					$error = array_map(array($user, 'lang'), $error);
				}

				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', 'deloutbox' => 'DEL_OUTBOX');
					if ($user_row['user_new'])
					{
						$quick_tool_ary['leave_nr'] = 'LEAVE_NR';
					}
				}
				else
				{
					$quick_tool_ary = array();

					if ($user_row['user_type'] != USER_FOUNDER)
					{
						$quick_tool_ary += array('banuser' => 'BAN_USER', 'banemail' => 'BAN_EMAIL', 'banip' => 'BAN_IP');
					}

					if ($user_row['user_type'] != USER_FOUNDER && $user_row['user_type'] != USER_IGNORE)
					{
						$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', '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';
					}
				}

				if ($config['load_onlinetrack'])
				{
					$sql = 'SELECT MAX(session_time) AS session_time, MIN(session_viewonline) AS session_viewonline
						FROM ' . SESSIONS_TABLE . "
						WHERE session_user_id = $user_id";
					$result = $db->sql_query($sql);
					$row = $db->sql_fetchrow($result);
					$db->sql_freeresult($result);

					$user_row['session_time'] = (isset($row['session_time'])) ? $row['session_time'] : 0;
					$user_row['session_viewonline'] = (isset($row['session_viewonline'])) ? $row['session_viewonline'] : 0;
					unset($row);
				}

				/**
				* Add additional quick tool options and overwrite user data
				*
				* @event core.acp_users_display_overview
				* @var	array	user_row			Array with user data
				* @var	array	quick_tool_ary		Ouick tool options
				* @since 3.1.0-a1
				*/
				$vars = array('user_row', 'quick_tool_ary');
				extract($phpbb_dispatcher->trigger_event('core.acp_users_display_overview', compact($vars)));

				$s_action_options = '<option class="sep" value="">' . $user->lang['SELECT_OPTION'] . '</option>';
				foreach ($quick_tool_ary as $value => $lang)
				{
					$s_action_options .= '<option value="' . $value . '">' . $user->lang['USER_ADMIN_' . $lang] . '</option>';
				}

				$last_active = (!empty($user_row['session_time'])) ? $user_row['session_time'] : $user_row['user_lastvisit'];

				$inactive_reason = '';
				if ($user_row['user_type'] == USER_INACTIVE)
				{
					$inactive_reason = $user->lang['INACTIVE_REASON_UNKNOWN'];

					switch ($user_row['user_inactive_reason'])
					{
						case INACTIVE_REGISTER:
							$inactive_reason = $user->lang['INACTIVE_REASON_REGISTER'];
						break;

						case INACTIVE_PROFILE:
							$inactive_reason = $user->lang['INACTIVE_REASON_PROFILE'];
						break;

						case INACTIVE_MANUAL:
							$inactive_reason = $user->lang['INACTIVE_REASON_MANUAL'];
						break;

						case INACTIVE_REMIND:
							$inactive_reason = $user->lang['INACTIVE_REASON_REMIND'];
						break;
					}
				}

				// Posts in Queue
				$sql = 'SELECT COUNT(post_id) as posts_in_queue
					FROM ' . POSTS_TABLE . '
					WHERE poster_id = ' . $user_id . '
						AND ' . $db->sql_in_set('post_visibility', array(ITEM_UNAPPROVED, ITEM_REAPPROVE));
				$result = $db->sql_query($sql);
				$user_row['posts_in_queue'] = (int) $db->sql_fetchfield('posts_in_queue');
				$db->sql_freeresult($result);

				$sql = 'SELECT post_id
					FROM ' . POSTS_TABLE . '
					WHERE poster_id = '. $user_id;
				$result = $db->sql_query_limit($sql, 1);
				$user_row['user_has_posts'] = (bool) $db->sql_fetchfield('post_id');
				$db->sql_freeresult($result);

				$template->assign_vars(array(
					'L_NAME_CHARS_EXPLAIN'		=> $user->lang($config['allow_name_chars'] . '_EXPLAIN', $user->lang('CHARACTERS', (int) $config['min_name_chars']), $user->lang('CHARACTERS', (int) $config['max_name_chars'])),
					'L_CHANGE_PASSWORD_EXPLAIN'	=> $user->lang($config['pass_complex'] . '_EXPLAIN', $user->lang('CHARACTERS', (int) $config['min_pass_chars']), $user->lang('CHARACTERS', (int) $config['max_pass_chars'])),
					'L_POSTS_IN_QUEUE'			=> $user->lang('NUM_POSTS_IN_QUEUE', $user_row['posts_in_queue']),
					'S_FOUNDER'					=> ($user->data['user_type'] == USER_FOUNDER) ? true : false,

					'S_OVERVIEW'		=> true,
					'S_USER_IP'			=> ($user_row['user_ip']) ? true : false,
					'S_USER_FOUNDER'	=> ($user_row['user_type'] == USER_FOUNDER) ? true : false,
					'S_ACTION_OPTIONS'	=> $s_action_options,
					'S_OWN_ACCOUNT'		=> ($user_id == $user->data['user_id']) ? true : false,
					'S_USER_INACTIVE'	=> ($user_row['user_type'] == USER_INACTIVE) ? true : false,

					'U_SHOW_IP'		=> $this->u_action . "&amp;u=$user_id&amp;ip=" . (($ip == 'ip') ? 'hostname' : 'ip'),
					'U_WHOIS'		=> $this->u_action . "&amp;action=whois&amp;user_ip={$user_row['user_ip']}",
					'U_MCP_QUEUE'	=> ($auth->acl_getf_global('m_approve')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue', true, $user->session_id) : '',
					'U_SEARCH_USER'	=> ($config['load_search'] && $auth->acl_get('u_search')) ? append_sid("{$phpbb_root_path}search.$phpEx", "author_id={$user_row['user_id']}&amp;sr=posts") : '',

					'U_SWITCH_PERMISSIONS'	=> ($auth->acl_get('a_switchperm') && $user->data['user_id'] != $user_row['user_id']) ? append_sid("{$phpbb_root_path}ucp.$phpEx", "mode=switch_perm&amp;u={$user_row['user_id']}&amp;hash=" . generate_link_hash('switchperm')) : '',

					'POSTS_IN_QUEUE'	=> $user_row['posts_in_queue'],
					'USER'				=> $user_row['username'],
					'USER_REGISTERED'	=> $user->format_date($user_row['user_regdate']),
					'REGISTERED_IP'		=> ($ip == 'hostname') ? gethostbyaddr($user_row['user_ip']) : $user_row['user_ip'],
					'USER_LASTACTIVE'	=> ($last_active) ? $user->format_date($last_active) : ' - ',
					'USER_EMAIL'		=> $user_row['user_email'],
					'USER_WARNINGS'		=> $user_row['user_warnings'],
					'USER_POSTS'		=> $user_row['user_posts'],
					'USER_HAS_POSTS'	=> $user_row['user_has_posts'],
					'USER_INACTIVE_REASON'	=> $inactive_reason,
				));

			break;

			case 'feedback':
			......
Аватара пользователя
Pazh
Former team member
Сообщения: 2317
Стаж: 14 лет 4 месяца
Благодарил (а): 43 раза
Поблагодарили: 506 раз
Контактная информация:

Re: С чего начинался phpBB

Сообщение Pazh »

Nekstati, смотря в какой среде работать - NotePad++ конечно не всегда с таким портянками справляется, а вот PhpStorm - легко сворачивает их
Помощь в ЛС/email только за WM или ЮMoney
Аватара пользователя
Sheer
Former team member
Сообщения: 12113
Стаж: 17 лет 1 месяц
Откуда: Калининград не Кенигсберг
Благодарил (а): 54 раза
Поблагодарили: 2752 раза
Контактная информация:

Re: С чего начинался phpBB

Сообщение Sheer »

Ну в общем частный случай в некоторой степени (кстати в 3.0 этот свитч почти такой же). А по-хорошему надо бы снабжать брейки комментариями.
Типо

Код: Выделить всё

case 'feedback':
...
break; // End case 'feedback':
Изображение
Общие ошибки новичков (07.11.2005) & Как задавать вопросы
Мини FAQ
Если ничто другое не помогает, прочтите, наконец, инструкцию!
"Никакая инструкция не может перечислить всех обязанностей должностного лица, предусмотреть все отдельные случаи и дать вперёд соответствующие указания, а поэтому господа инженеры должны проявить инициативу и, руководствуясь знаниями своей специальности и пользой дела, принять все усилия для оправдания своего назначения".
Циркуляр Морского технического комитета №15 от 29.11.1910 г.
Аватара пользователя
Siava
Поддержка
Поддержка
Сообщения: 5270
Стаж: 19 лет 2 месяца
Откуда: Питер
Благодарил (а): 188 раз
Поблагодарили: 800 раз
Контактная информация:

Re: С чего начинался phpBB

Сообщение Siava »

У меня тут книжка по PHP5 завалялась (середины 2000-х годов), а в ней вот чего имеется :)
Сфоткал три разворота из пяти:

Изображение
Изображение
Изображение

Отправлено спустя 3 минуты 3 секунды:
Smayliks, ;)
Еще одно нарушение правил и будете забанены. © Mr. Anderson
Ты очистил кеш? © Sheer
https://siava.ru (phpbb 2.0.x 3.5.x)
Аватара пользователя
LavIgor
Former team member
Сообщения: 3468
Стаж: 9 лет 11 месяцев
Благодарил (а): 41 раз
Поблагодарили: 932 раза

Re: С чего начинался phpBB

Сообщение LavIgor »

Siava писал(а): 09.07.2019 17:23 Сфоткал три разворота из пяти:
А почему только три?)

Отправлено спустя 2 минуты 2 секунды:
Sheer писал(а): 09.07.2019 16:36 А по-хорошему надо бы снабжать брейки комментариями.
Нет необходимости, если использовать, например, PhpStorm.
И плюс ко всему сами эти cases уже старый код, который неспешно, но переписывают.
Аватара пользователя
Sheer
Former team member
Сообщения: 12113
Стаж: 17 лет 1 месяц
Откуда: Калининград не Кенигсберг
Благодарил (а): 54 раза
Поблагодарили: 2752 раза
Контактная информация:

Re: С чего начинался phpBB

Сообщение Sheer »

LavIgor писал(а): 09.07.2019 20:01PhpStorm
€199.00 лицензия на 1 год :shock:
Изображение
Общие ошибки новичков (07.11.2005) & Как задавать вопросы
Мини FAQ
Если ничто другое не помогает, прочтите, наконец, инструкцию!
"Никакая инструкция не может перечислить всех обязанностей должностного лица, предусмотреть все отдельные случаи и дать вперёд соответствующие указания, а поэтому господа инженеры должны проявить инициативу и, руководствуясь знаниями своей специальности и пользой дела, принять все усилия для оправдания своего назначения".
Циркуляр Морского технического комитета №15 от 29.11.1910 г.
Аватара пользователя
Siava
Поддержка
Поддержка
Сообщения: 5270
Стаж: 19 лет 2 месяца
Откуда: Питер
Благодарил (а): 188 раз
Поблагодарили: 800 раз
Контактная информация:

Re: С чего начинался phpBB

Сообщение Siava »

LavIgor писал(а): 09.07.2019 20:01 А почему только три?)
Для ознакомления :)
Еще одно нарушение правил и будете забанены. © Mr. Anderson
Ты очистил кеш? © Sheer
https://siava.ru (phpbb 2.0.x 3.5.x)
Аватара пользователя
LavIgor
Former team member
Сообщения: 3468
Стаж: 9 лет 11 месяцев
Благодарил (а): 41 раз
Поблагодарили: 932 раза

Re: С чего начинался phpBB

Сообщение LavIgor »

Sheer, EAP-релизы доступны бесплатно с регулярным автообновлением (настройки при этом сохраняются).
Аватара пользователя
Пчелкин
phpBB 3.3.0
Сообщения: 11234
Стаж: 14 лет 2 месяца
Откуда: fotovideoforum.ru
Благодарил (а): 1782 раза
Поблагодарили: 1340 раз
Контактная информация:

Re: С чего начинался phpBB

Сообщение Пчелкин »

Хм. Вспоминатели старого доброго вечного. :D
А я помню еще и такое -
INT 10h, DH=13h (_1)
Это перевод на одну строку для принтера в МК. гы.. 8-)
Ответить

Вернуться в «phpBB-пространство»