<commit_before>#include <unistd.h>
#include <openssl/evp.h>
#include <openssl/aes.h>

#include "httplivestreaming.h"

// Derived the typedefs from libavformat/mpegtsenc.c in FFmpeg source
// because this is the only way to manipulate continuity counters.
// Original license claim is as follows.
/*
 * MPEG2 transport stream (aka DVB) muxer
 * Copyright (c) 2003 <NAME>
 *
 * This file is part of FFmpeg.
 *
 * FFmpeg 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 2.1 of the License, or (at your option) any later version.
 *
 * FFmpeg 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 FFmpeg; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */
/** START OF COPY **/
typedef struct MpegTSSection {
    int pid;
    int cc;
    void (*write_packet)(struct MpegTSSection *s, const uint8_t *packet);
    void *opaque;
} MpegTSSection;

typedef struct MpegTSService {
    MpegTSSection pmt; /* MPEG2 pmt table context */
    int sid;           /* service ID */
    char *name;
    char *provider_name;
    int pcr_pid;
    int pcr_packet_count;
    int pcr_packet_period;
} MpegTSService;

typedef struct MpegTSWrite {
    const AVClass *av_class;
    MpegTSSection pat; /* MPEG2 pat table */
    MpegTSSection sdt; /* MPEG2 sdt table context */
    MpegTSService **services;
    int sdt_packet_count;
    int sdt_packet_period;
    int pat_packet_count;
    int pat_packet_period;
    int nb_services;
    int onid;
    int tsid;
    int64_t first_pcr;
    int mux_rate; ///< set to 1 when VBR
    int pes_payload_size;

    int transport_stream_id;
    int original_network_id;
    int service_id;

    int pmt_start_pid;
    int start_pid;
    int m2ts_mode;

    int reemit_pat_pmt; // backward compatibility

    int flags;
    int copyts;
    int tables_version;

    int omit_video_pes_length;
} MpegTSWrite;

typedef struct MpegTSWriteStream {
    struct MpegTSService *service;
    int pid; /* stream associated pid */
    int cc;
    int payload_size;
    int first_pts_check; ///< first pts check needed
    int prev_payload_key;
    int64_t payload_pts;
    int64_t payload_dts;
    int payload_flags;
    uint8_t *payload;
    AVFormatContext *amux;
} MpegTSWriteStream;
/** END OF COPY **/

void encrypt_most_recent_file(HTTPLiveStreaming *hls) {
  char filepath[1024];
  FILE *fp;
  uint8_t *input_data;
  uint8_t *encrypted_data;
  int input_size;
  EVP_CIPHER_CTX enc_ctx;

  // init cipher context
  EVP_CIPHER_CTX_init(&enc_ctx);
  if (hls->encryption_key == NULL) {
    fprintf(stderr, "Warning: encryption_key is not set\n");
  }
  if (hls->encryption_iv == NULL) {
    fprintf(stderr, "Warning: encryption_iv is not set\n");
  }
  EVP_EncryptInit_ex(&enc_ctx, EVP_aes_128_cbc(), NULL, hls->encryption_key, hls->encryption_iv);

  // read original data
  snprintf(filepath, 1024, "%s/%d.ts", hls->dir, hls->most_recent_number);
  fp = fopen(filepath, "rb+");
  if (fp == NULL) {
    perror("Read ts file failed");
    return;
  }
  fseek(fp, 0, SEEK_END);
  input_size = ftell(fp);
  fseek(fp, 0, SEEK_SET);
  input_data = malloc(input_size);
  if (input_data == NULL) {
    perror("Can't malloc for input_data");
    return;
  }
  fread(input_data, 1, input_size, fp);

  // encrypt the data
  int c_len = input_size + AES_BLOCK_SIZE;
  int f_len;
  int encrypted_size;
  encrypted_data = malloc(c_len);
  if (encrypted_data == NULL) {
    perror("Can't malloc for encrypted_data");
    return;
  }
  EVP_EncryptUpdate(&enc_ctx, encrypted_data, &c_len, input_data, input_size);
  EVP_EncryptFinal_ex(&enc_ctx, encrypted_data+c_len, &f_len);
  encrypted_size = c_len + f_len;

  // write data to the same file
  fseek(fp, 0, SEEK_SET);
  fwrite(encrypted_data, 1, encrypted_size, fp);
  ftruncate(fileno(fp), encrypted_size);
  fclose(fp);

  // free up variables
  free(encrypted_data);
  free(input_data);
  EVP_CIPHER_CTX_cleanup(&enc_ctx);
}

