[horde] import calendar events into kronolith - using xmlRPC?
Jan Schneider
jan at horde.org
Thu Feb 11 13:39:56 UTC 2016
Zitat von Daniel <horde at daniu.de>:
> Zitat von Daniel <horde at daniu.de>:
>
>> Zitat von Michael J Rubinsky <mrubinsk at horde.org>:
>>
>>> Quoting Michael J Rubinsky <mrubinsk at horde.org>:
>>>
>>>> Quoting Daniel <horde at daniu.de>:
>>>>
>>>>> Zitat von Michael J Rubinsky <mrubinsk at horde.org>:
>>>>>
>>>>>> Quoting Daniel <horde at daniu.de>:
>>>>>>
>>>>>>> Hi,
>>>>>>>
>>>>>>> Quoting Michael J Rubinsky <mrubinsk at horde.org>:
>>>>>>>
>>>>>>>> Quoting Daniel <horde at daniu.de>:
>>>>>>>>
>>>>>>>>> Zitat von Michael J Rubinsky <mrubinsk at horde.org>:
>>>>>>>>>
>>>>>>>>>> Quoting Michael J Rubinsky <mrubinsk at horde.org>:
>>>>>>>>>>
>>>>>>>>>>> Quoting Jan Schneider <jan at horde.org>:
>>>>>>>>>>>
>>>>>>>>>>>> Zitat von Daniel <horde at daniu.de>:
>>>>>>>>>>>>
>>>>>>>>>>>>> Hi,
>>>>>>>>>>>>>
>>>>>>>>>>>>> I am new to the list - hope my request is in the right
>>>>>>>>>>>>> place here:
>>>>>>>>>>>>>
>>>>>>>>>>>>> My final goal is to get a calendar from google into
>>>>>>>>>>>>> kronolith. Unfortunately my provider did not setup
>>>>>>>>>>>>> kronolith so that I can do that with kronolith itsself
>>>>>>>>>>>>> so I think of a cron-job that does that with a php
>>>>>>>>>>>>> script (I am not talking about syncing - just copying
>>>>>>>>>>>>> the google calendar to kronolith. Since the google
>>>>>>>>>>>>> calendar itsself gets populated with a cron-job itsself
>>>>>>>>>>>>> it's ok to have accurate data only after copying). I can
>>>>>>>>>>>>> already read all appointments from google (caldav still
>>>>>>>>>>>>> works) - so I got a string with Vevent infos. The plan
>>>>>>>>>>>>> is to purge the existing calendar in kronolith and write
>>>>>>>>>>>>> all events from the string into the existing calendar.
>>>>>>>>>>>>>
>>>>>>>>>>>>> I tried to adjust this: http://theupstairsroom.com/66
>>>>>>>>>>>>> but don't seem to get it working at all. Partly because
>>>>>>>>>>>>> I don't have access to horde sources on the server from
>>>>>>>>>>>>> which I connect to the Horde - so I need to use another
>>>>>>>>>>>>> RPC-client. I would like to use the RPC-client built in
>>>>>>>>>>>>> php (epinion.com) which is turned on according to
>>>>>>>>>>>>> phpinfo. Somehow I cannot really find a good tutorial
>>>>>>>>>>>>> how to do that.
>>>>>>>>>>>>>
>>>>>>>>>>>>> Adjusting a script from php.net gave me the attached
>>>>>>>>>>>>> attempt. That one does nothing unfortunately ... (but at
>>>>>>>>>>>>> least no error message)
>>>>>>>>>>>>>
>>>>>>>>>>>>> Can someone point me in the right direction? Or is there
>>>>>>>>>>>>> a simpler way to achieve what I want to do?
>>>>>>>>>>>>>
>>>>>>>>>>>>> Is https a problem for what I want to do? Are my
>>>>>>>>>>>>> adjustments for that correct?
>>>>>>>>>>>>>
>>>>>>>>>>>>> Looking at the api it seems like the purge function from
>>>>>>>>>>>>> import in the GUI did not make it in there ... any
>>>>>>>>>>>>> chance to still do it or get it in the api?
>>>>>>>>>>>>>
>>>>>>>>>>>>> Thanks for any input!
>>>>>>>>>>>>>
>>>>>>>>>>>>> (BTW: there is a sourceforge project with exactly that
>>>>>>>>>>>>> topic, but it does not work any more and the author did
>>>>>>>>>>>>> not maintain it - I even asked him and he says he cannot
>>>>>>>>>>>>> help - http://sourceforge.net/projects/kron2gcalsync/)
>>>>>>>>>>>>>
>>>>>>>>>>>>> ***
>>>>>>>>>>>>> function do_call($host, $port, $request) {
>>>>>>>>>>>>>
>>>>>>>>>>>>> $url = "https://$host:$port/";
>>>>>>>>>>>>> //echo $url;
>>>>>>>>>>>>> $header[] = "Content-type: text/xml";
>>>>>>>>>>>>> $header[] = "Content-length: ".strlen($request);
>>>>>>>>>>>>> $to['user']='username';
>>>>>>>>>>>>> $to['pass']='password';
>>>>>>>>>>>>> $userpwd = $to['user'] .":". $to['pass'];
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> $ch = curl_init();
>>>>>>>>>>>>> curl_setopt($ch, CURLOPT_URL, $url);
>>>>>>>>>>>>> curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
>>>>>>>>>>>>> curl_setopt($ch, CURLOPT_TIMEOUT, 1);
>>>>>>>>>>>>> curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
>>>>>>>>>>>>> curl_setopt($ch, CURLOPT_USERPWD, $userpwd);
>>>>>>>>>>>>> curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
>>>>>>>>>>>>> curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
>>>>>>>>>>>>> curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
>>>>>>>>>>>>>
>>>>>>>>>>>>> $data = curl_exec($ch);
>>>>>>>>>>>>> if (curl_errno($ch)) {
>>>>>>>>>>>>> print curl_error($ch);
>>>>>>>>>>>>> } else {
>>>>>>>>>>>>> curl_close($ch);
>>>>>>>>>>>>> return $data;
>>>>>>>>>>>>> }
>>>>>>>>>>>>> }
>>>>>>>>>>>>>
>>>>>>>>>>>>> $host="path/rpc.php";
>>>>>>>>>>>>> $port=443;
>>>>>>>>>>>>> $request =
>>>>>>>>>>>>> xmlrpc_encode_request('kronolith.listCalendars', array());
>>>>>>>>>>>>> $response = do_call($host, $port, $request);
>>>>>>>>>>>>> echo $response;
>>>>>>>>>>>>> ***
>>>>>>>>>>>>>
>>>>>>>>>>>>> regards
>>>>>>>>>>>>>
>>>>>>>>>>>>> --
>>>>>>>>>>>>> Horde mailing list
>>>>>>>>>>>>> Frequently Asked Questions: http://horde.org/faq/
>>>>>>>>>>>>> To unsubscribe, mail: horde-unsubscribe at lists.horde.org
>>>>>>>>>>>>
>>>>>>>>>>>> You want to use the kronolith-import-icals script that
>>>>>>>>>>>> comes with Kronolith.
>>>>>>>>>>>
>>>>>>>>>>> This is correct, if you have shell access. If you don't,
>>>>>>>>>>> you should probably change to JSON as Jan suggests below.
>>>>>>>>>>> In newer versions of Horde we no longer support xmlrpc.
>>>>>>>>>>>
>>>>>>>>>>> Also:
>>>>>>>>>>> 1) Don't set the port number in CURL when you use https://
>>>>>>>>>>> already in the URL.
>>>>>>>>>>> 2) The proper method name would be
>>>>>>>>>>> "calendar.listCalendars", not "kronolith.listCalendars".
>>>>>>>>>>>
>>>>>>>>>>> So, for example (this is VERY rough and quickly done, so
>>>>>>>>>>> you might need to tweak some things):
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> function do_call($host, $method, $params) {
>>>>>>>>>>> $url = "https://$host";
>>>>>>>>>>> $header[] = "Content-type: application/json";
>>>>>>>>>>> $data = array('version' => '1.1', 'method' => $request);
>>>>>>>>>>
>>>>>>>>>> Sorry, this line should be (substitute $method for $request):
>>>>>>>>>> $data = array('version' => '1.1', 'method' => $method);
>>>>>>>>>
>>>>>>>>> sure - I found that ... works great! THANKS a lot!
>>>>>>>>>
>>>>>>>>> So now how about the other things:
>>>>>>>>> *do I need to delete all events manually or may I beg for a
>>>>>>>>> purge to be implemented in the api?
>>>>>>>>
>>>>>>>> Use the calendar.deleteCalendar method.
>>>>>>>
>>>>>>> I guess that should delete the calendar, not purge it? However
>>>>>>> I can't get that one to work ...
>>>>>>
>>>>>> Correct, which is the same thing that happens when you select
>>>>>> the purge checkbox in the UI.
>>>>>
>>>>> I don't think so ... that would mean that the calendar would get
>>>>> a new id after doing this or is it possible to define the id
>>>>> somehow? Are we talking about the same thing? I am talking about
>>>>> importing data (ical) in the ui and ticking "delete all data in
>>>>> the calendar" (sorry, my ui is german)
>>>>
>>>> It looks like our PHP doc is incorrect.
>>>> Kronolith_Driver::delete() is *supposed* to
>>>> "Delete a calendar and all of it's events", but looking at the
>>>> actual source code,
>>>> it only removes the events.
>>>>
>>>> In anticipation of your next question, the reason the events are
>>>> all removed individually (and not all at once as would be much
>>>> more efficient especially in a SQL backend) is because we need to
>>>> track the deletions in the Horde_History system for
>>>> synchronization clients.
>>>>
>>>>>>> ***
>>>>>>> $request = 'calendar.deleteCalendar';
>>>>>>>
>>>>>>> $params = array('calendar-id');
>>>>>>>
>>>>>>> $response = do_call($host, $request, $params);
>>>>>>> echo $response;
>>>>>>> ***
>>>>>>>
>>>>>>> gives me:
>>>>>>> {"version":"1.1","error":{"name":"JSONRPCError","code":999,"message":{"details":null,"logged":false}}}
>>>>>>
>>>>>> This looks like it should work (assuming it's the correct
>>>>>> calendar id and you have enough rights to remove it). Without
>>>>>> details from the server's log it's hard to say why it's not.
>>>>>>
>>>>>>>>> *Can I import the events with the api yet?
>>>>>>>>>
>>>>>>>>> I tried that one - (function and host omitted)
>>>>>>>>>
>>>>>>>>> ***
>>>>>>>>> $request = 'calendar.import';
>>>>>>>>> $input = <<<EOF
>>>>>>>>> BEGIN:VEVENT
>>>>>>>>> UID:20160901T130000Z-123401 at host.com
>>>>>>>>> DTSTAMP:20160110T1300Z
>>>>>>>>> DTSTART:20160110T163000Z
>>>>>>>>> DTEND:20160110T190000Z
>>>>>>>>> SUMMARY:Test1
>>>>>>>>> END:VEVENT
>>>>>>>>> UID:20160902T130000Z-123401 at host.com
>>>>>>>>> DTSTAMP:20160111T1300Z
>>>>>>>>> DTSTART:20160111T163000Z
>>>>>>>>> DTEND:20160111T190000Z
>>>>>>>>> SUMMARY:Test2
>>>>>>>>> END:VEVENT
>>>>>>>>> EOF;
>>>>>>>>> $params = array($input,'text/calendar','calendar-id');
>>>>>>>>> $response = do_call($host, $request, $params);
>>>>>>>>> echo $response;
>>>>>>>>> ***
>>>>>>>>>
>>>>>>>>> which imported just the first event ... any chance to make
>>>>>>>>> it import many events with one call? I am afraid that I get
>>>>>>>>> a timeout for the script otherwise ...
>>>>>>>>
>>>>>>>>
>>>>>>>> Correct, you can only import one VEVENT at a time.
>>>>>>>>
>>>>>>>> I'm confused by your statement about a timeout. A single
>>>>>>>> event will import faster than a large calendar. You are
>>>>>>>> likely to get server timeouts importing the full calendar at
>>>>>>>> once.
>>>>>>>>
>>>>>>>>> I'd love to see a function like this:
>>>>>>>>> public function import_many($content, $contentType,
>>>>>>>>> $calendar = null, $purge = FALSE)
>>>>>>>>>
>>>>>>>>> while it won't help me since my provider would not update
>>>>>>>>> Horde just for me ...
>>>>>>>
>>>>>>> just for reference:
>>>>>>> I was wrong - just as my string was - there was 1 BEGIN:VEVENT
>>>>>>> missing. Adding that missing part, I can import many events at
>>>>>>> once.
>>>>>>
>>>>>> Ah. Great. Not sure why I thought that :)
>>>>>>
>>>>>>
>>>>>>> concerning timeout: I was refering to timeout of my php
>>>>>>> script, not the connection to the server within the php
>>>>>>> script. I guess it is faster if I send all events as 1 string
>>>>>>> than sending each event with a seperate call.
>>>>>>
>>>>>> True. Though it takes longer on the server to process it.
>>>>>> Probably not an issue, but keep that in mind (your host may
>>>>>> have a too-low timeout configured on the server).
>>>>>>
>>>>>>> I guess I'm going to see how long it takes and in case of a
>>>>>>> problem break the string in parts. Since I don't need the ids
>>>>>>> afterwards should be OK like that.
>>>>>
>>>>> changed the code slightly for better handling (don't need to
>>>>> remove any username, host or password). Now I got 2 functions:
>>>>>
>>>>> the first one does work, but gets timed out so that I gotta call
>>>>> it at least once more so that the calendar is empty (php timeout
>>>>> is 60sec I think and it's around 700 events). The second does
>>>>> nothing ...
>>>>>
>>>>> Would appreciate if someone could test, especially what
>>>>> delete_cal does - remove the calendar or delete all events in it.
>>>>
>>>> Ok. The calendar/deleteCalendar method does just that, it *only*
>>>> removes the actual calendar share - it doesn't touch the events
>>>> storage.
>>>
>>> *sigh* Sorry - this is incorrect. calendar/deleteCalendar does
>>> both. It removes
>>> the events (by calling Kronolith_Driver::delete()) and then it
>>> removes the calendar
>>> share itself. So, you only have to call that one method, you don't
>>> have to iterate over the events on your own.
>>>
>>> Sorry for the confusion.
>>
>> Hi
>>
>> do I get it right, that after calling deleteCalendar the calendar
>> should be gone?
>>
>> On the server I am talking to it does nothing.
>>
>> Basically my problem however is that I do not yet know how to
>> really read from a caldav (in this case google) server what has
>> changed lately. I wanted to spare myself that and just erase
>> everything and write it once more (I had found a php script that
>> does that for owncloud which is really fast because there is a
>> command to erase all events at once in owncloud).
>>
>> I tweaked the code now so that it does only write events that had
>> been changed today (could adjust that to "lately") but that does
>> not erase events from kronolith that had been deleted on google.
>>
>> well - seems like the remaining problem does not belong here any
>> more and I gotta learn howto talk caldav ...
>
> Hi.
>
> sorry - now I got some problem again:
>
> I wrote this delete uid function:
>
>
> function delete_id($host, $user, $pw, $id) {
>
> $url = "https://$host";
> $header[] = "Content-type: application/json";
> $input = array('version' => '1.1', 'method' =>
> 'calendar.delete', 'params' => $id);
> $userpwd = $user . ':' . $pw;
> $ch = curl_init();
> curl_setopt($ch, CURLOPT_URL, $url);
> curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
> curl_setopt($ch, CURLOPT_TIMEOUT, 1);
> curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
> curl_setopt($ch, CURLOPT_USERPWD, $userpwd);
> curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
> curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
> curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($input));
> $data = curl_exec($ch);
> $processed=json_decode($data, true);
> if (curl_errno($ch)) {
> print curl_error($ch);
> } else {
> curl_close($ch);
> return $data;
> }
> }
>
> But unfortunately I get this reply (var_dump or $data):
>
> {"version":"1.1","error":{"name":"JSONRPCError","code":999,"message":"Parameters must be JSON objects or
> arrays."}}
Because your parameters are not an array or object:
'params' => $id
> BTW: why does my error handling not work? I would suppose that
> "curl_errno($ch)" is TRUE for an error.
No, this is for error on the HTTP level.
> Not 100% sure but I think it did work before ...
>
> I did other - quite similar - functions that work (besodes error
> handling ...):
> function import($host, $user, $pw, $cal, $caldata) {
> $params = array($caldata,'text/calendar', $cal);
> $url = "https://$host";
> $header[] = "Content-type: application/json";
> $input = array('version' => '1.1', 'method' => 'calendar.import');
> if (!empty($params)) {
> $input['params'] = $params;
> }
> $userpwd = $user . ':' . $pw;
> $ch = curl_init();
> curl_setopt($ch, CURLOPT_URL, $url);
> curl_setopt($ch, CURLOPT_RETURNTRANSFER, 100);
> curl_setopt($ch, CURLOPT_TIMEOUT, 100);
> curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
> curl_setopt($ch, CURLOPT_USERPWD, $userpwd);
> curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
> curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
> curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($input));
> $data = curl_exec($ch);
> if (curl_errno($ch)) {
> print curl_error($ch);
> } else {
> curl_close($ch);
> return $data;
> }
> }
>
> any help would be appreciated!
>
> regards
--
Jan Schneider
The Horde Project
http://www.horde.org/
More information about the horde
mailing list