C# ownCloud Connector
I recently setup my own ownCloud instance one of my servers as I have trust issues with cloud services like dropbox and box.net. Wherever possible I like to run my own services. After getting ownCloud configured I wanted to see if I could interact with it via API. Specfically I wanted to see if I could retrieve and play music files
Enter OwnCloudMusicClient. This is a C# project which contains a class that can be used to interact with ownCloud instances(OcClient). If I have more time and interest I might extend the API to do more than just download music files
A Download containing the class and a bare-bones console application which shows how to use it is available at the bottom of the page.
Note: Nextcloud has taken the place of OwnCloud in my environment. I have not tested this against newer OwnCloud or NextCloud installations
References
- ownCloud - Personal Cloud [ownCloud.org]
- ownCloud Developer Center [owncloud.org]
- ownCloud API [PHP] [api.owncloud.org]
- ownCloud External API [PHP] [doc.owncloud.org]
- ownCloud WebService API [apps.owncloud.org]
- Open Collaboration Services API Specification [freedesktop.org]
- social desktop - home of the OCS API [open-collaboration-services.org]
- Get Hot New Stuff (GHNS) API [apps.owncloud.com]
- Ampache XML API [ampache.org]
- RestSharp [restsharp.org]
- Newtonsoft's JSON.NET [james.newtonking.com]
Which ownCloud API?
When I first started down the path of creating a C# class to interact with ownCloud I was stymied by the various APIs that were available (OCS, GHNI, Ampache). The information is spread out across a number of domains (see the references above) and made it difficult for me to select the best API for my purposes.
In the end I just wirsharked the web UI and mimicked the calls that I captured. That seems to work!
OcClient API Information
Note: This class does depend on both RestSharp and JSON.NET. I rely heavily on these libraries when constructing REST applications and consider my class's dependency on them to be reasonable
The API made available by my ownCloud client class is pretty bare-bones right now:
- Connect & Authenticate (Happens in Class constructor)
- GetAvailableMusic()
- Returns a JSON.NET JObject with the JSON response from ownCloud
(See below for an example of what this JSON looks like)
- GetAudioFile()
- Returns a byte[] of the audio file. This can be written to disk or placed in a memory stream or whatever you want to do with it
How Do I Authenticate to ownCloud?
In case you just need to know how to authenticate against an ownCloud server instance, here is the relevant code from the OcClient class. It looks like cookies factor heavily into the equation:
/*
* Dependencies
*/
using RestSharp;
using Newtonsoft.Json.Linq;
using RestSharp.Contrib;
BaseUrl = baseUrl;
Username = username;
Password = password;
// Setup the RestClient with cookie container and path
Client = new RestClient(baseUrl);
Client.CookieContainer = new System.Net.CookieContainer();
// Authenticate Part 1 (get base cookie)
RestRequest Request = new RestRequest();
Request.RequestFormat = DataFormat.Json;
Request.Method = Method.GET;
var resp = Client.Execute(Request);
// Authenticate Part 2 (get rest of cookies)
Request = new RestRequest("//", Method.POST);
Request.AddParameter("user", Username);
Request.AddParameter("password", Password);
Request.AddParameter("password-clone", Password);
Request.AddParameter("remember_login", 1);
Request.AddParameter("timezone-offset", -7);
var response = Client.Execute(Request);
/*
* At this point we are authenticated to the owncloud instance and make API calls
*/
Wireshark Analysis notes
Cookies are important to the authentication process. Once authenticated I found that I had to preserve the cookies between requests or I'd get error codes from the ownCloud web service calls. When I examine the 'Cookie:' header in Wireshark I see the following values set:
oc_username=Admin;
oc_token=130fd91187fda9a9654a5b4b4f67b8e8;
oc_remember_login=1;
52121bb7552fb=drsddjhifmkhj47kh3jgqtvgp7
(The weird one that starts with 52121bb7552fb= was retrieved after the first call I make without a username or password. I bet it probably changes with time)
Music Collection JSON Format
Here is what you get back when you call the GetAvailableMusic() API:
{
"artists": [
{
"artist_name": "Of Monsters And Men",
"artist_id": "1"
}
],
"albums": [
{
"album_name": "My Head Is An Animal",
"album_artist": "1",
"album_id": "1"
}
],
"songs": [
{
"song_id": "1",
"song_name": "Little Talks",
"song_artist": "1",
"song_album": "1",
"song_path": "/06 Little Talks.mp3",
"song_user": "Admin",
"song_length": "0",
"song_track": "6",
"song_size": "0",
"song_playcount": "7",
"song_lastplayed": "1377041032"
}
]
}
Download
If you want to take a look at the code, you can download the archive here. Open the sln or csproj file to find the class. Source is MIT licensed so you can make effective use of it wherever you choose.