Skip to content

feat: use lib side check of valid lengths and prevent invalid requests being sent. #124

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 17 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions pyrogram/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,8 @@ def __init__(
self.message_cache = Cache(self.max_message_cache_size)
self.business_user_connection_cache = Cache(self.max_business_user_connection_cache_size)

self.app_constant: dict[str, "types.ClientConfigurationOption"] = {}

# Sometimes, for some reason, the server will stop sending updates and will only respond to pings.
# This watchdog will invoke updates.GetState in order to wake up the server and enable it sending updates again
# after some idle time has been detected.
Expand Down
2 changes: 2 additions & 0 deletions pyrogram/methods/bots/answer_inline_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ async def answer_inline_query(
InputTextMessageContent("Message content"))])
"""

utils.check_valid_length(client=self, text=results, arg_type="inline_query_results_max")

return await self.invoke(
raw.functions.messages.SetInlineBotResults(
query_id=int(inline_query_id),
Expand Down
9 changes: 7 additions & 2 deletions pyrogram/methods/chats/set_administrator_title.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.

from typing import Union
from typing import Optional, Union

import pyrogram
from pyrogram import raw
Expand All @@ -27,7 +27,7 @@ async def set_administrator_title(
self: "pyrogram.Client",
chat_id: Union[int, str],
user_id: Union[int, str],
title: str,
title: Optional[str] = None,
) -> bool:
"""Set a custom title (rank) to an administrator of a supergroup.

Expand All @@ -45,6 +45,7 @@ async def set_administrator_title(
For a contact that exists in your Telegram address book you can use his phone number (str).

title (``str``, *optional*):
New custom title for the administrator; 0-16 characters, emoji are not allowed.
A custom title that will be shown to all members instead of "Owner" or "Admin".
Pass None or "" (empty string) to remove the custom title.

Expand All @@ -56,6 +57,10 @@ async def set_administrator_title(

await app.set_administrator_title(chat_id, user_id, "Admin Title")
"""

if title:
utils.check_valid_length(client=self, text=title, arg_type="administrator_title_length_max")

chat_id = await self.resolve_peer(chat_id)
user_id = await self.resolve_peer(user_id)

Expand Down
1 change: 1 addition & 0 deletions pyrogram/methods/messages/edit_message_text.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ async def edit_message_text(
)
)
"""

if disable_web_page_preview and link_preview_options:
raise ValueError(
"Parameters `disable_web_page_preview` and `link_preview_options` are mutually "
Expand Down
4 changes: 4 additions & 0 deletions pyrogram/methods/messages/send_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ async def send_message(
]
]))
"""

if disable_web_page_preview and link_preview_options:
raise ValueError(
"Parameters `disable_web_page_preview` and `link_preview_options` are mutually "
Expand Down Expand Up @@ -196,6 +197,9 @@ async def send_message(
)
message, entities = (await utils.parse_text_entities(self, text, parse_mode, entities)).values()

if message:
utils.check_valid_length(client=self, text=message, arg_type="message_length_max")

session = None
business_connection = None
if business_connection_id:
Expand Down
6 changes: 6 additions & 0 deletions pyrogram/methods/users/update_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ async def update_profile(
await app.update_profile(last_name="")
"""

for var_name in ("first_name", "last_name",):
if var_value := locals()[var_name]:
utils.check_valid_length(client=self, text=var_value, arg_type="name_length_max")
if bio:
utils.check_valid_length(client=self, text=bio, arg_type="about_length_max")

