mshtml: Added hack to allow pass post data to IPersistMoniker::Load.
[wine] / dlls / crypt32 / str.c
1 /*
2  * Copyright 2006 Juan Lang for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18 #include <stdarg.h>
19 #include "windef.h"
20 #include "winbase.h"
21 #include "wincrypt.h"
22 #include "wine/debug.h"
23
24 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
25
26 DWORD WINAPI CertRDNValueToStrA(DWORD dwValueType, PCERT_RDN_VALUE_BLOB pValue,
27  LPSTR psz, DWORD csz)
28 {
29     DWORD ret = 0;
30
31     TRACE("(%ld, %p, %p, %ld)\n", dwValueType, pValue, psz, csz);
32
33     switch (dwValueType)
34     {
35     case CERT_RDN_ANY_TYPE:
36         break;
37     case CERT_RDN_PRINTABLE_STRING:
38     case CERT_RDN_IA5_STRING:
39         if (!psz || !csz)
40             ret = pValue->cbData;
41         else
42         {
43             DWORD chars = min(pValue->cbData, csz - 1);
44
45             if (chars)
46             {
47                 memcpy(psz, pValue->pbData, chars);
48                 ret += chars;
49                 csz -= chars;
50             }
51         }
52         break;
53     default:
54         FIXME("string type %ld unimplemented\n", dwValueType);
55     }
56     if (psz && csz)
57     {
58         *(psz + ret) = '\0';
59         csz--;
60         ret++;
61     }
62     else
63         ret++;
64     return ret;
65 }
66
67 DWORD WINAPI CertRDNValueToStrW(DWORD dwValueType, PCERT_RDN_VALUE_BLOB pValue,
68  LPWSTR psz, DWORD csz)
69 {
70     DWORD ret = 0;
71
72     TRACE("(%ld, %p, %p, %ld)\n", dwValueType, pValue, psz, csz);
73
74     switch (dwValueType)
75     {
76     case CERT_RDN_ANY_TYPE:
77         break;
78     case CERT_RDN_PRINTABLE_STRING:
79     case CERT_RDN_IA5_STRING:
80         if (!psz || !csz)
81             ret = pValue->cbData;
82         else
83         {
84             DWORD chars = min(pValue->cbData, csz - 1);
85
86             if (chars)
87             {
88                 DWORD i;
89
90                 for (i = 0; i < chars; i++)
91                     psz[i] = pValue->pbData[i];
92                 ret += chars;
93                 csz -= chars;
94             }
95         }
96         break;
97     default:
98         FIXME("string type %ld unimplemented\n", dwValueType);
99     }
100     if (psz && csz)
101     {
102         *(psz + ret) = '\0';
103         csz--;
104         ret++;
105     }
106     else
107         ret++;
108     return ret;
109 }
110
111 DWORD WINAPI CertNameToStrA(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName,
112  DWORD dwStrType, LPSTR psz, DWORD csz)
113 {
114     static const DWORD unsupportedFlags = CERT_NAME_STR_NO_QUOTING_FLAG |
115      CERT_NAME_STR_REVERSE_FLAG | CERT_NAME_STR_ENABLE_T61_UNICODE_FLAG;
116     static const char commaSep[] = ", ";
117     static const char semiSep[] = "; ";
118     static const char crlfSep[] = "\r\n";
119     static const char plusSep[] = " + ";
120     static const char spaceSep[] = " ";
121     DWORD ret = 0, bytes = 0;
122     BOOL bRet;
123     CERT_NAME_INFO *info;
124
125     TRACE("(%ld, %p, %08lx, %p, %ld)\n", dwCertEncodingType, pName, dwStrType,
126      psz, csz);
127     if (dwStrType & unsupportedFlags)
128         FIXME("unsupported flags: %08lx\n", dwStrType & unsupportedFlags);
129
130     bRet = CryptDecodeObjectEx(dwCertEncodingType, X509_NAME, pName->pbData,
131      pName->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &bytes);
132     if (bRet)
133     {
134         DWORD i, j, sepLen, rdnSepLen;
135         LPCSTR sep, rdnSep;
136
137         if (dwStrType & CERT_NAME_STR_SEMICOLON_FLAG)
138             sep = semiSep;
139         else if (dwStrType & CERT_NAME_STR_CRLF_FLAG)
140             sep = crlfSep;
141         else
142             sep = commaSep;
143         sepLen = strlen(sep);
144         if (dwStrType & CERT_NAME_STR_NO_PLUS_FLAG)
145             rdnSep = spaceSep;
146         else
147             rdnSep = plusSep;
148         rdnSepLen = strlen(rdnSep);
149         for (i = 0; ret < csz && i < info->cRDN; i++)
150         {
151             for (j = 0; ret < csz && j < info->rgRDN[i].cRDNAttr; j++)
152             {
153                 DWORD chars;
154
155                 if ((dwStrType & 0x000000ff) == CERT_OID_NAME_STR)
156                 {
157                     /* - 1 is needed to account for the NULL terminator. */
158                     chars = min(
159                      lstrlenA(info->rgRDN[i].rgRDNAttr[j].pszObjId),
160                      csz - ret - 1);
161                     if (psz && chars)
162                         memcpy(psz + ret, info->rgRDN[i].rgRDNAttr[j].pszObjId,
163                          chars);
164                     ret += chars;
165                     csz -= chars;
166                     if (csz > 1)
167                     {
168                         if (psz)
169                             *(psz + ret) = '=';
170                         ret++;
171                         csz--;
172                     }
173                 }
174                 /* FIXME: handle quoting */
175                 chars = CertRDNValueToStrA(
176                  info->rgRDN[i].rgRDNAttr[j].dwValueType, 
177                  &info->rgRDN[i].rgRDNAttr[j].Value, psz ? psz + ret : NULL,
178                  csz - ret - 1);
179                 if (chars)
180                     ret += chars - 1;
181                 if (j < info->rgRDN[i].cRDNAttr - 1)
182                 {
183                     if (psz && ret < csz - rdnSepLen - 1)
184                         memcpy(psz + ret, rdnSep, rdnSepLen);
185                     ret += rdnSepLen;
186                 }
187             }
188             if (i < info->cRDN - 1)
189             {
190                 if (psz && ret < csz - sepLen - 1)
191                     memcpy(psz + ret, sep, sepLen);
192                 ret += sepLen;
193             }
194         }
195         LocalFree(info);
196     }
197     if (psz && csz)
198     {
199         *(psz + ret) = '\0';
200         csz--;
201         ret++;
202     }
203     else
204         ret++;
205     return ret;
206 }
207
208 DWORD WINAPI CertNameToStrW(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName,
209  DWORD dwStrType, LPWSTR psz, DWORD csz)
210 {
211     static const DWORD unsupportedFlags = CERT_NAME_STR_NO_QUOTING_FLAG |
212      CERT_NAME_STR_REVERSE_FLAG | CERT_NAME_STR_ENABLE_T61_UNICODE_FLAG;
213     static const WCHAR commaSep[] = { ',',' ',0 };
214     static const WCHAR semiSep[] = { ';',' ',0 };
215     static const WCHAR crlfSep[] = { '\r','\n',0 };
216     static const WCHAR plusSep[] = { ' ','+',' ',0 };
217     static const WCHAR spaceSep[] = { ' ',0 };
218     DWORD ret = 0, bytes = 0;
219     BOOL bRet;
220     CERT_NAME_INFO *info;
221
222     TRACE("(%ld, %p, %08lx, %p, %ld)\n", dwCertEncodingType, pName, dwStrType,
223      psz, csz);
224     if (dwStrType & unsupportedFlags)
225         FIXME("unsupported flags: %08lx\n", dwStrType & unsupportedFlags);
226
227     bRet = CryptDecodeObjectEx(dwCertEncodingType, X509_NAME, pName->pbData,
228      pName->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &bytes);
229     if (bRet)
230     {
231         DWORD i, j, sepLen, rdnSepLen;
232         LPCWSTR sep, rdnSep;
233
234         if (dwStrType & CERT_NAME_STR_SEMICOLON_FLAG)
235             sep = semiSep;
236         else if (dwStrType & CERT_NAME_STR_CRLF_FLAG)
237             sep = crlfSep;
238         else
239             sep = commaSep;
240         sepLen = lstrlenW(sep);
241         if (dwStrType & CERT_NAME_STR_NO_PLUS_FLAG)
242             rdnSep = spaceSep;
243         else
244             rdnSep = plusSep;
245         rdnSepLen = lstrlenW(rdnSep);
246         for (i = 0; ret < csz && i < info->cRDN; i++)
247         {
248             for (j = 0; ret < csz && j < info->rgRDN[i].cRDNAttr; j++)
249             {
250                 DWORD chars;
251
252                 if ((dwStrType & 0x000000ff) == CERT_OID_NAME_STR)
253                 {
254                     /* - 1 is needed to account for the NULL terminator. */
255                     chars = min(
256                      lstrlenA(info->rgRDN[i].rgRDNAttr[j].pszObjId),
257                      csz - ret - 1);
258                     if (psz && chars)
259                     {
260                         DWORD k;
261
262                         for (k = 0; k < chars; k++)
263                             *(psz + ret + k) =
264                              info->rgRDN[i].rgRDNAttr[j].pszObjId[k];
265                     }
266                     ret += chars;
267                     csz -= chars;
268                     if (csz > 1)
269                     {
270                         if (psz)
271                             *(psz + ret) = '=';
272                         ret++;
273                         csz--;
274                     }
275                 }
276                 /* FIXME: handle quoting */
277                 chars = CertRDNValueToStrW(
278                  info->rgRDN[i].rgRDNAttr[j].dwValueType, 
279                  &info->rgRDN[i].rgRDNAttr[j].Value, psz ? psz + ret : NULL,
280                  csz - ret - 1);
281                 if (chars)
282                     ret += chars - 1;
283                 if (j < info->rgRDN[i].cRDNAttr - 1)
284                 {
285                     if (psz && ret < csz - rdnSepLen - 1)
286                         memcpy(psz + ret, rdnSep, rdnSepLen * sizeof(WCHAR));
287                     ret += rdnSepLen;
288                 }
289             }
290             if (i < info->cRDN - 1)
291             {
292                 if (psz && ret < csz - sepLen - 1)
293                     memcpy(psz + ret, sep, sepLen * sizeof(WCHAR));
294                 ret += sepLen;
295             }
296         }
297         LocalFree(info);
298     }
299     if (psz && csz)
300     {
301         *(psz + ret) = '\0';
302         csz--;
303         ret++;
304     }
305     else
306         ret++;
307     return ret;
308 }