1

Here is the data source, encoded by ISO-8859-1:

"x%DAe%91%C1%92%9B0%0C%86%9F%A5%3A%B3%C1%84%98%89%B9%F4%D0%F3%3EA%E9xd%5B%807%06S%23%B2%DD%EE%EC%BB%D7%24%E9%B4%9D%1E%3CcI%BF%A5O%BF%DF%21D%7B%D1%AF%23%21C%0BP%00%C7e%D5%26Et%16W%A6%04%ED%D7w%D8%BC%CB%D5s%D3%08%21T%16%AD6%26%82V%3Cn%BA%8Fi%DA%1B%EC%09%E2%DB%2B%A5%0A%C0e%E9%D1f%21%8C%CCK%DB%95%5D9%FA%80O%D5%E15%A2wq%1E%F6s%B0sW6%95%11%A7%DE%08el%D5%98S%D3H%A4%B3%B4u%AD%B0%E9%E5%09%0F%2F%CB%F0%D9O8%D0s%1C%D2%B1%2B%BFo%18%3C%BFue%25%C4%A7%AE%5C%FDOz%0A%7E%F2%DC%95gq%C9%99%1D%93%7E%40%5B%15%FB%8E%C8%3E%CE%19%E4%CB%E8g%CC%A5%D9%DB%CB%8C%D3%CE%26%A5%CC%89%40W%0A%D0%1E%B3%BC%0F8%40%3Bo%21%14%90b+%CDo%0B%DD%1A%E1%E6%7C%7C%DE%98%DC-%BCzG%BF%C3%BCz%22%0C%EC%27%FA%23%C0%8D%C7%982%E6%A3E%16e%A7%9D%1E%E3%1C%93%DEM%CD%F4b%9F%19%FC%95VF%BE%8B%B6%95%92%FE%D7Z%10%19r%B9%E8%87%F5w%BA5%26%BE3%27%1BW%D6%8F%25%B2%F5%7F%87%C7%EA%E3%5B%01%93%93%FA%FF%CF%05%7B%A6Z%2A%EC%8DR%27ekS%F7R%D6X%2BS%29stX%C1%C7%2F%7B%CD%B12"

I guess in swift, ISO-8859-1 is String.Encoding.isoLatin1

The content contained is

{"lock_wheat":"","topsSth":[{"uid":"8660009","score":0,"score_format":0,"setter":99,"appface":"http:hahaha","sex":1,"location":"China","nickname":"555","level":21,"flag":null,"role_type":1,"audioMuted":1,"videoMuted":0,"realtimeMuted":1,"authority_type":0,"head_honor_id":100021,"livestate":0,"user_score_format":"0","pk_score":null,"sort":21,"rcost_level":9,"cost_level":21}],"md5_tops_broadcaster":"666"}

PS: I edited some words above


I need to convert to the following Java code to Swift

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.Inflater;


