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

Daniel horde at daniu.de
Thu Feb 11 15:41:57 UTC 2016


Zitat von Jan Schneider <jan at horde.org>:

> Zitat von Daniel <horde at daniu.de>:
>
>> Zitat von Jan Schneider <jan at horde.org>:
>>
>>> 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
>>
>> Hi,
>>
>> thanks for the reply - I had tried to change it to:
>>      $input = array('version' => '1.1', 'method' =>  
>> 'calendar.delete', 'params' => array($id));
>>
>> which does not work either ...
>>
>> {"version":"1.1","error":{"name":"JSONRPCError","code":999,"message":{"details":null,"logged":false}}}
>>
>> any more ideas? I wonder that I am not asked for a calendar id ...  
>> Or is the uid independant of calendar id?
>>
>> regards
>
> See the logs for errors.

hmmm ... unfortunately no access to logs or is that impossible? My  
Horde installation is by my provider ...

So you are saying that my code is working for you? strange thing is  
that I think it worked before plus I got this one (workaround to  
delete all events in a calendar) which also works and is quite similar:

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;
       }
}

regards



More information about the horde mailing list