Sometimes busy time is not retrieved from iCloud (Using Caldav) for specific calendar - icloud

<C:calendar-query xmlns:D='DAV:'
xmlns:C='urn:ietf:params:xml:ns:caldav'>
<D:prop>
<D:getetag/>
<C:calendar-timezone xmlns:D='DAV:' xmlns:C='urn:ietf:params:xml:ns:caldav'></C:calendar-timezone>
<C:calendar-data>
<C:expand start='20170116T031008Z'
end='20170131T031008Z'/>
<C:comp name='VCALENDAR'>
<C:prop name='VERSION'/>
<C:comp name='VEVENT'>
<C:prop name='SUMMARY'/>
<C:prop name='DESCRIPTION'/>
<C:prop name='STATUS'/>
<C:prop name='TRANSP'/>
<C:prop name='ATTENDEE'/>
<C:prop name='UID'/>
<C:prop name='DTSTART'/>
<C:prop name='DTEND'/>
<C:prop name='DURATION'/>
<C:prop name='RRULE'/>
<C:prop name='RDATE'/>
<C:prop name='EXRULE'/>
<C:prop name='EXDATE'/>
<C:prop name='RECURRENCE-ID'/>
</C:comp>
</C:comp>
</C:calendar-data>
</D:prop>
<C:filter>
<C:comp-filter name='VCALENDAR'>
<C:comp-filter name='VEVENT'>
<C:time-range start='20170116T031008Z'
end='20170131T031008Z'/>
</C:comp-filter>
</C:comp-filter>
</C:filter>
</C:calendar-query>
Hi, I am using caldav extension to retrieve busy time(by time range) from iCloud calendar. I am using a calendar query with a "REPORT" method. It gives XML having busy time for all calendars within the time range. But sometimes it doesn't give busy time for a particular calendar. Suppose I am having 3 calendars so, sometimes it gives busy times for all 3 calendars and sometimes for only 2 calendars(by leaving same calendar). If I retry for busy then it gives busy time after 7-8 retry. But Sometimes it doesn't give even after 7-8 retries. What is happening?

I didn't find a reason that why it is happening. But I have changed the process of busy time retrieval so that it brings busy time from all calendars. Previously I was hitting this request to URL - https://PXX-caldav.icloud.com/token/calendars which is not working for some specific calendars consistently.
New process-:
STEP 1: Hit the same request at https://PXX-caldav.icloud.com/token/calendars/calendarId this gives you urls of all the events within the time range from a calendar(for those as well for which I wast not able to retrieve busy time). Here, it gives events from calendar with id calendarId(your calendar's Id). It gives me xml in something following xml -:
<href>/token/calendars/calendarId/event1Id.ics</href>
<href>/token/calendars/calendarId/event2Id.ics</href>
<href>/token/calendars/calendarId/event3Id.ics</href>
Now you have to parse the xml to retrieve all the urls.
STEP2: After that you have all the urls, you have to hit single, multi-get request having these urls, at same url to retrieve data from these url and show them as busy time.
URL -: https://PXX-caldav.icloud.com/token/calendars/calendarId
Request -:
<C:calendar-multiget xmlns:d='DAV:' xmlns:C='urn:ietf:params:xml:ns:caldav'>
<d:prop>
<d:getetag />
<C:calendar-data>
<C:comp name='VCALENDAR'>
<C:prop name='VERSION'/>
<C:comp name='VEVENT'>
<C:prop name='SUMMARY'/>
<C:prop name='DESCRIPTION'/>
<C:prop name='STATUS'/>
<C:prop name='TRANSP'/>
<C:prop name='ATTENDEE'/>
<C:prop name='UID'/>
<C:prop name='DTSTART'/>
<C:prop name='DTEND'/>
<C:prop name='DURATION'/>
<C:prop name='RRULE'/>
<C:prop name='RDATE'/>
<C:prop name='EXRULE'/>
<C:prop name='EXDATE'/>
<C:prop name='RECURRENCE-ID'/>
</C:comp>
</C:comp>
</C:calendar-data>
</d:prop><d:href>/token/calendars/calendarId/event1Id.ics</d:href>
<d:href>/token/calendars/calendarId/event2Id.ics</d:href>
<d:href>/token/calendars/calendarId/event3Id.ics</d:href>
</C:calendar-multiget>
It gives you data for all three events. This helps you to retrieve busy time from every calendar. If you have to retrieve events from multiple calendars then you have to repeat these two steps for every calendar.

