当前位置: 首页 > news >正文

用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
http://files.cnblogs.com/nbsofer/xve.7z
女孩不哭 @ 2012-08-18 23:37:03 @ http://www.cnblogs.com/nbsofer
PS:
    其实我对迅雷看看没一点兴趣...
    不过, 从XV文件看来, 迅雷很聪明~~~  那个聪明, 你懂的.

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


相关文章:

  • NSF之旅:3月6号,今天要完成相关研究和前两个内容的技术路线
  • 通用业务系统基础平台(五) 工作流系统
  • zookeeper -- 第八章 zk开源客户端 Curator介绍 (下)
  • Flex中使用HTTPService与服务器端交换数据
  • Oculus Touch再度被坑,这次是电商Saturn流出上架信息
  • 「镁客·请讲」打造一台眼睛专属“跑步机”,鹰视菲诺是如何用AI拯救近视的?...
  • 可关闭与最小化的右下角浮动广告代码
  • 第185天:百度星座案例
  • ccpuid:CPUID信息模块 V1.01版,支持GCC(兼容32位或64位的Windows/Linux)
  • C#面向服务编程技术WCF从入门到实战演练
  • java、数据库中命名规则
  • 分类模型——Logistics Regression
  • AR图书,看着很美其实有点坑
  • 有关libpthread.so库的问题
  • 运用免费OA让你有意想不到的效果
  • [笔记] php常见简单功能及函数
  • 【vuex入门系列02】mutation接收单个参数和多个参数
  • 【面试系列】之二:关于js原型
  • create-react-app项目添加less配置
  • iOS高仿微信项目、阴影圆角渐变色效果、卡片动画、波浪动画、路由框架等源码...
  • JavaScript设计模式与开发实践系列之策略模式
  • laravel5.5 视图共享数据
  • linux安装openssl、swoole等扩展的具体步骤
  • php面试题 汇集2
  • Promise面试题,控制异步流程
  • vue+element后台管理系统,从后端获取路由表,并正常渲染
  • 服务器从安装到部署全过程(二)
  • 好的网址,关于.net 4.0 ,vs 2010
  • 聊聊spring cloud的LoadBalancerAutoConfiguration
  • 前嗅ForeSpider教程:创建模板
  • 微信小程序上拉加载:onReachBottom详解+设置触发距离
  • 携程小程序初体验
  • 06-01 点餐小程序前台界面搭建
  • 【运维趟坑回忆录】vpc迁移 - 吃螃蟹之路
  • Android开发者必备:推荐一款助力开发的开源APP
  • ​TypeScript都不会用,也敢说会前端?
  • # 执行时间 统计mysql_一文说尽 MySQL 优化原理
  • ###项目技术发展史
  • #、%和$符号在OGNL表达式中经常出现
  • #14vue3生成表单并跳转到外部地址的方式
  • $(document).ready(function(){}), $().ready(function(){})和$(function(){})三者区别
  • (C语言)输入一个序列,判断是否为奇偶交叉数
  • (pt可视化)利用torch的make_grid进行张量可视化
  • (备忘)Java Map 遍历
  • (附源码)ssm考试题库管理系统 毕业设计 069043
  • (五)Python 垃圾回收机制
  • (一)80c52学习之旅-起始篇
  • (转)Java socket中关闭IO流后,发生什么事?(以关闭输出流为例) .
  • ***linux下安装xampp,XAMPP目录结构(阿里云安装xampp)
  • .dat文件写入byte类型数组_用Python从Abaqus导出txt、dat数据
  • .equals()到底是什么意思?
  • .Net mvc总结
  • .NET开源快速、强大、免费的电子表格组件
  • .NET学习全景图
  • .net中应用SQL缓存(实例使用)