2019年6月

因为工作需要用到SM2算法加解密,网络上找一圈,没有合用的,还被骗了一堆积分。

无奈只得自行编译,从GITHUB的GMSSL下载到最新的SSL库,VS2012下编译踩了不少坑,记录一下

GITHUB链接:https://github.com/guanzhi/GmSSL

fork了一下分支:https://github.com/eaglexmw-gmail/GmSSL

首先编译需要perl、VS2012、NASM三个工具,分别安装后,由于VS2012与NASM没有修改PATH环境变量

在执行perl Configure VC-WIN32时会报告工具缺失,可以使用set path=%path%;xxx;方式添加路径

这里记录第一个坑,VS2012修改PATH变量,不能只将VC\BIN这样的目录加入就完了,需要增加

C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE;C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\Tools;C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin;C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\vcpackages;C:\Windows\Microsoft.NET\Framework64\v4.0.30319;C:\Windows\Microsoft.NET\Framework64\v3.5;C:\Windows\Microsoft.NET\Framework\v4.0.30319;C:\Windows\Microsoft.NET\Framework\v3.5;

这么一堆路径都需要加入,否则还是会编译出错,参考:https://www.cnblogs.com/bluestorm/p/3321558.html

最简便的方法是调用VC提供的批处理,C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\Tools\vsvars32.bat

修改好后,使用nmake即可开始编译。

编译时有几处代码提示编译失败,都是属于C语言中,变量声明在有效代码后(VS严格禁止的),调换一下顺序即可