Related

How to set header to call soap service in mulesoft

I want to call one soap service through mulesoft.
To attach header to soap request body I used these links -Mule 3.7. Add custom SOAP header to web-service-consumer. As mentioned in this link, I have added "Message Properties" component before "Web Service Consumer", but I am getting below exception -
com.ctc.wstx.exc.WstxParsingException: Undeclared namespace prefix "soapenv" (for attribute "actor")
Also I tried it using Property component as mentioned here - https://dzone.com/articles/working-with-headers-in-mule-flows
Still I am not able to hit soap service. Is there any other way to add header to soap request body?
Header that i want to add to my soap request -
<wsse:Security soapenv:actor="AppID" soapenv:mustUnderstand="1"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken>
<wsse:Username>Pilot\ABCD</wsse:Username>
<wsse:Password wsse:Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">yt15#58</wsse:Password>
</wsse:UsernameToken>
--Update- My code-
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:dw="http://www.mulesoft.org/schema/mule/ee/dw" xmlns:ws="http://www.mulesoft.org/schema/mule/ws" xmlns:metadata="http://www.mulesoft.org/schema/mule/metadata" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/ws http://www.mulesoft.org/schema/mule/ws/current/mule-ws.xsd
http://www.mulesoft.org/schema/mule/ee/dw http://www.mulesoft.org/schema/mule/ee/dw/current/dw.xsd">
<ws:consumer-config name="Web_Service_Consumer_2" wsdlLocation="https://soa.abc.com/abcd_v4_0?wsdl" service="abcdService_vs0" port="xyz_Internal" serviceAddress=""https://soa.abc.com:56655/abcd_v4_0" doc:name="Web Service Consumer">
<ws:security>
<ws:wss-username-token username="user" password="password" passwordType="TEXT"/>
</ws:security>
</ws:consumer-config>
<sub-flow name="tempSub_Flow">
<set-property propertyName="soap.Security" value="<wsse:Security soapenv:actor="AppID" soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/></wsse:Security>" doc:name="Property"/>
<dw:transform-message doc:name="Transform Message">
<dw:set-payload><![CDATA[%dw 1.0
%output application/xml
%namespace ns0 urn:abc.com:schemas:gfr:a:b:service:2014-01-10
---
{
ns0#addTransaction:{
ns0#aTransaction: {
ns0#transactionCode: "xyz",
ns0#methodCode: "abc",
ns0#amount: flowVars.amount,
ns0#effectiveDate: now as :string {format: "yyyy-MM-dd"}
}
}
}]]></dw:set-payload>
</dw:transform-message>
<ws:consumer config-ref="Web_Service_Consumer_2" operation="addEftTransaction" doc:name="Web Service Consumer"/>
<dw:transform-message doc:name="Transform Message">
<dw:set-payload><![CDATA[%dw 1.0
%output application/java
%namespace ns0 urn:abc.com:schemas:gfr:a:b:service:2014-01-10
---
payload.ns0#addTransactionResponse.ns0#transactionNumber
]]></dw:set-payload>
</dw:transform-message>
</sub-flow>
</mule>
--- UPDATE ---
Two parts to the answer really, for the direct question of how to add SOAP headers, it looks like you might have missed declaring the namespace of soapenv for the Security element you were adding. For example, the below code should work for adding the "Security" header to the SOAP Envelope. The whole XML element must be defined, including any namespaces it uses.
<set-property propertyName="soap.Security" value="<wsse:Security soapenv:actor="AppID" soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><wsse:UsernameToken><wsse:Username>Pilot\ABCD</wsse:Username><wsse:Password wsse:Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">yt15#58</wsse:Password></wsse:UsernameToken></wsse:Security>" doc:name="Set soap.Security"/>
That looks pretty unattractive though, and since you are adding a username/password security header then you probably want to add this directly into the security element of the Web Service Consumer configuration itself:
<ws:consumer-config name="WSConfig" wsdlLocation="MyService.wsdl" service="MyService" port="MyPort" serviceAddress="https://example.com" doc:name="Web Service Consumer">
<ws:security>
<ws:wss-username-token username="Pilot\ABCD" password="yt15#58" passwordType="TEXT"/>
</ws:security>
</ws:consumer-config>
The issue with the above is that it won't add the soapenv:actor="appId" attribute.
It looks like the security configuration on the WS consumer will overwrite the actor attribute. The below code mostly works on Mule 3.8 and uses the sample WSDL found here: https://github.com/skjolber/mockito-soap-cxf/tree/master/src/test/resources/wsdl
The first flow builds the request to the SOAP web service, the second flow just receives the request made by the first flow and logs it.
<mule xmlns:metadata="http://www.mulesoft.org/schema/mule/metadata"
xmlns:dw="http://www.mulesoft.org/schema/mule/ee/dw"
xmlns:ws="http://www.mulesoft.org/schema/mule/ws"
xmlns:http="http://www.mulesoft.org/schema/mule/http"
xmlns="http://www.mulesoft.org/schema/mule/core"
xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/ws http://www.mulesoft.org/schema/mule/ws/current/mule-ws.xsd
http://www.mulesoft.org/schema/mule/ee/dw http://www.mulesoft.org/schema/mule/ee/dw/current/dw.xsd">
<ws:consumer-config name="BankCustomerService_WS_Consumer" wsdlLocation="BankCustomerService.wsdl" service="BankCustomerService" port="BankCustomerServicePort" serviceAddress="http://localhost:8778/services/bankCustomer" doc:name="Web Service Consumer">
<ws:security>
<ws:wss-username-token username="user" password="password" passwordType="TEXT"/>
</ws:security>
</ws:consumer-config>
<http:listener-config name="HTTP_TestListener" host="0.0.0.0" port="8092" doc:name="HTTP Listener Configuration"/>
<http:listener-config name="HTTP_WebServiceStub" host="0.0.0.0" port="8778" doc:name="HTTP Listener Configuration"/>
<flow name="soapsandboxFlow">
<http:listener config-ref="HTTP_TestListener" path="/soap" doc:name="HTTP"/>
<set-property propertyName="soap.Security" value="<wsse:Security soapenv:actor="AppID" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" />" doc:name="Set soap.Security"/>
<dw:transform-message doc:name="Transform Message">
<dw:set-payload><![CDATA[%dw 1.0
%output application/xml
%namespace ns0 http://example.bank.skjolber.github.com/v1
---
{
ns0#getAccountsRequest: {
ns0#customerNumber: 987654321,
ns0#certificate: 1234
}
}]]></dw:set-payload>
</dw:transform-message>
<ws:consumer config-ref="BankCustomerService_WS_Consumer" operation="getAccounts" doc:name="Web Service Consumer"/>
</flow>
<flow name="soapsandboxFlow1">
<http:listener config-ref="HTTP_WebServiceStub" path="services/bankCustomer" doc:name="HTTP"/>
<logger message="#[message.payloadAs(String)]" level="INFO" doc:name="Logger"/>
</flow>
</mule>
Running a simple GET request to localhost:8092 creates a static web service request and sends that to through the WS Consumer Component. The logger in the stub prints out the entire SOAP envelope, which as shown below includes the security header, but not the actor attribute:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<wsse:Security xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
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" soapenv:mustUnderstand="1">
<wsse:UsernameToken wsu:Id="UsernameToken-CA524029E5DEDE6E3715320371056746">
<wsse:Username>user</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">password</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soap:Header>
<soap:Body>
<ns0:getAccountsRequest xmlns:ns0="http://example.bank.skjolber.github.com/v1">
<ns0:customerNumber>987654321</ns0:customerNumber>
<ns0:certificate>1234</ns0:certificate>
</ns0:getAccountsRequest>
</soap:Body>
</soap:Envelope>
I will do a bit more research to see if I can include the actor attribute in the security header. As this is a standard attribute I it should be possible. I will update this answer when I can.
Johnson.

