<commit_before>package org.araymond.joal.ttorent.common.protocol.http;


import com.turn.ttorrent.bcodec.BDecoder;
import com.turn.ttorrent.bcodec.BEValue;
import com.turn.ttorrent.bcodec.BEncoder;
import com.turn.ttorrent.bcodec.InvalidBEncodingException;
import com.turn.ttorrent.common.Peer;
import com.turn.ttorrent.common.Torrent;
import com.turn.ttorrent.common.protocol.TrackerMessage.AnnounceRequestMessage;
import com.turn.ttorrent.common.protocol.http.HTTPTrackerMessage;
import org.araymond.joal.client.emulated.EmulatedClient;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.ByteBuffer;
import java.util.LinkedHashMap;
import java.util.Map;


/**
 * The announce request message for the HTTP tracker protocol.
 * <p>
 * <p>
 * This class represents the announce request message in the HTTP tracker
 * protocol. It doesn't add any specific fields compared to the generic
 * announce request message, but it provides the means to parse such
 * messages and craft them.
 * </p>
 *
 * @author mpetazzoni
 */
public final class HTTPAnnounceRequestMessage extends HTTPTrackerMessage implements AnnounceRequestMessage {

    private final byte[] infoHash;
    private final Peer peer;
    private final long uploaded;
    private final long downloaded;
    private final long left;
    private final boolean compact;
    private final boolean noPeerId;
    private final RequestEvent event;
    private final int numWant;

    private HTTPAnnounceRequestMessage(final ByteBuffer data, final byte[] infoHash, final Peer peer, final long uploaded, final long downloaded, final long left, final boolean compact, final boolean noPeerId, final RequestEvent event, final int numWant) {
        super(Type.ANNOUNCE_REQUEST, data);
        this.infoHash = infoHash;
        this.peer = peer;
        this.downloaded = downloaded;
        this.uploaded = uploaded;
        this.left = left;
        this.compact = compact;
        this.noPeerId = noPeerId;
        this.event = event;
        this.numWant = numWant;
    }

    @Override
    public byte[] getInfoHash() {
        return this.infoHash;
    }

    @Override
    public String getHexInfoHash() {
        return Torrent.byteArrayToHexString(this.infoHash);
    }

    @Override
    public byte[] getPeerId() {
        return this.peer.getPeerId().array();
    }

    @Override
    public String getHexPeerId() {
        return this.peer.getHexPeerId();
    }

    @Override
    public int getPort() {
        return this.peer.getPort();
    }

    @Override
    public long getUploaded() {
        return this.uploaded;
    }

    @Override
    public long getDownloaded() {
        return this.downloaded;
    }

    @Override
    public long getLeft() {
        return this.left;
    }

    @Override
    public boolean getCompact() {
        return this.compact;
    }

    @Override
    public boolean getNoPeerIds() {
        return this.noPeerId;
    }

    @Override
    public RequestEvent getEvent() {
        return this.event;
    }

    @Override
    public String getIp() {
        return this.peer.getIp();
    }

    @Override
    public int getNumWant() {
        return this.numWant;
    }

    /**
     * Build the announce request URL for the given tracker announce URL.
     *
     * @param trackerAnnounceURL The tracker's announce URL.
     * @return The URL object representing the announce request URL.
     */
    public URL buildAnnounceURL(final URL trackerAnnounceURL, final EmulatedClient emulatedClient) throws UnsupportedEncodingException, MalformedURLException {
        final String base = trackerAnnounceURL.toString();
        String emulatedClientQuery = emulatedClient.getQuery()
                .replaceAll("\\{infohash}", URLEncoder.encode(new String(this.getInfoHash(), Torrent.BYTE_ENCODING), Torrent.BYTE_ENCODING))
                .replaceAll("\\{peerid}", URLEncoder.encode(new String(this.getPeerId(), Torrent.BYTE_ENCODING), Torrent.BYTE_ENCODING))
                .replaceAll("\\{uploaded}", String.valueOf(this.getUploaded()))
                .replaceAll("\\{downloaded}", String.valueOf(this.getDownloaded()))
                .replaceAll("\\{left}", String.valueOf(this.getLeft()))
                .replaceAll("\\{numwant}", String.valueOf(emulatedClient.getNumwant().orElse(HTTPAnnounceRequestMessage.DEFAULT_NUM_WANT)))
                .replaceAll("\\{port}", String.valueOf(this.getPort()))
                .replaceAll("\\{ip}", this.getIp());


        if (emulatedClientQuery.contains("{key}")) {
            emulatedClientQuery = emulatedClientQuery
                    .replaceAll("\\{key}", URLEncoder.encode(emulatedClient.getKey().get(), Torrent.BYTE_ENCODING));
        }
        if (this.getEvent() == null || RequestEvent.NONE != this.getEvent()) {
            // if event was NONE, remove the event from the query string
            emulatedClientQuery = emulatedClientQuery.replaceAll("(event=\\{event})", "");
        } else {
            emulatedClientQuery = emulatedClientQuery.replaceAll("\\{event}", this.getEvent().getEventName());
        }

        final String url = base + (base.contains("?") ? "&" : "?") + emulatedClientQuery;

        return new URL(url);
    }

