[horde] import calendar events into kronolith - using xmlRPC?

Daniel horde at daniu.de
Thu Jan 21 20:15:36 UTC 2016


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)

>> ***
>> $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.

***
function delete_all($host, $user, $pw, $cal) {

       $params = array($cal);
       $url = "https://$host";
       $header[] = "Content-type: application/json";
       $input = array('version' => '1.1', 'method' => 'calendar.listUids');
       if (!empty($params)) {
          $input['params'] = $params;
       }
       $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);


       $input2 = array('version' => '1.1', 'method' => 'calendar.delete');


       foreach ($processed['result'] as $id){
         $params = array($id);
         if (!empty($params)) {
           $input2['params'] = $params;
         }
         curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($input2));
         $data = curl_exec($ch);
       }


       if (curl_errno($ch)) {
           print curl_error($ch);
       } else {
           curl_close($ch);
           return $data;
       }
}

function delete_cal ($host, $user, $pw, $cal){
       $params = array($cal);
       $url = "https://$host";
       $header[] = "Content-type: application/json";
       $input = array('version' => '1.1', 'method' =>  
'calendar.deleteCalendar');
       if (!empty($params)) {
          $input['params'] = $params;
       }
       $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);

       if (curl_errno($ch)) {
           print curl_error($ch);
       } else {
           curl_close($ch);
           return $data;
       }
}
***

Hey - but ... I am so much further now - before I tried lots of ways  
without any result ...

regards



More information about the horde mailing list