Diskuze: SOAP požadavek
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
niesom velmi zbehly v soap sluzbach, no myslim ze v prvom rade by mala byt metoda ktoru chces vykonat, implementovana na strane servera
Jan Vargovský:21.8.2016 23:17
Ahoj. Nejjednodušší cesta je asi ta, že jen dáš wsdl (URL?wsdl) přímo VS a on ti vygeneruje všechno potřebné, že ty to jen zavoláš a máš to přemapované z xml na instance toho responsu. To jak to tam konkrétně dostat už najdeš snad v každém tutoriálu nebo s trochou rozumu na to přijdeš i sám.
Btw, to wsdl by mělo být normálně public, takže když to hodíš do prohlížeče, tak by to na tebe mělo vyblít popis těch metod. Jestli si hraješ se soapem a jen chceš testovat jak tam co funguje (a jestli to tak vůbec fungovat má), tak doporučuji SoapUI.
Tak se mi snad podařilo získat wsdl. Je pravda, že mi služba nabídne požadovaná pole k vyplnění, ale nepřišel jsem na to jak získat odpověď
Třeba pomůže popis toho co konkrétně potřebuji.
Potřebuji ze serveru http://tsa.server.cz/abc/ webové služby Print2PDF 9 získat
časové razítko pro PDF dokument
WSDL:
<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:tns="http://software602.com/print2pdf/"
xmlns:s="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
targetNamespace="http://software602.com/print2pdf/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<wsdl:types>
<s:schema elementFormDefault="qualified"
targetNamespace="http://software602.com/print2pdf/">
<s:element name="GetTimeStamp">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="Hash" type="s:string" />
<s:element minOccurs="1" maxOccurs="1" name="Flags" type="s:long" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="GetTimeStampResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="GetTimeStampResult"
type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="Error" type="s:string" />
</s:sequence>
</s:complexType>
</s:element>
</s:schema>
</wsdl:types>
<wsdl:message name="GetTimeStampSoapIn">
<wsdl:part name="parameters" element="tns:GetTimeStamp" />
</wsdl:message>
<wsdl:message name="GetTimeStampSoapOut">
<wsdl:part name="parameters" element="tns:GetTimeStampResponse" />
</wsdl:message>
<wsdl:portType name="Print2PDF_WebServiceSoap">
<wsdl:operation name="GetTimeStamp">
<wsdl:input message="tns:GetTimeStampSoapIn" />
<wsdl:output message="tns:GetTimeStampSoapOut" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="Print2PDF_WebServiceSoap"
type="tns:Print2PDF_WebServiceSoap">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="GetTimeStamp">
<soap:operation
soapAction="http://software602.com/print2pdf/GetTimeStamp"
style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:binding name="Print2PDF_WebServiceSoap12"
type="tns:Print2PDF_WebServiceSoap">
<soap12:binding transport="http://schemas.xmlsoap.org/soap/http"
/>
<wsdl:operation name="GetTimeStamp">
<soap12:operation
soapAction="http://software602.com/print2pdf/GetTimeStamp"
style="document" />
<wsdl:input>
<soap12:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap12:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="Print2PDF_WebService">
<wsdl:port name="Print2PDF_WebServiceSoap"
binding="tns:Print2PDF_WebServiceSoap">
<soap:address location="http://tsa.server.cz/abc/Default.asmx" />
</wsdl:port>
<wsdl:port name="Print2PDF_WebServiceSoap12"
binding="tns:Print2PDF_WebServiceSoap12">
<soap12:address location="http://tsa.server.cz/abc/Default.asmx"
/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
Tak ten wsdl není úplný. Už jsem sehnal kompletní, který obsahuje
metodu GetTimeStamp.
Jako vstup je potřeba hash PDF ve stringu. Umím získat hash pouze v byte[].
Jak to převedu?
Jan Vargovský:23.8.2016 22:44
To záleží v jakém formátu to chtějí (tupé ascii, hex, ... ).
Tak už se mi podařilo získat i to razítko v byte[]
Teď nemůžu přijít na to jak ho vložit do PDF
Tak jinak
Mám níže uvedený kód, který proběhne naprosto bez problémů, ale v PDF
je pouze digitální podpis, certifikované časové razítko nikoli.
public void PodepisPdfCer(string SouborPDF, string OtiskCertifikatu)
{
//http://www.dotnetportal.cz/blogy/15/Null-Reference-Exception/5250/Digitalni-podepisovani-PDF-souboru-v-C-cast-2
//Get certificate
//Open the currently logged-in user certificate store
var store = new System.Security.Cryptography.X509Certificates.X509Store(System.Security.Cryptography.X509Certificates.StoreName.My, System.Security.Cryptography.X509Certificates.StoreLocation.CurrentUser);
store.Open(System.Security.Cryptography.X509Certificates.OpenFlags.ReadOnly);
string thumbprint = OtiskCertifikatu.Replace(" ", "").ToUpperInvariant();
if (thumbprint[0] == 8206)
{
thumbprint = thumbprint.Substring(1);
}
//Select a certificate from the certificate store
var certs = store.Certificates.Find(System.Security.Cryptography.X509Certificates.X509FindType.FindByThumbprint, thumbprint, true);
store.Close();
//Verify that a certificate exists
if (certs.Count == 0)
{
MessageBox.Show("Nelze najít určený certifikát v Current user certificate store!", "Sign PDF", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
//Open Pdf document
byte[] pdfData = File.ReadAllBytes(SouborPDF);
//Sign the PDF document
using (MemoryStream stream = new MemoryStream())
{
var reader = new PdfReader(pdfData);
var stp = PdfStamper.CreateSignature(reader, stream, '\0');
var sap = stp.SignatureAppearance;
//Protect certain features of the document
stp.SetEncryption(null,
Guid.NewGuid().ToByteArray(), //random password
PdfWriter.ALLOW_PRINTING | PdfWriter.ALLOW_COPY | PdfWriter.ALLOW_SCREENREADERS,
PdfWriter.ENCRYPTION_AES_256);
//Get certificate chain
var cp = new Org.BouncyCastle.X509.X509CertificateParser();
var certChain = new Org.BouncyCastle.X509.X509Certificate[] { cp.ReadCertificate(certs[0].RawData) };
sap.SetCrypto(null, certChain, null, PdfSignatureAppearance.WINCER_SIGNED);
//Set signature appearance
BaseFont helvetica = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1250, BaseFont.EMBEDDED);
iTextSharp.text.Font font = new iTextSharp.text.Font(helvetica, 12, iTextSharp.text.Font.NORMAL);
sap.Layer2Font = font;
//sap.SetVisibleSignature(new iTextSharp.text.Rectangle(415, 100, 585, 40), 1, null);
var dic = new PdfSignature(PdfName.ADOBE_PPKMS, PdfName.ADBE_PKCS7_SHA1);
//Set some stuff in the signature dictionary.
dic.Date = new PdfDate(sap.SignDate);
dic.Name = certs[0].Subject; //Certificate name
if (sap.Reason != null)
{
dic.Reason = sap.Reason;
}
if (sap.Location != null)
{
dic.Location = sap.Location;
}
//Set the crypto dictionary
sap.CryptoDictionary = dic;
//Set the size of the certificates and signature.
int csize = 4096; //Size of the signature - 4K
//Reserve some space for certs and signatures
var reservedSpace = new Dictionary<PdfName, int>();
reservedSpace[PdfName.CONTENTS] = csize * 2 + 2; //*2 because binary data is stored as hex strings. +2 for end of field
sap.PreClose(reservedSpace); //Actually reserve it
//Build the signature
System.Security.Cryptography.HashAlgorithm sha = new System.Security.Cryptography.SHA1CryptoServiceProvider();
var sapStream = sap.GetRangeStream();
int read = 0;
byte[] buff = new byte[8192];
while ((read = sapStream.Read(buff, 0, 8192)) > 0)
{
sha.TransformBlock(buff, 0, read, buff, 0);
}
sha.TransformFinalBlock(buff, 0, 0);
//Place message in a ContentInfo object. This is required to build a SignedCms object.
System.Security.Cryptography.Pkcs.ContentInfo contentInfo = new System.Security.Cryptography.Pkcs.ContentInfo(sha.Hash);
//Instantiate SignedCms object with the ContentInfo above.
//Has default SubjectIdentifierType IssuerAndSerialNumber.
System.Security.Cryptography.Pkcs.SignedCms signedCms = new System.Security.Cryptography.Pkcs.SignedCms(contentInfo, false);
//Formulate a CmsSigner object for the signer.
System.Security.Cryptography.Pkcs.CmsSigner cmsSigner = new System.Security.Cryptography.Pkcs.CmsSigner(certs[0]); //First cert in the chain is the signer cert
//Do the whole certificate chain. This way intermediate certificates get sent across as well.
cmsSigner.IncludeOption = System.Security.Cryptography.X509Certificates.X509IncludeOption.ExcludeRoot;
//Časové razítko z TSA
if (!String.IsNullOrEmpty(textBox_ServerCasovehoRazitka.Text.Trim()))
{
try
{
System.Security.Cryptography.AsnEncodedData timeData = new System.Security.Cryptography.Pkcs.Pkcs9AttributeObject(ID_TIME_STAMP_TOKEN,
DejCasoveRazitko(sha.Hash, textBox_ServerCasovehoRazitka.Text)
);
cmsSigner.UnsignedAttributes.Add(timeData);
}
catch (Exception e)
{
MessageBox.Show("Chyba TSA!\n" + e.Message);
}
}
//Sign the CMS/PKCS #7 message. The second argument is needed to ask for the pin.
signedCms.ComputeSignature(cmsSigner, false);
//Encode the CMS/PKCS #7 message.
byte[] pk = signedCms.Encode();
//Put the certs and signature into the reserved buffer
byte[] outc = new byte[csize];
Array.Copy(pk, 0, outc, 0, pk.Length);
//Put the reserved buffer into the reserved space
PdfDictionary certificateDictionary = new PdfDictionary();
certificateDictionary.Put(PdfName.CONTENTS, new PdfString(outc).SetHexWriting(true));
//Write the signature
sap.Close(certificateDictionary);
//Close the stamper and save it
stp.Close();
reader.Close();
byte[] signedData = stream.GetBuffer();
File.WriteAllBytes(SouborPDF, signedData);
}
}
static protected byte[] DejCasoveRazitko(byte[] PDF, string ServerTSA)
{
System.Security.Cryptography.HashAlgorithm algorithm = System.Security.Cryptography.MD5.Create(); //or use SHA1.Create();
StringBuilder sb = new StringBuilder();
foreach (byte b in algorithm.ComputeHash(PDF))
sb.Append(b.ToString("X2"));
NotservisTSA.GetTimeStampRequest Request = new NotservisTSA.GetTimeStampRequest(new NotservisTSA.GetTimeStampRequestBody(sb.ToString(), 0));
NotservisTSA.Print2PDF_WebServiceSoap Soap = new NotservisTSA.Print2PDF_WebServiceSoapClient();
((NotservisTSA.Print2PDF_WebServiceSoapClient)Soap).Endpoint.Address = new System.ServiceModel.EndpointAddress(new Uri(ServerTSA + "/Default.asmx"));
PodepsaniPDF.NotservisTSA.GetTimeStampResponse Response = Soap.GetTimeStamp(Request);
byte[] responseBytes = Encoding.ASCII.GetBytes(Response.Body.GetTimeStampResult);
return responseBytes;
}
Tak mírný posun. Podle pokynů CA jsem upravil kód do níže uvedeného
stavu
Nyní mi však kód spadne na řádku
Array.Copy(pk, 0, outc, 0, pk.Length);
protože csize=4096 ale pk.Length=8775.
Co s tím?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Net;
using iTextSharp.text;
using iTextSharp.text.pdf;
using Org.BouncyCastle.Tsp;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Asn1.Cmp;
using Org.BouncyCastle.Asn1.X509;
using System.Xml;
namespace PodepsaniPDF
{
public partial class Form_PodepsaniPDF : Form
{
private const String ID_TIME_STAMP_TOKEN = "1.2.840.113549.1.9.16.2.14"; // RFC 3161 id-aa-timeStampToken
public Form_PodepsaniPDF()
{
InitializeComponent();
}
private void Form_PodepsaniPDF_Load(object sender, EventArgs e)
{
comboBoxCertifikat.Items.Clear();
System.Security.Cryptography.X509Certificates.X509Store store = new System.Security.Cryptography.X509Certificates.X509Store(System.Security.Cryptography.X509Certificates.StoreName.My, System.Security.Cryptography.X509Certificates.StoreLocation.CurrentUser);
store.Open(System.Security.Cryptography.X509Certificates.OpenFlags.ReadOnly);
System.Security.Cryptography.X509Certificates.X509Certificate2Collection storecollection = (System.Security.Cryptography.X509Certificates.X509Certificate2Collection)store.Certificates;
foreach (System.Security.Cryptography.X509Certificates.X509Certificate2 x509 in storecollection)
{
if(Convert.ToDateTime(x509.GetExpirationDateString()) > DateTime.Now)
comboBoxCertifikat.Items.Add(x509.GetNameInfo(System.Security.Cryptography.X509Certificates.X509NameType.SimpleName, false) + "; " + x509.GetNameInfo(System.Security.Cryptography.X509Certificates.X509NameType.DnsName, true) + " #" + x509.Thumbprint);
}
if (comboBoxCertifikat.Items.Count > 0) comboBoxCertifikat.SelectedIndex = 0;
}
private void button_Zdroj_Click(object sender, EventArgs e)
{
OpenFileDialog VyberSouboru = new OpenFileDialog();
VyberSouboru.Title = "Výběr PDF souboru";
VyberSouboru.Multiselect = false;
VyberSouboru.Filter = "Soubor PDF | *.pdf";
if (VyberSouboru.ShowDialog() == DialogResult.OK)
{
textBox_Zdroj.Text = VyberSouboru.FileName;
textBox_Cil.Text = VyberSouboru.FileName.Replace(".pdf", "_Spodpisem.pdf");
}
}
private void button_Cil_Click(object sender, EventArgs e)
{
SaveFileDialog VyberSouboru = new SaveFileDialog();
VyberSouboru.Title = "Uložení PDF souboru";
VyberSouboru.Filter = "Soubor PDF | *.pdf";
VyberSouboru.FileName = textBox_Cil.Text;
if (VyberSouboru.ShowDialog() == DialogResult.OK)
{
textBox_Cil.Text = VyberSouboru.FileName;
}
}
private void buttonZpracovat_Click(object sender, EventArgs e)
{
try
{
File.Copy(textBox_Zdroj.Text, textBox_Cil.Text, true);
PodepisPdfCer(textBox_Cil.Text, comboBoxCertifikat.Text.Substring(comboBoxCertifikat.Text.LastIndexOf('#') + 1));
MessageBox.Show("Hotovo");
}
catch (Exception Chyba)
{
MessageBox.Show("Dokument se nepodařilo podepsat!\n\n" + Chyba.Message, "Chyba", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
public void PodepisPdfCer(string SouborPDF, string OtiskCertifikatu)
{
//http://www.dotnetportal.cz/blogy/15/Null-Reference-Exception/5250/Digitalni-podepisovani-PDF-souboru-v-C-cast-2
//Get certificate
//Open the currently logged-in user certificate store
var store = new System.Security.Cryptography.X509Certificates.X509Store(System.Security.Cryptography.X509Certificates.StoreName.My, System.Security.Cryptography.X509Certificates.StoreLocation.CurrentUser);
store.Open(System.Security.Cryptography.X509Certificates.OpenFlags.ReadOnly);
string thumbprint = OtiskCertifikatu.Replace(" ", "").ToUpperInvariant();
if (thumbprint[0] == 8206)
{
thumbprint = thumbprint.Substring(1);
}
//Select a certificate from the certificate store
var certs = store.Certificates.Find(System.Security.Cryptography.X509Certificates.X509FindType.FindByThumbprint, thumbprint, true);
store.Close();
//Verify that a certificate exists
if (certs.Count == 0)
{
MessageBox.Show("Nelze najít určený certifikát v Current user certificate store!", "Sign PDF", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
//Open Pdf document
byte[] pdfData = File.ReadAllBytes(SouborPDF);
//Sign the PDF document
using (MemoryStream stream = new MemoryStream())
{
var reader = new PdfReader(pdfData);
var stp = PdfStamper.CreateSignature(reader, stream, '\0');
var sap = stp.SignatureAppearance;
//Protect certain features of the document
stp.SetEncryption(null,
Guid.NewGuid().ToByteArray(), //random password
PdfWriter.ALLOW_PRINTING | PdfWriter.ALLOW_COPY | PdfWriter.ALLOW_SCREENREADERS,
PdfWriter.ENCRYPTION_AES_256);
//Get certificate chain
var cp = new Org.BouncyCastle.X509.X509CertificateParser();
var certChain = new Org.BouncyCastle.X509.X509Certificate[] { cp.ReadCertificate(certs[0].RawData) };
sap.SetCrypto(null, certChain, null, PdfSignatureAppearance.WINCER_SIGNED);
//Set signature appearance
BaseFont helvetica = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1250, BaseFont.EMBEDDED);
iTextSharp.text.Font font = new iTextSharp.text.Font(helvetica, 12, iTextSharp.text.Font.NORMAL);
sap.Layer2Font = font;
//sap.SetVisibleSignature(new iTextSharp.text.Rectangle(415, 100, 585, 40), 1, null);
var dic = new PdfSignature(PdfName.ADOBE_PPKMS, PdfName.ADBE_PKCS7_SHA1);
//Set some stuff in the signature dictionary.
dic.Date = new PdfDate(sap.SignDate);
dic.Name = certs[0].Subject; //Certificate name
if (sap.Reason != null)
{
dic.Reason = sap.Reason;
}
if (sap.Location != null)
{
dic.Location = sap.Location;
}
//Set the crypto dictionary
sap.CryptoDictionary = dic;
//Set the size of the certificates and signature.
int csize = 4096; //Size of the signature - 4K
//Reserve some space for certs and signatures
var reservedSpace = new Dictionary<PdfName, int>();
reservedSpace[PdfName.CONTENTS] = csize * 2 + 2; //*2 because binary data is stored as hex strings. +2 for end of field
sap.PreClose(reservedSpace); //Actually reserve it
//Build the signature
//System.Security.Cryptography.HashAlgorithm sha = new System.Security.Cryptography.SHA1CryptoServiceProvider();
System.Security.Cryptography.HashAlgorithm sha = new System.Security.Cryptography.SHA256CryptoServiceProvider();
var sapStream = sap.GetRangeStream();
int read = 0;
byte[] buff = new byte[8192];
while ((read = sapStream.Read(buff, 0, 8192)) > 0)
{
sha.TransformBlock(buff, 0, read, buff, 0);
}
sha.TransformFinalBlock(buff, 0, 0);
//Place message in a ContentInfo object. This is required to build a SignedCms object.
System.Security.Cryptography.Pkcs.ContentInfo contentInfo = new System.Security.Cryptography.Pkcs.ContentInfo(sha.Hash);
//Instantiate SignedCms object with the ContentInfo above.
//Has default SubjectIdentifierType IssuerAndSerialNumber.
System.Security.Cryptography.Pkcs.SignedCms signedCms = new System.Security.Cryptography.Pkcs.SignedCms(contentInfo, false);
//Formulate a CmsSigner object for the signer.
System.Security.Cryptography.Pkcs.CmsSigner cmsSigner = new System.Security.Cryptography.Pkcs.CmsSigner(certs[0]); //First cert in the chain is the signer cert
//Do the whole certificate chain. This way intermediate certificates get sent across as well.
cmsSigner.IncludeOption = System.Security.Cryptography.X509Certificates.X509IncludeOption.ExcludeRoot;
//Časové razítko z TSA
if (!String.IsNullOrEmpty(textBox_ServerCasovehoRazitka.Text.Trim()))
{
try
{
System.Security.Cryptography.AsnEncodedData timeData = new System.Security.Cryptography.Pkcs.Pkcs9AttributeObject(ID_TIME_STAMP_TOKEN,
DejCasoveRazitko(stream.GetBuffer(), textBox_ServerCasovehoRazitka.Text)
);
cmsSigner.UnsignedAttributes.Add(timeData);
}
catch (Exception e)
{
MessageBox.Show("Chyba TSA!\n" + e.Message);
}
}
//Sign the CMS/PKCS #7 message. The second argument is needed to ask for the pin.
signedCms.ComputeSignature(cmsSigner, false);
//Encode the CMS/PKCS #7 message.
byte[] pk = signedCms.Encode();
//Put the certs and signature into the reserved buffer
byte[] outc = new byte[csize];
Array.Copy(pk, 0, outc, 0, pk.Length);
//Put the reserved buffer into the reserved space
PdfDictionary certificateDictionary = new PdfDictionary();
certificateDictionary.Put(PdfName.CONTENTS, new PdfString(outc).SetHexWriting(true));
//Write the signature
sap.Close(certificateDictionary);
//Close the stamper and save it
stp.Close();
reader.Close();
byte[] signedData = stream.GetBuffer();
File.WriteAllBytes(SouborPDF, signedData);
}
}
static protected byte[] DejCasoveRazitko(byte[] PDF, string ServerTSA)
{
System.Security.Cryptography.SHA256Managed hashString = new System.Security.Cryptography.SHA256Managed();
string hex = "";
var hashValue = hashString.ComputeHash(PDF);
foreach (byte x in hashValue)
{
hex += String.Format("{0:x2}", x);
}
// VSTUPEM je hash dokumentu, pro který se razítko vyžaduje
NotservisTSA.GetTimeStampRequest Request = new NotservisTSA.GetTimeStampRequest(new NotservisTSA.GetTimeStampRequestBody(hex, 0));
NotservisTSA.Print2PDF_WebServiceSoap Soap = new NotservisTSA.Print2PDF_WebServiceSoapClient();
((NotservisTSA.Print2PDF_WebServiceSoapClient)Soap).Endpoint.Address = new System.ServiceModel.EndpointAddress(new Uri(ServerTSA + "/Default.asmx"));
// VÝSTUPEM je zakódované časové razítko (GetTimeStampResult - BASE-64 v kódované struktuře TimeStampResp, viz RFC 3161) a návratová hodnota s případným popisem chyby.
PodepsaniPDF.NotservisTSA.GetTimeStampResponse Response = Soap.GetTimeStamp(Request);
byte[] responseBytes = Encoding.ASCII.GetBytes(Response.Body.GetTimeStampResult);
if(!String.IsNullOrEmpty(Response.Body.Error))
MessageBox.Show(Response.Body.Error, "Chyba", MessageBoxButtons.OK, MessageBoxIcon.Error);
return responseBytes;
}
}
}
Zobrazeno 10 zpráv z 10.