diff --git a/app/Console/Commands/Test.php b/app/Console/Commands/Test.php new file mode 100644 index 00000000..94746cc1 --- /dev/null +++ b/app/Console/Commands/Test.php @@ -0,0 +1,43 @@ +create($request->all()); + $resource = new AgentAllowResource($result); + return success('agent allow store', $resource); } /** @@ -47,21 +50,26 @@ class AgentAllowController extends Controller * * @param \Illuminate\Http\Request $request * @param int $id - * @return \Illuminate\Http\Response + * @return array */ public function update(Request $request, $id) { - // + $result = AgentAllow::query()->findOrFail($id); + $result->update($request->all()); + $resource = new AgentAllowResource($result); + return success('agent allow update', $resource); } /** * Remove the specified resource from storage. * * @param int $id - * @return \Illuminate\Http\Response + * @return array */ public function destroy($id) { - // + $result = AgentAllow::query()->findOrFail($id); + $success = $result->delete(); + return success('agent allow delete', $success); } } diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php new file mode 100644 index 00000000..17efbc77 --- /dev/null +++ b/app/Http/Controllers/UserController.php @@ -0,0 +1,70 @@ +getList($request->all()); + $resource = UserResource::collection($result); + return success('user list', $resource); + } + + /** + * Store a newly created resource in storage. + * + * @param \Illuminate\Http\Request $request + * @return array + */ + public function store(Request $request) + { + $result = (new UserRepository())->store($request->all()); + $resource = new UserResource($result); + return success('user store', $resource); + } + + /** + * Display the specified resource. + * + * @param int $id + * @return \Illuminate\Http\Response + */ + public function show($id) + { + // + } + + /** + * Update the specified resource in storage. + * + * @param \Illuminate\Http\Request $request + * @param int $id + * @return array + */ + public function update(Request $request, $id) + { + + } + + /** + * Remove the specified resource from storage. + * + * @param int $id + * @return array + */ + public function destroy($id) + { + + } +} diff --git a/app/Http/Requests/AgentAllowRequest.php b/app/Http/Requests/AgentAllowRequest.php new file mode 100644 index 00000000..19b81a8d --- /dev/null +++ b/app/Http/Requests/AgentAllowRequest.php @@ -0,0 +1,41 @@ + 'required|string', + 'start_name' => 'required|string', + 'peer_id_pattern' => 'required|string', + 'peer_id_match_num' => 'required|numeric', + 'peer_id_matchtype' => 'required|in:hex,dec', + 'peer_id_start' => 'required|string', + 'agent_pattern' => 'required|string', + 'agent_match_num' => 'required|numeric', + 'agent_matchtype' => 'required|in:hex,dec', + 'agent_start' => 'required|string', + 'exception' => 'required|in:yes,no', + 'allowhttps' => 'required|in:yes,no', + ]; + } +} diff --git a/app/Http/Resources/UserResource.php b/app/Http/Resources/UserResource.php new file mode 100644 index 00000000..58db6d31 --- /dev/null +++ b/app/Http/Resources/UserResource.php @@ -0,0 +1,24 @@ + $this->id, + 'username' => $this->username, + 'uploaded' => $this->uploaded, + 'downloaded' => $this->downloaded, + ]; + } +} diff --git a/app/Models/NexusModel.php b/app/Models/NexusModel.php index b788b338..3b89ebdf 100644 --- a/app/Models/NexusModel.php +++ b/app/Models/NexusModel.php @@ -11,5 +11,7 @@ class NexusModel extends Model public $timestamps = false; - + protected $casts = [ + 'added' => 'datetime' + ]; } diff --git a/app/Models/User.php b/app/Models/User.php index 804799ba..48abe6ae 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -17,9 +17,7 @@ class User extends Authenticatable * @var array */ protected $fillable = [ - 'name', - 'email', - 'password', + 'username', 'email', 'passhash', 'secret', 'status', 'added' ]; /** @@ -28,8 +26,7 @@ class User extends Authenticatable * @var array */ protected $hidden = [ - 'password', - 'remember_token', + 'passhash', 'secret' ]; /** @@ -38,6 +35,6 @@ class User extends Authenticatable * @var array */ protected $casts = [ - 'email_verified_at' => 'datetime', + 'added' => 'datetime', ]; } diff --git a/app/Repositories/UserRepository.php b/app/Repositories/UserRepository.php new file mode 100644 index 00000000..53bf96e7 --- /dev/null +++ b/app/Repositories/UserRepository.php @@ -0,0 +1,86 @@ +where('email', $email)->exists(); + if ($exists) { + throw new \InvalidArgumentException("The email address: $email is already in use"); + } + if (mb_strlen($password) < 6 || mb_strlen($password) > 40) { + throw new \InvalidArgumentException("Invalid password: $password, it should be more than 6 character and less than 40 character"); + } + if ($password != $confirmPassword) { + throw new \InvalidArgumentException("confirmPassword: $confirmPassword != password: $password"); + } + $setting = get_setting('main'); + $secret = mksecret(); + $passhash = md5($secret . $password . $secret); + $insert = [ + 'username' => $username, + 'passhash' => $passhash, + 'secret' => $secret, + 'email' => $email, + 'stylesheet' => $setting['defstylesheet'], + 'status' => 'confirmed', + 'added' => now()->toDateTimeString(), + ]; + Log::info("create user: " . nexus_json_encode($insert)); + + return User::query()->create($insert); + } + + public function getList(array $params) + { + $query = User::query(); + $sortField = 'id'; + $validSortFields = ['uploaded', 'downloaded', ]; + if (!empty($params['sort']) && in_array($params['sort'], $validSortFields)) { + $sortField = $params['sort']; + } + $fields = ['id', 'username', 'avatar', 'email', 'uploaded', 'downloaded', 'class', 'added']; + if (!empty($params['fields'])) { + $fields = $params['fields']; + } + + if (!empty($params['id'])) { + $query->where('id', $params['id']); + } + if (!empty($params['username'])) { + $query->where('username', $params['username']); + } + if (!empty($params['email'])) { + $query->where('email', $params['email']); + } + + $result = $query->orderBy($sortField, 'desc')->select($fields)->paginate(); + + return $result; + + } +} \ No newline at end of file diff --git a/composer.json b/composer.json index eb1120b4..3bb03571 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,8 @@ "Database\\Seeders\\": "database/seeders/" }, "files": [ - "include/globalfunctions.php" + "include/globalfunctions.php", + "include/functions.php" ] }, "require": { diff --git a/config/logging.php b/config/logging.php index 1aa06aa3..91dd4c35 100644 --- a/config/logging.php +++ b/config/logging.php @@ -37,7 +37,7 @@ return [ 'channels' => [ 'stack' => [ 'driver' => 'stack', - 'channels' => ['single'], + 'channels' => ['daily'], 'ignore_exceptions' => false, ], diff --git a/include/bittorrent.php b/include/bittorrent.php index fd8b2ed1..67ded965 100644 --- a/include/bittorrent.php +++ b/include/bittorrent.php @@ -10,7 +10,6 @@ $showversion = " - Powered by ".PROJECTNAME; $rootpath= dirname(__DIR__); set_include_path(get_include_path() . PATH_SEPARATOR . $rootpath); $rootpath .= "/"; -require $rootpath . 'include/functions.php'; require $rootpath . 'classes/class_advertisement.php'; require $rootpath . 'classes/class_attendance.php'; require $rootpath . 'include/core.php'; diff --git a/include/core.php b/include/core.php index 4f146c3e..c9355d0e 100644 --- a/include/core.php +++ b/include/core.php @@ -11,7 +11,7 @@ if (!file_exists($rootpath . '.env')) { $installScriptRelativePath = 'install/install.php'; $installScriptFile = $rootpath . "public/$installScriptRelativePath"; if (file_exists($installScriptFile)) { - redirect($installScriptRelativePath); + nexus_redirect($installScriptRelativePath); } } require $rootpath . 'vendor/autoload.php'; diff --git a/include/functions.php b/include/functions.php index 4c79817d..45abb5b2 100644 --- a/include/functions.php +++ b/include/functions.php @@ -1251,7 +1251,7 @@ function allowedemails() return $list['value']; } -function redirect($url) +function nexus_redirect($url) { if (substr($url, 0, 4) != 'http') { $url = getSchemeAndHttpHost() . '/' . trim($url, '/'); diff --git a/include/globalfunctions.php b/include/globalfunctions.php index 72bb852f..bb763a3d 100644 --- a/include/globalfunctions.php +++ b/include/globalfunctions.php @@ -428,6 +428,12 @@ function getBaseUrl() return trim($url, '/'); } + +function nexus_json_encode($data) +{ + return json_encode($data, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES); +} + function api(...$args) { if (!isset($args[2])) { @@ -459,7 +465,7 @@ function api(...$args) 'ret' => (int)$ret, 'msg' => (string)$msg, 'data' => $data, - 'timeuse' => (float)number_format(microtime(true) - $start, 3), + 'time' => (float)number_format(microtime(true) - $start, 3), ]; } diff --git a/lang/chs/lang_clients.php b/lang/chs/lang_clients.php new file mode 100644 index 00000000..9ee2bc84 --- /dev/null +++ b/lang/chs/lang_clients.php @@ -0,0 +1,41 @@ + '客户端管理', + 'text_manage' => '管理', + 'text_add' => '添加', + 'text_client' => '客户端', + 'text_delete' => '删除', + 'text_edit' => '编辑', + 'col_id' => 'ID', + 'col_name' => 'Name', + 'col_name_help' => '仅允许数字、字母、下划线', + 'col_label' => '显示标签', + 'col_type' => '类型', + 'col_required' => '不能为空', + 'col_help' => '辅助说明', + 'col_options' => '选项', + 'col_options_help' => '类型为单选、多选、下拉时必填,一行一个,格式:选项值|选项描述文本', + 'col_action' => '操作', + 'col_is_single_row' => '展示时单独一行', + 'col_family' => '家族', + 'col_start_name' => '起始名称', + 'col_peer_id_pattern' => 'Peer 正则', + 'col_peer_id_match_num' => 'Peer 匹配次数', + 'col_peer_id_matchtype' => 'Peer 匹配类型', + 'col_peer_id_start' => 'Peer 起始', + 'col_agent_pattern' => 'Agent 正则', + 'col_agent_match_num' => 'Agent 匹配次数', + 'col_agent_matchtype' => 'Agent 匹配类型', + 'col_agent_start' => 'Agent 起始', + + 'js_sure_to_delete_this' => '你确信要删除此项目吗?', + 'submit_submit' => '提交', + 'client_type_text' => '短文本', + 'client_type_textarea' => '长文本', + 'client_type_radio' => '横向单选', + 'client_type_checkbox' => '横向多选', + 'client_type_select' => '下拉单选', + 'client_type_image' => '图片', + +]; \ No newline at end of file diff --git a/nexus/Client/Client.php b/nexus/Client/Client.php new file mode 100644 index 00000000..242b2440 --- /dev/null +++ b/nexus/Client/Client.php @@ -0,0 +1,463 @@ + [ + 'table' => 'agent_allowed_family', + 'table_columns' => [ + 'id', 'family', 'start_name', +// 'peer_id_pattern', 'peer_id_match_num', 'peer_id_matchtype', 'peer_id_start', + 'agent_pattern', 'agent_match_num', 'agent_matchtype', 'agent_start', + ], + 'form_fields' => [ + 'family', 'start_name', + 'peer_id_pattern', 'peer_id_match_num', 'peer_id_matchtype', 'peer_id_start', + 'agent_pattern', 'agent_match_num', 'agent_matchtype', 'agent_start', + 'exception', 'allowhttps', 'comment', + ], + ], + ]; + + private $type; + + public function __construct($type) + { + if (!isset(self::$types[$type])) { + throw new \InvalidArgumentException("Invalid type: $type"); + } + $this->type = $type; + } + + public function getTypeHuman($type) + { + global $lang_fields; + $map = [ + self::TYPE_TEXT => $lang_fields['field_type_text'], + self::TYPE_TEXTAREA => $lang_fields['field_type_textarea'], + self::TYPE_RADIO => $lang_fields['field_type_radio'], + self::TYPE_CHECKBOX => $lang_fields['field_type_checkbox'], + self::TYPE_SELECT => $lang_fields['field_type_select'], + self::TYPE_IMAGE => $lang_fields['field_type_image'], + ]; + return $map[$type] ?? ''; + } + + public function getTypeRadioOptions() + { + $out = []; + foreach (self::$types as $key => $value) { + $out[$key] = sprintf('%s(%s)', $value['text'], $this->getTypeHuman($key)); + } + return $out; + } + + + public function radio($name, $options, $current = null) + { + $arr = []; + foreach ($options as $value => $label) { + $arr[] = sprintf( + '', + $name, $value, (string)$current === (string)$value ? ' checked' : '', $label + ); + } + return implode('', $arr); + } + + function buildFieldForm(array $row = []) + { + global $lang_fields, $lang_functions; + $trName = tr($lang_fields['col_name'] . '*', '  ' . $lang_fields['col_name_help'], 1, '', true); + $trLabel = tr($lang_fields['col_label'] . '*', '', 1, '', true); + $trType = tr($lang_fields['col_type'] . '*', $this->radio('type', $this->getTypeRadioOptions(), $row['type'] ?? null), 1, '', true); + $trRequired = tr($lang_fields['col_required'] . '*', $this->radio('required', ['0' => $lang_functions['text_no'], '1' => $lang_functions['text_yes']], $row['required'] ?? null), 1, '', true); + $trHelp = tr($lang_fields['col_help'], '', 1, '', true); + $trOptions = tr($lang_fields['col_options'], '
' . $lang_fields['col_options_help'], 1, '', true); + $trIsSingleRow = tr($lang_fields['col_is_single_row'] . '*', $this->radio('is_single_row', ['0' => $lang_functions['text_no'], '1' => $lang_functions['text_yes']], $row['is_single_row'] ?? null), 1, '', true); + $id = $row['id'] ?? 0; + $form = << +

{$lang_fields['text_field']}

+
+
+ + + {$trName} + {$trLabel} + {$trType} + {$trRequired} + {$trHelp} + {$trOptions} + {$trIsSingleRow} +
+
+
+ +
+
+ +HTML; + return $form; + } + + private function getHeader() + { + global $lang_clients; + $header = []; + foreach (self::$types[$this->type]['table_columns'] as $column) { + $header[$column] = $lang_clients['col_' . $column] ?? ucfirst($column); + } + $header['action'] = $lang_clients['col_action']; + return $header; + } + + function buildClientTable() + { + global $lang_clients, $lang_functions; + $tableName = self::$types[$this->type]['table']; + $perPage = 10; + $total = get_row_count($tableName); + list($paginationTop, $paginationBottom, $limit) = pager($perPage, $total, "?"); + $sql = "select * from $tableName order by family asc $limit"; + $res = sql_query($sql); + $header = $this->getHeader(); + $rows = []; + while ($row = mysql_fetch_assoc($res)) { + $row['action'] = sprintf( + "%s | %s", + $row['id'], $lang_clients['js_sure_to_delete_this'], $lang_clients['text_delete'], $row['id'], $lang_clients['text_edit'] + ); + $rows[] = $row; + } + $head = <<{$lang_clients['client_management']} +
+ + {$lang_clients['text_add']} + +
+HEAD; + $table = $this->buildTable($header, $rows); + return $head . $table . $paginationBottom; + } + + public function save($data) + { + global $lang_functions, $lang_fields; + $attributes = []; + if (empty($data['name'])) { + throw new \InvalidArgumentException("{$lang_fields['col_name']} {$lang_functions['text_required']}"); + } + if (!preg_match('/^\w+$/', $data['name'])) { + throw new \InvalidArgumentException("{$lang_fields['col_name']} {$lang_functions['text_invalid']}"); + } + $attributes['name'] = $data['name']; + + if (empty($data['label'])) { + throw new \InvalidArgumentException("{$lang_fields['col_label']} {$lang_functions['text_required']}"); + } + $attributes['label'] = $data['label']; + + if (empty($data['type'])) { + throw new \InvalidArgumentException("{$lang_fields['col_type']} {$lang_functions['text_required']}"); + } + if (!isset(self::$types[$data['type']])) { + throw new \InvalidArgumentException("{$lang_fields['col_type']} {$lang_functions['text_invalid']}"); + } + $attributes['type'] = $data['type']; + + if (!isset($data['required'])) { + throw new \InvalidArgumentException("{$lang_fields['col_required']} {$lang_functions['text_required']}"); + } + if (!in_array($data['required'], ["0", "1"], true)) { + throw new \InvalidArgumentException("{$lang_fields['col_name']} {$lang_functions['text_invalid']}"); + } + $attributes['required'] = $data['required']; + + if (!isset($data['is_single_row'])) { + throw new \InvalidArgumentException("{$lang_fields['col_is_single_row']} {$lang_functions['text_required']}"); + } + if (!in_array($data['is_single_row'], ["0", "1"], true)) { + throw new \InvalidArgumentException("{$lang_fields['col_is_single_row']} {$lang_functions['text_invalid']}"); + } + $attributes['is_single_row'] = $data['is_single_row']; + + $attributes['help'] = $data['help'] ?? ''; + $attributes['options'] = trim($data['options'] ?? ''); + $now = date('Y-m-d H:i:s'); + $attributes['updated_at'] = $now; + $table = 'torrents_custom_fields'; + if (!empty($data['id'])) { + $result = DB::update($table, $attributes, "id = " . sqlesc($data['id'])); + } else { + $attributes['created_at'] = $now; + $result = DB::insert($table, $attributes); + } + return $result; + } + + + public function buildFieldCheckbox($name, $current = []) + { + $sql = 'select * from torrents_custom_fields'; + $res = sql_query($sql); + if (!is_array($current)) { + $current = explode(',', $current); + } + $checkbox = ''; + while ($row = mysql_fetch_assoc($res)) { + $checkbox .= sprintf( + '', + $name, $row['id'], in_array($row['id'], $current) ? ' checked' : '', "{$row['name']}[{$row['label']}]" + ); + } + $checkbox .= ''; + return $checkbox; + + } + + public function renderOnUploadPage($torrentId = 0) + { + global $browsecatmode; + $searchBox = DB::getOne('searchbox', "id = $browsecatmode"); + if (empty($searchBox)) { + throw new \RuntimeException("Invalid search box: $browsecatmode"); + } + $customValues = $this->listTorrentCustomField($torrentId); + $sql = sprintf('select * from torrents_custom_fields where id in (%s)', $searchBox['custom_fields'] ?: 0); + $res = sql_query($sql); + $html = ''; + while ($row = mysql_fetch_assoc($res)) { + $name = "custom_fields[{$row['id']}]"; + $currentValue = $customValues[$row['id']]['custom_field_value'] ?? ''; + if ($row['type'] == self::TYPE_TEXT) { + $html .= tr($row['label'], sprintf('', $name, $currentValue), 1); + } elseif ($row['type'] == self::TYPE_TEXTAREA) { + $html .= tr($row['label'], sprintf('', $name, $currentValue), 1); + } elseif ($row['type'] == self::TYPE_RADIO || $row['type'] == self::TYPE_CHECKBOX) { + if ($row['type'] == self::TYPE_CHECKBOX) { + $name .= '[]'; + } + $part = ""; + foreach (preg_split('/[\r\n]+/', trim($row['options'])) as $option) { + if (empty($option) || ($pos = strpos($option, '|')) === false) { + continue; + } + $value = substr($option, 0, $pos); + $label = substr($option, $pos + 1); + $checked = ""; + if ($row['type'] == self::TYPE_RADIO && (string)$currentValue === (string)$value) { + $checked = " checked"; + } + if ($row['type'] == self::TYPE_CHECKBOX && in_array($value, (array)$currentValue)) { + $checked = " checked"; + } + $part .= sprintf( + '', + $row['type'], $name, $value, $checked, $label + ); + } + $html .= tr($row['label'], $part, 1); + } elseif ($row['type'] == self::TYPE_SELECT) { + $part = ''; + $html .= tr($row['label'], $part, 1); + } elseif ($row['type'] == self::TYPE_IMAGE) { + $callbackFunc = "preview_custom_field_image_" . $row['id']; + $iframeId = "iframe_$callbackFunc"; + $inputId = "input_$callbackFunc"; + $imgId = "attach" . $row['id']; + $previewBoxId = "preview_$callbackFunc"; + $y = ''; + $y .= sprintf('', $inputId, $name, $currentValue); + $y .= '
'; + if (!empty($currentValue)) { + if (substr($currentValue, 0, 4) == 'http') { + $y .= formatImg($currentValue, true, 700, 0, $imgId); + } else { + $y .= format_comment($currentValue); + } + } + $y .= '
'; + $y .= << + function {$callbackFunc}(delkey, url) + { + var previewBox = $('$previewBoxId') + var existsImg = $('$imgId') + var input = $('$inputId') + if (existsImg) { + previewBox.removeChild(existsImg) + input.value = '' + } + var img = document.createElement('img') + img.src=url + img.setAttribute('onload', 'Scale(this, 700, 0);') + img.setAttribute('onclick', 'Preview(this);') + input.value = '[attach]' + delkey + '[/attach]' + img.id='$imgId' + previewBox.appendChild(img) + } + +JS; + $html .= tr($row['label'], $y, 1); + } + } + return $html; + } + + public function listTorrentCustomField($torrentId, $searchBoxId = 0) + { + global $browsecatmode; + if ($searchBoxId <= 0) { + $searchBoxId = $browsecatmode; + } + //suppose torrentId is array + $isArray = true; + $torrentIdArr = $torrentId; + if (!is_array($torrentId)) { + $isArray = false; + $torrentIdArr = [$torrentId]; + } + $torrentIdStr = implode(',', $torrentIdArr); + $res = sql_query("select f.*, v.custom_field_value, v.torrent_id from torrents_custom_field_values v inner join torrents_custom_fields f on v.custom_field_id = f.id inner join searchbox box on box.id = $searchBoxId and find_in_set(f.id, box.custom_fields) where torrent_id in ($torrentIdStr)"); + $values = []; + $result = []; + while ($row = mysql_fetch_assoc($res)) { + $typeInfo = self::$types[$row['type']]; + if ($typeInfo['has_option']) { + $options = preg_split('/[\r\n]+/', trim($row['options'])); + $optionsArr = []; + foreach ($options as $option) { + $pos = strpos($option, '|'); + $value = substr($option, 0, $pos); + $label = substr($option, $pos + 1); + $optionsArr[$value] = $label; + } + $row['options'] = $optionsArr; + } + $result[$row['torrent_id']][$row['id']] = $row; + if ($typeInfo['is_value_multiple']) { + $values[$row['torrent_id']][$row['id']][] = $row['custom_field_value']; + } else { + $values[$row['torrent_id']][$row['id']] = $row['custom_field_value']; + } + } + foreach ($result as $tid => &$fields) { + foreach ($fields as &$field) { + $field['custom_field_value'] = $values[$tid][$field['id']]; + } + } + return $isArray ? $result : ($result[$torrentId] ?? []); + } + + public function renderOnTorrentDetailsPage($torrentId) + { + global $browsecatmode; + $displayName = get_searchbox_value($browsecatmode, 'custom_fields_display_name'); + $display = get_searchbox_value($browsecatmode, 'custom_fields_display'); + $customFields = $this->listTorrentCustomField($torrentId); +// dd($displayName, $display, $customFields); + $mixedRowContent = nl2br($display); + $rowByRowHtml = ''; + foreach ($customFields as $field) { + $content = $this->formatCustomFieldValue($field); + $mixedRowContent = str_replace("<%{$field['name']}.label%>", $field['label'], $mixedRowContent); + $mixedRowContent = str_replace("<%{$field['name']}.value%>", $content, $mixedRowContent); + if ($field['is_single_row']) { + $rowByRowHtml .= tr($field['label'], $content, 1); + } + } + $result = $rowByRowHtml; + if (!empty($mixedRowContent)) { + $result .= tr($displayName, $mixedRowContent, 1); + } + return $result; + } + + + + protected function formatCustomFieldValue(array $customFieldWithValue) + { + $result = ''; + $fieldValue = $customFieldWithValue['custom_field_value']; + switch ($customFieldWithValue['type']) { + case self::TYPE_TEXT: + case self::TYPE_TEXTAREA: + $result .= format_comment($fieldValue); + break; + case self::TYPE_IMAGE: + if (substr($fieldValue, 0, 4) == 'http') { + $result .= formatImg($fieldValue, true, 700, 0, "attach{$customFieldWithValue['id']}"); + } else { + $result .= format_comment($fieldValue); + } + break; + case self::TYPE_RADIO: + case self::TYPE_CHECKBOX: + case self::TYPE_SELECT; + $fieldContent = []; + foreach ((array)$fieldValue as $item) { + $fieldContent[] = $customFieldWithValue['options'][$item] ?? ''; + } + $result .= implode(' ', $fieldContent); + break; + default: + break; + } + return $result; + } + + public function prepareTorrents(array $torrentIdArr) + { + $customFieldValues = $this->listTorrentCustomField($torrentIdArr); + $result = []; + foreach ($customFieldValues as $tid => &$customFields) { + foreach ($customFields as &$field) { + $field['custom_field_value_formatted'] = $this->formatCustomFieldValue($field); + $result[$tid][$field['name']] = $field; + } + } + $this->preparedTorrentCustomFieldValues = $result; + } + + public function getPreparedTorrent($torrentId = null, $fieldName = null) + { + if (is_null($torrentId)) { + return $this->preparedTorrentCustomFieldValues; + } + if (is_null($fieldName)) { + return $this->preparedTorrentCustomFieldValues[$torrentId] ?? []; + } + return $this->preparedTorrentCustomFieldValues[$torrentId][$fieldName] ?? ''; + } + + + + +} \ No newline at end of file diff --git a/nexus/Core/Management.php b/nexus/Core/Management.php new file mode 100644 index 00000000..46341bfa --- /dev/null +++ b/nexus/Core/Management.php @@ -0,0 +1,26 @@ +'; + foreach ($header as $key => $value) { + $table .= sprintf('%s', $value); + } + $table .= ''; + foreach ($rows as $row) { + $table .= ''; + foreach ($header as $headerKey => $headerValue) { + $table .= sprintf('%s', $row[$headerKey] ?? ''); + } + $table .= ''; + } + $table .= ''; + return $table; + } + + +} \ No newline at end of file diff --git a/nexus/Install/Install.php b/nexus/Install/Install.php index f16a0794..92fedb52 100644 --- a/nexus/Install/Install.php +++ b/nexus/Install/Install.php @@ -261,7 +261,7 @@ class Install public function gotoStep($step) { - redirect(getBaseUrl() . "?step=$step"); + nexus_redirect(getBaseUrl() . "?step=$step"); } public function maxStep() diff --git a/public/clients.php b/public/clients.php new file mode 100644 index 00000000..cf6997f0 --- /dev/null +++ b/public/clients.php @@ -0,0 +1,58 @@ +buildClientTable(); + echo $r; + stdfoot(); +} elseif ($action == 'add') { + stdhead($lang_clients['field_management']." - ".$lang_clients['text_add']); + begin_main_frame(); + echo $client->buildFieldForm(); +} elseif ($action == 'submit') { + try { + $result = $client->save($_REQUEST); + nexus_redirect('clients.php?action=view'); + } catch (\Exception $e) { + stderr($lang_clients['field_management'], $e->getMessage()); + } +} elseif ($action == 'edit') { + $id = intval($_GET['id'] ?? 0); + if ($id == 0) { + stderr($lang_clients['field_management'], "Invalid id"); + } + $sql = "select * from torrents_custom_fields where id = $id"; + $res = sql_query($sql); + $row = mysql_fetch_assoc($res); + if (empty($row)) { + stderr('', 'Invalid id'); + } + stdhead($lang_clients['field_management']." - ".$lang_clients['text_edit']); + begin_main_frame(); + echo $client->buildFieldForm($row); +} elseif ($action == 'del') { + $id = intval($_GET['id'] ?? 0); + if ($id == 0) { + stderr($lang_clients['field_management'], "Invalid id"); + } + $sql = "delete from torrents_custom_fields where id = $id"; + $res = sql_query($sql); + nexus_redirect('clients.php?action=view'); +} + + + diff --git a/public/fields.php b/public/fields.php index c534c005..6144876c 100644 --- a/public/fields.php +++ b/public/fields.php @@ -23,7 +23,7 @@ if ($action == 'view') { } elseif ($action == 'submit') { try { $result = $field->save($_REQUEST); - redirect('fields.php?action=view'); + nexus_redirect('fields.php?action=view'); } catch (\Exception $e) { stderr($lang_fields['field_management'], $e->getMessage()); } @@ -48,7 +48,7 @@ if ($action == 'view') { } $sql = "delete from torrents_custom_fields where id = $id"; $res = sql_query($sql); - redirect('fields.php?action=view'); + nexus_redirect('fields.php?action=view'); } diff --git a/public/maxlogin.php b/public/maxlogin.php index c6f57478..dd7f9ec0 100644 --- a/public/maxlogin.php +++ b/public/maxlogin.php @@ -21,7 +21,7 @@ function safe_query ($query,$id,$where = '') { $result = sql_query($query); if (!$result) return sqlerr(__FILE__,__LINE__); - redirect("maxlogin.php?update=".htmlspecialchars($where)); + nexus_redirect("maxlogin.php?update=".htmlspecialchars($where)); } function searchform () { ?> diff --git a/public/mybonus.php b/public/mybonus.php index a9b381ce..e6dc9dd0 100644 --- a/public/mybonus.php +++ b/public/mybonus.php @@ -333,7 +333,7 @@ if ($action == "exchange") { $up = $upload + $bonusarray['menge']; $bonuscomment = date("Y-m-d") . " - " .$points. " Points for upload bonus.\n " .$bonuscomment; sql_query("UPDATE users SET uploaded = ".sqlesc($up).", seedbonus = seedbonus - $points, bonuscomment = ".sqlesc($bonuscomment)." WHERE id = ".sqlesc($userid)) or sqlerr(__FILE__, __LINE__); - redirect("" . get_protocol_prefix() . "$BASEURL/mybonus.php?do=upload"); + nexus_redirect("" . get_protocol_prefix() . "$BASEURL/mybonus.php?do=upload"); } } //=== trade for one month VIP status ***note "SET class = '10'" change "10" to whatever your VIP class number is @@ -346,7 +346,7 @@ if ($action == "exchange") { $vip_until = date("Y-m-d H:i:s",(strtotime(date("Y-m-d H:i:s")) + 28*86400)); $bonuscomment = date("Y-m-d") . " - " .$points. " Points for 1 month VIP Status.\n " .htmlspecialchars($bonuscomment); sql_query("UPDATE users SET class = '".UC_VIP."', vip_added = 'yes', vip_until = ".sqlesc($vip_until).", seedbonus = seedbonus - $points WHERE id = ".sqlesc($userid)) or sqlerr(__FILE__, __LINE__); - redirect("" . get_protocol_prefix() . "$BASEURL/mybonus.php?do=vip"); + nexus_redirect("" . get_protocol_prefix() . "$BASEURL/mybonus.php?do=vip"); } //=== trade for invites elseif($art == "invite") { @@ -356,7 +356,7 @@ if ($action == "exchange") { $inv = $invites+$bonusarray['menge']; $bonuscomment = date("Y-m-d") . " - " .$points. " Points for invites.\n " .htmlspecialchars($bonuscomment); sql_query("UPDATE users SET invites = ".sqlesc($inv).", seedbonus = seedbonus - $points WHERE id = ".sqlesc($userid)) or sqlerr(__FILE__, __LINE__); - redirect("" . get_protocol_prefix() . "$BASEURL/mybonus.php?do=invite"); + nexus_redirect("" . get_protocol_prefix() . "$BASEURL/mybonus.php?do=invite"); } //=== trade for special title /**** the $words array are words that you DO NOT want the user to have... use to filter "bad words" & user class... @@ -370,7 +370,7 @@ if ($action == "exchange") { $title = str_replace($words, $lang_mybonus['text_wasted_karma'], $title); $bonuscomment = date("Y-m-d") . " - " .$points. " Points for custom title. Old title is ".htmlspecialchars(trim($CURUSER["title"]))." and new title is $title\n " .htmlspecialchars($bonuscomment); sql_query("UPDATE users SET title = $title, seedbonus = seedbonus - $points, bonuscomment = ".sqlesc($bonuscomment)." WHERE id = ".sqlesc($userid)) or sqlerr(__FILE__, __LINE__); - redirect("" . get_protocol_prefix() . "$BASEURL/mybonus.php?do=title"); + nexus_redirect("" . get_protocol_prefix() . "$BASEURL/mybonus.php?do=title"); } elseif($art == "noad" && $enablead_advertisement == 'yes' && $enablebonusnoad_advertisement == 'yes') { if (($enablenoad_advertisement == 'yes' && get_user_class() >= $noad_advertisement) || strtotime($CURUSER['noaduntil']) >= TIMENOW || get_user_class() < $bonusnoad_advertisement) @@ -379,7 +379,7 @@ if ($action == "exchange") { $noaduntil = date("Y-m-d H:i:s",(TIMENOW + $bonusarray['menge'])); $bonuscomment = date("Y-m-d") . " - " .$points. " Points for ".$bonusnoadtime_advertisement." days without ads.\n " .htmlspecialchars($bonuscomment); sql_query("UPDATE users SET noad='yes', noaduntil='".$noaduntil."', seedbonus = seedbonus - $points, bonuscomment = ".sqlesc($bonuscomment)." WHERE id=".sqlesc($userid)); - redirect("" . get_protocol_prefix() . "$BASEURL/mybonus.php?do=noad"); + nexus_redirect("" . get_protocol_prefix() . "$BASEURL/mybonus.php?do=noad"); } } elseif($art == 'gift_2') // charity giving @@ -404,7 +404,7 @@ if ($action == "exchange") { sql_query("UPDATE users SET seedbonus = seedbonus - $points, charity = charity + $points, bonuscomment = ".sqlesc($bonuscomment)." WHERE id = ".sqlesc($userid)) or sqlerr(__FILE__, __LINE__); $charityPerUser = $points/$charityReceiverCount; sql_query("UPDATE users SET seedbonus = seedbonus + $charityPerUser WHERE enabled='yes' AND 10737418240 < downloaded AND $ratiocharity > uploaded/downloaded") or sqlerr(__FILE__, __LINE__); - redirect("" . get_protocol_prefix() . "$BASEURL/mybonus.php?do=charity"); + nexus_redirect("" . get_protocol_prefix() . "$BASEURL/mybonus.php?do=charity"); } else { @@ -466,7 +466,7 @@ if ($action == "exchange") { $msg = sqlesc($msg); sql_query("INSERT INTO messages (sender, subject, receiver, msg, added) VALUES(0, $subject, $useridgift, $msg, $added)") or sqlerr(__FILE__, __LINE__); $usernamegift = unesc($_POST["username"]); - redirect("" . get_protocol_prefix() . "$BASEURL/mybonus.php?do=transfer"); + nexus_redirect("" . get_protocol_prefix() . "$BASEURL/mybonus.php?do=transfer"); } else{ print(""); diff --git a/routes/api.php b/routes/api.php index e4c5ad13..2b0da44e 100644 --- a/routes/api.php +++ b/routes/api.php @@ -16,4 +16,5 @@ use Illuminate\Support\Facades\Route; Route::group([], function () { Route::resource('agent-allow', \App\Http\Controllers\AgentAllowController::class); + Route::resource('user', \App\Http\Controllers\UserController::class); });

".$lang_mybonus['text_oups']."