mirror of
https://github.com/wulkanowy/wulkanowy.git
synced 2025-02-22 15:14:44 +01:00
[API] Add support for adfs login (#76)
This commit is contained in:
parent
cb2d4a905d
commit
1740047aea
2
.gitignore
vendored
2
.gitignore
vendored
@ -44,3 +44,5 @@ local.properties
|
|||||||
.Trashes
|
.Trashes
|
||||||
ehthumbs.db
|
ehthumbs.db
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
.idea/codeStyles/
|
||||||
|
.idea/caches/
|
||||||
|
@ -44,7 +44,11 @@ public class Client {
|
|||||||
String[] url = creds[0].split("://");
|
String[] url = creds[0].split("://");
|
||||||
|
|
||||||
protocol = url[0];
|
protocol = url[0];
|
||||||
host = url[1];
|
String[] path = url[1].split("/");
|
||||||
|
host = path[0];
|
||||||
|
if (path.length > 1) {
|
||||||
|
symbol = path[1];
|
||||||
|
}
|
||||||
email = creds[2];
|
email = creds[2];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ package io.github.wulkanowy.api;
|
|||||||
|
|
||||||
public class VulcanException extends Exception {
|
public class VulcanException extends Exception {
|
||||||
|
|
||||||
protected VulcanException(String message) {
|
public VulcanException(String message) {
|
||||||
super(message);
|
super(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,12 +31,27 @@ public class Login {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Document sendCredentials(String email, String password) throws IOException, VulcanException {
|
Document sendCredentials(String email, String password) throws IOException, VulcanException {
|
||||||
Document html = client.postPageByUrl(LOGIN_PAGE_URL, new String[][]{
|
String[][] credentials = new String[][]{
|
||||||
{"LoginName", email},
|
{"LoginName", email},
|
||||||
{"Password", password}
|
{"Password", password}
|
||||||
});
|
};
|
||||||
|
|
||||||
Element errorMessage = html.select(".ErrorMessage").first();
|
String nextUrl = LOGIN_PAGE_URL;
|
||||||
|
Document loginPage = client.getPageByUrl(nextUrl, false);
|
||||||
|
|
||||||
|
Element formFirst = loginPage.select("#form1").first();
|
||||||
|
if (null != formFirst) { // on adfs login
|
||||||
|
Document formSecond = client.postPageByUrl(
|
||||||
|
formFirst.attr("abs:action"),
|
||||||
|
getFormStateParams(formFirst, "", "")
|
||||||
|
);
|
||||||
|
credentials = getFormStateParams(formSecond, email, password);
|
||||||
|
nextUrl = formSecond.select("#form1").first().attr("abs:action");
|
||||||
|
}
|
||||||
|
|
||||||
|
Document html = client.postPageByUrl(nextUrl, credentials);
|
||||||
|
|
||||||
|
Element errorMessage = html.select(".ErrorMessage, #ErrorTextLabel").first();
|
||||||
if (null != errorMessage) {
|
if (null != errorMessage) {
|
||||||
throw new BadCredentialsException(errorMessage.text());
|
throw new BadCredentialsException(errorMessage.text());
|
||||||
}
|
}
|
||||||
@ -44,6 +59,21 @@ public class Login {
|
|||||||
return html;
|
return html;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String[][] getFormStateParams(Element form, String email, String password) {
|
||||||
|
return new String[][]{
|
||||||
|
{"__VIEWSTATE", form.select("#__VIEWSTATE").val()},
|
||||||
|
{"__VIEWSTATEGENERATOR", form.select("#__VIEWSTATEGENERATOR").val()},
|
||||||
|
{"__EVENTVALIDATION", form.select("#__EVENTVALIDATION").val()},
|
||||||
|
{"__db", form.select("input[name=__db]").val()},
|
||||||
|
{"PassiveSignInButton.x", "0"},
|
||||||
|
{"PassiveSignInButton.y", "0"},
|
||||||
|
{"SubmitButton.x", "0"},
|
||||||
|
{"SubmitButton.y", "0"},
|
||||||
|
{"UsernameTextBox", email},
|
||||||
|
{"PasswordTextBox", password},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
String sendCertificate(Document doc, String defaultSymbol) throws IOException, VulcanException {
|
String sendCertificate(Document doc, String defaultSymbol) throws IOException, VulcanException {
|
||||||
String certificate = doc.select("input[name=wresult]").val();
|
String certificate = doc.select("input[name=wresult]").val();
|
||||||
|
|
||||||
@ -53,6 +83,10 @@ public class Login {
|
|||||||
Document targetDoc = sendCertData(doc);
|
Document targetDoc = sendCertData(doc);
|
||||||
String title = targetDoc.select("title").text();
|
String title = targetDoc.select("title").text();
|
||||||
|
|
||||||
|
if ("Working...".equals(title)) { // on adfs login
|
||||||
|
title = sendCertData(targetDoc).select("title").text();
|
||||||
|
}
|
||||||
|
|
||||||
if ("Logowanie".equals(title)) {
|
if ("Logowanie".equals(title)) {
|
||||||
throw new AccountPermissionException("No account access. Try another symbol");
|
throw new AccountPermissionException("No account access. Try another symbol");
|
||||||
}
|
}
|
||||||
|
@ -95,12 +95,15 @@ public class Timetable {
|
|||||||
moveWarningToLessonNode(e);
|
moveWarningToLessonNode(e);
|
||||||
|
|
||||||
switch (e.size()) {
|
switch (e.size()) {
|
||||||
|
case 2:
|
||||||
|
Element span = e.last().select("span").first();
|
||||||
|
if (span.hasClass(LessonTypes.CLASS_MOVED_OR_CANCELED)) {
|
||||||
|
lesson.setNewMovedInOrChanged(true);
|
||||||
|
lesson.setDescription("poprzednio: " + getLessonAndGroupInfoFromSpan(span)[0]);
|
||||||
|
}
|
||||||
case 1:
|
case 1:
|
||||||
addLessonInfoFromElement(lesson, e.first());
|
addLessonInfoFromElement(lesson, e.first());
|
||||||
break;
|
break;
|
||||||
case 2:
|
|
||||||
addLessonInfoFromElement(lesson, e.last());
|
|
||||||
break;
|
|
||||||
case 3:
|
case 3:
|
||||||
addLessonInfoFromElement(lesson, e.get(1));
|
addLessonInfoFromElement(lesson, e.get(1));
|
||||||
break;
|
break;
|
||||||
|
@ -24,6 +24,7 @@ public class LoginTest {
|
|||||||
|
|
||||||
Client client = Mockito.mock(Client.class);
|
Client client = Mockito.mock(Client.class);
|
||||||
Mockito.when(client.postPageByUrl(Mockito.anyString(), Mockito.any(String[][].class))).thenReturn(doc);
|
Mockito.when(client.postPageByUrl(Mockito.anyString(), Mockito.any(String[][].class))).thenReturn(doc);
|
||||||
|
Mockito.when(client.getPageByUrl(Mockito.anyString(), Mockito.anyBoolean())).thenReturn(doc);
|
||||||
|
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
@ -56,10 +57,8 @@ public class LoginTest {
|
|||||||
Login login = new Login(client);
|
Login login = new Login(client);
|
||||||
|
|
||||||
Assert.assertEquals(
|
Assert.assertEquals(
|
||||||
getFixtureAsString("cert.xml").replaceAll("\\s+",""),
|
getFixtureAsString("cert-stock.xml").replaceAll("\\s+",""),
|
||||||
login.sendCredentials("a@a", "passwd")
|
login.sendCredentials("a@a", "passwd").select("input[name=wresult]").attr("value").replaceAll("\\s+","")
|
||||||
.select("input[name=wresult]").attr("value")
|
|
||||||
.replaceAll("\\s+","")
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,21 +82,21 @@ public class LoginTest {
|
|||||||
public void sendCertificateAccountPermissionTest() throws Exception {
|
public void sendCertificateAccountPermissionTest() throws Exception {
|
||||||
Login login = new Login(getClient("Logowanie-brak-dostepu.html"));
|
Login login = new Login(getClient("Logowanie-brak-dostepu.html"));
|
||||||
|
|
||||||
login.sendCertificate(getFixtureAsDocument("cert.xml"), "demo123");
|
login.sendCertificate(getFixtureAsDocument("cert-stock.xml"), "demo123");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = LoginErrorException.class)
|
@Test(expected = LoginErrorException.class)
|
||||||
public void sendCertificateLoginErrorTest() throws Exception {
|
public void sendCertificateLoginErrorTest() throws Exception {
|
||||||
Login login = new Login(getClient("Logowanie-certyfikat.html")); // change to other document
|
Login login = new Login(getClient("Logowanie-certyfikat.html")); // change to other document
|
||||||
|
|
||||||
login.sendCertificate(getFixtureAsDocument("cert.xml"), "demo123");
|
login.sendCertificate(getFixtureAsDocument("cert-stock.xml"), "demo123");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void findSymbolInCertificateTest() throws Exception {
|
public void findSymbolInCertificateTest() throws Exception {
|
||||||
Login login = new Login(getClient("Logowanie-certyfikat.html"));
|
Login login = new Login(getClient("Logowanie-certyfikat.html"));
|
||||||
|
|
||||||
String certificate = getFixtureAsString("cert.xml");
|
String certificate = getFixtureAsString("cert-stock.xml");
|
||||||
|
|
||||||
Assert.assertEquals("demo12345", login.findSymbolInCertificate(certificate));
|
Assert.assertEquals("demo12345", login.findSymbolInCertificate(certificate));
|
||||||
}
|
}
|
||||||
|
@ -110,6 +110,7 @@ public class TimetableTest extends StudentAndParentTestCase {
|
|||||||
Assert.assertEquals("Uroczyste zakończenie roku szkolnego", full.getWeekTable().getDay(4).getLesson(0).getSubject());
|
Assert.assertEquals("Uroczyste zakończenie roku szkolnego", full.getWeekTable().getDay(4).getLesson(0).getSubject());
|
||||||
Assert.assertEquals("Fizyka", full.getWeekTable().getDay(0).getLesson(0).getSubject());
|
Assert.assertEquals("Fizyka", full.getWeekTable().getDay(0).getLesson(0).getSubject());
|
||||||
Assert.assertEquals("Metodologia programowania", full.getWeekTable().getDay(1).getLesson(0).getSubject());
|
Assert.assertEquals("Metodologia programowania", full.getWeekTable().getDay(1).getLesson(0).getSubject());
|
||||||
|
Assert.assertEquals("Język niemiecki", full.getWeekTable().getDay(4).getLesson(2).getSubject());
|
||||||
Assert.assertEquals("", holidays.getWeekTable().getDay(3).getLesson(3).getSubject());
|
Assert.assertEquals("", holidays.getWeekTable().getDay(3).getLesson(3).getSubject());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,6 +123,7 @@ public class TimetableTest extends StudentAndParentTestCase {
|
|||||||
Assert.assertEquals("Nowak Jadwiga", full.getWeekTable().getDay(2).getLesson(0).getTeacher());
|
Assert.assertEquals("Nowak Jadwiga", full.getWeekTable().getDay(2).getLesson(0).getTeacher());
|
||||||
Assert.assertEquals("Nowicka Irena", full.getWeekTable().getDay(3).getLesson(1).getTeacher());
|
Assert.assertEquals("Nowicka Irena", full.getWeekTable().getDay(3).getLesson(1).getTeacher());
|
||||||
Assert.assertEquals("Baran Małgorzata", full.getWeekTable().getDay(4).getLesson(0).getTeacher());
|
Assert.assertEquals("Baran Małgorzata", full.getWeekTable().getDay(4).getLesson(0).getTeacher());
|
||||||
|
Assert.assertEquals("", full.getWeekTable().getDay(4).getLesson(1).getTeacher());
|
||||||
Assert.assertEquals("", holidays.getWeekTable().getDay(3).getLesson(3).getTeacher());
|
Assert.assertEquals("", holidays.getWeekTable().getDay(3).getLesson(3).getTeacher());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,7 +150,10 @@ public class TimetableTest extends StudentAndParentTestCase {
|
|||||||
Assert.assertEquals("zastępstwo (poprzednio: Religia)", full.getWeekTable().getDay(2).getLesson(0).getDescription());
|
Assert.assertEquals("zastępstwo (poprzednio: Religia)", full.getWeekTable().getDay(2).getLesson(0).getDescription());
|
||||||
Assert.assertEquals("zastępstwo (poprzednio: Wychowanie fizyczne)", full.getWeekTable().getDay(3).getLesson(1).getDescription());
|
Assert.assertEquals("zastępstwo (poprzednio: Wychowanie fizyczne)", full.getWeekTable().getDay(3).getLesson(1).getDescription());
|
||||||
Assert.assertEquals("", full.getWeekTable().getDay(4).getLesson(0).getDescription());
|
Assert.assertEquals("", full.getWeekTable().getDay(4).getLesson(0).getDescription());
|
||||||
|
Assert.assertEquals("", full.getWeekTable().getDay(4).getLesson(1).getDescription());
|
||||||
|
Assert.assertEquals("poprzednio: Wychowanie fizyczne", full.getWeekTable().getDay(4).getLesson(2).getDescription());
|
||||||
Assert.assertEquals("egzamin", full.getWeekTable().getDay(3).getLesson(0).getDescription());
|
Assert.assertEquals("egzamin", full.getWeekTable().getDay(3).getLesson(0).getDescription());
|
||||||
|
Assert.assertEquals("", full.getWeekTable().getDay(4).getLesson(1).getDescription());
|
||||||
Assert.assertEquals("", holidays.getWeekTable().getDay(3).getLesson(3).getDescription());
|
Assert.assertEquals("", holidays.getWeekTable().getDay(3).getLesson(3).getDescription());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,6 +242,8 @@ public class TimetableTest extends StudentAndParentTestCase {
|
|||||||
Assert.assertTrue(full.getWeekTable().getDay(1).getLesson(2).isNewMovedInOrChanged());
|
Assert.assertTrue(full.getWeekTable().getDay(1).getLesson(2).isNewMovedInOrChanged());
|
||||||
Assert.assertTrue(full.getWeekTable().getDay(1).getLesson(3).isNewMovedInOrChanged());
|
Assert.assertTrue(full.getWeekTable().getDay(1).getLesson(3).isNewMovedInOrChanged());
|
||||||
Assert.assertTrue(full.getWeekTable().getDay(3).getLesson(1).isNewMovedInOrChanged());
|
Assert.assertTrue(full.getWeekTable().getDay(3).getLesson(1).isNewMovedInOrChanged());
|
||||||
|
Assert.assertFalse(full.getWeekTable().getDay(4).getLesson(1).isNewMovedInOrChanged());
|
||||||
|
Assert.assertTrue(full.getWeekTable().getDay(4).getLesson(2).isNewMovedInOrChanged());
|
||||||
Assert.assertFalse(holidays.getWeekTable().getDay(3).getLesson(3).isNewMovedInOrChanged());
|
Assert.assertFalse(holidays.getWeekTable().getDay(3).getLesson(3).isNewMovedInOrChanged());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,10 @@
|
|||||||
<title>Working...</title>
|
<title>Working...</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<form method="POST" name="hiddenform" action="https://fake-log.com/Default/LoginEndpoint.aspx">
|
<form method="POST" name="hiddenform" action="https://fakelog.cf/Default/LoginEndpoint.aspx">
|
||||||
<input type="hidden" name="wa" value="wsignin1.0">
|
<input type="hidden" name="wa" value="wsignin1.0">
|
||||||
<input type="hidden" name="wresult" value="<trust:RequestSecurityTokenResponseCollection xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512"><trust:RequestSecurityTokenResponse Context="https://uonetplus.fake-log.com/Default/LoginEndpoint.aspx"><trust:RequestedSecurityToken><saml:Assertion AssertionID="_12345678-1234-1234-1234-1234567890ab" IssueInstant="2017-10-18T22:00:29.006Z" Issuer="CUFSTokenService" MajorVersion="1" MinorVersion="1" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion"><saml:AttributeStatement><saml:Attribute AttributeName="UserInstance" AttributeNamespace="http://schemas.fake-log.com/ws/identity/claims"><saml:AttributeValue>Default</saml:AttributeValue><saml:AttributeValue>demo12345</saml:AttributeValue><saml:AttributeValue>incorrect value</saml:AttributeValue><saml:AttributeValue>warszawa</saml:AttributeValue><saml:AttributeValue>asdf</saml:AttributeValue><saml:AttributeValue>asdfsdf</saml:AttributeValue></saml:Attribute></saml:AttributeStatement></saml:Assertion></trust:RequestedSecurityToken></trust:RequestSecurityTokenResponse></trust:RequestSecurityTokenResponseCollection>">
|
<input type="hidden" name="wresult" value="<trust:RequestSecurityTokenResponseCollection xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512"><trust:RequestSecurityTokenResponse Context="https://uonetplus.fakelog.cf/Default/LoginEndpoint.aspx"><trust:RequestedSecurityToken><saml:Assertion AssertionID="_12345678-1234-1234-1234-1234567890ab" IssueInstant="2017-10-18T22:00:29.006Z" Issuer="CUFSTokenService" MajorVersion="1" MinorVersion="1" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion"><saml:AttributeStatement><saml:Attribute AttributeName="UserInstance" AttributeNamespace="http://schemas.fakelog.cf/ws/identity/claims"><saml:AttributeValue>Default</saml:AttributeValue><saml:AttributeValue>demo12345</saml:AttributeValue><saml:AttributeValue>incorrect value</saml:AttributeValue><saml:AttributeValue>warszawa</saml:AttributeValue><saml:AttributeValue>asdf</saml:AttributeValue><saml:AttributeValue>asdfsdf</saml:AttributeValue></saml:Attribute></saml:AttributeStatement></saml:Assertion></trust:RequestedSecurityToken></trust:RequestSecurityTokenResponse></trust:RequestSecurityTokenResponseCollection>">
|
||||||
<input type="hidden" name="wctx" value="https://fake-log.com/Default/LoginEndpoint.aspx">
|
<input type="hidden" name="wctx" value="https://fakelog.cf/Default/LoginEndpoint.aspx">
|
||||||
<noscript>
|
<noscript>
|
||||||
<p>Script is disabled. Click Submit to continue.</p>
|
<p>Script is disabled. Click Submit to continue.</p>
|
||||||
<input type="submit" value="Submit">
|
<input type="submit" value="Submit">
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
<trust:RequestSecurityTokenResponseCollection xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">
|
<trust:RequestSecurityTokenResponseCollection xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">
|
||||||
<trust:RequestSecurityTokenResponse Context="https://uonetplus.fake-log.com/Default/LoginEndpoint.aspx">
|
<trust:RequestSecurityTokenResponse Context="https://uonetplus.fakelog.cf/Default/LoginEndpoint.aspx">
|
||||||
<trust:RequestedSecurityToken>
|
<trust:RequestedSecurityToken>
|
||||||
<saml:Assertion AssertionID="_12345678-1234-1234-1234-1234567890ab" IssueInstant="2017-10-18T22:00:29.006Z" Issuer="CUFSTokenService" MajorVersion="1" MinorVersion="1" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion">
|
<saml:Assertion AssertionID="_12345678-1234-1234-1234-1234567890ab" IssueInstant="2017-10-18T22:00:29.006Z" Issuer="CUFSTokenService" MajorVersion="1" MinorVersion="1" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion">
|
||||||
<saml:AttributeStatement>
|
<saml:AttributeStatement>
|
||||||
<saml:Attribute AttributeName="UserInstance" AttributeNamespace="http://schemas.fake-log.com/ws/identity/claims">
|
<saml:Attribute AttributeName="UserInstance" AttributeNamespace="http://schemas.fakelog.cf/ws/identity/claims">
|
||||||
<saml:AttributeValue>Default</saml:AttributeValue>
|
<saml:AttributeValue>Default</saml:AttributeValue>
|
||||||
<saml:AttributeValue>demo12345</saml:AttributeValue>
|
<saml:AttributeValue>demo12345</saml:AttributeValue>
|
||||||
<saml:AttributeValue>incorrect value</saml:AttributeValue>
|
<saml:AttributeValue>incorrect value</saml:AttributeValue>
|
@ -82,13 +82,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>
|
|
||||||
<span class="x-treelabel-ppl x-treelabel-inv">Metodologia programowania [zaw2]</span>
|
|
||||||
<span class="x-treelabel-ppl x-treelabel-inv"></span>
|
|
||||||
<span class="x-treelabel-ppl x-treelabel-inv">Baran Małgorzata</span>
|
|
||||||
<span class="x-treelabel-ppl x-treelabel-inv">36</span>
|
|
||||||
<span class="x-treelabel-rlz">(zmiana organizacji zajęć)</span>
|
|
||||||
</div>
|
|
||||||
<div>
|
<div>
|
||||||
<span class="x-treelabel-ppl x-treelabel-zas">Wychowanie fizyczne [zaw2]</span>
|
<span class="x-treelabel-ppl x-treelabel-zas">Wychowanie fizyczne [zaw2]</span>
|
||||||
<span class="x-treelabel-ppl x-treelabel-zas"></span>
|
<span class="x-treelabel-ppl x-treelabel-zas"></span>
|
||||||
@ -96,6 +89,13 @@
|
|||||||
<span class="x-treelabel-ppl x-treelabel-zas">G3</span>
|
<span class="x-treelabel-ppl x-treelabel-zas">G3</span>
|
||||||
<span class="x-treelabel-rlz">(przeniesiona z lekcji 7, 01.12.2017)</span>
|
<span class="x-treelabel-rlz">(przeniesiona z lekcji 7, 01.12.2017)</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<span class="x-treelabel-ppl x-treelabel-inv">Metodologia programowania [zaw2]</span>
|
||||||
|
<span class="x-treelabel-ppl x-treelabel-inv"></span>
|
||||||
|
<span class="x-treelabel-ppl x-treelabel-inv">Baran Małgorzata</span>
|
||||||
|
<span class="x-treelabel-ppl x-treelabel-inv">36</span>
|
||||||
|
<span class="x-treelabel-rlz">(zmiana organizacji zajęć)</span>
|
||||||
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>
|
<div>
|
||||||
@ -118,7 +118,18 @@
|
|||||||
<span class="x-treelabel-rlz">(zastępstwo)</span>
|
<span class="x-treelabel-rlz">(zastępstwo)</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td></td>
|
<td>
|
||||||
|
<div>
|
||||||
|
<span class="">Uroczyste rozpoczecie roku szkolnego 2017/2018</span>
|
||||||
|
<span class=""></span>
|
||||||
|
<span class=""></span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span class="x-treelabel-ppl">Uroczyste rozpoczecie roku szkolnego 2017/2018</span>
|
||||||
|
<span class="x-treelabel-ppl"></span>
|
||||||
|
<span class="x-treelabel-ppl"></span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>2</td>
|
<td>2</td>
|
||||||
@ -165,7 +176,20 @@
|
|||||||
<span></span>
|
<span></span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td></td>
|
<td>
|
||||||
|
<div>
|
||||||
|
<span class="">Język niemiecki [wf_grupa_2]</span>
|
||||||
|
<span class=""></span>
|
||||||
|
<span class=""></span>
|
||||||
|
<span class=""></span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span class="x-treelabel-ppl x-treelabel-inv">Wychowanie fizyczne [wf_grupa_2]</span>
|
||||||
|
<span class="x-treelabel-ppl x-treelabel-inv"></span>
|
||||||
|
<span class="x-treelabel-ppl x-treelabel-inv">Nauczycielel</span>
|
||||||
|
<span class="x-treelabel-ppl x-treelabel-inv">106</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>3</td>
|
<td>3</td>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user