Komunikacja z Epuap - podpis Xades

Komunikacja z Epuap - podpis Xades
DY
  • Rejestracja:prawie 21 lat
  • Ostatnio:8 miesięcy
0

Witam
Borykam się już od pewnego czasu z implementacją komunikacji z portalem ePuap w Java, a dokładniej chodzi mi o zaimplementowanie całej ich koperty SOAP do komunikacji. Szukając w internecie okazało się że nie ma tego wiele. Bardzo pomocna była strona http://www.extern.pl/artykuly/ws-security_epuap/. Na początku zabrnąłem niestety w ślepą uliczkę (przynajmniej tak mi się wydaje) bo do podpisu używałem biblioteki WSS4J, niestety jak się okazuje Xades to chyba troszeczkę coś innego. Przy WSS4J używałem takiego kodu

Kopiuj
WSSConfig.init();
		
		String soapXML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+
				"<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns:user=\"http://userinfo.zp.epuap.gov.pl\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" +
				"<SOAP-ENV:Body xmlns:ns=\"http://ejb.draco.comarch.com\">" +
					"<ns:getUserInfo>" +
						"<ns:tgsId></ns:tgsId>" +					
						"<ns:appId></ns:appId>" +
					"</ns:getUserInfo>" +
				"</SOAP-ENV:Body>" +
				"</SOAP-ENV:Envelope>";
		
		Document doc = SOAPUtil.toSOAPPart(soapXML);
		
		
		
		Properties clientProperties = new Properties();
        clientProperties.put("org.apache.wss4j.crypto.provider", "org.apache.wss4j.common.crypto.Merlin");
        clientProperties.put("org.apache.wss4j.crypto.merlin.keystore.type", "jks");
        clientProperties.put("org.apache.wss4j.crypto.merlin.keystore.password", "haslo");
        clientProperties.put("org.apache.wss4j.crypto.merlin.keystore.alias", "alias");
        clientProperties.put("org.apache.wss4j.crypto.merlin.keystore.file", "plik.jks");
        
        Crypto crypto = new Merlin(clientProperties, this.getClass().getClassLoader(), null);
			
		WSSecHeader secHeader = new WSSecHeader();
		secHeader.insertSecurityHeader(doc);        
		
		WSSecTimestamp timestamp = new WSSecTimestamp();
		timestamp.setTimeToLive(3 * 3600);
		doc = timestamp.build(doc, secHeader);				
		
	        
		WSSecSignature builder = new WSSecSignature();
		builder.setUserInfo("uzytkownik", "haslo");	
		builder.setKeyIdentifierType(WSConstants.X509_KEY_IDENTIFIER);
		
		List<WSEncryptionPart> parts = new ArrayList<WSEncryptionPart>();
        WSEncryptionPart encP = new WSEncryptionPart("Timestamp", WSConstants.WSU_NS,"");
        WSEncryptionPart bodyPart = new WSEncryptionPart(WSConstants.ELEM_BODY, WSConstants.URI_SOAP11_ENV, "");
        parts.add(bodyPart);
        parts.add(encP);
        builder.setParts(parts);   
		
		Document signedDoc = builder.build(doc, crypto, secHeader);
 

W wyniku czego dostawałem taką kopertę:

Kopiuj
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:user="http://userinfo.zp.epuap.gov.pl" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
   <SOAP-ENV:Header>
      <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" SOAP-ENV:mustUnderstand="1">
         <wsse:BinarySecurityToken EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" Id="e6bac805-2ee5-4d82-8e8e-ee4c0a37e705" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3">MIICSjCCAbOgAwIBAgIJAIXSDNq9Dr0hMA0GCSqGSIb3DQEBBQUAMG0xCzAJBgNVBAYTAlBMMR4wHAYDVQQKExVDUEkgQ0EgZm9yIGVwdWFwIFRFU1QxHjAcBgNVBAsTFUNQSSBDQSBmb3IgZXB1YXAgVEVTVDEeMBwGA1UEAxMVQ1BJIENBIGZvciBlcHVhcCBURVNUMB4XDTE0MDgxNTAwMDAwMFoXDTE2MDgxNDIzNTk1OVowRTELMAkGA1UEBhMCUEwxDDAKBgNVBAoTA0NQSTETMBEGA1UECxMKZGFtaWFuU29mdDETMBEGA1UEAxMKZGFtaWFuU29mdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAzXr0F9mUTQ5Ow4XqwEpCEsGZKBG+OrSmqFzFpC+gC23L96gnFYVGl5Cv5vT8fMnRlb9m7ebsH7bVFL1UsRbg4xyRi8Rf/kefSGOZmtmQG3X1BsfLsYfhXBhYC8qvjJfnm8pVaHZ1joxcUapzwTQp2Se/EFTAodJV24JL8T8XdXcCAwEAAaMaMBgwCQYDVR0TBAIwADALBgNVHQ8EBAMCB4AwDQYJKoZIhvcNAQEFBQADgYEAF2+pSbCJzxg0Zd75fO0zNviPvZJU6FD2aq6YQGKGghMSfBXH6M3oX6AdHWD9nXrvGCqB6aNBdeww1RbF7qOugUYxmZ6fqxVRwADrSP81Uz8rLBQVovieCjlXdeWvXt4CGyeu1AcdXYMnsdTtvXHHAdAoqMTP+klPAM0MrsN+GRA=</wsse:BinarySecurityToken>
         <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="SIG-444db4cb-7f98-469a-acc5-f15470eaf298">
            <ds:SignedInfo>
               <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
                  <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="SOAP-ENC SOAP-ENV user xsd xsi" />
               </ds:CanonicalizationMethod>
               <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
               <ds:Reference URI="#id-de9cadef-6ab1-4f68-9106-b7c87ed85a95">
                  <ds:Transforms>
                     <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
                        <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="SOAP-ENC user xsd xsi" />
                     </ds:Transform>
                  </ds:Transforms>
                  <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
                  <ds:DigestValue>QGFHPvQm0xoKx6UfJioDhycuvzg=</ds:DigestValue>
               </ds:Reference>
               <ds:Reference URI="#TS-15747850-9adf-4990-a5ee-8c23bb50ba87">
                  <ds:Transforms>
                     <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
                        <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="wsse SOAP-ENC SOAP-ENV user xsd xsi" />
                     </ds:Transform>
                  </ds:Transforms>
                  <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
                  <ds:DigestValue>24WiH+AtrGk4tcUVi/mj5mTEPxM=</ds:DigestValue>
               </ds:Reference>
            </ds:SignedInfo>
            <ds:SignatureValue>ZRRjF9ejiNp8v89CgEIpPJTAn87RGL5f6/49XvdN1IfRrjbiEmYidbi0GH9Dafuh5Y1OnG5qzSg3BdCLRX3iAgciomGw7EpEg6m9SSzKZC3iwCMtLaEGdzkKHYqMkdJrb6h0PYBSYJ9JUNbYbBewt1/ksSXkChWehGMyLRspeR8=</ds:SignatureValue>
            <ds:KeyInfo Id="KI-218aa69e-2dd2-41ee-bcaa-482a8cefd64b">
               <wsse:SecurityTokenReference wsu:Id="STR-d9f5821a-36ec-4e5c-9887-2158e68ee1ff">
                  <wsse:Reference URI="#e6bac805-2ee5-4d82-8e8e-ee4c0a37e705" />
               </wsse:SecurityTokenReference>
            </ds:KeyInfo>
         </ds:Signature>
         <wsu:Timestamp wsu:Id="TS-15747850-9adf-4990-a5ee-8c23bb50ba87">
            <wsu:Created>2015-01-22T11:47:58.057Z</wsu:Created>
            <wsu:Expires>2015-01-22T14:47:58.057Z</wsu:Expires>
         </wsu:Timestamp>
      </wsse:Security>
   </SOAP-ENV:Header>
   <SOAP-ENV:Body xmlns:ns="http://ejb.draco.comarch.com" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="id-de9cadef-6ab1-4f68-9106-b7c87ed85a95">
      <ns:getUserInfo>
         <ns:tgsId></ns:tgsId>
         <ns:appId></ns:appId>
      </ns:getUserInfo>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

 