return bool(
await self.invoke(
raw.functions.account.UpdateProfile(
Expand Down
55 changes: 53 additions & 2 deletions pyrogram/session/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
from io import BytesIO

import pyrogram
from pyrogram import raw
from pyrogram import raw, types
from pyrogram.connection import Connection
from pyrogram.crypto import mtproto
from pyrogram.errors import (
Expand Down Expand Up @@ -125,7 +125,7 @@ async def start(self):
await self.send(raw.functions.Ping(ping_id=0), timeout=self.START_TIMEOUT)

if not self.is_cdn:
await self.send(
cfg = await self.send(
raw.functions.InvokeWithLayer(
layer=layer,
query=raw.functions.InitConnection(
Expand All @@ -146,6 +146,57 @@ async def start(self):
),
timeout=self.START_TIMEOUT
)
if isinstance(cfg, raw.types.Config): # TODO
for key in [
"chat_size_max",
"megagroup_size_max",
"forwarded_count_max",
"online_update_period_ms",
"online_cloud_timeout_ms",
"edit_time_limit",
"revoke_time_limit",
"revoke_pm_time_limit",
"stickers_recent_limit",
"channels_read_media_period",
"me_url_prefix",
"caption_length_max",
"message_length_max",
"gif_search_username",
"venue_search_username",
"img_search_username",
"autologin_token",
]:
self.client.app_constant[
key
] = types.ClientConfigurationOption(
key=key,
value=getattr(cfg, key, None)
) if getattr(cfg, key, None) else None
self.client.app_constant[
"name_length_max"
] = types.ClientConfigurationOption(
key="name_length_max",
value=64
)
self.client.app_constant[
"administrator_title_length_max"
] = types.ClientConfigurationOption(
key="administrator_title_length_max",
value=16
)
self.client.app_constant[
"inline_query_results_max"
] = types.ClientConfigurationOption(
key="inline_query_results_max",
value=50
)
# TODO
self.client.app_constant[
"about_length_max"
] = types.ClientConfigurationOption(
key="about_length_max",
value=70, # 140
)

self.ping_task = self.loop.create_task(self.ping_worker())

Expand Down
1 change: 1 addition & 0 deletions pyrogram/types/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from .bots_and_keyboards import *
from .chat_drafts import *
from .chat_topics import *
from .client_configuration import *
from .inline_mode import *
from .input_media import *
from .input_paid_media import *
Expand Down
2 changes: 1 addition & 1 deletion pyrogram/types/chat_topics/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2017-present <https://github.com/TelegramPlayGround>
#
# This file is part of Pyrogram.
#
Expand Down
24 changes: 24 additions & 0 deletions pyrogram/types/client_configuration/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present <https://github.com/TelegramPlayGround>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.

from .client_configuration_option import ClientConfigurationOption


__all__ = [
"ClientConfigurationOption",
]
46 changes: 46 additions & 0 deletions pyrogram/types/client_configuration/client_configuration_option.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present <https://github.com/TelegramPlayGround>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.


from typing import Optional, Union

from ..object import Object


class ClientConfigurationOption(Object):
"""This object represents the value of an option.

Parameters:
key (``str``):
The name of the option.

value (``bool`` | ``int`` | ``str``, *optional*):
The value of the option. Can be None if it is an unknown option or an option which has a default value.

"""

def __init__(
self,
*,
key: str = None,
value: Union[bool, int, str] = None,
):
super().__init__()

self.key = key
self.value = value
19 changes: 19 additions & 0 deletions pyrogram/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -659,3 +659,22 @@ def is_list_like(obj):
Ported from https://github.com/LonamiWebs/Telethon/blob/1cb5ff1dd54ecfad41711fc5a4ecf36d2ad8eaf6/telethon/utils.py#L902
"""
return isinstance(obj, (list, tuple, set, dict, range))


def check_valid_length(
client: "pyrogram.Client",
text: Union[list, str],
arg_type: str,
):
if not isinstance(text, (str, list)):
raise ValueError(f"Argument {arg_type} must be a str | list")

text_length = len(text)
max_length = client.app_constant.get(arg_type)

if not max_length:
raise ValueError(f"Argument {arg_type} is not supported")

error_info = f"\nInvalid length of {text_length} for arg {arg_type}\nValid Length: {max_length.value}"

assert bool(text_length <= max_length.value), error_info