zoukankan      html  css  js  c++  java
  • 用C语言写的迅雷看看XV文件提取器及C语言源代码

    tfref

        如果你没用过迅雷看看, 或是不知道XV文件的, ...
        写了很久了, 但是担心版权问题, 一直没有帖出来~~~
        能提取截止目前最新版本的迅雷看看XV文件. 好了, 不多说, 懒得多说.
        还是开源吧, 效果图以后补上. 暂时没有需要转换的文件. :-)
        这一版本我忘了写检查磁盘剩余空间的过程, 呃, ...

    /*
    tabsize:4
    */
    #include <stdio.h>
    #include <string.h>
    #define _WIN32_WINNT 0x0502
    #include <Windows.h>
    
    int cntFileProcessed = 0;    //count file that processed, accumulated.
    int scrWidth;                //screen width
    
    void ResetCursorPos(void)
    {
        CONSOLE_SCREEN_BUFFER_INFO sbi;
        COORD co;
        HANDLE hOutput;
        hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
        GetConsoleScreenBufferInfo(hOutput, &sbi);
        co.X = sbi.dwCursorPosition.X-(5+1+4);    //e.g.:1024M,100%
        co.Y = sbi.dwCursorPosition.Y;
        SetConsoleCursorPosition(hOutput, co);
        //sure to leave hOutput as it was
        return;    
    }
    
    void ExtractFile(char* filespec)
    {
    #define BUFSIZE ((1<<20)*5)    //5M buffer
        HANDLE hFileIn = NULL;    //handle of input file
        HANDLE hFileOut = NULL;    //handle of output file
    
        DWORD dwSizeRead = 0;    //the ReadFile function Read size
        DWORD dwSizeWritten = 0;//the WriteFile function Written size
        DWORD dwSize = 0;
        
        int magicNumber = 0;    //you may know when you look, I suppose.
        int fileType = 0;        //indicates what file it is
    
        LARGE_INTEGER li;        //for SetFilePointer function use,2M offset of REAL movie data
    
        BYTE hdr[4];            //the *.xv file header
        BYTE ch;                //
        char* pchar;            //tmp use
        char fileOut[MAX_PATH];    //namely, the output file
        BYTE* buffer = NULL;    //block extraction data, every time it extracts 5MB data at most
    
        char* errMsg = NULL;    //FormatMessage
        int lastErr = 0;        //GetLastError
    
        int percent = 0;        //percentage of processed data
        int readSize = 0;        //total size Read
        DWORD fileSize;            //total file size, for percentage use
    
        int prtLen;                //the printf(and its relative) returned
        int dotLen;                //as you see at the screen
    
        int k;                    //I think you know...
        
        li.LowPart = 1<<21;
        li.HighPart = 0;
    
        buffer = (BYTE*)malloc(BUFSIZE);    //5M buffer size
        if(buffer == NULL)
        {
            fprintf(stderr, "内存分配失败!\n");
            return;
        }
    
        hFileIn = CreateFile(filespec, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
        if(hFileIn == INVALID_HANDLE_VALUE)
        {
            free(buffer);
            buffer = NULL;
            lastErr = GetLastError();
            if(FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, lastErr, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), (LPSTR)&errMsg, 1, NULL))
            {
                fprintf(stderr, "CreateFile:%s\n%s", filespec, errMsg);
                LocalFree((HLOCAL)errMsg);
                errMsg = NULL;
            }
            return;
        }
        fileSize = GetFileSize(hFileIn, NULL);
        if(fileSize <= 0x00200000)
        {
            fprintf(stderr, "文件大小不正确,不能小于2M.(%s)\n", filespec);
            free(buffer);
            buffer = NULL;
            CloseHandle(hFileIn);
            hFileIn = NULL;
            return;
        }
    
        fileSize -= 0x00200000;    //2M offset of REAL Video data
    
        SetFilePointerEx(hFileIn, li, NULL, FILE_BEGIN);
        if(!ReadFile(hFileIn, hdr, 4, &dwSizeRead, NULL) || dwSizeRead==0)
        {
            lastErr = GetLastError();
            if(FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, lastErr, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), (LPSTR)&errMsg, 1, NULL))
            {
                fprintf(stderr, "ReadFile:%s\n%s", filespec, errMsg);
                LocalFree((HLOCAL)errMsg);
                errMsg = NULL;
            }
            CloseHandle(hFileIn);
            hFileIn = NULL;
            free(buffer);
            buffer = NULL;
            return;
        }
        
        magicNumber = (338-hdr[1])&0xFF;
        if((BYTE)(hdr[1]+magicNumber)=='R' && (BYTE)(hdr[2]+magicNumber)=='M' && (BYTE)(hdr[3]+magicNumber)=='F')
        {
            fileType = 1;
            goto _go;
        }
        
        magicNumber = (294-hdr[1])&0xFF;
        if((BYTE)(hdr[2]+magicNumber)==178 && (BYTE)(hdr[3]+magicNumber)==117)        
        {
            fileType = 2;
            goto _go;
        }
    
        magicNumber = (332-hdr[1])&0xFF ;
        if((BYTE)(hdr[1]+magicNumber)==76 && (BYTE)(hdr[2]+magicNumber)==86)
        {
            fileType = 3 ;
            goto _go;
        }
    
        magicNumber=(329-hdr[1])&0xFF ;
        if((BYTE)(hdr[1]+magicNumber)==73 && (BYTE)(hdr[2]+magicNumber)==70 && (BYTE)(hdr[3]+magicNumber)==70)
        {
            fileType = 4 ;
            goto _go;
        }
        magicNumber=(256-hdr[1])&0xFF ;
        if(!(magicNumber+hdr[2]))
        {
            fileType = 5 ;
            goto _go;
        }
    
        magicNumber=(256-hdr[1])&0xFF ;
        if((BYTE)(hdr[2]+magicNumber)==1 && (BYTE)(hdr[3]+magicNumber)==186)
        {
            fileType = 6 ;
            goto _go;
        }
    
        magicNumber=(325-hdr[1])&0xFF ;
        if((BYTE)(hdr[1]+magicNumber)==69 && (BYTE)(hdr[2]+magicNumber)==223 && (BYTE)(hdr[3]+magicNumber)==163)
        {
            fileType = 7 ;
            goto _go;
        }
    
        fprintf(stderr, "不能识别的文件格式!(%s)\n", filespec);
        free(buffer);
        buffer = NULL;
        CloseHandle(hFileIn);
        hFileIn = NULL;
        return;
    
    _go:
        ch = 0;
        pchar = strrchr(filespec,'\\');
        if(!pchar)
            pchar = strrchr(filespec, '/');
        pchar = pchar==NULL?filespec:pchar+1;
        switch(fileType)
        {
        case 1://rm/rmvb
            ch = 46;
            sprintf(fileOut, "%s%s", pchar, ".rmvb");
            break;
        case 2://wmv
            ch = 48;
            sprintf(fileOut, "%s%s", pchar, ".wmv");
            break;
        case 3://flv
            ch = 70;
            sprintf(fileOut, "%s%s", pchar, ".flv");
            break;
        case 4://avi
            ch = 82;
            sprintf(fileOut, "%s%s", pchar, ".avi");
            break;
        case 5://mp4
            ch = 0;
            sprintf(fileOut, "%s%s", pchar, ".mp4");
            break;
        case 6://mpeg
            ch = 0;
            sprintf(fileOut, "%s%s", pchar, ".mpeg");
            break;
        case 7://mkv
            ch = 26;
            sprintf(fileOut, "%s%s", pchar, ".mkv");
            break;
        default:
            break;
        }
        hFileOut = CreateFile(fileOut, GENERIC_WRITE, FILE_SHARE_READ, NULL, /*CREATE_ALWAYS*/CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
        if(hFileOut == INVALID_HANDLE_VALUE)
        {
            lastErr = GetLastError();
            if(FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, lastErr, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), (LPSTR)&errMsg, 1, NULL))
            {
                fprintf(stderr, "CreateFile:%s\n%s", fileOut, errMsg);
                LocalFree((HLOCAL)errMsg);
                errMsg = NULL;
            }
            CloseHandle(hFileIn);
            hFileIn = NULL;
            free(buffer);
            buffer = NULL;
            return;
        }
        
        WriteFile(hFileOut, (LPVOID)&ch, 1, &dwSizeWritten, NULL);
        
        //handle file header
        for(k = 1; k < 4; k++)
            hdr[k] = (BYTE)((hdr[k]+magicNumber)&0xFF);
        WriteFile(hFileOut, &hdr[1], 3, &dwSizeWritten, NULL);
    
        //handle encrypted data. is it simple?
        ReadFile(hFileIn, buffer, 1019, &dwSizeRead, NULL);
        for(k=0; k<1019; k++)
            buffer[k] = (BYTE)(buffer[k]+magicNumber & 0xFF);
        WriteFile(hFileOut, buffer, 1019, &dwSizeWritten, NULL);
    
        readSize += 1024;
        prtLen = printf("%s(%s)", filespec, strrchr(fileOut, '.'));
        dotLen = scrWidth-prtLen%scrWidth;
        if(dotLen<=10)
            dotLen += scrWidth;
        dotLen -= 1;
        while(dotLen--)
            printf(".");
        //it looks like this: left edge-->|mymov.xv(.flv).............1024M, 99% | <--right edge
    
        //copy rest file, original :-), and show sth. useful. how smart thunder kankan was.
        while(ReadFile(hFileIn, buffer, BUFSIZE, &dwSizeRead, NULL) && dwSizeRead != 0)
        {
            WriteFile(hFileOut, buffer, dwSizeRead, &dwSizeWritten, NULL);
            readSize += dwSizeRead;
            ResetCursorPos();
            printf("%4dM,%3d%%", (int)(readSize/(1<<20)), (int)(readSize/(float)fileSize*100));
        }
        printf("\n");
        CloseHandle(hFileIn);
        CloseHandle(hFileOut);
        hFileIn = NULL;
        hFileOut = NULL;
        free(buffer);
        buffer = NULL;
    
        cntFileProcessed++;
        return;
    }
    
    //parse if there to be a wild char
    void HandleFile(char* filespec)
    {
        WIN32_FIND_DATA fd;
        HANDLE hFile = NULL;
        char findpath[260];
        char tmppath[260];
        char* pchar = NULL;
    
        hFile = FindFirstFile(filespec, &fd);
        if(hFile == INVALID_HANDLE_VALUE)
        {
            fprintf(stderr, "没有文件用于处理!\n");
            return;
        }
    
        strncpy(findpath, filespec, sizeof(findpath));
        //we need to add a full current path to the dest file 
        //since the fd.cFileName member does not include the path
        pchar = strrchr(findpath, '\\');
        if(!pchar)
            pchar = strrchr(findpath, '/');    //sometimes, it's not back-slash-ed.
        if(pchar)
            *(pchar+1) = '\0';
        do 
        {
            if(!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))    //eliminate directory
            {
                if(pchar)
                {
                    sprintf(tmppath, "%s%s", findpath, fd.cFileName);    //now it's full path
                    ExtractFile(tmppath);
                }
                else
                {
                    ExtractFile(fd.cFileName);    //in current dir
                }
            }
        } while (FindNextFile(hFile, &fd));    //continue deep search
        FindClose(hFile);
        hFile = NULL;
        return;
    }
    
    void Usage(char* name)
    {
        char* ptr = strrchr(name, '\\');    //only the name we need, not the full path
        char* pmsg = 
            "迅雷看看XV文件提取器 - 版本:1.0\n"
            "作者:女孩不哭 编译时间:" __DATE__ " " __TIME__ "\n\n"
            "使用方法:\"%s /y 文件\", 输出文件在当前工作目录下\n\n"
            "敬告:迅雷XV文件包含受版权保护的内容.\n"
            "本程序仅供研究和学习使用, 请自觉将提取的文件立即删除.\n"
            "切勿将本程序及其提取的文件使用于任何其它用途.\n"
            "对于使用本程序造成的任何后果, 由使用者自行承担法律责任!\n"
            "要接受此协议, 请从命令行传入/y作为第1个参数, 文件作为第2个参数.\n";
        if(!ptr)
            ptr = strrchr(name, '/');
        if(!ptr)    //the cur dir is just in the exe dir
            ptr = name-1;//ptr+1
        printf(pmsg, ptr+1);
        return;
    }
    
    int main(int argc, char** argv)
    {
        CONSOLE_SCREEN_BUFFER_INFO sbi;
        if(argc!=3 || stricmp(argv[1], "/y"))    //xve /y file format expected
        {
            Usage(argv[0]);
            return 1;
        }
        GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &sbi);
        scrWidth = sbi.dwSize.X;    //width, in characters
    
        HandleFile(argv[2]);    //enum files if a wild char is detected
        printf("处理了 %d 个文件!\n", cntFileProcessed);
        return 0;
    }

    项目及bin下载:
    http://alioss.twofei.com/windows/xve.7z
    https://files.cnblogs.com/nbsofer/xve.7z
    女孩不哭 @ 2012-08-18 23:37:03 @ http://www.cnblogs.com/nbsofer
    PS:
        其实我对迅雷看看没一点兴趣...
        不过, 从XV文件看来, 迅雷很聪明~~~  那个聪明, 你懂的.

    2013-06-09测试, 仍然能用


  • 相关阅读:
    Linux下yum安装mysql
    centos下无法使用lsof命令"-bash: lsof: command not found"
    大数据与区块链的联系与区别
    java.lang.NullPointerException报错的几种情况
    算法概述
    区块链简史
    word导出失败问题
    [Python3网络爬虫开发实战] 1.9.5-Scrapyrt的安装
    [Python3网络爬虫开发实战] 1.9.3-Scrapyd-Client的安装
    [Python3网络爬虫开发实战] 1.9.2-Scrapyd的安装
  • 原文地址:https://www.cnblogs.com/memset/p/2645979.html
Copyright © 2011-2022 走看看