[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