iCloud Caldav 连接以获取日历

Posted

技术标签:

【中文标题】iCloud Caldav 连接以获取日历【英文标题】:ICloud Caldav connection to get calendars 【发布时间】:2018-11-19 10:36:11 【问题描述】:

我正在尝试连接到 iCloud 日历并解析事件,如果我使用公共日历 url 并且它工作正常,我可以做到这一点。但是这样做我无法更新我需要CalDav 连接的事件。

我很挣扎,因为这里的大多数示例都返回 404 Not Found。

任何人都可以在 C# 中指导我“ICloud Caldav 连接以获取日历”示例或工作示例。

请记住,对于上述内容,我的帐户只有 UsernamePassword,因此我必须加载日历列表。

【问题讨论】:

【参考方案1】:

发现this的文章对完成任务很有帮助:

示例代码:

static string calendarURI = "https://caldav.icloud.com/";
    static string username = "abc@icloud.com";
    static string password = "xxxx-xxxx-xxxx-xxxx";
    //static string content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><propfind xlmns=\"DAV:\"><allprop/></propfind>";
    static string content = "<propfind xmlns='DAV:'><prop><current-user-principal/></prop></propfind>";

public async static void GetCalendars()
    

        try
        
            ResponseStream = ExectueMethod(username, password, calendarURI, "PROPFIND", null, content, "application/x-www-form-urlencoded","0");

            XmlDocument = new XmlDocument();
            XmlDocument.Load(ResponseStream);
            string xmlInner = XmlDocument.InnerXml;

            XmlDocument innerXmlDocument = new XmlDocument();
            innerXmlDocument.LoadXml(xmlInner);

            XmlNode statusCheck = innerXmlDocument.GetElementsByTagName("status")[0];
            if (statusCheck != null)
            
                string status = statusCheck.InnerText.Trim();
                if (status == "HTTP/1.1 200 OK")
                
                    XmlNode tag = innerXmlDocument.GetElementsByTagName("current-user-principal")[0];
                    if (tag != null)
                    
                        XmlNode taghref = tag.ChildNodes[0];
                        if (taghref != null)
                        
                            string href = taghref.InnerText.Trim();

                            string baseUrl = "https://caldav.icloud.com" + href;

                            Console.WriteLine("BASSE URL :" + baseUrl);
                            content = "<propfind xmlns='DAV:' xmlns:cd='urn:ietf:params:xml:ns:caldav'><prop><cd:calendar-home-set/></prop></propfind>";
                            ResponseStream = ExectueMethod(username, password, baseUrl, "PROPFIND", null, content, "application/x-www-form-urlencoded","0");

                            XmlDocument = new XmlDocument();
                            XmlDocument.Load(ResponseStream);
                            xmlInner = XmlDocument.InnerXml;

                            innerXmlDocument = new XmlDocument();
                            innerXmlDocument.LoadXml(xmlInner);
                            tag = innerXmlDocument.GetElementsByTagName("calendar-home-set")[0];
                            if (tag != null)
                            
                                taghref = tag.ChildNodes[0];
                                if (taghref != null)
                                
                                    string calURL = taghref.InnerText.Trim();
                                    Console.WriteLine("CALENDER URL :" + calURL);
                                    content = "<propfind xmlns='DAV:'><prop><displayname/><getctag />calendar-data</prop></propfind>";

                                    ResponseStream = ExectueMethod(username, password, calURL, "PROPFIND", null, content, "application/x-www-form-urlencoded","1");
                                    XmlDocument = new XmlDocument();
                                    XmlDocument.Load(ResponseStream);
                                    xmlInner = XmlDocument.InnerXml;

                                    innerXmlDocument = new XmlDocument();
                                    innerXmlDocument.LoadXml(xmlInner);
                                    int xx = 0;

                                    foreach (XmlNode row in innerXmlDocument.GetElementsByTagName("response"))
                                    
                                        if (xx > 0)
                                        
                                            string calhrefUrlfinal = row.InnerXml.Remove(row.InnerXml.IndexOf("</href>"));
                                            calhrefUrlfinal = calhrefUrlfinal.Replace("<href xmlns=\"DAV:\">", "");
                                            string Calname = row.InnerXml.Remove(row.InnerXml.IndexOf("</displayname>"));
                                            Calname = Calname.Remove(0, Calname.IndexOf("<displayname>")).Replace("<displayname>", "").Trim();

                                            string statusx = row.InnerXml.Remove(row.InnerXml.IndexOf("</status>"));
                                            statusx = statusx.Remove(0, statusx.IndexOf("<status>")).Replace("<status>", "").Trim();

                                            if (statusx == "HTTP/1.1 200 OK")
                                            
                                                Console.Write("THIS IS VALID CAL!");
                                                // ADD THIS CAL TO LIST TO SHOW!
                                                content = "<propfind xmlns='DAV:'><prop><calendar-data/><getctag /></prop></propfind>";

                                                ResponseStream = ExectueMethod(username, password, calhrefUrlfinal, "PROPFIND", null, content, "application/x-www-form-urlencoded", "1");
                                                XmlDocument = new XmlDocument();
                                                XmlDocument.Load(ResponseStream);
                                                xmlInner = XmlDocument.InnerXml;

                                                XmlDocument icsSoc = new XmlDocument();
                                                icsSoc.LoadXml(xmlInner);

                                                foreach (XmlNode ics in icsSoc.GetElementsByTagName("href"))
                                                
                                                    string t = ics.InnerText.Trim();
                                                    if (t.Contains(".ics"))
                                                    
                                                        DownloadICS(t, Calname + ".ics");
                                                        break;
                                                    
                                                

                                            

                                        
                                        xx = xx + 1;
                                    

                                
                            
                        
                    
                
            
        
        catch (Exception ex)
         
    

       private static void DownloadICS(string pathUri, string fileNames)
    
        WebClient request = new WebClient();
        request.Credentials = new NetworkCredential(username, password);

        Byte[] data = request.DownloadData(pathUri);
        var str = System.Text.Encoding.Default.GetString(data);
        string path = "icloudCalenders\\" + fileNames.Substring(fileNames.LastIndexOf(" / ") + 1);

        FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
        fs.Write(data, 0, data.Length);
        fs.Close();

    