diff -r -u -N -w GmSSL-master/crypto/sm9/sm9_asn1.c GmSSL-master_new/crypto/sm9/sm9_asn1.c--- GmSSL-master/crypto/sm9/sm9_asn1.c    2019-06-15 23:42:35.000000000 +0800
+++ GmSSL-master_new/crypto/sm9/sm9_asn1.c    2019-06-25 18:16:49.931390600 +0800@@-285,9 +285,9@@
{
intret;
ASN1_OCTET_STRING s;
+ int len = 0;
s.type
=V_ASN1_OCTET_STRING;
s.data
=NULL;- int len = 0;if (inlen >SM9_MAX_PLAINTEXT_LENGTH) {
SM9err(SM9_F_SM9_CIPHERTEXT_SIZE, SM9_R_PLAINTEXT_TOO_LONG);
diff
-r -u -N -w GmSSL-master/crypto/sm9/sm9_rate.c GmSSL-master_new/crypto/sm9/sm9_rate.c--- GmSSL-master/crypto/sm9/sm9_rate.c 2019-06-15 23:42:35.000000000 +0800 +++ GmSSL-master_new/crypto/sm9/sm9_rate.c 2019-06-25 18:18:18.959395000 +0800@@-1303,14 +1303,15@@static int fp12_inv(fp12_t r, const fp12_t a, const BIGNUM *p, BN_CTX *ctx)
{
- if (fp4_is_zero(a[2])) {
fp4_t k;
fp4_t t;
+fp4_t r0, r1, r2;+ + if (fp4_is_zero(a[2])) {if (!fp4_init(t, ctx)) {return 0;
}
-fp4_t r0, r1, r2;
fp4_init(r0, ctx);
fp4_init(r1, ctx);
fp4_init(r2, ctx);
@@
-2239,6 +2240,8@@
BIGNUM
*k =BN_new();intok;+fp12_t x, y;+point_init(&G, ctx);
point_init(
&P, ctx);

@@
-2280,8 +2283,6@@
ok
= point_equ_hex(&P, Ppubs, ctx);
printf(
"point test %d: %s\n", __LINE__, ok ? "ok" : "error");-fp12_t x, y;-fp12_init(x, ctx);
fp12_init(y, ctx);

diff
-r -u -N -w GmSSL-master/ssl/statem/statem_gmtls.c GmSSL-master_new/ssl/statem/statem_gmtls.c--- GmSSL-master/ssl/statem/statem_gmtls.c 2019-06-15 23:42:35.000000000 +0800 +++ GmSSL-master_new/ssl/statem/statem_gmtls.c 2019-06-25 18:19:36.844416900 +0800@@-303,11 +303,12@@int gmtls_construct_server_certificate(SSL *s)
{
unsigned
longalg_a;- alg_a = s->s3->tmp.new_cipher->algorithm_auth;intl;
unsigned
char *p;int al = -1;+ alg_a = s->s3->tmp.new_cipher->algorithm_auth;+l= 3 +SSL_HM_HEADER_LENGTH(s);if (alg_a & SSL_aSM2) {

 patch文件下载地址:https://files.cnblogs.com/files/eaglexmw/gmssl_20190625_patch.7z

编译成功后,使用nmake install安装,由于默认安装路径在C:\Program Files (x86)\GmSSL,因此,需要管理员权限

管理员权限我通常是采取找到cmd.exe(所在路径C:\windows\system32),右键后管理员运行办法来完成

安装后,即可包含、链接相应库等后续开发了。

 

VS2012下自定义打开文件对话框,MFC的CFileDialog封装了太多,太复杂,绕得头晕,自己封装一个得了

#pragma once#include<objbase.h>#include<commdlg.h>#include"ImagePreviewStatic.h"

//XFileDialog

class XFileDialog : publicCWnd
{
DECLARE_DYNAMIC(XFileDialog)
public:
XFileDialog(BOOL bOpenFileDialog,
//TRUE for FileOpen, FALSE for FileSaveAs LPCTSTR lpszDefExt =NULL,
LPCTSTR lpszFileName
=NULL,
DWORD dwFlags
= OFN_HIDEREADONLY |OFN_OVERWRITEPROMPT,
LPCTSTR lpszFilter
= NULL, LPCTSTR lpszInitFolder =NULL,
CWnd
* pParentWnd =NULL);virtual ~XFileDialog();public:void EndDialog(intnResult);virtualBOOL OnInitDialog();virtual longDoModal();virtual void DoDataExchange(CDataExchange *pDX);virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT*pResult);virtual void ProcFileChange(TCHAR*strFullName);protected:
OPENFILENAME m_ofn;
BOOL m_bOpenFileDialog;
//TRUE for file open, FALSE for file save CString m_strFilter; //filter string TCHAR m_szFileTitle[64]; //contains file title after return TCHAR m_szFileName[_MAX_PATH]; //contains full path name after return CWnd* m_pParentWnd; //parent/owner window HWND m_hWndTop; //top level parent window (may be disabled) CImagePreviewStatic m_preview;

DECLARE_MESSAGE_MAP()
};
1 //XFileDialog.cpp : implementation file2 //3 
4 #include "stdafx.h"
5 #include "XFileDialog.h"
6 #include "resource.h"
7 
8 //XFileDialog
9 
10 UINT_PTR CALLBACK OFNHookProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);11 
12 UINT_PTR CALLBACK OFNHookProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)13 {14     if (hWnd ==NULL)15         return 0;16     _AFX_THREAD_STATE* pThreadState =AfxGetThreadState();17     if (pThreadState->m_pAlternateWndInit != NULL && CWnd::FromHandlePermanent(hWnd) ==NULL)18 {19         ASSERT_KINDOF(XFileDialog, pThreadState->m_pAlternateWndInit);20         pThreadState->m_pAlternateWndInit->SubclassWindow(hWnd);21         pThreadState->m_pAlternateWndInit =NULL;22 }23 
24     if (message ==WM_INITDIALOG)25 {26         /*
27 _afxMsgLBSELCHANGE = ::RegisterWindowMessage(LBSELCHSTRING);28 _afxMsgSHAREVI = ::RegisterWindowMessage(SHAREVISTRING);29 _afxMsgFILEOK = ::RegisterWindowMessage(FILEOKSTRING);30 _afxMsgCOLOROK = ::RegisterWindowMessage(COLOROKSTRING);31 _afxMsgHELP = ::RegisterWindowMessage(HELPMSGSTRING);32 _afxMsgSETRGB = ::RegisterWindowMessage(SETRGBSTRING);33         */
34 
35         XFileDialog* pDlg =DYNAMIC_DOWNCAST(XFileDialog, CWnd::FromHandlePermanent(hWnd));36         if (pDlg !=NULL)37             return pDlg->OnInitDialog();38         else
39             return 1;40 }41 
42     return 0;43 }44 
45 BEGIN_MESSAGE_MAP(XFileDialog, CWnd)46 END_MESSAGE_MAP()47 
48 XFileDialog::XFileDialog(BOOL bOpenFileDialog, LPCTSTR lpszDefExt, LPCTSTR lpszFileName,49         DWORD dwFlags, LPCTSTR lpszFilter, LPCTSTR lpszInitFolder, CWnd*pParentWnd) :50 CWnd()51 {52     m_szFileName[0] = '\0';53     m_szFileTitle[0] = '\0';54     m_bOpenFileDialog =bOpenFileDialog;55 
56     m_pParentWnd =NULL;57     m_hWndTop =NULL;58 
59     memset(&m_ofn, 0, sizeof(OPENFILENAME)); //initialize structure to 0/NULL
60 
61     m_ofn.Flags |=  dwFlags | OFN_ENABLETEMPLATE |OFN_HIDEREADONLY | OFN_EXPLORER  |OFN_ENABLEHOOK;62     m_ofn.lpstrTitle   =  _T("图像文件预览对话框");63     m_ofn.lpstrInitialDir =lpszInitFolder;64 
65     m_ofn.lStructSize =  sizeof(OPENFILENAME);66     m_ofn.lpstrFile =m_szFileName;67     m_ofn.nMaxFile =_countof(m_szFileName);68     m_ofn.lpstrDefExt =lpszDefExt;69     m_ofn.lpstrFileTitle =(LPTSTR)m_szFileTitle;70     m_ofn.nMaxFileTitle =_countof(m_szFileTitle);71     if(dwFlags &OFN_ENABLETEMPLATE)72         m_ofn.Flags &= ~OFN_ENABLESIZING;73     m_ofn.hInstance =AfxGetResourceHandle();74     m_ofn.lpfnHook =(LPOFNHOOKPROC)OFNHookProc;75     m_ofn.lpTemplateName =MAKEINTRESOURCE(IDD_IMAGEPREVIEWDLG);76 
77     //setup initial file name
78     if (lpszFileName !=NULL)79 Checked::tcsncpy_s(m_szFileName, _countof(m_szFileName), lpszFileName, _TRUNCATE);80 
81     //Translate filter into commdlg format (lots of \0)
82     if (lpszFilter !=NULL)83 {84         m_strFilter =lpszFilter;85         LPTSTR pch = m_strFilter.GetBuffer(0); //modify the buffer in place86         //MFC delimits with '|' not '\0'
87         while ((pch = _tcschr(pch, '|')) !=NULL)88             *pch++ = '\0';89         m_ofn.lpstrFilter =m_strFilter;90         //do not call ReleaseBuffer() since the string contains '\0' characters
91 }92 }93 
94 XFileDialog::~XFileDialog()95 {96 }97 
98 void XFileDialog::EndDialog(intnResult)99 {100 ASSERT(::IsWindow(m_hWnd));101 
102 ::EndDialog(m_hWnd, nResult);103 }104 
105 BOOL XFileDialog::OnInitDialog()106 {107     //transfer data into the dialog from member variables
108 #if 1
109     if (!UpdateData(FALSE))110 {111         TRACE(traceAppMsg, 0, "Warning: UpdateData failed during dialog init.\n");112         EndDialog(-1);113         returnFALSE;114 }115 #endif
116 
117     GetDlgItem(IDC_IMAGEPREVIEW)->ModifyStyle ( SS_TYPEMASK, SS_OWNERDRAW );118 
119     return TRUE;    //set focus to first one
120 }121 
122 void XFileDialog::DoDataExchange(CDataExchange *pDX)123 {124 CWnd::DoDataExchange(pDX);125 DDX_Control(pDX, IDC_IMAGEPREVIEW, m_preview);126 }127 
128 void XFileDialog::ProcFileChange(TCHAR*strFullName){129     //如果是文件名
130     DWORD nFileAtts =GetFileAttributes(strFullName);131     if ((FILE_ATTRIBUTE_NORMAL == nFileAtts) ||
132         (0 == (nFileAtts & (FILE_ATTRIBUTE_DEVICE |FILE_ATTRIBUTE_DIRECTORY )) ) ){133 m_preview.SetFilename(strFullName);134     } else{135         //m_preview.SetFilename(NULL);
136 }137 }138 
139 
140 BOOL XFileDialog::OnNotify(WPARAM, LPARAM lp, LRESULT *pResult)141 {142     LPOFNOTIFY of =(LPOFNOTIFY) lp;143 CString       csTemp;144 TCHAR       strFileName[_MAX_PATH];145 
146 HWND hParent;147 UINT nfiles;148 
149     switch (of->hdr.code)150 {151     caseCDN_SELCHANGE:152         hParent = GetParent()->GetSafeHwnd();153         nfiles =CommDlg_OpenSave_GetFilePath(hParent, strFileName, _MAX_PATH);154         if (nfiles > 0) {155 ProcFileChange(strFileName);156             //MessageBox(strFileName);
157 }158         break;159 
160     caseCDN_FOLDERCHANGE:161         //Once we    get    this notification our old subclassing of162         //the    SHELL window is    lost, so we    have to163         //subclass it    again. (Changing the folder    causes a164         //destroy    and    recreate of    the    SHELL window).165         //if (m_wndHook.GetSafeHwnd()    != HWND(NULL))166         //m_wndHook.UnsubclassWindow();167 
168         //m_wndHook.SubclassWindow(GetParent()->GetDlgItem(lst2)->GetSafeHwnd());169         //UpdatePreview(_T(""));
170         break;171 }172 
173     *pResult = 0;174     returnFALSE;175 }176 
177 longXFileDialog::DoModal()178 {179     HWND hWndFocus =::GetFocus();180     BOOL bEnableParent =FALSE;181     //allow OLE servers to disable themselves
182     CWinApp* pApp =AfxGetApp();183     if (pApp !=NULL)184         pApp->EnableModeless(FALSE);185 
186     _AFX_THREAD_STATE* pThreadState =AfxGetThreadState();187     pThreadState->m_pAlternateWndInit = this;188     //AfxHookWindowCreate(this);
189 
190     HWND hWndParent = CWnd::GetSafeOwner_(m_pParentWnd->GetSafeHwnd(), &m_hWndTop);;191     if (hWndParent && hWndParent != ::GetDesktopWindow() &&::IsWindowEnabled(hWndParent))192 {193 ::EnableWindow(hWndParent, FALSE);194         bEnableParent =TRUE;195 }196 
197     INT_PTR nResult = 0;198 
199     if(m_bOpenFileDialog)200         nResult = GetOpenFileName(&m_ofn);201     else
202         nResult = GetSaveFileName(&m_ofn);203 
204     if(nResult)205         ASSERT(pThreadState->m_pAlternateWndInit ==NULL);206 
207     //Second part of special case for file open/save dialog.
208     if(bEnableParent)209 ::EnableWindow(hWndParent, TRUE);210     if(::IsWindow(hWndFocus))211 ::SetFocus(hWndFocus);212 
213     AfxUnhookWindowCreate();   //just in case
214     Detach();               //just in case
215 
216     if (pApp !=NULL)217         pApp->EnableModeless(TRUE);218 
219     return nResult ?nResult : IDCANCEL;220 }221 
222 
223 IMPLEMENT_DYNAMIC(XFileDialog, CWnd)224 
225 //XFileDialog message handlers
ImagePreviewStatic.h其实就是一个CStatic的继承类,实现图片预览
1 /*
2 *    $Header: $3 *4 *    $History: $5  */
6 #pragma once
7 
8 #include <atlimage.h>
9 
10 //CImagePrieviewStatic
11 class CImagePreviewStatic :    publicCStatic12 {13 DECLARE_DYNAMIC(CImagePreviewStatic)14 public:15 CImagePreviewStatic();16     virtual            ~CImagePreviewStatic();17 
18     virtualBOOL    Create();19     virtual    voidDrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);20 
21     voidSetFilename(LPCTSTR    szFilename);22 
23 protected:24 WCHAR            m_wsFilename[_MAX_PATH];25     Image            *m_img;26     Graphics        *m_graphics;27     CImage          *m_img2;28 
29 DECLARE_MESSAGE_MAP()30 };
1 /*
2 *    $Header: $3 *4 *    $History: $5  */
6 #include "stdafx.h"
7 #include "ImagePreviewStatic.h"
8 
9 
10 //CImagePrieviewStatic
11 IMPLEMENT_DYNAMIC(CImagePreviewStatic, CStatic)12 
13 CImagePreviewStatic::CImagePreviewStatic() : CStatic()14 {15     m_img = (Image *) NULL;16     m_graphics = (Graphics *) NULL;17     m_img2 = (CImage*) NULL;18 }19 
20 CImagePreviewStatic::~CImagePreviewStatic()21 {22     if(m_img) {23         deletem_img;24 }25     if(m_graphics) {26         deletem_graphics;27 }28     if(m_img2) {29         deletem_img2;30 }31 }32 
33 BOOL CImagePreviewStatic::Create()34 {35     if (GetSafeHwnd() !=HWND(NULL))36 {37         m_img =    newImage(m_wsFilename);38         m_graphics = newGraphics(GetSafeHwnd());39         returnTRUE;40 }41 
42     returnFALSE;43 }44 
45 voidCImagePreviewStatic::SetFilename(LPCTSTR szFilename)46 {47 #ifndef    _UNICODE48 USES_CONVERSION;49 #endif
50 
51 ASSERT(szFilename);52 ASSERT(AfxIsValidString(szFilename));53 
54     TRACE("%s\n", szFilename);55 
56 #ifndef    _UNICODE57 wcscpy(m_wsFilename, A2W(szFilename));58 #else
59 wcscpy(m_wsFilename, szFilename);60 #endif
61 
62     //delete m_img;63     //m_img =    new    Image(m_wsFilename,    FALSE);
64     if(m_img2) {65         deletem_img2;66 }67     m_img2 = newCImage();68     m_img2->Load(szFilename);69 
70 Invalidate();71 }72 
73 void CImagePreviewStatic::DrawItem(LPDRAWITEMSTRUCT    /*lpDrawItemStruct*/)74 {75 Unit  units;76 CRect rect;77 
78     /*
79 if (m_img != NULL)80 {81 GetClientRect(&rect);82 
83 RectF destRect(REAL(rect.left),    REAL(rect.top),    REAL(rect.Width()),    REAL(rect.Height())),84 srcRect;85 m_img->GetBounds(&srcRect, &units);86 m_graphics->DrawImage(m_img, destRect, srcRect.X, srcRect.Y, srcRect.Width,    srcRect.Height,    UnitPixel, NULL);87 }88     */
89     if (m_img2 !=NULL) {90         HWND hWnd = GetParent()->m_hWnd;91         HDC hDc =::GetDC(hWnd);92         GetWindowRect(&rect);93         ::ScreenToClient(hWnd, (LPPOINT)&rect);94         ::ScreenToClient(hWnd, (LPPOINT)(&rect) + 1);95         //获取到HDC
96         m_img2->Draw(hDc,rect);97 }98 }99 
100 BEGIN_MESSAGE_MAP(CImagePreviewStatic, CStatic)101 END_MESSAGE_MAP()102 
103 //CImagePrieviewStatic message handlers

其中的对话框资源
IDD_IMAGEPREVIEWDLG DIALOGEX 0, 0, 365, 177
STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
    CONTROL         "",IDC_IMAGEPREVIEW,"Static",SS_OWNERDRAW,7,7,351,163
END

 

string与wstring的互相转换接口(Windows版本)

std::wstring stringToWstring( const std::string & str )
{
	LPCSTR	pszSrc	= str.c_str();
	int	nLen = MultiByteToWideChar( CP_ACP, 0, pszSrc, -1, NULL, 0 );
	if ( nLen == 0 )
		return(std::wstring( L"" ) );

	wchar_t* pwszDst = new wchar_t[nLen];
	if ( !pwszDst )
		return(std::wstring( L"" ) );

	MultiByteToWideChar( CP_ACP, 0, pszSrc, -1, pwszDst, nLen );
	std::wstring wstr( pwszDst );
	delete[] pwszDst;
	pwszDst = NULL;

	return(wstr);
}


std::string wstringToString( const std::wstring & wstr )
{
	LPCWSTR pwszSrc = wstr.c_str();
	int	nLen = WideCharToMultiByte( CP_ACP, 0, pwszSrc, -1, NULL, 0, NULL, NULL );
	if ( nLen == 0 )
		return(std::string( "" ) );

	char* pszDst = new char[nLen];
	if ( !pszDst )
		return(std::string( "" ) );

	WideCharToMultiByte( CP_ACP, 0, pwszSrc, -1, pszDst, nLen, NULL, NULL );
	std::string str( pszDst );
	delete[] pszDst;
	pszDst = NULL;

	return(str);
}

  

base64编解码的两个函数,声明,参考网络上的代码实现。

unsigned char *base64_encode(unsigned char *str, long* lpBufLen)  
{  
    long len;  
    long str_len;  
    unsigned char *res;  
    int i,j;  
//定义base64编码表  
	const unsigned char *base64_table = (const unsigned char *)("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");  
  
//计算经过base64编码后的字符串长度  
    str_len=strlen((char*)str);  
    if(str_len % 3 == 0)  
        len=str_len/3*4;  
    else  
        len=(str_len/3+1)*4;

	if (NULL != lpBufLen) {
		*lpBufLen = len;
	}
  
    res = (unsigned char *)malloc(sizeof(unsigned char)*len+1);  
    res[len]='\0';  
  
//以3个8位字符为一组进行编码  
    for(i=0,j=0;i<len-2;j+=3,i+=4)  
    {  
        res[i]=base64_table[str[j]>>2]; //取出第一个字符的前6位并找出对应的结果字符  
        res[i+1]=base64_table[(str[j]&0x3)<<4 | (str[j+1]>>4)]; //将第一个字符的后位与第二个字符的前4位进行组合并找到对应的结果字符  
        res[i+2]=base64_table[(str[j+1]&0xf)<<2 | (str[j+2]>>6)]; //将第二个字符的后4位与第三个字符的前2位组合并找出对应的结果字符  
        res[i+3]=base64_table[str[j+2]&0x3f]; //取出第三个字符的后6位并找出结果字符  
    }  
  
    switch(str_len % 3)  
    {  
        case 1:  
            res[i-2]='=';  
            res[i-1]='=';  
            break;  
        case 2:  
            res[i-1]='=';  
            break;  
    }
  
    return res;  
}

unsigned char *base64_decode(unsigned char *code, long* lpBufLen)  
{  
//根据base64表,以字符找到对应的十进制数据  
    int table[]={0,0,0,0,0,0,0,0,0,0,0,0,
    		 0,0,0,0,0,0,0,0,0,0,0,0,
    		 0,0,0,0,0,0,0,0,0,0,0,0,
    		 0,0,0,0,0,0,0,62,0,0,0,
    		 63,52,53,54,55,56,57,58,
    		 59,60,61,0,0,0,0,0,0,0,0,
    		 1,2,3,4,5,6,7,8,9,10,11,12,
    		 13,14,15,16,17,18,19,20,21,
    		 22,23,24,25,0,0,0,0,0,0,26,
    		 27,28,29,30,31,32,33,34,35,
    		 36,37,38,39,40,41,42,43,44,
    		 45,46,47,48,49,50,51
    	       };  
    long len;  
    long str_len;  
    unsigned char *res;  
    int i,j;  
  
//计算解码后的字符串长度  
    len=strlen((char*)code);  
//判断编码后的字符串后是否有=  
    if(strstr((char*)code,"=="))  
        str_len=len/4*3-2;  
    else if(strstr((char*)code,"="))  
        str_len=len/4*3-1;  
    else  
        str_len=len/4*3;  
  
	if (NULL != lpBufLen) {
		*lpBufLen = str_len;
	}

    res=(unsigned char*)malloc(sizeof(unsigned char)*str_len+1);  
    res[str_len]='\0';  
  
//以4个字符为一位进行解码  
    for(i=0,j=0;i < len-2;j+=3,i+=4)  
    {  
        res[j]=((unsigned char)table[code[i]])<<2 | (((unsigned char)table[code[i+1]])>>4); //取出第一个字符对应base64表的十进制数的前6位与第二个字符对应base64表的十进制数的后2位进行组合  
        res[j+1]=(((unsigned char)table[code[i+1]])<<4) | (((unsigned char)table[code[i+2]])>>2); //取出第二个字符对应base64表的十进制数的后4位与第三个字符对应bas464表的十进制数的后4位进行组合  
        res[j+2]=(((unsigned char)table[code[i+2]])<<6) | ((unsigned char)table[code[i+3]]); //取出第三个字符对应base64表的十进制数的后2位与第4个字符进行组合  
    }  
  
    return res;  
  
} 

  

Jetbrains系列产品2019.1.3最新激活方法[持续更新]

本站惯例:本文假定你知道Jetbrains家的产品。不知道可以问问搜索引擎。

大家熟知Jetbrains的话应该知道:他们家的所有产品升级到2018.2.1及以上版本后,先前可用的注册服务器都失效了,无法激活升级到最新版本体验最新黑科技。

这次要送的这份礼就是: Jetbrains全系列产品2019.1.3及以下版本(理论上适用于目前所有新老版本)最新注册服务器(License Server)的破解,可使用它来激活你手头上的Jetbrains IDE,具体支持产品和版本见下文的列表。

先上传送门:[Gitee仓库(已被封)],也可以直接下载(Direct download link - v2.1.1),具体使用方法已写在压缩包的 README.pdf / README.txt内(包内另附操作截图)。

使用QQ Group联系我:30347526(二群)
使用QQ Group联系我:30347511(一群)
//

已更新v2.1.1, Build Date: 2019-05-29,重新下载jetbrains-agent.jar替换。

支持Activation code注册码激活(自定义License name的朋友访问>这里<),可用于网络不佳或离线环境。


在以下IDE版本测试可成功激活:

  • IntelliJ IDEA 2019.1.3及以下
  • AppCode 2019.1.3及以下
  • CLion 2019.1.4及以下
  • DataGrip 2019.1.3及以下
  • GoLand 2019.1.3及以下
  • PhpStorm 2019.1.2及以下
  • PyCharm 2019.1.3及以下
  • Rider 2019.1.2及以下
  • RubyMine 2019.1.2及以下
  • WebStorm 2019.1.3及以下


下面是国际惯例:

本项目只做个人学习研究之用,不得用于商业用途!

若资金允许,请点击链接购买正版,谢谢合作!

学生凭学生证可免费申请正版授权!

创业公司可5折购买正版授权!