    public static HTTPAnnounceRequestMessage parse(final ByteBuffer data)
            throws IOException, MessageValidationException {
        final BEValue decoded = BDecoder.bdecode(data);
        if (decoded == null) {
            throw new MessageValidationException(
                    "Could not decode tracker message (not B-encoded?)!");<commit_msg>Fix a if condition to fix missing event in tracker request.<commit_after>package org.araymond.joal.ttorent.common.protocol.http;


import com.turn.ttorrent.bcodec.BDecoder;
import com.turn.ttorrent.bcodec.BEValue;
import com.turn.ttorrent.bcodec.BEncoder;
import com.turn.ttorrent.bcodec.InvalidBEncodingException;
import com.turn.ttorrent.common.Peer;
import com.turn.ttorrent.common.Torrent;
import com.turn.ttorrent.common.protocol.TrackerMessage.AnnounceRequestMessage;
import com.turn.ttorrent.common.protocol.http.HTTPTrackerMessage;
import org.araymond.joal.client.emulated.EmulatedClient;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.ByteBuffer;
import java.util.LinkedHashMap;
import java.util.Map;


/**
 * The announce request message for the HTTP tracker protocol.
 * <p>
 * <p>
 * This class represents the announce request message in the HTTP tracker
 * protocol. It doesn't add any specific fields compared to the generic
 * announce request message, but it provides the means to parse such
 * messages and craft them.
 * </p>
 *
 * @author mpetazzoni
 */
public final class HTTPAnnounceRequestMessage extends HTTPTrackerMessage implements AnnounceRequestMessage {

    private final byte[] infoHash;
    private final Peer peer;
    private final long uploaded;
    private final long downloaded;
    private final long left;
    private final boolean compact;
    private final boolean noPeerId;
    private final RequestEvent event;
    private final int numWant;

    private HTTPAnnounceRequestMessage(final ByteBuffer data, final byte[] infoHash, final Peer peer, final long uploaded, final long downloaded, final long left, final boolean compact, final boolean noPeerId, final RequestEvent event, final int numWant) {
        super(Type.ANNOUNCE_REQUEST, data);
        this.infoHash = infoHash;
        this.peer = peer;
        this.downloaded = downloaded;
        this.uploaded = uploaded;
        this.left = left;
        this.compact = compact;
        this.noPeerId = noPeerId;
        this.event = event;
        this.numWant = numWant;
    }

    @Override
    public byte[] getInfoHash() {
        return this.infoHash;
    }

    @Override
    public String getHexInfoHash() {
        return Torrent.byteArrayToHexString(this.infoHash);
    }

    @Override
    public byte[] getPeerId() {
        return this.peer.getPeerId().array();
    }

    @Override
    public String getHexPeerId() {
        return this.peer.getHexPeerId();
    }

    @Override
    public int getPort() {
        return this.peer.getPort();
    }

    @Override
    public long getUploaded() {
        return this.uploaded;
    }

    @Override
    public long getDownloaded() {
        return this.downloaded;
    }

    @Override
    public long getLeft() {
        return this.left;
    }

    @Override
    public boolean getCompact() {
        return this.compact;
    }

    @Override
    public boolean getNoPeerIds() {
        return this.noPeerId;
    }

    @Override
    public RequestEvent getEvent() {
        return this.event;
    }

    @Override
    public String getIp() {
        return this.peer.getIp();
    }

    @Override
    public int getNumWant() {
        return this.numWant;
    }

    /**
     * Build the announce request URL for the given tracker announce URL.
     *
     * @param trackerAnnounceURL The tracker's announce URL.
     * @return The URL object representing the announce request URL.
     */
    public URL buildAnnounceURL(final URL trackerAnnounceURL, final EmulatedClient emulatedClient) throws UnsupportedEncodingException, MalformedURLException {
        final String base = trackerAnnounceURL.toString();
        String emulatedClientQuery = emulatedClient.getQuery()
                .replaceAll("\\{infohash}", URLEncoder.encode(new String(this.getInfoHash(), Torrent.BYTE_ENCODING), Torrent.BYTE_ENCODING))
                .replaceAll("\\{peerid}", URLEncoder.encode(new String(this.getPeerId(), Torrent.BYTE_ENCODING), Torrent.BYTE_ENCODING))
                .replaceAll("\\{uploaded}", String.valueOf(this.getUploaded()))
                .replaceAll("\\{downloaded}", String.valueOf(this.getDownloaded()))
                .replaceAll("\\{left}", String.valueOf(this.getLeft()))
                .replaceAll("\\{numwant}", String.valueOf(emulatedClient.getNumwant().orElse(HTTPAnnounceRequestMessage.DEFAULT_NUM_WANT)))
                .replaceAll("\\{port}", String.valueOf(this.getPort()))
                .replaceAll("\\{ip}", this.getIp());


        if (emulatedClientQuery.contains("{key}")) {
            emulatedClientQuery = emulatedClientQuery
                    .replaceAll("\\{key}", URLEncoder.encode(emulatedClient.getKey().get(), Torrent.BYTE_ENCODING));
        }
        if (this.getEvent() == null || this.getEvent() == RequestEvent.NONE) {
            // if event was NONE, remove the event from the query string
            emulatedClientQuery = emulatedClientQuery.replaceAll("(event=\\{event})", "");
        } else {
            emulatedClientQuery = emulatedClientQuery.replaceAll("\\{event}", this.getEvent().getEventName());
        }

        final String url = base + (base.contains("?") ? "&" : "?") + emulatedClientQuery;

        return new URL(url);
    }

    public static HTTPAnnounceRequestMessage parse(final ByteBuffer data)
            throws IOException, MessageValidationException {
        final BEValue decoded = BDecoder.bdecode(data);
        if (decoded == null) {
            throw new MessageValidationException(
                    "Could not decode tracker message (not B-encoded?)!");
{'fraction_non_alphanumeric': 0.10409735597968832, 'fraction_numerical': 0.0, 'mean_word_length': 2.955332409972299, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 16, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1378566', 'n_tokens_mistral': 3245, 'n_tokens_neox': 3105, 'n_words': 789}