// Write m3u8 file
int write_index(HTTPLiveStreaming *hls, int is_end) {
  FILE *file;
  char buf[128];
  char tmp_filepath[1024];
  char filepath[1024];
  int i;

  snprintf(tmp_filepath, 1024, "%s/_%s", hls->dir, hls->index_filename);
  file = fopen(tmp_filepath, "w");
  if (!file) {
    perror("fopen");
    return -1;
  }

  // header
  // What features are available in each version can be found on:
  // https://developer.apple.com/library/ios/qa/qa1752/_index.html
  snprintf(buf, 128, "#EXTM3U\n#EXT-X-VERSION:3\n#EXT-X-TARGETDURATION:%d\n#EXT-X-MEDIA-SEQUENCE:%d\n#EXT-X-ALLOW-CACHE:NO\n",
      hls->target_duration, hls->most_recent_number);
  fwrite(buf, 1, strlen(buf), file);

  // insert encryption header if needed<commit_msg>Add support for OpenSSL 1.1.0<commit_after>#include <unistd.h>
#include <openssl/evp.h>
#include <openssl/aes.h>

#include "httplivestreaming.h"

// Derived the typedefs from libavformat/mpegtsenc.c in FFmpeg source
// because this is the only way to manipulate continuity counters.
// Original license claim is as follows.
/*
 * MPEG2 transport stream (aka DVB) muxer
 * Copyright (c) 2003 <NAME>
 *
 * This file is part of FFmpeg.
 *
 * FFmpeg 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 2.1 of the License, or (at your option) any later version.
 *
 * FFmpeg 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 FFmpeg; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */
/** START OF COPY **/
typedef struct MpegTSSection {
    int pid;
    int cc;
    void (*write_packet)(struct MpegTSSection *s, const uint8_t *packet);
    void *opaque;
} MpegTSSection;

typedef struct MpegTSService {
    MpegTSSection pmt; /* MPEG2 pmt table context */
    int sid;           /* service ID */
    char *name;
    char *provider_name;
    int pcr_pid;
    int pcr_packet_count;
    int pcr_packet_period;
} MpegTSService;

typedef struct MpegTSWrite {
    const AVClass *av_class;
    MpegTSSection pat; /* MPEG2 pat table */
    MpegTSSection sdt; /* MPEG2 sdt table context */
    MpegTSService **services;
    int sdt_packet_count;
    int sdt_packet_period;
    int pat_packet_count;
    int pat_packet_period;
    int nb_services;
    int onid;
    int tsid;
    int64_t first_pcr;
    int mux_rate; ///< set to 1 when VBR
    int pes_payload_size;

    int transport_stream_id;
    int original_network_id;
    int service_id;

    int pmt_start_pid;
    int start_pid;
    int m2ts_mode;

    int reemit_pat_pmt; // backward compatibility

    int flags;
    int copyts;
    int tables_version;

    int omit_video_pes_length;
} MpegTSWrite;

typedef struct MpegTSWriteStream {
    struct MpegTSService *service;
    int pid; /* stream associated pid */
    int cc;
    int payload_size;
    int first_pts_check; ///< first pts check needed
    int prev_payload_key;
    int64_t payload_pts;
    int64_t payload_dts;
    int payload_flags;
    uint8_t *payload;
    AVFormatContext *amux;
} MpegTSWriteStream;
/** END OF COPY **/

void encrypt_most_recent_file(HTTPLiveStreaming *hls) {
  char filepath[1024];
  FILE *fp;
  uint8_t *input_data;
  uint8_t *encrypted_data;
  int input_size;
  EVP_CIPHER_CTX *enc_ctx;

  // init cipher context
  enc_ctx = EVP_CIPHER_CTX_new();
  if (enc_ctx == NULL) {
    fprintf(stderr, "Error: encrypt_most_recent_file: EVP_CIPHER_CTX_new failed\n");
    return;
  }

  if (hls->encryption_key == NULL) {
    fprintf(stderr, "Warning: encryption_key is not set\n");
  }
  if (hls->encryption_iv == NULL) {
    fprintf(stderr, "Warning: encryption_iv is not set\n");
  }
  EVP_EncryptInit_ex(enc_ctx, EVP_aes_128_cbc(), NULL, hls->encryption_key, hls->encryption_iv);

  // read original data
  snprintf(filepath, 1024, "%s/%d.ts", hls->dir, hls->most_recent_number);
  fp = fopen(filepath, "rb+");
  if (fp == NULL) {
    perror("Read ts file failed");
    return;
  }
  fseek(fp, 0, SEEK_END);
  input_size = ftell(fp);
  fseek(fp, 0, SEEK_SET);
  input_data = malloc(input_size);
  if (input_data == NULL) {
    perror("Can't malloc for input_data");
    return;
  }
  fread(input_data, 1, input_size, fp);

  // encrypt the data
  int c_len = input_size + AES_BLOCK_SIZE;
  int f_len;
  int encrypted_size;
  encrypted_data = malloc(c_len);
  if (encrypted_data == NULL) {
    perror("Can't malloc for encrypted_data");
    return;
  }
  EVP_EncryptUpdate(enc_ctx, encrypted_data, &c_len, input_data, input_size);
  EVP_EncryptFinal_ex(enc_ctx, encrypted_data+c_len, &f_len);
  encrypted_size = c_len + f_len;

  // write data to the same file
  fseek(fp, 0, SEEK_SET);
  fwrite(encrypted_data, 1, encrypted_size, fp);
  ftruncate(fileno(fp), encrypted_size);
  fclose(fp);

  // free up variables
  free(encrypted_data);
  free(input_data);
  EVP_CIPHER_CTX_free(enc_ctx);
}

// Write m3u8 file
int write_index(HTTPLiveStreaming *hls, int is_end) {
  FILE *file;
  char buf[128];
  char tmp_filepath[1024];
  char filepath[1024];
  int i;

  snprintf(tmp_filepath, 1024, "%s/_%s", hls->dir, hls->index_filename);
  file = fopen(tmp_filepath, "w");
  if (!file) {
    perror("fopen");
    return -1;
  }

  // header
  // What features are available in each version can be found on:
  // https://developer.apple.com/library/ios/qa/qa1752/_index.html
  snprintf(buf, 128, "#EXTM3U\n#EXT-X-VERSION:3\n#EXT-X-TARGETDURATION:%d\n#EXT-X-MEDIA-SEQUENCE:%d\n#EXT-X-ALLOW-CACHE:NO\n",
      hls->target_duration, hls->most_recent_number);
  fwrite(buf, 1, strlen(buf), file);

  // insert encryption header if needed
{'fraction_non_alphanumeric': 0.10640975987606506, 'fraction_numerical': 0.015201394268009295, 'mean_word_length': 3.609103078982597, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 31, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5961000', 'n_tokens_mistral': 3874, 'n_tokens_neox': 3658, 'n_words': 1025}