Niestety ePuap odrzucał moje zapytanie z odpowiedzią WSDoAllReceiver: security processing failed. Uruchomiłem sobie oczywiście kod w PHP z wymienionej wcześniej strony i jak to bywa on działa a obie koperty wyglądają tak samo (tzn. różnią się wartości DigestValue oraz SignatureValue i stąd wynika zapewne różnica w stosunku do Xades). Zacząłem próbować z biblioteką Xades4J na podstawie kodu z wątku Podpis Xades na pliku XML ale jak na razie bez pozytywnych rezultatów tzn. to co wygenerowałem zupełnie nie przypomina pokazanej wcześniej koperty nie mówiąc już o wartości sygnatury. Kod:

Kopiuj
String alias = "";
            char haslo[] = "haslo".toCharArray();

            // zaladowanie pliki p12
            KeyStore store = KeyStore.getInstance("PKCS12");
            store.load(new FileInputStream("plik.p12"), haslo);

            
            // wyciagnij klucz prywatny
            Key privKey = store.getKey(alias, haslo);
            final PrivateKey privateKey = (PrivateKey) privKey;
            
            // wyciagnij certyfikat
            final X509Certificate cert = (X509Certificate) store.getCertificate(alias);

            // provider dla xades
            KeyingDataProvider keyingDataProv = new KeyingDataProvider() {

                public List<X509Certificate> getSigningCertificateChain() throws SigningCertChainException, UnexpectedJCAException {
                    return (List<X509Certificate>) (Object) Arrays.asList(cert);
                }

                public PrivateKey getSigningKey(X509Certificate signingCert) throws SigningKeyException, UnexpectedJCAException {
                    return privateKey;
                }
            };
            
            AlgorithmsProviderEx ap = new DefaultAlgorithmsProviderEx() {
                @Override
                public String getDigestAlgorithmForDataObjsReferences() {
                        return "http://www.w3.org/2000/09/xmldsig#sha1";
                }
                @Override
                public Algorithm getSignatureAlgorithm(String keyAlgorithmName)
                                throws UnsupportedAlgorithmException {
                        return new GenericAlgorithm(XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1);
                }
                @Override
                public String getDigestAlgorithmForReferenceProperties() {
                        return "http://www.w3.org/2000/09/xmldsig#sha1";
                }
            };
        
            
            // plik xml do podpisania
            String inputFile = "";
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            dbf.setNamespaceAware(true);
            DocumentBuilder db = dbf.newDocumentBuilder();
            org.w3c.dom.Document inDoc = db.parse(new FileInputStream(inputFile));

            // profil podpisu xades
            XadesSigningProfile profile = new XadesBesSigningProfile(keyingDataProv).withAlgorithmsProviderEx(ap);
            
          
            // zmienna podpisujaca
            XadesSigner signer = profile.newSigner();
            
            
            // dodatkowe dane do podpisu       
            SignedDataObjects dataObjs = new SignedDataObjects();
            DataObjectReference obj = new DataObjectReference("");    
           
            obj.withTransform(new DataObjectTransform("http://www.w3.org/2001/10/xml-exc-c14n#"));           
            dataObjs.withSignedDataObject(obj);

            // podpisanie
            signer.sign(dataObjs, inDoc.getDocumentElement());

            // Zapis podpisanego pliku
            String outputFile = "";
            OutputStream os = new FileOutputStream(outputFile);
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer trans = tf.newTransformer();
            trans.transform(new DOMSource(inDoc), new StreamResult(os));

Wynik:

Kopiuj
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:user="http://userinfo.zp.epuap.gov.pl" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
   <SOAP-ENV:Body xmlns:ns="http://ejb.draco.comarch.com" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" Id="abcd">
      <ns:getUserInfo>
         <ns:tgsId></ns:tgsId>
         <ns:appId></ns:appId>
      </ns:getUserInfo>
   </SOAP-ENV:Body>
   <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="xmldsig-089c463a-9afe-480d-9e39-4e7fe1eb00e7">
      <ds:SignedInfo>
         <ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
         <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
         <ds:Reference Id="xmldsig-089c463a-9afe-480d-9e39-4e7fe1eb00e7-ref0" URI="">
            <ds:Transforms>
               <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
            </ds:Transforms>
            <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
            <ds:DigestValue>TI95y7S79osPz9WCiRXwptz2vmE=</ds:DigestValue>
         </ds:Reference>
         <ds:Reference Type="http://uri.etsi.org/01903#SignedProperties" URI="#xmldsig-089c463a-9afe-480d-9e39-4e7fe1eb00e7-signedprops">
            <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
            <ds:DigestValue>2Rl17TWjQZ71k2e9vtMX1uUFxN0=</ds:DigestValue>
         </ds:Reference>
      </ds:SignedInfo>
      <ds:SignatureValue Id="xmldsig-089c463a-9afe-480d-9e39-4e7fe1eb00e7-sigvalue">YpuextXY+k3GG+BPtlkJ97U99udTZe5z6ushOlihHcyt9LG2DobBc44C0YgyBxKVmzAe8coMzm+5
DMrFhBLVHBEx45Mka4o6jOpQoxvUQD6OM5nU8xbt1m7dZ7+3VzlilmiJVQL1kdA5R0HFbI9DrRlD
C89Y0+h0idS+vh/5gAo=</ds:SignatureValue>
      <ds:KeyInfo>
         <ds:X509Data>
            <ds:X509Certificate>MIICSjCCAbOgAwIBAgIJAIXSDNq9Dr0hMA0GCSqGSIb3DQEBBQUAMG0xCzAJBgNVBAYTAlBMMR4w
HAYDVQQKExVDUEkgQ0EgZm9yIGVwdWFwIFRFU1QxHjAcBgNVBAsTFUNQSSBDQSBmb3IgZXB1YXAg
VEVTVDEeMBwGA1UEAxMVQ1BJIENBIGZvciBlcHVhcCBURVNUMB4XDTE0MDgxNTAwMDAwMFoXDTE2
MDgxNDIzNTk1OVowRTELMAkGA1UEBhMCUEwxDDAKBgNVBAoTA0NQSTETMBEGA1UECxMKZGFtaWFu
U29mdDETMBEGA1UEAxMKZGFtaWFuU29mdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAzXr0
F9mUTQ5Ow4XqwEpCEsGZKBG+OrSmqFzFpC+gC23L96gnFYVGl5Cv5vT8fMnRlb9m7ebsH7bVFL1U
sRbg4xyRi8Rf/kefSGOZmtmQG3X1BsfLsYfhXBhYC8qvjJfnm8pVaHZ1joxcUapzwTQp2Se/EFTA
odJV24JL8T8XdXcCAwEAAaMaMBgwCQYDVR0TBAIwADALBgNVHQ8EBAMCB4AwDQYJKoZIhvcNAQEF
BQADgYEAF2+pSbCJzxg0Zd75fO0zNviPvZJU6FD2aq6YQGKGghMSfBXH6M3oX6AdHWD9nXrvGCqB
6aNBdeww1RbF7qOugUYxmZ6fqxVRwADrSP81Uz8rLBQVovieCjlXdeWvXt4CGyeu1AcdXYMnsdTt
vXHHAdAoqMTP+klPAM0MrsN+GRA=</ds:X509Certificate>
         </ds:X509Data>
      </ds:KeyInfo>
      <ds:Object>
         <xades:QualifyingProperties xmlns:xades="http://uri.etsi.org/01903/v1.3.2#" xmlns:xades141="http://uri.etsi.org/01903/v1.4.1#" Target="#xmldsig-089c463a-9afe-480d-9e39-4e7fe1eb00e7">
            <xades:SignedProperties Id="xmldsig-089c463a-9afe-480d-9e39-4e7fe1eb00e7-signedprops">
               <xades:SignedSignatureProperties>
                  <xades:SigningTime>2015-01-22T13:00:08.569+01:00</xades:SigningTime>
                  <xades:SigningCertificate>
                     <xades:Cert>
                        <xades:CertDigest>
                           <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
                           <ds:DigestValue>okFqGkp1+kY2NdB8m8cQTLROKq0=</ds:DigestValue>
                        </xades:CertDigest>
                        <xades:IssuerSerial>
                           <ds:X509IssuerName>CN=CPI CA for epuap TEST,OU=CPI CA for epuap TEST,O=CPI CA for epuap TEST,C=PL</ds:X509IssuerName>
                           <ds:X509SerialNumber>9642783885767916833</ds:X509SerialNumber>
                        </xades:IssuerSerial>
                     </xades:Cert>
                  </xades:SigningCertificate>
               </xades:SignedSignatureProperties>
            </xades:SignedProperties>
         </xades:QualifyingProperties>
      </ds:Object>
   </ds:Signature>
