read_2004_compressed_section (Bit_Chain *dat, Dwg_Data *restrict dwg,
                              Bit_Chain *sec_dat, BITCODE_RL section_type)
{
  uint32_t address, sec_mask, initial_address;
  uint32_t max_decomp_size;
  Dwg_Section_Info *info = NULL;
  encrypted_section_header es;
  BITCODE_RC *decomp;
  BITCODE_BL i, j;
  int error = 0;

  for (i = 0; i < dwg->header.section_infohdr.num_desc && !info; ++i)
    {
      if (dwg->header.section_info[i].type == section_type)
        {
          info = &dwg->header.section_info[i];
          break;
        }
    }
  sec_dat->chain = NULL; // fixes double-free
  if (!info)
    {
      LOG_WARN ("Failed to find section_info[" FORMAT_BL "] with type 0x%x", i,
                section_type);
      return DWG_ERR_SECTIONNOTFOUND;
    }
  else
    {
      LOG_TRACE ("\nFound section_info[" FORMAT_BL
                 "] %s type 0x%x with %d sections (%scompressed):\n",
                 i, info->name, section_type, info->num_sections,
                 info->compressed == 2 ? "" : "un");
    }

  max_decomp_size = info->num_sections * info->max_decomp_size;
  if (max_decomp_size == 0)
    {
      LOG_ERROR ("Section %s count or max decompression size is zero. "
                 "Sections: %u, Max size: %u",
                 info->name, info->num_sections, info->max_decomp_size);
      return DWG_ERR_INVALIDDWG;
    }
  decomp = (BITCODE_RC *)calloc (max_decomp_size, sizeof (BITCODE_RC));
  if (!decomp)
    {
      LOG_ERROR ("Out of memory with %u sections", info->num_sections);
      return DWG_ERR_OUTOFMEM;
    }
  initial_address = info->sections[0] ? info->sections[0]->address : 0;
  sec_dat->bit = 0;
  sec_dat->byte = 0;
  sec_dat->version = dat->version;
  sec_dat->from_version = dat->from_version;
  sec_dat->chain = decomp;

  for (i = 0; i < info->num_sections; ++i)
    {
      if (!info->sections[i])
        {
          LOG_WARN ("Skip empty section %u %s", i, info->name);
          continue;
        }
      address = info->sections[i]->address;
      dat->byte = address;
      bit_read_fixed (dat, es.char_data, 32);

      //? if encrypted properties: security_type & 2 ??
      sec_mask = 0x4164536b ^ address;
      for (j = 0; j < 8; ++j)
        es.long_data[j] ^= sec_mask;

      LOG_INFO ("=== Section %s (%u) @%u ===\n", info->name, i, address)
      if (es.fields.tag != 0x4163043b)
        {
          LOG_WARN ("Section Tag:      0x%x  (should be 0x4163043b)",
                    (unsigned)es.fields.tag);
        }
      else
        {
          LOG_INFO ("Section Tag:      0x%x\n", (unsigned)es.fields.tag);
        }
      LOG_INFO ("Section Type:     %u\n", (unsigned)es.fields.section_type)
      // this is the number of bytes that is read in decompress_R2004_section
      // (+ 2bytes)
      LOG_INFO ("Data size:        0x%x/%u\n", (unsigned)es.fields.data_size,
                (unsigned)es.fields.data_size)
      LOG_INFO ("Comp data size:   0x%x\n", (unsigned)es.fields.section_size)
      LOG_TRACE ("StartOffset:      0x%x\n", (unsigned)es.fields.address)
      LOG_HANDLE ("Unknown:          0x%x\n", (unsigned)es.fields.unknown)
      LOG_HANDLE ("Checksum1:        0x%x\n", (unsigned)es.fields.checksum_1)
      LOG_HANDLE ("Checksum2:        0x%x\n", (unsigned)es.fields.checksum_2)
      LOG_TRACE ("Section start:    %lu\n\n", dat->byte);

      // GH #126 part 4
      // LOG_INSANE ("i:                     %u\n", i)
      // LOG_INSANE ("decomp:                %p\n", decomp)
      // LOG_INSANE ("info->max_decomp_size: %u\n", info->max_decomp_size)
      // LOG_INSANE ("max_decomp_size:       %u\n", max_decomp_size)
      // LOG_INSANE ("bytes_left:            %d\n",
      //            max_decomp_size - (i * info->max_decomp_size))

      // check if compressed at all
      if (info->compressed == 2)
        {
          error = decompress_R2004_section (
              dat, &decomp[i * info->max_decomp_size],       // offset
              max_decomp_size - (i * info->max_decomp_size), // bytes left
              es.fields.data_size);
          if (error > DWG_ERR_CRITICAL)
            {
              sec_dat->chain = NULL; // fix double-free
              free (decomp);
              return error;
            }
          sec_dat->size = max_decomp_size;
        }
      else
        {
          if (!(info->size <= max_decomp_size)
              || !((unsigned long)(address + es.fields.address + 32
                                   + info->size)
                   <= dat->size))
            {
              sec_dat->chain = NULL;
              free (decomp);
              return DWG_ERR_INVALIDDWG;
            }
          memcpy (&decomp[i * info->size],
                  &dat->chain[address + es.fields.address + 32], info->size);
          sec_dat->size = info->size;
        }
    }

  return error;
}
read_2004_compressed_section (Bit_Chain *dat, Dwg_Data *restrict dwg,
                              Bit_Chain *sec_dat, BITCODE_RL section_type)
{
  uint32_t address, sec_mask, initial_address;
  uint32_t max_decomp_size;
  Dwg_Section_Info *info = NULL;
  encrypted_section_header es;
  BITCODE_RC *decomp;
  BITCODE_BL i, j;
  int error = 0;

  for (i = 0; i < dwg->header.section_infohdr.num_desc && !info; ++i)
    {
      if (dwg->header.section_info[i].type == section_type)
        {
          info = &dwg->header.section_info[i];
          break;
        }
    }
  sec_dat->chain = NULL;  
  if (!info)
    {
      LOG_WARN ("Failed to find section_info[" FORMAT_BL "] with type 0x%x", i,
                section_type);
      return DWG_ERR_SECTIONNOTFOUND;
    }
  else
    {
      LOG_TRACE ("\nFound section_info[" FORMAT_BL
                 "] %s type 0x%x with %d sections (%scompressed):\n",
                 i, info->name, section_type, info->num_sections,
                 info->compressed == 2 ? "" : "un");
    }

  max_decomp_size = info->num_sections * info->max_decomp_size;
  if (max_decomp_size == 0)
    {
      LOG_ERROR ("Section %s count or max decompression size is zero. "
                 "Sections: %u, Max size: %u",
                 info->name, info->num_sections, info->max_decomp_size);
      return DWG_ERR_INVALIDDWG;
    }
  decomp = (BITCODE_RC *)calloc (max_decomp_size, sizeof (BITCODE_RC));
  if (!decomp)
    {
      LOG_ERROR ("Out of memory with %u sections", info->num_sections);
      return DWG_ERR_OUTOFMEM;
    }
  initial_address = info->sections[0] ? info->sections[0]->address : 0;
  sec_dat->bit = 0;
  sec_dat->byte = 0;
  sec_dat->version = dat->version;
  sec_dat->from_version = dat->from_version;
  sec_dat->chain = decomp;

  for (i = 0; i < info->num_sections; ++i)
    {
      if (!info->sections[i])
        {
          LOG_WARN ("Skip empty section %u %s", i, info->name);
          continue;
        }
      address = info->sections[i]->address;
      dat->byte = address;
      bit_read_fixed (dat, es.char_data, 32);

       
      sec_mask = 0x4164536b ^ address;
      for (j = 0; j < 8; ++j)
        es.long_data[j] ^= sec_mask;

      LOG_INFO ("=== Section %s (%u) @%u ===\n", info->name, i, address)
      if (es.fields.tag != 0x4163043b)
        {
          LOG_WARN ("Section Tag:      0x%x  (should be 0x4163043b)",
                    (unsigned)es.fields.tag);
        }
      else
        {
          LOG_INFO ("Section Tag:      0x%x\n", (unsigned)es.fields.tag);
        }
      LOG_INFO ("Section Type:     %u\n", (unsigned)es.fields.section_type)
       
       
      LOG_INFO ("Data size:        0x%x/%u\n", (unsigned)es.fields.data_size,
                (unsigned)es.fields.data_size)
      LOG_INFO ("Comp data size:   0x%x\n", (unsigned)es.fields.section_size)
      LOG_TRACE ("StartOffset:      0x%x\n", (unsigned)es.fields.address)
      LOG_HANDLE ("Unknown:          0x%x\n", (unsigned)es.fields.unknown)
      LOG_HANDLE ("Checksum1:        0x%x\n", (unsigned)es.fields.checksum_1)
      LOG_HANDLE ("Checksum2:        0x%x\n", (unsigned)es.fields.checksum_2)
      LOG_TRACE ("Section start:    %lu\n\n", dat->byte);

       
       
       
       
       
       
       

       
      if (info->compressed == 2)
        {
          error = decompress_R2004_section (
              dat, &decomp[i * info->max_decomp_size],        
              max_decomp_size - (i * info->max_decomp_size),  
              es.fields.data_size);
          if (error > DWG_ERR_CRITICAL)
            {
              sec_dat->chain = NULL;  
              free (decomp);
              return error;
            }
          sec_dat->size = max_decomp_size;
        }
      else
        {
          if (!(info->size <= max_decomp_size)
              || !((unsigned long)(address + es.fields.address + 32
                                   + info->size)
                   <= dat->size))
            {
              sec_dat->chain = NULL;
              free (decomp);
              return DWG_ERR_INVALIDDWG;
            }
          memcpy (&decomp[i * info->size],
                  &dat->chain[address + es.fields.address + 32], info->size);
          sec_dat->size = info->size;
        }
    }

  return error;
}