Forbidden error : While fetching events from iCloud using caldav extension

URL -: https://pxx-caldav.icloud.com/token/calendars/calendarId
#"<C:calendar-query xmlns:D='DAV:'
xmlns:C='urn:ietf:params:xml:ns:caldav'>
<D:prop>
<D:getetag/>
<C:calendar-timezone xmlns:D='DAV:' xmlns:C='urn:ietf:params:xml:ns:caldav'></C:calendar-timezone>
<C:calendar-data>
<C:expand start='{0}'
end='{1}'/>
<C:comp name='VCALENDAR'>
<C:prop name='VERSION'/>
<C:comp name='VEVENT'>
<C:prop name='SUMMARY'/>
<C:prop name='DESCRIPTION'/>
<C:prop name='STATUS'/>
<C:prop name='TRANSP'/>
<C:prop name='ATTENDEE'/>
<C:prop name='UID'/>
<C:prop name='DTSTART'/>
<C:prop name='DTEND'/>
<C:prop name='DURATION'/>
<C:prop name='RRULE'/>
<C:prop name='RDATE'/>
<C:prop name='EXRULE'/>
<C:prop name='EXDATE'/>
<C:prop name='RECURRENCE-ID'/>
</C:comp>
</C:comp>
</C:calendar-data>
</D:prop>
<C:filter>
<C:comp-filter name='VCALENDAR'>
<C:comp-filter name='VEVENT'>
<C:time-range start='{0}'
end='{1}'/>
</C:comp-filter>
</C:comp-filter>
</C:filter>
</C:calendar-query>"
while retrieving events it gives forbidden error on some particular calendars of some accounts. While retrieving calendars it shows read/write access but while fetching events it gives error. It gives error on few calendars but error is continuous on them.
I am getting following error -:
<error> <supported-report /> </error>
Calendars are WebDAV collections with a DAV:resourcetype of C:calendar (see https://www.rfc-editor.org/rfc/rfc4791#section-4.2 ) but there are other types of collections (calendar home, scheduling inbox, dropbox, etc...).
What is most likely happening is that you are issuing a calendar query against a collection which is not a calendar collection, hence the supported-report error.
You need to retrieve the DAV:resourcetype property of each collection and, only if it is a calendar, issue the above report.

django get data response from specific ip

I am working on an API integration. I am using django==1.10.5 and python34. The app involves sending request from my server to another server which is connected through a VPN.
password = "xxxxxxxxxxxxxxxxx"
spid = "xxxxxxxxxxxxxxxxx"
serviceid = "xxxxxxxxxxxxxxxxx"
sendershortcode = "xxxxxxxxxxxxxxxxx"
initiator = "xxxxxxxxxxxxxxxxx"
initiator_password = "xxxxxxxxxxxxxxxxx"
recieveridentifier = "xxxxxxxxxxxxxxxxx"
body = """<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:req="http://api-v1.gen.mm.vodafone.com/mminterface/request">
<soapenv:Header>
<tns:RequestSOAPHeader xmlns:tns="http://www.huawei.com/schema/osg/common/v2_1">
<tns:spId>"""+spid+"""</tns:spId>
<tns:serviceId>"""+serviceid+"""</tns:serviceId>
<tns:spPassword>"""+encoded_password+"""</tns:spPassword>
<tns:timeStamp>"""+reqTime+"""</tns:timeStamp>
</tns:RequestSOAPHeader>
</soapenv:Header>
<soapenv:Body>
<req:RequestMsg>
<![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<request xmlns="http://api-v1.gen.mm.vodafone.com/mminterface/request">
<Transaction>
<CommandID>SalaryPayment</CommandID>
<LanguageCode></LanguageCode>
<OriginatorConversationID>"""+originator+"""</OriginatorConversationID>
<ConversationID></ConversationID>
<Remark></Remark>
<Parameters>
<Parameter>
<Key>Amount</Key>
<Value>200</Value>
</Parameter>
</Parameters>
<ReferenceData>
<ReferenceItem>
<Key>QueueTimeoutURL</Key>
<Value>http://138.197.41.74:80/user/test/</Value>
</ReferenceItem>
</ReferenceData>
<Timestamp>"""+reqTime+"""</Timestamp>
</Transaction>
<Identity>
<Caller>
<CallerType>2</CallerType>
<ThirdPartyID>broker_4</ThirdPartyID>
<Password>k+JtvqNV3eg=</Password>
<CheckSum>CheckSum0</CheckSum>
<ResultURL>http://138.197.41.74:80/results/B2C/</ResultURL>
</Caller>
<Initiator>
<IdentifierType>11</IdentifierType>
<Identifier>"""+initiator+"""</Identifier>
<SecurityCredential>YwBlXbjEFjh/UQ0cZhrk+4X9TxAIc3z8zf4rXZRZRLW32cm+c/lJYQ3ZFVThna+41x8EukAHZhuR44QiF5J1GF/9QaYwK1i1rIX2i/Fa9bRJ4fn/REYd/vE1/pUPn4GnfLib151RYQyO7KsLipLFk8Hr9SYq62MSrOxgyAd1bJXQ4SdEJwk0LtCZSTWBaZySbPJt/P0FBfG71kLkrP0P0pn1cuuuJoA3KJ5+RuX5WpsXR0HFFyyJFEwAlQ9oSmKW5fzCwEKMaKTKgScfyDXmhuiFZvrSmdV3H0o4Hhl17IQR8M1fwIk9JfxrSUqVRBrEqVKJrOOlSF/T7xLJTo0fpQ==</SecurityCredential>
<ShortCode>777133</ShortCode>
</Initiator>
<PrimaryParty>
<IdentifierType>4</IdentifierType>
<Identifier>777133</Identifier>
<ShortCode>777133</ShortCode>
</PrimaryParty>
<ReceiverParty>
<IdentifierType>1</IdentifierType>
<Identifier>"""+recieveridentifier+"""</Identifier>
<ShortCode>ShortCode1</ShortCode>
</ReceiverParty>
<AccessDevice>
<IdentifierType>1</IdentifierType>
<Identifier>Identifier3</Identifier>
</AccessDevice>
</Identity>
<KeyOwner>1</KeyOwner>
</request>]]></req:RequestMsg>
</soapenv:Body>
</soapenv:Envelope>"""
headers = {'content-type': 'Content-Type: text/xml; charset=utf-8'}
url = "http://xxx.xxx.xxxx.xxx:xxxx/mminterface/request"
response = requests.post(url=url, headers = headers, data = body)
#print (response.content)
respO = xmltodict.parse(response.content)
myresponse = json.dumps(respO)
This code works fine i am able to get a respose from the other server.
My question is the other server is sending some other data which am getting when i tcpdup response i.e. tcpdump -A -s 0 'src xxx.xxx.xxx.xxx and tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'
From doing this am getting this content.
<?xml version='1.0' encoding='UTF-8'?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<res:ResultMsg xmlns:res="http://api-v1.gen.mm.vodafone.com/mminterface/result">
<![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Result xmlns="http://api-v1.gen.mm.vodafone.com/mminterface/result">
<ResultType>0</ResultType>
<ResultCode>0</ResultCode>
<ResultDesc>The service request has been accepted successfully.</ResultDesc>
<OriginatorConversationID>Z8MPEFVZ</OriginatorConversationID>
<ConversationID>AG_20170508_00006c8d2d96c6efbeab</ConversationID>
<TransactionID>LE80192FMG</TransactionID>
<ResultParameters>
<ResultParameter>
<Key>TransactionReceipt</Key>
<Value>LE80192FMG</Value>
</ResultParameter>
<ResultParameter>
<Key>TransactionAmount</Key>
<Value>200</Value></ResultParameter>
<ResultParameter>
<Key>B2CWorkingAccountAvailableFunds</Key>
<Value>0.00</Value>
</ResultParameter>
<ResultParameter>
<Key>B2CUtilityAccountAvailableFunds</Key>
<Value>5508.00</Value>
</ResultParameter>
<ResultParameter>
<Key>TransactionCompletedDateTime</Key>
<Value>08.05.2017 09:37:07</Value>
</ResultParameter>
<ResultParameter>
<Key>ReceiverPartyPublicName</Key>
<Value>254703381233</Value>
</ResultParameter>
<ResultParameter>
<Key>B2CChargesPaidAccountAvailableFu 06:38:49.685570 IP 196-201-214-127.safaricom.co.ke.60575 > mambowallet.http: Flags [P.], seq 1380:1741, ack 1, win 4380, length 361 ..gP...5 ..nds</Key>
<Value>-275.00</Value>
</ResultParameter>
<ResultParameter>
<Key>B2CRecipientIsRegisteredCustomer</Key>
<Value>N</Value></ResultParameter>
</ResultParameters>
<ReferenceData><ReferenceItem>
<Key>QueueTimeoutURL</Key>
<Value>http://138.197.41.74:80/user/test/</Value>
</ReferenceItem>
</ReferenceData>
</Result>]]>
</res:ResultMsg>
</soapenv:Body> </soapenv:Envelope>
Can someone help how i can get this content on the django view?
tcpdump image
you can do a tcpdump inside your python code using subprocess:
from subprocess import check_output
out = check_output(['tcpdump','args'])
you get the response in out and then you can work with it. for example:
out = check_output(['tcpdump', 'ether[0] & 1 = 0 and ip[16] >= 224'])
and you need to be root also