</SOAP-ENV:Envelope>

Robię coś nie tak ale nie wiem niestety gdzie. Może ktoś przechodził już to wszystko i mógłby pomóc. Byłbym niezmiernie wdzięczny bo już powoli tracę nadzieje.

DY
  • Rejestracja:prawie 21 lat
  • Ostatnio:8 miesięcy
0

Sprawa już nieaktualna. Wss4j działało tylko zamiast:

Kopiuj
builder.setKeyIdentifierType(WSConstants.X509_KEY_IDENTIFIER);

należało użyć

Kopiuj
builder.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
LO
  • Rejestracja:około 10 lat
  • Ostatnio:około 10 lat
  • Postów:1
0

Obecnie też przyszło mi się borykać z problemem zbudowania poprawnej koperty SOAP dla WS Authorization. Próbuję wywołać metodę getUserInfo. Otrzymuję komunikat WSDoAllReceiver: security processing failed. Dodałem Timestamp, ale to nic nie dało. Na jaki endpoint wysyłasz kopertę SOAP? Czy otrzymujesz poprawną odpowiedź ? Czy metoda rzeczywiście zwraca wszystkie elementy, które WSDL ma w swoim schemacie? Imię, nazwisko, e-mail? Czy mógłbyś podesłać przykładową kopertę, która zwraca Ci prawidłowy wynik?

DY
  • Rejestracja:prawie 21 lat
  • Ostatnio:8 miesięcy
0

Witam

Nie wiem czy to jeszcze aktualne bo chyba dość późno odpowiadam. Wysyłam zapytanie na https://hetman.epuap.gov.pl/axis2/services/AuthorizationWS. W schemacie jest wszystko poprawnie zwracane o ile dostaniesz prawidłową odpowiedź. Sprawdź czy dodajesz w nagłówku BinarySecurityToken bo to akurat u mnie było nie tak. Tak na marginesie jeżeli musisz wyciągnąć naprawdę ważne dane tj. Imię Nazwisko + PESEL to jedynym i chyba najprostszym sposobem jest podpisanie dokumentu profilem zaufanym poprzez platformę ePuap. Wszystko jest dość dokładnie opisane na epuapowych stronach (no może z małymi wyjątkami).

0

Witam
Chciałbym zapytać, skąd w ogóle bierze się te Certyfikaty X905, do pola X509Certificate ?
Potrzebuję wykonać obsługę wysyłki JPK w PHP i nie mogę znaleźć jakieś odpowiedzi wprost skąd wziąć ten certyfikat ?
I wartości do innych pól xml w strukturze xades:SignedProperties ?

PA
  • Rejestracja:ponad 22 lata
  • Ostatnio:około 6 godzin
  • Postów:3873
0
CZ
  • Rejestracja:ponad 7 lat
  • Ostatnio:ponad 5 lat
  • Postów:4
0

Czy komunikacja poprzez WS-SECURITY z serwerami EPUAP'u jest dostępna tylko dla podmiotów publicznych (urzędy państwowe), czy może każda firma komercyjna również ma taką możliwość ? Pytam gdyż komuś w naszej firmie wpadło do głowy, aby umożliwić klientom którzy nie mają podpisu kwalifikowanego wykonywanie wysyłki plików JPK za pomocą profilu zaufanego (podpis pliku InitUpload.xml). Czy coś takiego jest możliwe ?

Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)