public class HelloWorld {
    public static String decompress(String data, String charset) throws UnsupportedEncodingException {
        byte[] bytes = data.getBytes(charset);
        byte[] output = new byte[0];

        Inflater decompresser = new Inflater();
        decompresser.reset();
        decompresser.setInput(bytes);

        ByteArrayOutputStream o = new ByteArrayOutputStream(bytes.length);
        try {
            byte[] buf = new byte[1024];
            while (!decompresser.finished()) {
                int i = decompresser.inflate(buf);
                o.write(buf, 0, i);
            }
            output = o.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                o.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        decompresser.end();
        return new String(output);
    }



    public static String decompress(String data) throws UnsupportedEncodingException {
        String decodeTmp = URLDecoder.decode(data, "ISO-8859-1");
        System.out.println(decodeTmp);
        return decompress(decodeTmp, "ISO-8859-1");
    }



    public static void main(String[] args) {
    
        String data = "x%DAe%91%C1%92%9B0%0C%86%9F%A5%3A%B3%C1%84%98%89%B9%F4%D0%F3%3EA%E9xd%5B%807%06S%23%B2%DD%EE%EC%BB%D7%24%E9%B4%9D%1E%3CcI%BF%A5O%BF%DF%21D%7B%D1%AF%23%21C%0BP%00%C7e%D5%26Et%16W%A6%04%ED%D7w%D8%BC%CB%D5s%D3%08%21T%16%AD6%26%82V%3Cn%BA%8Fi%DA%1B%EC%09%E2%DB%2B%A5%0A%C0e%E9%D1f%21%8C%CCK%DB%95%5D9%FA%80O%D5%E15%A2wq%1E%F6s%B0sW6%95%11%A7%DE%08el%D5%98S%D3H%A4%B3%B4u%AD%B0%E9%E5%09%0F%2F%CB%F0%D9O8%D0s%1C%D2%B1%2B%BFo%18%3C%BFue%25%C4%A7%AE%5C%FDOz%0A%7E%F2%DC%95gq%C9%99%1D%93%7E%40%5B%15%FB%8E%C8%3E%CE%19%E4%CB%E8g%CC%A5%D9%DB%CB%8C%D3%CE%26%A5%CC%89%40W%0A%D0%1E%B3%BC%0F8%40%3Bo%21%14%90b+%CDo%0B%DD%1A%E1%E6%7C%7C%DE%98%DC-%BCzG%BF%C3%BCz%22%0C%EC%27%FA%23%C0%8D%C7%982%E6%A3E%16e%A7%9D%1E%E3%1C%93%DEM%CD%F4b%9F%19%FC%95VF%BE%8B%B6%95%92%FE%D7Z%10%19r%B9%E8%87%F5w%BA5%26%BE3%27%1BW%D6%8F%25%B2%F5%7F%87%C7%EA%E3%5B%01%93%93%FA%FF%CF%05%7B%A6Z%2A%EC%8DR%27ekS%F7R%D6X%2BS%29stX%C1%C7%2F%7B%CD%B12";
         try {
             String dateNew = decompress(data);
             System.out.println(dateNew);
          } catch (Exception e) {
                e.printStackTrace();
          }
    }
}

Here is what I tried:

I am obstructed at this java line

String decodeTmp = URLDecoder.decode(data, "ISO-8859-1");

Here prints

xÚeÁ0 ¥:³Á¹ôÐó>Aéxd[7S#²Ýîì»×$é´<cI¿¥O¿ß!D{ѯ#!C PÇeÕ&EtW¦í×wؼËÕs!T­6&V<nºiÚì âÛ+¥ ÀeéÑf!ÌKÛ]9úOÕá5¢wqös°sW6§elÕSÓH¤³´u­°éå /ËðÙO8ÐsÒ±+¿o<¿ue%ħ®\ýOz ~òÜgqÉ~@[ûÈ>ÎäËègÌ¥ÙÛËÓÎ&¥Ì@W г¼8@;o!b Ío Ýáæ||ÞÜ-¼zG¿Ã¼z" ì'ú#ÀÇ2æ£Ee§ãÞMÍôbüVF¾¶þ×Zr¹èõwº5&¾3'Ö%²õÇêã[úÿÏ{¦Z*ìR'ekS÷R

as for URLDecoder in Java, I don't know such thing in Swift.

Joakim Danielson
  • 43,251
  • 5
  • 22
  • 52
dengST30
  • 3,643
  • 24
  • 25
  • No. I have seen `removingPercentEncoding` before I ask. – dengST30 Nov 22 '21 at 08:58
  • 1
    There is a method that can do it but it's deprecated since iOS 9. Best bet is to decode as Latin1, then manually unescape percents using Latin1 character table. – Sulthan Nov 22 '21 at 10:01
  • 1
    "Here is what I tried:" and what's that exactly? – Larme Nov 22 '21 at 10:50
  • I worked morning and noon. Still don't know how to achieve step one – dengST30 Nov 22 '21 at 10:56
  • I guess , the string is in data format . How to make data ( as string )to data – dengST30 Nov 22 '21 at 10:57
  • I guess I need to decode string , then I can get hex array easily . And bits to string , is easy – dengST30 Nov 22 '21 at 10:58
  • I tried, encode to utf8. decode to latin I . string to data , data to string , none works – dengST30 Nov 22 '21 at 10:59
  • What is it @Sulthan ? – dengST30 Nov 22 '21 at 11:00
  • I also searched in github. Not lucky – dengST30 Nov 22 '21 at 12:16
  • 1
    I don't know if this is going somewhere, I'm just curious as it was the first time I saw that encoding... But combining https://stackoverflow.com/a/59720584/1801544 and https://stackoverflow.com/questions/70034125/how-do-you-decode-utf8-literals-like-xc3-xa6-in-swift-5 , I get somewhere near your "Here prints": `let test = String(bytes: initialString.replacingOccurrences(of: "%", with: "\\x").components(separatedBy: "\\x").dropFirst().compactMap { UInt8($0, radix: 16) }, encoding: .isoLatin1)` – Larme Nov 22 '21 at 16:08
  • 1
    What's strange is that it's supposed to be .windows1250, not isoLatin1 https://stackoverflow.com/questions/44730379/how-can-i-convert-a-string-such-as-iso-8859-1-to-its-string-encoding-counte – Larme Nov 22 '21 at 16:09
  • 1
    @Larme: My *guess* is that the input is percent-encoded (deflate compressed) *binary data.* Decoding that is isoLatin1 might work by chance, but does not look like the correct approach to me. It also remains to revert the compression (what the Inflater does in the Java code). – I'll try something later when I have the time. – Martin R Nov 22 '21 at 16:24
  • 1
    I can un-escape the string to data, which starts with `0x78 0xDA`. According to https://stackoverflow.com/q/9050260/1187415 that indicates zlib compressed data, but I haven't managed yet to decompress using the Compression library. Perhaps one has to use plain zlib calls, I am not sure. – Martin R Nov 22 '21 at 20:27

1 Answers1

0

Here is Objective - C solution:

as @Martin R said, zlib

as @Sulthan said, deprecated since iOS 9

#include <zlib.h>

@implementation NSData (Compression)

#pragma mark -
#pragma mark Zlib Compression routines
- (NSData *) zlibInflate
{
    if ([self length] == 0) return self;
    
    unsigned full_length = [self length];
    unsigned half_length = [self length] / 2;
    
    NSMutableData *decompressed = [NSMutableData dataWithLength: full_length + half_length];
    BOOL done = NO;
    int status;
    
    z_stream strm;
    strm.next_in = (Bytef *)[self bytes];
    strm.avail_in = [self length];
    strm.total_out = 0;
    strm.zalloc = Z_NULL;
    strm.zfree = Z_NULL;
    
    if (inflateInit (&strm) != Z_OK) return nil;
    
    while (!done)
    {
        // Make sure we have enough room and reset the lengths.
        if (strm.total_out >= [decompressed length])
            [decompressed increaseLengthBy: half_length];
        strm.next_out = [decompressed mutableBytes] + strm.total_out;
        strm.avail_out = [decompressed length] - strm.total_out;
        
        // Inflate another chunk.
        status = inflate (&strm, Z_SYNC_FLUSH);
        if (status == Z_STREAM_END) done = YES;
        else if (status != Z_OK) break;
    }
    if (inflateEnd (&strm) != Z_OK) return nil;
    
    // Set real length.
    if (done)
    {
        [decompressed setLength: strm.total_out];
        return [NSData dataWithData: decompressed];
    }
    else return nil;
}


@end





@implementation NSString (ZlibData)

- (NSDictionary *)transformZLibData{
    NSString *str = [self stringByReplacingOccurrencesOfString:@"+" withString:@"%20"];
    
    NSString *latin1String = [str stringByReplacingPercentEscapesUsingEncoding:NSISOLatin1StringEncoding];
    
    NSData *latin1Data = [latin1String dataUsingEncoding:NSISOLatin1StringEncoding];
    
    NSData *inflateData = [latin1Data zlibInflate];
    
    if (![inflateData isKindOfClass:[NSData class]] || inflateData.length < 1) {
        return nil;
    }
    id jsonObj = [NSJSONSerialization JSONObjectWithData:inflateData options:NSJSONReadingAllowFragments error:nil];
    NSLog(@"%@", jsonObj);
    
    if (![jsonObj isKindOfClass:[NSDictionary class]]) {
        return nil;
    }
    return [NSDictionary dictionaryWithDictionary:(NSDictionary *)jsonObj];
}

@end

call like this:

let data = "x%DAe%91%C1%92%9B0%0C%86%9F%A5%3A%B3%C1%84%98%89%B9%F4%D0%F3%3EA%E9xd%5B%807%06S%23%B2%DD%EE%EC%BB%D7%24%E9%B4%9D%1E%3CcI%BF%A5O%BF%DF%21D%7B%D1%AF%23%21C%0BP%00%C7e%D5%26Et%16W%A6%04%ED%D7w%D8%BC%CB%D5s%D3%08%21T%16%AD6%26%82V%3Cn%BA%8Fi%DA%1B%EC%09%E2%DB%2B%A5%0A%C0e%E9%D1f%21%8C%CCK%DB%95%5D9%FA%80O%D5%E15%A2wq%1E%F6s%B0sW6%95%11%A7%DE%08el%D5%98S%D3H%A4%B3%B4u%AD%B0%E9%E5%09%0F%2F%CB%F0%D9O8%D0s%1C%D2%B1%2B%BFo%18%3C%BFue%25%C4%A7%AE%5C%FDOz%0A%7E%F2%DC%95gq%C9%99%1D%93%7E%40%5B%15%FB%8E%C8%3E%CE%19%E4%CB%E8g%CC%A5%D9%DB%CB%8C%D3%CE%26%A5%CC%89%40W%0A%D0%1E%B3%BC%0F8%40%3Bo%21%14%90b+%CDo%0B%DD%1A%E1%E6%7C%7C%DE%98%DC-%BCzG%BF%C3%BCz%22%0C%EC%27%FA%23%C0%8D%C7%982%E6%A3E%16e%A7%9D%1E%E3%1C%93%DEM%CD%F4b%9F%19%FC%95VF%BE%8B%B6%95%92%FE%D7Z%10%19r%B9%E8%87%F5w%BA5%26%BE3%27%1BW%D6%8F%25%B2%F5%7F%87%C7%EA%E3%5B%01%93%93%FA%FF%CF%05%7B%A6Z%2A%EC%8DR%27ekS%F7R%D6X%2BS%29stX%C1%C7%2F%7B%CD%B12"
        
if let dict = data.transformZLibData() as? [String:Any] { }
dengST30
  • 3,643
  • 24
  • 25