Getting vCards from iCloud using PHP

Searched thru serverfault.com, stackoverflow.com, apple.stackexchange.com, googled and still not getting far. Need someone to help.
I'm trying to get all vCards from iCloud accounts.
I'm starting from the plugin from Roundcube/CardDav.
From the articles such as:
stackoverflow.com/questions/24202551/manipulate-groups-in-icloud-with-carddav-protocol
sabre.io/dav/building-a-carddav-client/
sabre.io/dav/clients/osx-addressbook/
stackoverflow.com/questions/15111887/how-to-import-icloud-contacts-in-php#
tools.ietf.org/html/rfc6352#section-8.7.1
I managed to get the Principal, the Principal's address. But the last step of getting the card returns ContentLength of 0.
Here is what I do:
- use icloud email as username
- use icloud password
To get the Principal, using "https : / / contacts.icloud.com/" as URL, PROPFIND, DEPTH 0:
<?xml version="1.0" encoding="UTF-8"?>
<d:propfind xmlns:d="DAV:">
<d:prop>
<d:current-user-principal/>
</d:prop>
</d:propfind>
Response:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<multistatus xmlns="DAV:">
<response>
<href>/</href>
<propstat>
<prop>
<current-user-principal>
<href>/1331115018/principal/</href>
</current-user-principal>
</prop>
<status>HTTP/1.1 200 OK</status>
</propstat>
</response>
</multistatus>
Next, here is what I do to get the home, using "https : / /contacts.icloud.com/1331115018/principal/", PROPFIND, DEPTH 0:
<?xml version="1.0" encoding="UTF-8"?>
<d:propfind xmlns:d="DAV:" xmlns:card="urn:ietf:params:xml:ns:carddav">
<d:prop>
<card:addressbook-home-set/>
</d:prop>
</d:propfind>
Response:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<multistatus xmlns="DAV:">
<response>
<href>/1331115018/principal/</href>
<propstat>
<prop>
<addressbook-home-set xmlns="urn:ietf:params:xml:ns:carddav">
<href xmlns="DAV:">https://p44-contacts.icloud.com:443/1331115018/carddavhome/</href>
</addressbook-home-set>
</prop>
<status>HTTP/1.1 200 OK</status>
</propstat>
</response>
</multistatus>
Finally, here is what I do to try to get all the vCards, using https : / / p44-contacts.icloud.com:443/1331115018/carddavhome/, REPORT, DEPTH 1:
<?xml version="1.0" encoding="utf-8" ?>
<C:addressbook-multiget xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:carddav">
<D:prop>
<D:getetag/>
<C:address-data>
<C:prop name="UID"/>
<C:prop name="EMAIL"/>
<C:prop name="FN"/>
</C:address-data>
</D:prop>
</C:addressbook-multiget>
Response:
<?xml version="1.0" encoding="UTF-8"?>
<multistatus xmlns="DAV:" xmlns:CD="urn:ietf:params:xml:ns:carddav" xmlns:CS="http://calendarserver.org/ns/">
</multistatus>
or
<?xml version="1.0" encoding="utf-8" ?>
<C:addressbook-query xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:carddav">
<D:prop>
<D:getetag/>
<C:address-data>
<C:prop name="UID"/>
<C:prop name="EMAIL"/>
<C:prop name="FN"/>
</C:address-data>
</D:prop>
</C:addressbook-query>
Response:
<?xml version="1.0" encoding="UTF-8"?>
<multistatus xmlns="DAV:" xmlns:CD="urn:ietf:params:xml:ns:carddav" xmlns:CS="http://calendarserver.org/ns/">
<response>
<href>/1331115018/carddavhome/</href>
<propstat>
<prop> <getetag>"C=0#U=9123588c-8038-439c-a547-19c866d1ed06"</getetag>
<address-data xmlns="urn:ietf:params:xml:ns:carddav">
</address-data>
</prop>
<status>HTTP/1.1 200 OK</status>
</propstat>
</response>
</multistatus>
or
<?xml version="1.0" encoding="utf-8" ?>
<C:addressbook-query xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:carddav">
<D:prop>
<D:getetag/>
<C:address-data>
<C:prop name="UID"/>
<C:prop name="EMAIL"/>
<C:prop name="FN"/>
</C:address-data>
</D:prop>
<C:prop-filter name="EMAIL">
<C:text-match collation="i;unicode-casemap" match-type="equals">me</C:text-match>
</C:prop-filter>
</C:filter>
</C:addressbook-query>
Response:
"Didn't understand the report"
What do I have to do?
The CardDAV home (your https://p44-contacts.icloud.com:443/1331115018/carddavhome/) contains the CardDAV collections (aka the 'address books'), not the vCards (which contain contacts and contact groups). You need to take one more hop.
You can list the addressbook collections in the home using a regular PROPFIND Depth 1 and then query those for the contacts with the report you specify. Like so:
PROPFIND /1331115018/carddavhome/ HTTP/1.1
Depth: 1
Host: p44-contacts.icloud.com:443
Authorization: ...
Content-Type: text/xml; charset=utf-8
Content-Length: ...
<propfind xmlns="DAV:">
<prop>
<displayname />
<resourcetype />
</prop>
</propfind>
This returns you the list of all sub-collections in the CardDAV home collection.
The collections which have an addressbook resourcetype are CardDAV addressbook collections and can be queried using an addressbook-query or addressbook-multiget report, using a sync-report if that is supported (iCloud does) or again using a simple PROPFIND. Depends on what you want.
Given an address book collection URL a 'real' client would usually use a sync-report to grab the URLs of all changed objects if the server supports that, or just grab the URLs, Content-Type and ETags of all contained vCards using a PROPFIND as a fallback. For example:
PROPFIND /1331115018/carddavhome/contacts/ HTTP/1.1
Depth: 1
Host: p44-contacts.icloud.com:443
Authorization: ...
Content-Type: text/xml; charset=utf-8
Content-Length: ...
<propfind xmlns="DAV:">
<prop>
<getetag />
<getcontenttype />
</prop>
</propfind>
This gives you the URLs of all objects in the address book collection. Which you can then retrieve using simple GETs or a multiget REPORT.
BTW: In your addressbook-multiget REPORT you do not list any vCard URLs, hence the result set will always be empty ... You can read about multiget in RFC 6352.
Note: In iCloud there is usually just one addressbook collection in the home, but in other servers it is quite common to have multiple. Also in some servers the CalDAV and CardDAV homes are the same collection (i.e. remember to actually check the resourcetype of the sub-collections in the respective home collections).
This is a great introduction on CardDAV: Building a CardDAV client.
Or this one on YouTube: FOSDEM 2009 CalDAV.
<card:addressbook-multiget xmlns:d="DAV:" xmlns:card="urn:ietf:params:xml:ns:carddav">
<d:prop>
<d:getetag />
<card:address-data />
</d:prop>
<d:href>/1331115018/carddavhome/card/vcard_UUID.vcf</d:href>
</card:addressbook-multiget>
Let try this in the REPORT Request.
Getting your credentials: https://github.com/muhlba91/icloud/blob/master/groovy_java/gui-2.1.0.zip! Keep in mind: https://support.apple.com/en-us/HT204397
Getting your vCards: https://github.com/andig/carddav2fb - just use the download command: php carddav2fb download yourdownload.vcf

JPA Delete Query is not working in EJB

I am trying to delete entities using JPQL in stateless EJB. Following is my code -
#PersistenceContext(unitName="mysql")
protected EntityManager em;
Query query=null;
#stateless
public class Test{
public void delete(){
query = em.createQuery("delete from JPAAgentInfo a WHERE a.client_id=?1 and a.agent_id=?2");
query.setParameter(1, 111);
query.setParameter(2, 1);
query.executeUpdate();
}
}
However above code throws following exception -
javax.persistence.TransactionRequiredException: Executing an update/delete query
10:25:17,503 ERROR [io.undertow.request] (default task-1) UT005023: Exception handling request to /servlet/delete: javax.persistence.TransactionRequiredException: Executing an update/delete query
at org.hibernate.jpa.spi.AbstractQueryImpl.executeUpdate(AbstractQueryImpl.java:71) [hibernate-entitymanager-4.3.5.Final.jar:4.3.5.Final]
at org.jboss.as.jpa.container.QueryNonTxInvocationDetacher.executeUpdate(QueryNonTxInvocationDetacher.java:80) [wildfly-jpa-8.1.0.Final.jar:8.1.0.Final]
at com.bitbyte.servlet.ChatServer.doGet(ChatServer.java:81) [classes:]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:687) [jboss-servlet-api_3.1_spec-1.0.0.Final.jar:1.0.0.Final]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) [jboss-servlet-api_3.1_spec-1.0.0.Final.jar:1.0.0.Final]
at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:61) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:113) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:56) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:45) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:61) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final
at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:58) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:70) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.security.handlers.SecurityInitialHandler.handleRequest(SecurityInitialHandler.java:76) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:240) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:227) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:73) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:146) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:177) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:727) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [rt.jar:1.7.0_65]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [rt.jar:1.7.0_65]
at java.lang.Thread.run(Thread.java:745) [rt.jar:1.7.0_65]
It says "javax.persistence.TransactionRequiredException".
You cannot run database updates without a transaction (only queries are allowed).
One way to do that would be with the #Transactional annotation.