private static Stream ExectueMethod(string username, string password, string caldevURI, string methodName, WebHeaderCollection headers, string content, string contentType,string depth)
    
        HttpWebRequest httpGetRequest = (HttpWebRequest)WebRequest.Create(caldevURI);
        httpGetRequest.Credentials = new NetworkCredential(username, password);
        httpGetRequest.PreAuthenticate = true;
        httpGetRequest.Method = methodName;
        httpGetRequest.Headers.Add("Depth", depth);
        httpGetRequest.Headers.Add("Authorization", username);

        //httpGetRequest.UserAgent = "DAVKit/3.0.6 (661); CalendarStore/3.0.8 (860); iCal/3.0.8 (1287); Mac OS X/10.5.8 (9L31a)";
        httpGetRequest.UserAgent = "curl/7.37.0";
        if (!string.IsNullOrWhiteSpace(contentType))
        
            httpGetRequest.ContentType = contentType;
        


        using (var streamWriter = new StreamWriter(httpGetRequest.GetRequestStream()))
        
            string data = content;

            streamWriter.Write(data);
        

        //Stream requestStream = httpGetRequest.GetRequestStream();
        //requestStream.Write(optionsArray, 0, optionsArray.Length);
        //requestStream.Close();

        HttpWebResponse httpGetResponse = (HttpWebResponse)httpGetRequest.GetResponse();
        Stream responseStream = httpGetResponse.GetResponseStream();

        return responseStream;
    

【讨论】:

以上是关于iCloud Caldav 连接以获取日历的主要内容,如果未能解决你的问题,请参考以下文章

CalDAV 请求 gGt iCloud 日历事件

从 iCloud 获取 CalDAV 事件返回“403 Forbidden”

iCloud日历删除事件请求不适用于caldav

如何从 Caldav 客户端为 iCloud 日历删除重复的事件条目

CALDAV 在 icloud 中添加带有注释的事件

是否有 C++ CalDav 协议库可以连接到 iCloud//Yahoo [关闭]