├── .gitignore ├── LICENSE ├── README.md ├── email_lookup.md ├── examples ├── ApiExample.cpp │ ├── bin │ │ └── .gitkeep │ ├── build │ │ └── vs2005 │ │ │ ├── OhlohApiExample.sln │ │ │ └── OhlohApiExample.vcproj │ ├── compile.sh │ ├── include │ │ ├── HTTPDownload.h │ │ ├── TCPSocket.h │ │ ├── main.h │ │ ├── md5.h │ │ ├── tinystr.h │ │ └── tinyxml.h │ ├── src │ │ ├── ApiExample │ │ ├── HTTPDownload.cpp │ │ ├── TCPSocket.cpp │ │ ├── main.cpp │ │ ├── makefile │ │ ├── md5.cpp │ │ ├── tinystr.cpp │ │ ├── tinyxml.cpp │ │ ├── tinyxmlerror.cpp │ │ └── tinyxmlparser.cpp │ └── temp.xml ├── ApiExample.java ├── README.md ├── account_sample.pl ├── account_sample.py ├── account_sample.rb ├── account_sample.sh └── oauth2 │ ├── README.md │ └── ohloh_oauth2_sinatra.rb └── reference ├── account.md ├── activity_fact.md ├── affiliated_committers.md ├── analysis.md ├── code_location.md ├── contributor_fact.md ├── contributor_language_fact.md ├── enlistment.md ├── factoid.md ├── kudo.md ├── kudo_score.md ├── language.md ├── organization-collection.md ├── organization.md ├── outside_committers.md ├── outside_projects.md ├── portfolio_projects.md ├── position.md ├── project.md ├── size_fact.md ├── stack.md └── stack_entry.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2025 Black Duck Software, Inc. and its contributors. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Open Hub API Documentation 2 | 3 | ## Welcome 4 | 5 | The Open Hub API is a free, REST-based programming interface to the Black Duck Open Hub open source directory. You can use the Open Hub API to create your own applications and web services based on Open Hub data. 6 | 7 | ## Getting Help 8 | 9 | This page contains important summary information to help you get started. In-depth online documentation is available, linked by the table of contents below. 10 | 11 | Some sample code can be found on the [Examples](examples/) page. For questions not covered in the documenation, the [Open Hub Technical Issues Help](https://community.blackduck.com/s/topic/0TO2H000000gHS1WAM/black-duck-open-hub-help) can provide additional help. 12 | 13 | Send bug reports to info@openhub.net. 14 | 15 | ## Table of Contents 16 | + [Lookup By Email](email_lookup.md) 17 | + [Using OAuth with the Open Hub API](examples/oauth2) 18 | + [Examples](examples/) 19 | + Open Hub API Reference 20 | - [Account](reference/account.md) 21 | - [Account News](reference/news.md) 22 | - [ActivityFact](reference/activity_fact.md) 23 | - [AffiliatedCommitters](reference/affiliated_committers.md) 24 | - [Analysis](reference/analysis.md) 25 | - [ContributorFact](reference/contributor_fact.md) 26 | - [ContributorLanguageFact](reference/contributor_language_fact.md) 27 | - [Enlistment](reference/enlistment.md) 28 | - [Factoid](reference/factoid.md) 29 | - [Kudo](reference/kudo.md) 30 | - [KudoScore](reference/kudo_score.md) 31 | - [Language](reference/language.md) 32 | - [Message](reference/message.md) 33 | - [Organization](reference/organization.md) 34 | - [Organization-collection](reference/organization-collection.md) 35 | - [OutsideCommitters](reference/outside_committers.md) 36 | - [OutsideProjects](reference/outside_projects.md) 37 | - [PortfolioProjects](reference/portfolio_projects.md) 38 | - [Position](reference/position.md) 39 | - [Project](reference/project.md) 40 | - [Repository](reference/repository.md) 41 | - [SizeFact](reference/size_fact.md) 42 | - [Stack](reference/stack.md) 43 | - [StackEntry](reference/stack_entry.md) 44 | + [API Use Agreement](http://blog.openhub.net/terms-2/) 45 | + [Apply for an API Key](https://www.openhub.net/accounts/me/api_keys/new) 46 | + [API Key Status](https://www.openhub.net/accounts/me/api_keys) 47 | 48 | ## Terms of Use 49 | 50 | The Open Hub API has some restrictions. Please review the complete [Terms of Use](https://community.blackduck.com/s/article/Black-Duck-Open-Hub-API-Use-Agreement) before you begin. 51 | 52 | We ask that you cite Open Hub in publications that use our data. Please include a link to https://www.openhub.net on your web pages. 53 | 54 | Our terms require you to provide a link back to our site. While you’re free to use any method you’d prefer, we’ve provided this small button for your convenience: ![Open Hub Button](https://www.openhub.net/images/badges/mini.gif) 55 | 56 | We recommend linking to our home page. The following html will link the small badge to our home page: 57 | 58 | ```html 59 | 60 | ``` 61 | 62 | ## API Key 63 | 64 | Before you can access the Open Hub API, you must [register your application](https://www.openhub.net/accounts/me/api_keys/new) and obtain an API key. Bandwidth will initially be limited to 1,000 requests per API key per day. 65 | 66 | An API Key should be unique to each application that accesses the Open Hub API. You can register up to five applications. 67 | 68 | It is important not to share API keys. In order to access or modify account data, your application must be granted permission by an individual Open Hub account holder. This permission is granted on a per-key basis. 69 | 70 | You can [register a new application](https://www.openhub.net/accounts/me/api_keys/new) or [view the status](https://www.openhub.net/accounts/me/api_keys) of your existing applications online. 71 | 72 | If you have special requirements for additional keys, or if you are interested in building a large-scale application, please contact us at info@openhub.net. 73 | 74 | ## OAuth Impersonation 75 | 76 | The standard Open Hub API allows read-only access to Open Hub data. 77 | 78 | Using OAuth, you can impersonate an Open Hub account while accessing the Open Hub API. This enables you to write to the Open Hub database, and also to access or modify private account information. You must first be granted permission to do this by an Open Hub account holder. 79 | 80 | You can read more at [Using OAuth with the Open Hub API](examples/oauth2#using-oauth-20). 81 | 82 | ## Forming a Request 83 | 84 | The Open Hub API returns XML-formatted data in response to HTTP GET requests. 85 | 86 | The design concept is that for each web page on Open Hub, there may be an equivalent XML-formatted version of the page. Most pages on the Black Duck Open Hub have an XML representation. 87 | 88 | You must do three things to receive an XML-formatted response: 89 | 90 | 1. Append a `.xml` extension to the basic URL. For example, instead of `https://www.openhub.net/p/1`, which returns an HTML page, you would request `https://www.openhub.net/p/1.xml`. 91 | 2. Provide your API Key as an HTTP parameter. Your request will be forbidden without a valid `api_key`. 92 | 93 | For example, to view the project with ID=1 as XML, using an example API key, the complete URL would be: 94 | 95 | ``` 96 | https://www.openhub.net/p/1.xml?api_key=01234567890123456789 97 | ``` 98 | 99 | For the sake of brevity, the `api_key` parameter will be omitted from the examples in this documentation. Remember to always include it in your actual queries. 100 | 101 | Note that the Open Hub API previously required the use of a version parameter `v`. This is no longer required, and will be ignored. 102 | 103 | ## XML Response Format 104 | 105 | A sample response to a project request might be: 106 | 107 | ```xml 108 | 109 | 110 | success 111 | 112 | 113 | 1 114 | Subversion 115 | 2006-10-10T15:51:31Z 116 | 2007-08-22T17:31:17Z 117 | Subversion has rapidly become the version control standard.... 118 | http://subversion.tigris.org/ 119 | http://subversion.tigris.org/project_packages.html 120 | 121 | 1096 122 | 51898 123 | 124 | 51898 125 | 1 126 | 2007-07-12T12:21:11Z 127 | 2007-07-12T12:18:54Z 128 | 2001-08-01T00:00:00Z 129 | 2007-07-01T00:00:00Z 130 | 55 131 | 319283 132 | 7 133 | C/C++ 134 | 135 | 136 | 137 | 138 | ``` 139 | 140 | All XML returned from the Open Hub API will be contained within a root element called ``, which will always contain a `` element. 141 | 142 | The `` element will contain either `success` or `failed`. 143 | 144 | When the `` value is `success`, the HTTP response code will be `200`, and the `` element contains the data you requested. 145 | 146 | If the `status` is `failed`, then the HTTP response code will be set appropriately (usually Bad Request or Not Found), and an `` element will be present containing human-readable help text. For example: 147 | 148 | ```xml 149 | 150 | 151 | failed 152 | A valid api_key is required to access this URL. 153 | 154 | ``` 155 | 156 | Details about this project response can be found in the Open Hub API Reference [project page](reference/project.md). 157 | 158 | ## Collection Requests 159 | 160 | ### Collection Request Parameters 161 | 162 | + __query__ - Results will be filtered by the provided string. Only items that contain the query string in their names or descriptions will be returned. Filtering is case insenstive. Only alphanumeric characters are accepted. All non-alphanumeric characters will be replaced by spaces. Filtering is not available on all API methods, and the searched text depends on the type of object requested. Check the reference documentation for specifics. 163 | + __sort__ - Controls the sort order of the returned results. Typical supported values are name, created_at, and updated_at. The specific sort options available depend on the type of object requested, so check to the reference documentation for specifics. _API does not support reverse sorting_. 164 | + __page__ - In most cases, the Open Hub API returns at most 25 items per request. Pass this parameter to request subsequent items beyond the first page. This parameter is _one-based_, with a default value of 1. If you pass a value outside the range of available pages, you will receive the first page. 165 | 166 | For example, to get the second page of projects containing “java” or “Java” in their titles, descriptions, or tags, you would request: 167 | 168 | ``` 169 | GET https://www.openhub.net/p.xml?query=java&page=2 170 | ``` 171 | 172 | ### Collection Response XML Format 173 | 174 | Some results will contain a collection of values. When this happens, the `` element will contain some additional elements: 175 | 176 | + __items_returned__ - The number of items returned in this response. 177 | + __items_available__ - The total number of database items matching the query, including those already returned. 178 | + __first_item_position__ - The zero-based index of the first item returned 179 | 180 | For example, the response to `https://www.openhub.net/p.xml` might begin: 181 | 182 | ```xml 183 | 184 | success 185 | 25 186 | 7056 187 | 0 188 | 189 | 190 | 9 191 | Mozilla Firefox 192 | .... 193 | ``` 194 | 195 | - - - 196 | Copyright 2025 Black Duck Software, Inc. Unless otherwise marked, this work is licensed under a [Creative Commons Attribution 3.0 Unported License](http://creativecommons.org/licenses/by/3.0/). 197 | -------------------------------------------------------------------------------- /email_lookup.md: -------------------------------------------------------------------------------- 1 | ## Lookup By Email 2 | 3 | The Open Hub API allows you to retrieve an [Account](reference/account.md) using the MD5 hash of the account’s email address. 4 | 5 | You can pass the MD5 hash of an email address in any URL that normally expects an Account ID. 6 | 7 | This is useful if you know someone’s email address, but do not know the Open Hub account ID. This might be the case if you are hosting a web site with registered users who have supplied their email addresses. With the Open Hub API, you can easily find Open Hub statistics about your registered users. 8 | 9 | For example, here’s how to find the account data for `info@openhub.net`: 10 | + Generate the MD5 hash for `info@openhub.net`. From a irb shell you can do this simply: 11 | ```shell 12 | require 'digest' 13 | Digest::MD5.hexdigest('info@openhub.net').to_s 14 | f1c4c8746d8e42872f6db32977ad5d61 15 | ``` 16 | 17 | + Pass this hash in place of the account ID in the normal http request: 18 | ```shell 19 | $ curl https://www.openhub.net/accounts/f1c4c8746d8e42872f6db32977ad5d61.xml?api_key= 20 | ``` 21 | 22 | Open Hub does not publish email addresses. You must already know the email address of the account you are looking for. Because the search is done using the MD5 hash of the email address, the email address comparison is case sensitive and must match exactly. 23 | -------------------------------------------------------------------------------- /examples/ApiExample.cpp/bin/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackducksoftware/ohloh_api/c369980fca22b7724371c95e2837f830ad51983e/examples/ApiExample.cpp/bin/.gitkeep -------------------------------------------------------------------------------- /examples/ApiExample.cpp/build/vs2005/OhlohApiExample.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 9.00 3 | # Visual Studio 2005 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenHubApiExample", "OpenHubApiExample.vcproj", "{EA66C001-B006-4DBA-9542-A5E887BA420C}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | debug|Win32 = debug|Win32 9 | release|Win32 = release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {EA66C001-B006-4DBA-9542-A5E887BA420C}.debug|Win32.ActiveCfg = debug|Win32 13 | {EA66C001-B006-4DBA-9542-A5E887BA420C}.debug|Win32.Build.0 = debug|Win32 14 | {EA66C001-B006-4DBA-9542-A5E887BA420C}.release|Win32.ActiveCfg = release|Win32 15 | {EA66C001-B006-4DBA-9542-A5E887BA420C}.release|Win32.Build.0 = release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /examples/ApiExample.cpp/build/vs2005/OhlohApiExample.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 14 | 15 | 16 | 17 | 18 | 26 | 29 | 32 | 35 | 38 | 41 | 57 | 60 | 63 | 66 | 79 | 82 | 88 | 91 | 94 | 97 | 100 | 103 | 106 | 107 | 115 | 118 | 121 | 124 | 127 | 130 | 139 | 142 | 145 | 148 | 157 | 160 | 163 | 166 | 169 | 172 | 175 | 178 | 181 | 182 | 183 | 184 | 185 | 186 | 191 | 194 | 195 | 198 | 199 | 202 | 203 | 206 | 207 | 210 | 211 | 214 | 215 | 218 | 219 | 222 | 223 | 224 | 229 | 232 | 233 | 236 | 237 | 240 | 241 | 244 | 245 | 248 | 249 | 252 | 253 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | -------------------------------------------------------------------------------- /examples/ApiExample.cpp/compile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # The MIT License (MIT) 3 | # 4 | # Copyright (c) 2013 Lars Wesselius 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | 24 | cd src/ 25 | make 26 | -------------------------------------------------------------------------------- /examples/ApiExample.cpp/include/HTTPDownload.h: -------------------------------------------------------------------------------- 1 | /* 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2013 Lars Wesselius 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | */ 24 | 25 | #ifndef __HTTPDOWNLOAD_H__ 26 | #define __HTTPDOWNLOAD_H__ 27 | 28 | #include "TCPSocket.h" 29 | 30 | #include 31 | #include 32 | 33 | class HTTPDownload 34 | { 35 | public: 36 | HTTPDownload(void) { } 37 | virtual ~HTTPDownload(void) { } 38 | 39 | bool start(const std::string &url); 40 | void stop(void); 41 | 42 | protected: 43 | bool _parseHeader(const std::string &header); 44 | bool _download(const std::string &url); 45 | 46 | TCPSocket *mSocket; 47 | std::ofstream mFile; 48 | }; 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /examples/ApiExample.cpp/include/TCPSocket.h: -------------------------------------------------------------------------------- 1 | /* 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2013 Lars Wesselius 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | */ 24 | 25 | #ifndef __TCP_SOCKET_H__ 26 | #define __TCP_SOCKET_H__ 27 | 28 | 29 | #include 30 | 31 | class TCPSocket 32 | { 33 | public: 34 | TCPSocket(void); 35 | ~TCPSocket(void); 36 | 37 | void connect(const std::string &server, const int &port); 38 | void disconnect(void); 39 | bool connected(void) { return mSocket; } 40 | 41 | void send(const std::string &msg); 42 | int recieve(std::string &ret); 43 | bool eof(void) { return mEOF; } 44 | 45 | protected: 46 | int mSocket; 47 | bool mEOF; 48 | }; 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /examples/ApiExample.cpp/include/main.h: -------------------------------------------------------------------------------- 1 | /* 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2013 Lars Wesselius 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | */ 24 | 25 | #ifndef __MAIN_H__ 26 | #define __MAIN_H__ 27 | 28 | #if defined( __WIN32__ ) || defined( _WIN32 ) 29 | # define OS_WINDOWS 30 | # include 31 | #else 32 | # define OS_LINUX 33 | # include 34 | # include 35 | # include 36 | # include 37 | # include 38 | # include 39 | # include 40 | # include 41 | # include 42 | #endif 43 | 44 | #include 45 | #include 46 | 47 | 48 | std::pair parseCommandLine(int argc, const char * argv[]); 49 | void parseAndShowResult(); 50 | 51 | #endif 52 | 53 | -------------------------------------------------------------------------------- /examples/ApiExample.cpp/include/md5.h: -------------------------------------------------------------------------------- 1 | // MD5.CC - source code for the C++/object oriented translation and 2 | // modification of MD5. 3 | 4 | // Translation and modification (c) 1995 by Mordechai T. Abzug 5 | 6 | // This translation/ modification is provided "as is," without express or 7 | // implied warranty of any kind. 8 | 9 | // The translator/ modifier does not claim (1) that MD5 will do what you think 10 | // it does; (2) that this translation/ modification is accurate; or (3) that 11 | // this software is "merchantible." (Language for this disclaimer partially 12 | // copied from the disclaimer below). 13 | 14 | /* based on: 15 | 16 | MD5.H - header file for MD5C.C 17 | MDDRIVER.C - test driver for MD2, MD4 and MD5 18 | 19 | Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All 20 | rights reserved. 21 | 22 | License to copy and use this software is granted provided that it 23 | is identified as the "RSA Data Security, Inc. MD5 Message-Digest 24 | Algorithm" in all material mentioning or referencing this software 25 | or this function. 26 | 27 | License is also granted to make and use derivative works provided 28 | that such works are identified as "derived from the RSA Data 29 | Security, Inc. MD5 Message-Digest Algorithm" in all material 30 | mentioning or referencing the derived work. 31 | 32 | RSA Data Security, Inc. makes no representations concerning either 33 | the merchantability of this software or the suitability of this 34 | software for any particular purpose. It is provided "as is" 35 | without express or implied warranty of any kind. 36 | 37 | These notices must be retained in any copies of any part of this 38 | documentation and/or software. 39 | 40 | */ 41 | 42 | #include 43 | #include 44 | #include 45 | 46 | using namespace std; 47 | 48 | class MD5 { 49 | 50 | public: 51 | // methods for controlled operation: 52 | MD5 (); // simple initializer 53 | void update (unsigned char *input, unsigned int input_length); 54 | void update (istream& stream); 55 | void update (ifstream& stream); 56 | void finalize (); 57 | 58 | // constructors for special circumstances. All these constructors finalize 59 | // the MD5 context. 60 | MD5 (unsigned char *string); // digest string, finalize 61 | MD5 (istream& stream); // digest stream, finalize 62 | MD5 (ifstream& stream); // digest stream, close, finalize 63 | 64 | // methods to acquire finalized result 65 | unsigned char *raw_digest (); // digest as a 16-byte binary array 66 | char * hex_digest (); // digest as a 33-byte ascii-hex string 67 | friend ostream& operator<< (ostream&, MD5 context); 68 | 69 | 70 | 71 | private: 72 | 73 | // first, some types: 74 | typedef unsigned int uint4; // assumes integer is 4 words long 75 | typedef unsigned short int uint2; // assumes short integer is 2 words long 76 | typedef unsigned char uint1; // assumes char is 1 word long 77 | 78 | // next, the private data: 79 | uint4 state[4]; 80 | uint4 count[2]; // number of *bits*, mod 2^64 81 | uint1 buffer[64]; // input buffer 82 | uint1 digest[16]; 83 | uint1 finalized; 84 | 85 | // last, the private methods, mostly static: 86 | void init (); // called by all constructors 87 | void transform (uint1 *buffer); // does the real update work. Note 88 | // that length is implied to be 64. 89 | 90 | static void encode (uint1 *dest, uint4 *src, uint4 length); 91 | static void decode (uint4 *dest, uint1 *src, uint4 length); 92 | static void memcpy (uint1 *dest, uint1 *src, uint4 length); 93 | static void memset (uint1 *start, uint1 val, uint4 length); 94 | 95 | static inline uint4 rotate_left (uint4 x, uint4 n); 96 | static inline uint4 F (uint4 x, uint4 y, uint4 z); 97 | static inline uint4 G (uint4 x, uint4 y, uint4 z); 98 | static inline uint4 H (uint4 x, uint4 y, uint4 z); 99 | static inline uint4 I (uint4 x, uint4 y, uint4 z); 100 | static inline void FF (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, 101 | uint4 s, uint4 ac); 102 | static inline void GG (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, 103 | uint4 s, uint4 ac); 104 | static inline void HH (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, 105 | uint4 s, uint4 ac); 106 | static inline void II (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, 107 | uint4 s, uint4 ac); 108 | 109 | }; 110 | -------------------------------------------------------------------------------- /examples/ApiExample.cpp/include/tinystr.h: -------------------------------------------------------------------------------- 1 | /* 2 | www.sourceforge.net/projects/tinyxml 3 | Original file by Yves Berquin. 4 | 5 | This software is provided 'as-is', without any express or implied 6 | warranty. In no event will the authors be held liable for any 7 | damages arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any 10 | purpose, including commercial applications, and to alter it and 11 | redistribute it freely, subject to the following restrictions: 12 | 13 | 1. The origin of this software must not be misrepresented; you must 14 | not claim that you wrote the original software. If you use this 15 | software in a product, an acknowledgment in the product documentation 16 | would be appreciated but is not required. 17 | 18 | 2. Altered source versions must be plainly marked as such, and 19 | must not be misrepresented as being the original software. 20 | 21 | 3. This notice may not be removed or altered from any source 22 | distribution. 23 | */ 24 | 25 | /* 26 | * THIS FILE WAS ALTERED BY Tyge Lovset, 7. April 2005. 27 | * 28 | * - completely rewritten. compact, clean, and fast implementation. 29 | * - sizeof(TiXmlString) = pointer size (4 bytes on 32-bit systems) 30 | * - fixed reserve() to work as per specification. 31 | * - fixed buggy compares operator==(), operator<(), and operator>() 32 | * - fixed operator+=() to take a const ref argument, following spec. 33 | * - added "copy" constructor with length, and most compare operators. 34 | * - added swap(), clear(), size(), capacity(), operator+(). 35 | */ 36 | 37 | #ifndef TIXML_USE_STL 38 | 39 | #ifndef TIXML_STRING_INCLUDED 40 | #define TIXML_STRING_INCLUDED 41 | 42 | #include 43 | #include 44 | 45 | /* The support for explicit isn't that universal, and it isn't really 46 | required - it is used to check that the TiXmlString class isn't incorrectly 47 | used. Be nice to old compilers and macro it here: 48 | */ 49 | #if defined(_MSC_VER) && (_MSC_VER >= 1200 ) 50 | // Microsoft visual studio, version 6 and higher. 51 | #define TIXML_EXPLICIT explicit 52 | #elif defined(__GNUC__) && (__GNUC__ >= 3 ) 53 | // GCC version 3 and higher.s 54 | #define TIXML_EXPLICIT explicit 55 | #else 56 | #define TIXML_EXPLICIT 57 | #endif 58 | 59 | 60 | /* 61 | TiXmlString is an emulation of a subset of the std::string template. 62 | Its purpose is to allow compiling TinyXML on compilers with no or poor STL support. 63 | Only the member functions relevant to the TinyXML project have been implemented. 64 | The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase 65 | a string and there's no more room, we allocate a buffer twice as big as we need. 66 | */ 67 | class TiXmlString 68 | { 69 | public : 70 | // The size type used 71 | typedef size_t size_type; 72 | 73 | // Error value for find primitive 74 | static const size_type npos; // = -1; 75 | 76 | 77 | // TiXmlString empty constructor 78 | TiXmlString () : rep_(&nullrep_) 79 | { 80 | } 81 | 82 | // TiXmlString copy constructor 83 | TiXmlString ( const TiXmlString & copy) : rep_(0) 84 | { 85 | init(copy.length()); 86 | memcpy(start(), copy.data(), length()); 87 | } 88 | 89 | // TiXmlString constructor, based on a string 90 | TIXML_EXPLICIT TiXmlString ( const char * copy) : rep_(0) 91 | { 92 | init( static_cast( strlen(copy) )); 93 | memcpy(start(), copy, length()); 94 | } 95 | 96 | // TiXmlString constructor, based on a string 97 | TIXML_EXPLICIT TiXmlString ( const char * str, size_type len) : rep_(0) 98 | { 99 | init(len); 100 | memcpy(start(), str, len); 101 | } 102 | 103 | // TiXmlString destructor 104 | ~TiXmlString () 105 | { 106 | quit(); 107 | } 108 | 109 | // = operator 110 | TiXmlString& operator = (const char * copy) 111 | { 112 | return assign( copy, (size_type)strlen(copy)); 113 | } 114 | 115 | // = operator 116 | TiXmlString& operator = (const TiXmlString & copy) 117 | { 118 | return assign(copy.start(), copy.length()); 119 | } 120 | 121 | 122 | // += operator. Maps to append 123 | TiXmlString& operator += (const char * suffix) 124 | { 125 | return append(suffix, static_cast( strlen(suffix) )); 126 | } 127 | 128 | // += operator. Maps to append 129 | TiXmlString& operator += (char single) 130 | { 131 | return append(&single, 1); 132 | } 133 | 134 | // += operator. Maps to append 135 | TiXmlString& operator += (const TiXmlString & suffix) 136 | { 137 | return append(suffix.data(), suffix.length()); 138 | } 139 | 140 | 141 | // Convert a TiXmlString into a null-terminated char * 142 | const char * c_str () const { return rep_->str; } 143 | 144 | // Convert a TiXmlString into a char * (need not be null terminated). 145 | const char * data () const { return rep_->str; } 146 | 147 | // Return the length of a TiXmlString 148 | size_type length () const { return rep_->size; } 149 | 150 | // Alias for length() 151 | size_type size () const { return rep_->size; } 152 | 153 | // Checks if a TiXmlString is empty 154 | bool empty () const { return rep_->size == 0; } 155 | 156 | // Return capacity of string 157 | size_type capacity () const { return rep_->capacity; } 158 | 159 | 160 | // single char extraction 161 | const char& at (size_type index) const 162 | { 163 | assert( index < length() ); 164 | return rep_->str[ index ]; 165 | } 166 | 167 | // [] operator 168 | char& operator [] (size_type index) const 169 | { 170 | assert( index < length() ); 171 | return rep_->str[ index ]; 172 | } 173 | 174 | // find a char in a string. Return TiXmlString::npos if not found 175 | size_type find (char lookup) const 176 | { 177 | return find(lookup, 0); 178 | } 179 | 180 | // find a char in a string from an offset. Return TiXmlString::npos if not found 181 | size_type find (char tofind, size_type offset) const 182 | { 183 | if (offset >= length()) return npos; 184 | 185 | for (const char* p = c_str() + offset; *p != '\0'; ++p) 186 | { 187 | if (*p == tofind) return static_cast< size_type >( p - c_str() ); 188 | } 189 | return npos; 190 | } 191 | 192 | void clear () 193 | { 194 | //Lee: 195 | //The original was just too strange, though correct: 196 | // TiXmlString().swap(*this); 197 | //Instead use the quit & re-init: 198 | quit(); 199 | init(0,0); 200 | } 201 | 202 | /* Function to reserve a big amount of data when we know we'll need it. Be aware that this 203 | function DOES NOT clear the content of the TiXmlString if any exists. 204 | */ 205 | void reserve (size_type cap); 206 | 207 | TiXmlString& assign (const char* str, size_type len); 208 | 209 | TiXmlString& append (const char* str, size_type len); 210 | 211 | void swap (TiXmlString& other) 212 | { 213 | Rep* r = rep_; 214 | rep_ = other.rep_; 215 | other.rep_ = r; 216 | } 217 | 218 | private: 219 | 220 | void init(size_type sz) { init(sz, sz); } 221 | void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; } 222 | char* start() const { return rep_->str; } 223 | char* finish() const { return rep_->str + rep_->size; } 224 | 225 | struct Rep 226 | { 227 | size_type size, capacity; 228 | char str[1]; 229 | }; 230 | 231 | void init(size_type sz, size_type cap) 232 | { 233 | if (cap) 234 | { 235 | // Lee: the original form: 236 | // rep_ = static_cast(operator new(sizeof(Rep) + cap)); 237 | // doesn't work in some cases of new being overloaded. Switching 238 | // to the normal allocation, although use an 'int' for systems 239 | // that are overly picky about structure alignment. 240 | const size_type bytesNeeded = sizeof(Rep) + cap; 241 | const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int ); 242 | rep_ = reinterpret_cast( new int[ intsNeeded ] ); 243 | 244 | rep_->str[ rep_->size = sz ] = '\0'; 245 | rep_->capacity = cap; 246 | } 247 | else 248 | { 249 | rep_ = &nullrep_; 250 | } 251 | } 252 | 253 | void quit() 254 | { 255 | if (rep_ != &nullrep_) 256 | { 257 | // The rep_ is really an array of ints. (see the allocator, above). 258 | // Cast it back before delete, so the compiler won't incorrectly call destructors. 259 | delete [] ( reinterpret_cast( rep_ ) ); 260 | } 261 | } 262 | 263 | Rep * rep_; 264 | static Rep nullrep_; 265 | 266 | } ; 267 | 268 | 269 | inline bool operator == (const TiXmlString & a, const TiXmlString & b) 270 | { 271 | return ( a.length() == b.length() ) // optimization on some platforms 272 | && ( strcmp(a.c_str(), b.c_str()) == 0 ); // actual compare 273 | } 274 | inline bool operator < (const TiXmlString & a, const TiXmlString & b) 275 | { 276 | return strcmp(a.c_str(), b.c_str()) < 0; 277 | } 278 | 279 | inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); } 280 | inline bool operator > (const TiXmlString & a, const TiXmlString & b) { return b < a; } 281 | inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); } 282 | inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); } 283 | 284 | inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; } 285 | inline bool operator == (const char* a, const TiXmlString & b) { return b == a; } 286 | inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); } 287 | inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); } 288 | 289 | TiXmlString operator + (const TiXmlString & a, const TiXmlString & b); 290 | TiXmlString operator + (const TiXmlString & a, const char* b); 291 | TiXmlString operator + (const char* a, const TiXmlString & b); 292 | 293 | 294 | /* 295 | TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString. 296 | Only the operators that we need for TinyXML have been developped. 297 | */ 298 | class TiXmlOutStream : public TiXmlString 299 | { 300 | public : 301 | 302 | // TiXmlOutStream << operator. 303 | TiXmlOutStream & operator << (const TiXmlString & in) 304 | { 305 | *this += in; 306 | return *this; 307 | } 308 | 309 | // TiXmlOutStream << operator. 310 | TiXmlOutStream & operator << (const char * in) 311 | { 312 | *this += in; 313 | return *this; 314 | } 315 | 316 | } ; 317 | 318 | #endif // TIXML_STRING_INCLUDED 319 | #endif // TIXML_USE_STL 320 | -------------------------------------------------------------------------------- /examples/ApiExample.cpp/src/ApiExample: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackducksoftware/ohloh_api/c369980fca22b7724371c95e2837f830ad51983e/examples/ApiExample.cpp/src/ApiExample -------------------------------------------------------------------------------- /examples/ApiExample.cpp/src/HTTPDownload.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2013 Lars Wesselius 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | */ 24 | 25 | #include "HTTPDownload.h" 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #define HTTP_RESPONSE_MAX_SIZE 65536 33 | 34 | /* HTTP/1.0 status codes from RFC1945, provided for reference. */ 35 | /* Successful 2xx. */ 36 | #define HTTP_STATUS_OK 200 37 | #define HTTP_STATUS_CREATED 201 38 | #define HTTP_STATUS_ACCEPTED 202 39 | #define HTTP_STATUS_NO_CONTENT 204 40 | #define HTTP_STATUS_PARTIAL_CONTENTS 206 41 | 42 | /* Redirection 3xx. */ 43 | #define HTTP_STATUS_MULTIPLE_CHOICES 300 44 | #define HTTP_STATUS_MOVED_PERMANENTLY 301 45 | #define HTTP_STATUS_MOVED_TEMPORARILY 302 46 | #define HTTP_STATUS_SEE_OTHER 303 /* from HTTP/1.1 */ 47 | #define HTTP_STATUS_NOT_MODIFIED 304 48 | #define HTTP_STATUS_TEMPORARY_REDIRECT 307 /* from HTTP/1.1 */ 49 | 50 | /* Client error 4xx. */ 51 | #define HTTP_STATUS_BAD_REQUEST 400 52 | #define HTTP_STATUS_UNAUTHORIZED 401 53 | #define HTTP_STATUS_FORBIDDEN 403 54 | #define HTTP_STATUS_NOT_FOUND 404 55 | #define HTTP_STATUS_RANGE_NOT_SATISFIABLE 416 56 | 57 | /* Server errors 5xx. */ 58 | #define HTTP_STATUS_INTERNAL 500 59 | #define HTTP_STATUS_NOT_IMPLEMENTED 501 60 | #define HTTP_STATUS_BAD_GATEWAY 502 61 | #define HTTP_STATUS_UNAVAILABLE 503 62 | 63 | bool HTTPDownload::start(const std::string &url) 64 | { 65 | mSocket = new TCPSocket(); 66 | return _download(url); 67 | } 68 | 69 | void HTTPDownload::stop() 70 | { 71 | delete mSocket; 72 | mSocket = 0; 73 | } 74 | 75 | bool HTTPDownload::_parseHeader(const std::string &header) 76 | { 77 | std::string line = header.substr(0, header.find_first_of('\n')); 78 | size_t index = 0, size = line.size(); 79 | 80 | /* Check the HTTP of the header */ 81 | if (line.compare(0,4, "HTTP") != 0) 82 | return false; 83 | index = 4; 84 | 85 | /* Check for the HTTP version of the header (it may not exist so skip it if its not there)*/ 86 | if (index < size && line[index] == '/') 87 | { 88 | ++index; 89 | while (index < size && isdigit(line[index])) 90 | index++; 91 | if (index < size && line[index] == '.') 92 | index++; 93 | while (index < size && isdigit(line[index])) 94 | index++; 95 | } 96 | if (index < size && line[index] != ' ') 97 | return false; 98 | ++index; 99 | 100 | /* Get the status code */ 101 | if (size - index < 3) 102 | return false; 103 | int status = atoi(line.substr(index, 3).c_str()); 104 | index += 3; 105 | while (index < size && line[index] == ' ') 106 | ++index; 107 | std::string message = line.substr(index); 108 | 109 | /* Parse the status code */ 110 | switch (status) 111 | { 112 | case HTTP_STATUS_BAD_REQUEST: 113 | case HTTP_STATUS_UNAUTHORIZED: 114 | case HTTP_STATUS_FORBIDDEN: 115 | case HTTP_STATUS_NOT_FOUND: 116 | case HTTP_STATUS_INTERNAL: 117 | case HTTP_STATUS_NOT_IMPLEMENTED: 118 | case HTTP_STATUS_BAD_GATEWAY: 119 | case HTTP_STATUS_UNAVAILABLE: 120 | return false; 121 | } 122 | 123 | std::string rest = header; 124 | index = rest.find_first_of('\r'); 125 | std::map settings; 126 | while (index != std::string::npos) 127 | { 128 | rest = rest.substr(index); 129 | if (rest[0] == '\n' && rest[1] == '\r' && rest[2] == '\n') 130 | break; 131 | 132 | std::string line = rest.substr(0,rest.find('\r',1)); 133 | while (line[0] == '\n' || line[0] == '\r' || line[0] == ' ' || line[0] == '\t') 134 | line = line.substr(1); 135 | size_t sep = line.find_first_of(':'); 136 | if (sep != std::string::npos) 137 | { 138 | std::string value = line.substr(sep+1); 139 | while (value[0] == ' ') 140 | value = value.substr(1); 141 | settings.insert(std::make_pair(line.substr(0,sep), value)); 142 | } 143 | index = rest.find('\r', 1); 144 | } 145 | if (((status > 299 && status < 308) && settings.find("Location") != settings.end()) || settings.find("Location") != settings.end()) 146 | { 147 | std::cerr << "[Downloader] Download location has changed to " << settings["Location"] << "\n"; 148 | mFile.close(); 149 | _download(settings["Location"]); 150 | return false; 151 | } 152 | 153 | return true; 154 | } 155 | 156 | bool HTTPDownload::_download(const std::string &url) 157 | { 158 | std::string location; 159 | std::cout << url << std::endl; 160 | 161 | /* Check for correct url type and strip it */ 162 | if (url.compare(0,7,"http://") != 0) 163 | { 164 | if (url.find("://") != std::string::npos) 165 | return false; 166 | location = url; 167 | } 168 | else 169 | { 170 | location = url.substr(7); 171 | } 172 | 173 | /* Get the server and the location of the file */ 174 | std::string::size_type index = location.find_first_of('/'); 175 | std::string::size_type dp = location.find_first_of(':'); 176 | 177 | int port = 80; 178 | if (dp != std::string::npos && dp < index) 179 | { 180 | port = atoi(location.substr(dp+1, index).c_str()); 181 | location = location.erase(dp, index-dp); 182 | index = dp; 183 | } 184 | 185 | std::string server = ""; 186 | std::string fileLocation = ""; 187 | std::string name = ""; 188 | if (index == std::string::npos) 189 | { 190 | server = location; 191 | fileLocation = ""; 192 | } 193 | else 194 | { 195 | server = location.substr(0,index); 196 | name = location.substr(location.find_last_of('/')+1); 197 | fileLocation = location.substr(index+1); 198 | } 199 | 200 | /* Do some error checking and force std names/locations */ 201 | if (server.empty()) 202 | { 203 | server = fileLocation; 204 | fileLocation = ""; 205 | } 206 | if (name.empty()) 207 | name = "index.html"; 208 | 209 | mSocket->connect(server, port); 210 | 211 | if (mSocket->connected()) 212 | { 213 | std::cout << "Connected." << std::endl; 214 | } 215 | else 216 | { 217 | std::cout << "Not connected." << std::endl; 218 | } 219 | 220 | std::cout << "Requesting file.." << std::endl; 221 | /* Send header .. */ 222 | std::stringstream header; 223 | header << "GET /" << fileLocation << " HTTP/1.1\r\n"; 224 | header << "Host: " << server << "\r\n"; 225 | header << "Connection: Close\r\n"; 226 | header << "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n"; 227 | header << "User-Agent: Downloader 0.1 (i686; X11; Linux)\r\n\r\n"; 228 | 229 | mSocket->send(header.str()); 230 | 231 | 232 | std::string buf, httpheader; 233 | /* Recieve the first packet with the http header */ 234 | mSocket->recieve(buf); 235 | 236 | 237 | /* Extract the REAL http header out of all the data */ 238 | short i = 0; 239 | while (!(buf[i] == '\r' && buf[i+1] == '\n' && buf[i+2] == '\r' && buf[i+3] == '\n')) 240 | ++i; 241 | 242 | /* Parse the http header */ 243 | if (!_parseHeader(buf.substr(0,i))) 244 | { 245 | std::cout << buf.substr(0, i) << std::endl; 246 | std::cout << "Request failed. Invalid api key?" << std::endl; 247 | return false; 248 | } 249 | 250 | 251 | /* Open the file which we're going to download */ 252 | mFile.open("temp.xml", std::ios::trunc); 253 | mFile << buf.substr(i+4); 254 | 255 | short ret; 256 | 257 | /* Get the rest of the data */ 258 | while (!mSocket->eof()) 259 | { 260 | //std::cerr << buf; 261 | ret = mSocket->recieve(buf); 262 | mFile << buf; 263 | mFile.flush(); 264 | } 265 | mFile.close(); 266 | 267 | std::cout << "Request completed." << std::endl; 268 | mSocket->disconnect(); 269 | return true; 270 | } 271 | -------------------------------------------------------------------------------- /examples/ApiExample.cpp/src/TCPSocket.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2013 Lars Wesselius 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | */ 24 | 25 | #include "TCPSocket.h" 26 | #include "main.h" 27 | #include 28 | 29 | 30 | #define RESPONSE_MAX_SIZE 65536 31 | 32 | TCPSocket::TCPSocket() 33 | { 34 | mSocket = 0; 35 | mEOF = false; 36 | } 37 | 38 | TCPSocket::~TCPSocket() 39 | { 40 | 41 | } 42 | 43 | void TCPSocket::connect(const std::string &server, const int &port) 44 | { 45 | struct hostent *he; // Host to connect to 46 | struct sockaddr_in server_addr; // Address of the server 47 | 48 | if ((he = gethostbyname(server.c_str())) == NULL) 49 | return; 50 | 51 | if ((mSocket = socket(PF_INET, SOCK_STREAM, 0)) == -1) 52 | return; 53 | 54 | server_addr.sin_family = AF_INET; 55 | server_addr.sin_port = htons(port); 56 | server_addr.sin_addr = *((struct in_addr *)he->h_addr); 57 | memset(server_addr.sin_zero, '\0', sizeof server_addr.sin_zero); 58 | 59 | if (::connect(mSocket,(struct sockaddr *)&server_addr, sizeof server_addr) == -1) 60 | return; 61 | } 62 | 63 | void TCPSocket::disconnect() 64 | { 65 | #ifdef OS_WINDOWS 66 | closesocket(mSocket); 67 | #else 68 | close(mSocket); 69 | #endif 70 | mSocket = 0; 71 | mEOF = false; 72 | } 73 | 74 | void TCPSocket::send(const std::string &msg) 75 | { 76 | int sended = 0; 77 | size_t tosend = msg.size(); 78 | while (sended < tosend) 79 | { 80 | int n; 81 | if ((n = ::send(mSocket, msg.substr(sended).c_str(), tosend-sended, 0)) == -1) 82 | { 83 | mEOF = true; 84 | return; 85 | } 86 | sended += n; 87 | } 88 | } 89 | 90 | int TCPSocket::recieve(std::string &ret) 91 | { 92 | char buffer[RESPONSE_MAX_SIZE]; 93 | int retv; 94 | if ((retv = recv(mSocket, buffer, RESPONSE_MAX_SIZE, 0)) == -1) 95 | { 96 | mEOF = true; 97 | return 0; 98 | } 99 | if (retv == 0) 100 | mEOF = true; 101 | ret = std::string(buffer, retv); 102 | return retv; 103 | } 104 | -------------------------------------------------------------------------------- /examples/ApiExample.cpp/src/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 4 | 5 | */ 6 | 7 | /* 8 | MD5 algorithm implementation 9 | RSA Data Security, Inc. MD5 Message-Digest 10 | Algorithm 11 | 12 | For more details please consult md5.c 13 | */ 14 | #include "main.h" 15 | #include "HTTPDownload.h" 16 | #include "md5.h" 17 | #include "tinyxml.h" 18 | #include 19 | #include 20 | #include 21 | 22 | int main(int argc, const char * argv[]) 23 | { 24 | std::cout << std::endl << "Initializing.." << std::endl; 25 | #ifdef OS_WINDOWS 26 | WSADATA data; 27 | WSAStartup(MAKEWORD(1, 1), &data); 28 | #endif 29 | HTTPDownload * download = new HTTPDownload(); 30 | 31 | std::pair infoPair = parseCommandLine(argc, argv); 32 | 33 | if (infoPair.first.empty() || infoPair.second.empty()) 34 | { 35 | return 1; 36 | } 37 | 38 | std::cout << "Forming request.." << std::endl; 39 | 40 | 41 | std::istringstream str(infoPair.second); 42 | MD5 md5(str); 43 | 44 | std::string urlString = "https://www.openhub.net/accounts/"; 45 | urlString += md5.hex_digest(); 46 | urlString += ".xml?api_key=" + infoPair.first + "&v=1"; 47 | 48 | if (download->start(urlString)) 49 | { 50 | parseAndShowResult(); 51 | } 52 | 53 | std::cout << std::endl << "Press the return key to exit." << std::endl; 54 | std::cin.get(); 55 | return 1; 56 | } 57 | 58 | std::pair parseCommandLine(int argc, const char * argv[]) 59 | { 60 | if (argc == 3) 61 | { 62 | return std::pair(argv[1], argv[2]); 63 | } 64 | else 65 | { 66 | std::cout << "Usage:" << std::endl; 67 | #ifdef OS_WINDOWS 68 | std::cout << "ApiExample.exe [api_key] [user_email]" << std::endl; 69 | #else 70 | std::cout << "./ApiExample [api_key] [user_email]" << std::endl; 71 | #endif 72 | } 73 | 74 | return std::pair("", ""); 75 | } 76 | 77 | void parseAndShowResult() 78 | { 79 | std::cout << "Parsing file." << std::endl; 80 | TiXmlDocument doc("temp.xml"); 81 | doc.LoadFile(); 82 | TiXmlHandle docHandle(&doc); 83 | 84 | TiXmlElement * firstElements = docHandle.FirstChild("response").ToElement(); 85 | 86 | 87 | 88 | TiXmlElement * statusElem = 0; 89 | statusElem = firstElements->FirstChildElement(); 90 | 91 | if (!statusElem) 92 | { 93 | std::cout << "Corrupt file, wrong request made?" << std::endl; 94 | return; 95 | } 96 | 97 | if (std::string(statusElem->GetText()).compare("success") != 0) 98 | { 99 | TiXmlElement * errorElem = firstElements->FirstChildElement("error"); 100 | 101 | std::cout << "Parsing failed with message: " << errorElem->GetText() << std::endl; 102 | return; 103 | } 104 | 105 | TiXmlElement * accountElement = firstElements->FirstChild("result")->FirstChild("account")->ToElement(); 106 | 107 | TiXmlElement * nameElement = 0; 108 | nameElement = accountElement->FirstChildElement("name"); 109 | 110 | if (nameElement == 0) 111 | { 112 | std::cout << "Parsing failed, could not find 'name' element." << std::endl; 113 | return; 114 | } 115 | 116 | std::cout << "Located name: " << nameElement->GetText() << std::endl;; 117 | } 118 | 119 | 120 | -------------------------------------------------------------------------------- /examples/ApiExample.cpp/src/makefile: -------------------------------------------------------------------------------- 1 | COMPILER = g++ 2 | GCFLAGS = -I ../include/ 3 | 4 | all: 5 | ${COMPILER} ${GCFLAGS} -o ../bin/ApiExample main.cpp HTTPDownload.cpp TCPSocket.cpp md5.cpp tinyxml.cpp tinystr.cpp tinyxmlerror.cpp tinyxmlparser.cpp 6 | -------------------------------------------------------------------------------- /examples/ApiExample.cpp/src/md5.cpp: -------------------------------------------------------------------------------- 1 | // MD5.CC - source code for the C++/object oriented translation and 2 | // modification of MD5. 3 | 4 | // Translation and modification (c) 1995 by Mordechai T. Abzug 5 | 6 | // This translation/ modification is provided "as is," without express or 7 | // implied warranty of any kind. 8 | 9 | // The translator/ modifier does not claim (1) that MD5 will do what you think 10 | // it does; (2) that this translation/ modification is accurate; or (3) that 11 | // this software is "merchantible." (Language for this disclaimer partially 12 | // copied from the disclaimer below). 13 | 14 | /* based on: 15 | 16 | MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm 17 | MDDRIVER.C - test driver for MD2, MD4 and MD5 18 | 19 | 20 | Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All 21 | rights reserved. 22 | 23 | License to copy and use this software is granted provided that it 24 | is identified as the "RSA Data Security, Inc. MD5 Message-Digest 25 | Algorithm" in all material mentioning or referencing this software 26 | or this function. 27 | 28 | License is also granted to make and use derivative works provided 29 | that such works are identified as "derived from the RSA Data 30 | Security, Inc. MD5 Message-Digest Algorithm" in all material 31 | mentioning or referencing the derived work. 32 | 33 | RSA Data Security, Inc. makes no representations concerning either 34 | the merchantability of this software or the suitability of this 35 | software for any particular purpose. It is provided "as is" 36 | without express or implied warranty of any kind. 37 | 38 | These notices must be retained in any copies of any part of this 39 | documentation and/or software. 40 | 41 | */ 42 | 43 | 44 | 45 | 46 | 47 | 48 | #include "md5.h" 49 | 50 | #include 51 | #include 52 | #include 53 | 54 | 55 | 56 | 57 | // MD5 simple initialization method 58 | 59 | MD5::MD5(){ 60 | 61 | init(); 62 | 63 | } 64 | 65 | 66 | 67 | 68 | // MD5 block update operation. Continues an MD5 message-digest 69 | // operation, processing another message block, and updating the 70 | // context. 71 | 72 | void MD5::update (uint1 *input, uint4 input_length) { 73 | 74 | uint4 input_index, buffer_index; 75 | uint4 buffer_space; // how much space is left in buffer 76 | 77 | if (finalized){ // so we can't update! 78 | cerr << "MD5::update: Can't update a finalized digest!" << endl; 79 | return; 80 | } 81 | 82 | // Compute number of bytes mod 64 83 | buffer_index = (unsigned int)((count[0] >> 3) & 0x3F); 84 | 85 | // Update number of bits 86 | if ( (count[0] += ((uint4) input_length << 3))<((uint4) input_length << 3) ) 87 | count[1]++; 88 | 89 | count[1] += ((uint4)input_length >> 29); 90 | 91 | 92 | buffer_space = 64 - buffer_index; // how much space is left in buffer 93 | 94 | // Transform as many times as possible. 95 | if (input_length >= buffer_space) { // ie. we have enough to fill the buffer 96 | // fill the rest of the buffer and transform 97 | memcpy (buffer + buffer_index, input, buffer_space); 98 | transform (buffer); 99 | 100 | // now, transform each 64-byte piece of the input, bypassing the buffer 101 | for (input_index = buffer_space; input_index + 63 < input_length; 102 | input_index += 64) 103 | transform (input+input_index); 104 | 105 | buffer_index = 0; // so we can buffer remaining 106 | } 107 | else 108 | input_index=0; // so we can buffer the whole input 109 | 110 | 111 | // and here we do the buffering: 112 | memcpy(buffer+buffer_index, input+input_index, input_length-input_index); 113 | } 114 | 115 | 116 | // MD5 update for istreams. 117 | // Like update for files; see above. 118 | 119 | void MD5::update(istream& stream){ 120 | 121 | unsigned char buffer[1024]; 122 | int len; 123 | 124 | while (stream.good()){ 125 | stream.read((char*)buffer, 1024); // note that return value of read is unusable. 126 | len=stream.gcount(); 127 | update(buffer, len); 128 | } 129 | 130 | } 131 | 132 | 133 | 134 | 135 | 136 | 137 | // MD5 update for ifstreams. 138 | // Like update for files; see above. 139 | 140 | void MD5::update(ifstream& stream){ 141 | 142 | unsigned char buffer[1024]; 143 | int len; 144 | 145 | while (stream.good()){ 146 | stream.read((char*)buffer, 1024); // note that return value of read is unusable. 147 | len=stream.gcount(); 148 | update(buffer, len); 149 | } 150 | 151 | } 152 | 153 | 154 | 155 | 156 | 157 | 158 | // MD5 finalization. Ends an MD5 message-digest operation, writing the 159 | // the message digest and zeroizing the context. 160 | 161 | 162 | void MD5::finalize (){ 163 | 164 | unsigned char bits[8]; 165 | unsigned int index, padLen; 166 | static uint1 PADDING[64]={ 167 | 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 170 | }; 171 | 172 | if (finalized){ 173 | cerr << "MD5::finalize: Already finalized this digest!" << endl; 174 | return; 175 | } 176 | 177 | // Save number of bits 178 | encode (bits, count, 8); 179 | 180 | // Pad out to 56 mod 64. 181 | index = (uint4) ((count[0] >> 3) & 0x3f); 182 | padLen = (index < 56) ? (56 - index) : (120 - index); 183 | update (PADDING, padLen); 184 | 185 | // Append length (before padding) 186 | update (bits, 8); 187 | 188 | // Store state in digest 189 | encode (digest, state, 16); 190 | 191 | // Zeroize sensitive information 192 | memset (buffer, 0, sizeof(*buffer)); 193 | 194 | finalized=1; 195 | 196 | } 197 | 198 | MD5::MD5(istream& stream){ 199 | 200 | init(); // must called by all constructors 201 | update (stream); 202 | finalize(); 203 | } 204 | 205 | 206 | 207 | MD5::MD5(ifstream& stream){ 208 | 209 | init(); // must called by all constructors 210 | update (stream); 211 | finalize(); 212 | } 213 | 214 | 215 | 216 | unsigned char *MD5::raw_digest(){ 217 | 218 | uint1 *s = new uint1[16]; 219 | 220 | if (!finalized){ 221 | cerr << "MD5::raw_digest: Can't get digest if you haven't "<< 222 | "finalized the digest!" <> 8) & 0xff); 410 | output[j+2] = (uint1) ((input[i] >> 16) & 0xff); 411 | output[j+3] = (uint1) ((input[i] >> 24) & 0xff); 412 | } 413 | } 414 | 415 | 416 | 417 | 418 | // Decodes input (unsigned char) into output (UINT4). Assumes len is 419 | // a multiple of 4. 420 | void MD5::decode (uint4 *output, uint1 *input, uint4 len){ 421 | 422 | unsigned int i, j; 423 | 424 | for (i = 0, j = 0; j < len; i++, j += 4) 425 | output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) | 426 | (((uint4)input[j+2]) << 16) | (((uint4)input[j+3]) << 24); 427 | } 428 | 429 | 430 | 431 | 432 | 433 | // Note: Replace "for loop" with standard memcpy if possible. 434 | void MD5::memcpy (uint1 *output, uint1 *input, uint4 len){ 435 | 436 | unsigned int i; 437 | 438 | for (i = 0; i < len; i++) 439 | output[i] = input[i]; 440 | } 441 | 442 | 443 | 444 | // Note: Replace "for loop" with standard memset if possible. 445 | void MD5::memset (uint1 *output, uint1 value, uint4 len){ 446 | 447 | unsigned int i; 448 | 449 | for (i = 0; i < len; i++) 450 | output[i] = value; 451 | } 452 | 453 | 454 | 455 | // ROTATE_LEFT rotates x left n bits. 456 | 457 | inline unsigned int MD5::rotate_left (uint4 x, uint4 n){ 458 | return (x << n) | (x >> (32-n)) ; 459 | } 460 | 461 | 462 | 463 | 464 | // F, G, H and I are basic MD5 functions. 465 | 466 | inline unsigned int MD5::F (uint4 x, uint4 y, uint4 z){ 467 | return (x & y) | (~x & z); 468 | } 469 | 470 | inline unsigned int MD5::G (uint4 x, uint4 y, uint4 z){ 471 | return (x & z) | (y & ~z); 472 | } 473 | 474 | inline unsigned int MD5::H (uint4 x, uint4 y, uint4 z){ 475 | return x ^ y ^ z; 476 | } 477 | 478 | inline unsigned int MD5::I (uint4 x, uint4 y, uint4 z){ 479 | return y ^ (x | ~z); 480 | } 481 | 482 | 483 | 484 | // FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. 485 | // Rotation is separate from addition to prevent recomputation. 486 | 487 | 488 | inline void MD5::FF(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, 489 | uint4 s, uint4 ac){ 490 | a += F(b, c, d) + x + ac; 491 | a = rotate_left (a, s) +b; 492 | } 493 | 494 | inline void MD5::GG(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, 495 | uint4 s, uint4 ac){ 496 | a += G(b, c, d) + x + ac; 497 | a = rotate_left (a, s) +b; 498 | } 499 | 500 | inline void MD5::HH(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, 501 | uint4 s, uint4 ac){ 502 | a += H(b, c, d) + x + ac; 503 | a = rotate_left (a, s) +b; 504 | } 505 | 506 | inline void MD5::II(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, 507 | uint4 s, uint4 ac){ 508 | a += I(b, c, d) + x + ac; 509 | a = rotate_left (a, s) +b; 510 | } 511 | -------------------------------------------------------------------------------- /examples/ApiExample.cpp/src/tinystr.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackducksoftware/ohloh_api/c369980fca22b7724371c95e2837f830ad51983e/examples/ApiExample.cpp/src/tinystr.cpp -------------------------------------------------------------------------------- /examples/ApiExample.cpp/src/tinyxmlerror.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | www.sourceforge.net/projects/tinyxml 3 | Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) 4 | 5 | This software is provided 'as-is', without any express or implied 6 | warranty. In no event will the authors be held liable for any 7 | damages arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any 10 | purpose, including commercial applications, and to alter it and 11 | redistribute it freely, subject to the following restrictions: 12 | 13 | 1. The origin of this software must not be misrepresented; you must 14 | not claim that you wrote the original software. If you use this 15 | software in a product, an acknowledgment in the product documentation 16 | would be appreciated but is not required. 17 | 18 | 2. Altered source versions must be plainly marked as such, and 19 | must not be misrepresented as being the original software. 20 | 21 | 3. This notice may not be removed or altered from any source 22 | distribution. 23 | */ 24 | 25 | 26 | #include "tinyxml.h" 27 | 28 | // The goal of the seperate error file is to make the first 29 | // step towards localization. tinyxml (currently) only supports 30 | // english error messages, but the could now be translated. 31 | // 32 | // It also cleans up the code a bit. 33 | // 34 | 35 | const char* TiXmlBase::errorString[ TIXML_ERROR_STRING_COUNT ] = 36 | { 37 | "No error", 38 | "Error", 39 | "Failed to open file", 40 | "Memory allocation failed.", 41 | "Error parsing Element.", 42 | "Failed to read Element name", 43 | "Error reading Element value.", 44 | "Error reading Attributes.", 45 | "Error: empty tag.", 46 | "Error reading end tag.", 47 | "Error parsing Unknown.", 48 | "Error parsing Comment.", 49 | "Error parsing Declaration.", 50 | "Error document empty.", 51 | "Error null (0) or unexpected EOF found in input stream.", 52 | "Error parsing CDATA.", 53 | "Error when TiXmlDocument added to document, because TiXmlDocument can only be at the root.", 54 | }; 55 | -------------------------------------------------------------------------------- /examples/ApiExample.cpp/src/tinyxmlparser.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | www.sourceforge.net/projects/tinyxml 3 | Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com) 4 | 5 | This software is provided 'as-is', without any express or implied 6 | warranty. In no event will the authors be held liable for any 7 | damages arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any 10 | purpose, including commercial applications, and to alter it and 11 | redistribute it freely, subject to the following restrictions: 12 | 13 | 1. The origin of this software must not be misrepresented; you must 14 | not claim that you wrote the original software. If you use this 15 | software in a product, an acknowledgment in the product documentation 16 | would be appreciated but is not required. 17 | 18 | 2. Altered source versions must be plainly marked as such, and 19 | must not be misrepresented as being the original software. 20 | 21 | 3. This notice may not be removed or altered from any source 22 | distribution. 23 | */ 24 | 25 | 26 | #include 27 | #include 28 | 29 | #include "tinyxml.h" 30 | 31 | //#define DEBUG_PARSER 32 | #if defined( DEBUG_PARSER ) 33 | # if defined( DEBUG ) && defined( _MSC_VER ) 34 | # include 35 | # define TIXML_LOG OutputDebugString 36 | # else 37 | # define TIXML_LOG printf 38 | # endif 39 | #endif 40 | 41 | // Note tha "PutString" hardcodes the same list. This 42 | // is less flexible than it appears. Changing the entries 43 | // or order will break putstring. 44 | TiXmlBase::Entity TiXmlBase::entity[ NUM_ENTITY ] = 45 | { 46 | { "&", 5, '&' }, 47 | { "<", 4, '<' }, 48 | { ">", 4, '>' }, 49 | { """, 6, '\"' }, 50 | { "'", 6, '\'' } 51 | }; 52 | 53 | // Bunch of unicode info at: 54 | // http://www.unicode.org/faq/utf_bom.html 55 | // Including the basic of this table, which determines the #bytes in the 56 | // sequence from the lead byte. 1 placed for invalid sequences -- 57 | // although the result will be junk, pass it through as much as possible. 58 | // Beware of the non-characters in UTF-8: 59 | // ef bb bf (Microsoft "lead bytes") 60 | // ef bf be 61 | // ef bf bf 62 | 63 | const unsigned char TIXML_UTF_LEAD_0 = 0xefU; 64 | const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; 65 | const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; 66 | 67 | const int TiXmlBase::utf8ByteTable[256] = 68 | { 69 | // 0 1 2 3 4 5 6 7 8 9 a b c d e f 70 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00 71 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10 72 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x20 73 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x30 74 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40 75 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x50 76 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60 77 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x70 End of ASCII range 78 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80 0x80 to 0xc1 invalid 79 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90 80 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0 81 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0 82 | 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0 0xc2 to 0xdf 2 byte 83 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0 84 | 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xe0 0xe0 to 0xef 3 byte 85 | 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid 86 | }; 87 | 88 | 89 | void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ) 90 | { 91 | const unsigned long BYTE_MASK = 0xBF; 92 | const unsigned long BYTE_MARK = 0x80; 93 | const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; 94 | 95 | if (input < 0x80) 96 | *length = 1; 97 | else if ( input < 0x800 ) 98 | *length = 2; 99 | else if ( input < 0x10000 ) 100 | *length = 3; 101 | else if ( input < 0x200000 ) 102 | *length = 4; 103 | else 104 | { *length = 0; return; } // This code won't covert this correctly anyway. 105 | 106 | output += *length; 107 | 108 | // Scary scary fall throughs. 109 | switch (*length) 110 | { 111 | case 4: 112 | --output; 113 | *output = (char)((input | BYTE_MARK) & BYTE_MASK); 114 | input >>= 6; 115 | case 3: 116 | --output; 117 | *output = (char)((input | BYTE_MARK) & BYTE_MASK); 118 | input >>= 6; 119 | case 2: 120 | --output; 121 | *output = (char)((input | BYTE_MARK) & BYTE_MASK); 122 | input >>= 6; 123 | case 1: 124 | --output; 125 | *output = (char)(input | FIRST_BYTE_MARK[*length]); 126 | } 127 | } 128 | 129 | 130 | /*static*/ int TiXmlBase::IsAlpha( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) 131 | { 132 | // This will only work for low-ascii, everything else is assumed to be a valid 133 | // letter. I'm not sure this is the best approach, but it is quite tricky trying 134 | // to figure out alhabetical vs. not across encoding. So take a very 135 | // conservative approach. 136 | 137 | // if ( encoding == TIXML_ENCODING_UTF8 ) 138 | // { 139 | if ( anyByte < 127 ) 140 | return isalpha( anyByte ); 141 | else 142 | return 1; // What else to do? The unicode set is huge...get the english ones right. 143 | // } 144 | // else 145 | // { 146 | // return isalpha( anyByte ); 147 | // } 148 | } 149 | 150 | 151 | /*static*/ int TiXmlBase::IsAlphaNum( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) 152 | { 153 | // This will only work for low-ascii, everything else is assumed to be a valid 154 | // letter. I'm not sure this is the best approach, but it is quite tricky trying 155 | // to figure out alhabetical vs. not across encoding. So take a very 156 | // conservative approach. 157 | 158 | // if ( encoding == TIXML_ENCODING_UTF8 ) 159 | // { 160 | if ( anyByte < 127 ) 161 | return isalnum( anyByte ); 162 | else 163 | return 1; // What else to do? The unicode set is huge...get the english ones right. 164 | // } 165 | // else 166 | // { 167 | // return isalnum( anyByte ); 168 | // } 169 | } 170 | 171 | 172 | class TiXmlParsingData 173 | { 174 | friend class TiXmlDocument; 175 | public: 176 | void Stamp( const char* now, TiXmlEncoding encoding ); 177 | 178 | const TiXmlCursor& Cursor() { return cursor; } 179 | 180 | private: 181 | // Only used by the document! 182 | TiXmlParsingData( const char* start, int _tabsize, int row, int col ) 183 | { 184 | assert( start ); 185 | stamp = start; 186 | tabsize = _tabsize; 187 | cursor.row = row; 188 | cursor.col = col; 189 | } 190 | 191 | TiXmlCursor cursor; 192 | const char* stamp; 193 | int tabsize; 194 | }; 195 | 196 | 197 | void TiXmlParsingData::Stamp( const char* now, TiXmlEncoding encoding ) 198 | { 199 | assert( now ); 200 | 201 | // Do nothing if the tabsize is 0. 202 | if ( tabsize < 1 ) 203 | { 204 | return; 205 | } 206 | 207 | // Get the current row, column. 208 | int row = cursor.row; 209 | int col = cursor.col; 210 | const char* p = stamp; 211 | assert( p ); 212 | 213 | while ( p < now ) 214 | { 215 | // Treat p as unsigned, so we have a happy compiler. 216 | const unsigned char* pU = (const unsigned char*)p; 217 | 218 | // Code contributed by Fletcher Dunn: (modified by lee) 219 | switch (*pU) { 220 | case 0: 221 | // We *should* never get here, but in case we do, don't 222 | // advance past the terminating null character, ever 223 | return; 224 | 225 | case '\r': 226 | // bump down to the next line 227 | ++row; 228 | col = 0; 229 | // Eat the character 230 | ++p; 231 | 232 | // Check for \r\n sequence, and treat this as a single character 233 | if (*p == '\n') { 234 | ++p; 235 | } 236 | break; 237 | 238 | case '\n': 239 | // bump down to the next line 240 | ++row; 241 | col = 0; 242 | 243 | // Eat the character 244 | ++p; 245 | 246 | // Check for \n\r sequence, and treat this as a single 247 | // character. (Yes, this bizarre thing does occur still 248 | // on some arcane platforms...) 249 | if (*p == '\r') { 250 | ++p; 251 | } 252 | break; 253 | 254 | case '\t': 255 | // Eat the character 256 | ++p; 257 | 258 | // Skip to next tab stop 259 | col = (col / tabsize + 1) * tabsize; 260 | break; 261 | 262 | case TIXML_UTF_LEAD_0: 263 | if ( encoding == TIXML_ENCODING_UTF8 ) 264 | { 265 | if ( *(p+1) && *(p+2) ) 266 | { 267 | // In these cases, don't advance the column. These are 268 | // 0-width spaces. 269 | if ( *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 ) 270 | p += 3; 271 | else if ( *(pU+1)==0xbfU && *(pU+2)==0xbeU ) 272 | p += 3; 273 | else if ( *(pU+1)==0xbfU && *(pU+2)==0xbfU ) 274 | p += 3; 275 | else 276 | { p +=3; ++col; } // A normal character. 277 | } 278 | } 279 | else 280 | { 281 | ++p; 282 | ++col; 283 | } 284 | break; 285 | 286 | default: 287 | if ( encoding == TIXML_ENCODING_UTF8 ) 288 | { 289 | // Eat the 1 to 4 byte utf8 character. 290 | int step = TiXmlBase::utf8ByteTable[*((const unsigned char*)p)]; 291 | if ( step == 0 ) 292 | step = 1; // Error case from bad encoding, but handle gracefully. 293 | p += step; 294 | 295 | // Just advance one column, of course. 296 | ++col; 297 | } 298 | else 299 | { 300 | ++p; 301 | ++col; 302 | } 303 | break; 304 | } 305 | } 306 | cursor.row = row; 307 | cursor.col = col; 308 | assert( cursor.row >= -1 ); 309 | assert( cursor.col >= -1 ); 310 | stamp = p; 311 | assert( stamp ); 312 | } 313 | 314 | 315 | const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding ) 316 | { 317 | if ( !p || !*p ) 318 | { 319 | return 0; 320 | } 321 | if ( encoding == TIXML_ENCODING_UTF8 ) 322 | { 323 | while ( *p ) 324 | { 325 | const unsigned char* pU = (const unsigned char*)p; 326 | 327 | // Skip the stupid Microsoft UTF-8 Byte order marks 328 | if ( *(pU+0)==TIXML_UTF_LEAD_0 329 | && *(pU+1)==TIXML_UTF_LEAD_1 330 | && *(pU+2)==TIXML_UTF_LEAD_2 ) 331 | { 332 | p += 3; 333 | continue; 334 | } 335 | else if(*(pU+0)==TIXML_UTF_LEAD_0 336 | && *(pU+1)==0xbfU 337 | && *(pU+2)==0xbeU ) 338 | { 339 | p += 3; 340 | continue; 341 | } 342 | else if(*(pU+0)==TIXML_UTF_LEAD_0 343 | && *(pU+1)==0xbfU 344 | && *(pU+2)==0xbfU ) 345 | { 346 | p += 3; 347 | continue; 348 | } 349 | 350 | if ( IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' ) // Still using old rules for white space. 351 | ++p; 352 | else 353 | break; 354 | } 355 | } 356 | else 357 | { 358 | while ( *p && IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' ) 359 | ++p; 360 | } 361 | 362 | return p; 363 | } 364 | 365 | #ifdef TIXML_USE_STL 366 | /*static*/ bool TiXmlBase::StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ) 367 | { 368 | for( ;; ) 369 | { 370 | if ( !in->good() ) return false; 371 | 372 | int c = in->peek(); 373 | // At this scope, we can't get to a document. So fail silently. 374 | if ( !IsWhiteSpace( c ) || c <= 0 ) 375 | return true; 376 | 377 | *tag += (char) in->get(); 378 | } 379 | } 380 | 381 | /*static*/ bool TiXmlBase::StreamTo( std::istream * in, int character, TIXML_STRING * tag ) 382 | { 383 | //assert( character > 0 && character < 128 ); // else it won't work in utf-8 384 | while ( in->good() ) 385 | { 386 | int c = in->peek(); 387 | if ( c == character ) 388 | return true; 389 | if ( c <= 0 ) // Silent failure: can't get document at this scope 390 | return false; 391 | 392 | in->get(); 393 | *tag += (char) c; 394 | } 395 | return false; 396 | } 397 | #endif 398 | 399 | // One of TinyXML's more performance demanding functions. Try to keep the memory overhead down. The 400 | // "assign" optimization removes over 10% of the execution time. 401 | // 402 | const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name, TiXmlEncoding encoding ) 403 | { 404 | // Oddly, not supported on some comilers, 405 | //name->clear(); 406 | // So use this: 407 | *name = ""; 408 | assert( p ); 409 | 410 | // Names start with letters or underscores. 411 | // Of course, in unicode, tinyxml has no idea what a letter *is*. The 412 | // algorithm is generous. 413 | // 414 | // After that, they can be letters, underscores, numbers, 415 | // hyphens, or colons. (Colons are valid ony for namespaces, 416 | // but tinyxml can't tell namespaces from names.) 417 | if ( p && *p 418 | && ( IsAlpha( (unsigned char) *p, encoding ) || *p == '_' ) ) 419 | { 420 | const char* start = p; 421 | while( p && *p 422 | && ( IsAlphaNum( (unsigned char ) *p, encoding ) 423 | || *p == '_' 424 | || *p == '-' 425 | || *p == '.' 426 | || *p == ':' ) ) 427 | { 428 | //(*name) += *p; // expensive 429 | ++p; 430 | } 431 | if ( p-start > 0 ) { 432 | name->assign( start, p-start ); 433 | } 434 | return p; 435 | } 436 | return 0; 437 | } 438 | 439 | const char* TiXmlBase::GetEntity( const char* p, char* value, int* length, TiXmlEncoding encoding ) 440 | { 441 | // Presume an entity, and pull it out. 442 | TIXML_STRING ent; 443 | int i; 444 | *length = 0; 445 | 446 | if ( *(p+1) && *(p+1) == '#' && *(p+2) ) 447 | { 448 | unsigned long ucs = 0; 449 | ptrdiff_t delta = 0; 450 | unsigned mult = 1; 451 | 452 | if ( *(p+2) == 'x' ) 453 | { 454 | // Hexadecimal. 455 | if ( !*(p+3) ) return 0; 456 | 457 | const char* q = p+3; 458 | q = strchr( q, ';' ); 459 | 460 | if ( !q || !*q ) return 0; 461 | 462 | delta = q-p; 463 | --q; 464 | 465 | while ( *q != 'x' ) 466 | { 467 | if ( *q >= '0' && *q <= '9' ) 468 | ucs += mult * (*q - '0'); 469 | else if ( *q >= 'a' && *q <= 'f' ) 470 | ucs += mult * (*q - 'a' + 10); 471 | else if ( *q >= 'A' && *q <= 'F' ) 472 | ucs += mult * (*q - 'A' + 10 ); 473 | else 474 | return 0; 475 | mult *= 16; 476 | --q; 477 | } 478 | } 479 | else 480 | { 481 | // Decimal. 482 | if ( !*(p+2) ) return 0; 483 | 484 | const char* q = p+2; 485 | q = strchr( q, ';' ); 486 | 487 | if ( !q || !*q ) return 0; 488 | 489 | delta = q-p; 490 | --q; 491 | 492 | while ( *q != '#' ) 493 | { 494 | if ( *q >= '0' && *q <= '9' ) 495 | ucs += mult * (*q - '0'); 496 | else 497 | return 0; 498 | mult *= 10; 499 | --q; 500 | } 501 | } 502 | if ( encoding == TIXML_ENCODING_UTF8 ) 503 | { 504 | // convert the UCS to UTF-8 505 | ConvertUTF32ToUTF8( ucs, value, length ); 506 | } 507 | else 508 | { 509 | *value = (char)ucs; 510 | *length = 1; 511 | } 512 | return p + delta + 1; 513 | } 514 | 515 | // Now try to match it. 516 | for( i=0; iappend( cArr, len ); 595 | } 596 | } 597 | else 598 | { 599 | bool whitespace = false; 600 | 601 | // Remove leading white space: 602 | p = SkipWhiteSpace( p, encoding ); 603 | while ( p && *p 604 | && !StringEqual( p, endTag, caseInsensitive, encoding ) ) 605 | { 606 | if ( *p == '\r' || *p == '\n' ) 607 | { 608 | whitespace = true; 609 | ++p; 610 | } 611 | else if ( IsWhiteSpace( *p ) ) 612 | { 613 | whitespace = true; 614 | ++p; 615 | } 616 | else 617 | { 618 | // If we've found whitespace, add it before the 619 | // new character. Any whitespace just becomes a space. 620 | if ( whitespace ) 621 | { 622 | (*text) += ' '; 623 | whitespace = false; 624 | } 625 | int len; 626 | char cArr[4] = { 0, 0, 0, 0 }; 627 | p = GetChar( p, cArr, &len, encoding ); 628 | if ( len == 1 ) 629 | (*text) += cArr[0]; // more efficient 630 | else 631 | text->append( cArr, len ); 632 | } 633 | } 634 | } 635 | if ( p ) 636 | p += strlen( endTag ); 637 | return p; 638 | } 639 | 640 | #ifdef TIXML_USE_STL 641 | 642 | void TiXmlDocument::StreamIn( std::istream * in, TIXML_STRING * tag ) 643 | { 644 | // The basic issue with a document is that we don't know what we're 645 | // streaming. Read something presumed to be a tag (and hope), then 646 | // identify it, and call the appropriate stream method on the tag. 647 | // 648 | // This "pre-streaming" will never read the closing ">" so the 649 | // sub-tag can orient itself. 650 | 651 | if ( !StreamTo( in, '<', tag ) ) 652 | { 653 | SetError( TIXML_ERROR_PARSING_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); 654 | return; 655 | } 656 | 657 | while ( in->good() ) 658 | { 659 | int tagIndex = (int) tag->length(); 660 | while ( in->good() && in->peek() != '>' ) 661 | { 662 | int c = in->get(); 663 | if ( c <= 0 ) 664 | { 665 | SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); 666 | break; 667 | } 668 | (*tag) += (char) c; 669 | } 670 | 671 | if ( in->good() ) 672 | { 673 | // We now have something we presume to be a node of 674 | // some sort. Identify it, and call the node to 675 | // continue streaming. 676 | TiXmlNode* node = Identify( tag->c_str() + tagIndex, TIXML_DEFAULT_ENCODING ); 677 | 678 | if ( node ) 679 | { 680 | node->StreamIn( in, tag ); 681 | bool isElement = node->ToElement() != 0; 682 | delete node; 683 | node = 0; 684 | 685 | // If this is the root element, we're done. Parsing will be 686 | // done by the >> operator. 687 | if ( isElement ) 688 | { 689 | return; 690 | } 691 | } 692 | else 693 | { 694 | SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); 695 | return; 696 | } 697 | } 698 | } 699 | // We should have returned sooner. 700 | SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); 701 | } 702 | 703 | #endif 704 | 705 | const char* TiXmlDocument::Parse( const char* p, TiXmlParsingData* prevData, TiXmlEncoding encoding ) 706 | { 707 | ClearError(); 708 | 709 | // Parse away, at the document level. Since a document 710 | // contains nothing but other tags, most of what happens 711 | // here is skipping white space. 712 | if ( !p || !*p ) 713 | { 714 | SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); 715 | return 0; 716 | } 717 | 718 | // Note that, for a document, this needs to come 719 | // before the while space skip, so that parsing 720 | // starts from the pointer we are given. 721 | location.Clear(); 722 | if ( prevData ) 723 | { 724 | location.row = prevData->cursor.row; 725 | location.col = prevData->cursor.col; 726 | } 727 | else 728 | { 729 | location.row = 0; 730 | location.col = 0; 731 | } 732 | TiXmlParsingData data( p, TabSize(), location.row, location.col ); 733 | location = data.Cursor(); 734 | 735 | if ( encoding == TIXML_ENCODING_UNKNOWN ) 736 | { 737 | // Check for the Microsoft UTF-8 lead bytes. 738 | const unsigned char* pU = (const unsigned char*)p; 739 | if ( *(pU+0) && *(pU+0) == TIXML_UTF_LEAD_0 740 | && *(pU+1) && *(pU+1) == TIXML_UTF_LEAD_1 741 | && *(pU+2) && *(pU+2) == TIXML_UTF_LEAD_2 ) 742 | { 743 | encoding = TIXML_ENCODING_UTF8; 744 | useMicrosoftBOM = true; 745 | } 746 | } 747 | 748 | p = SkipWhiteSpace( p, encoding ); 749 | if ( !p ) 750 | { 751 | SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); 752 | return 0; 753 | } 754 | 755 | while ( p && *p ) 756 | { 757 | TiXmlNode* node = Identify( p, encoding ); 758 | if ( node ) 759 | { 760 | p = node->Parse( p, &data, encoding ); 761 | LinkEndChild( node ); 762 | } 763 | else 764 | { 765 | break; 766 | } 767 | 768 | // Did we get encoding info? 769 | if ( encoding == TIXML_ENCODING_UNKNOWN 770 | && node->ToDeclaration() ) 771 | { 772 | TiXmlDeclaration* dec = node->ToDeclaration(); 773 | const char* enc = dec->Encoding(); 774 | assert( enc ); 775 | 776 | if ( *enc == 0 ) 777 | encoding = TIXML_ENCODING_UTF8; 778 | else if ( StringEqual( enc, "UTF-8", true, TIXML_ENCODING_UNKNOWN ) ) 779 | encoding = TIXML_ENCODING_UTF8; 780 | else if ( StringEqual( enc, "UTF8", true, TIXML_ENCODING_UNKNOWN ) ) 781 | encoding = TIXML_ENCODING_UTF8; // incorrect, but be nice 782 | else 783 | encoding = TIXML_ENCODING_LEGACY; 784 | } 785 | 786 | p = SkipWhiteSpace( p, encoding ); 787 | } 788 | 789 | // Was this empty? 790 | if ( !firstChild ) { 791 | SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, encoding ); 792 | return 0; 793 | } 794 | 795 | // All is well. 796 | return p; 797 | } 798 | 799 | void TiXmlDocument::SetError( int err, const char* pError, TiXmlParsingData* data, TiXmlEncoding encoding ) 800 | { 801 | // The first error in a chain is more accurate - don't set again! 802 | if ( error ) 803 | return; 804 | 805 | assert( err > 0 && err < TIXML_ERROR_STRING_COUNT ); 806 | error = true; 807 | errorId = err; 808 | errorDesc = errorString[ errorId ]; 809 | 810 | errorLocation.Clear(); 811 | if ( pError && data ) 812 | { 813 | data->Stamp( pError, encoding ); 814 | errorLocation = data->Cursor(); 815 | } 816 | } 817 | 818 | 819 | TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding ) 820 | { 821 | TiXmlNode* returnNode = 0; 822 | 823 | p = SkipWhiteSpace( p, encoding ); 824 | if( !p || !*p || *p != '<' ) 825 | { 826 | return 0; 827 | } 828 | 829 | TiXmlDocument* doc = GetDocument(); 830 | p = SkipWhiteSpace( p, encoding ); 831 | 832 | if ( !p || !*p ) 833 | { 834 | return 0; 835 | } 836 | 837 | // What is this thing? 838 | // - Elements start with a letter or underscore, but xml is reserved. 839 | // - Comments: "; 1346 | 1347 | if ( !StringEqual( p, startTag, false, encoding ) ) 1348 | { 1349 | document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding ); 1350 | return 0; 1351 | } 1352 | p += strlen( startTag ); 1353 | p = ReadText( p, &value, false, endTag, false, encoding ); 1354 | return p; 1355 | } 1356 | 1357 | 1358 | const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) 1359 | { 1360 | p = SkipWhiteSpace( p, encoding ); 1361 | if ( !p || !*p ) return 0; 1362 | 1363 | // int tabsize = 4; 1364 | // if ( document ) 1365 | // tabsize = document->TabSize(); 1366 | 1367 | if ( data ) 1368 | { 1369 | data->Stamp( p, encoding ); 1370 | location = data->Cursor(); 1371 | } 1372 | // Read the name, the '=' and the value. 1373 | const char* pErr = p; 1374 | p = ReadName( p, &name, encoding ); 1375 | if ( !p || !*p ) 1376 | { 1377 | if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding ); 1378 | return 0; 1379 | } 1380 | p = SkipWhiteSpace( p, encoding ); 1381 | if ( !p || !*p || *p != '=' ) 1382 | { 1383 | if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); 1384 | return 0; 1385 | } 1386 | 1387 | ++p; // skip '=' 1388 | p = SkipWhiteSpace( p, encoding ); 1389 | if ( !p || !*p ) 1390 | { 1391 | if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); 1392 | return 0; 1393 | } 1394 | 1395 | const char* end; 1396 | const char SINGLE_QUOTE = '\''; 1397 | const char DOUBLE_QUOTE = '\"'; 1398 | 1399 | if ( *p == SINGLE_QUOTE ) 1400 | { 1401 | ++p; 1402 | end = "\'"; // single quote in string 1403 | p = ReadText( p, &value, false, end, false, encoding ); 1404 | } 1405 | else if ( *p == DOUBLE_QUOTE ) 1406 | { 1407 | ++p; 1408 | end = "\""; // double quote in string 1409 | p = ReadText( p, &value, false, end, false, encoding ); 1410 | } 1411 | else 1412 | { 1413 | // All attribute values should be in single or double quotes. 1414 | // But this is such a common error that the parser will try 1415 | // its best, even without them. 1416 | value = ""; 1417 | while ( p && *p // existence 1418 | && !IsWhiteSpace( *p ) && *p != '\n' && *p != '\r' // whitespace 1419 | && *p != '/' && *p != '>' ) // tag end 1420 | { 1421 | if ( *p == SINGLE_QUOTE || *p == DOUBLE_QUOTE ) { 1422 | // [ 1451649 ] Attribute values with trailing quotes not handled correctly 1423 | // We did not have an opening quote but seem to have a 1424 | // closing one. Give up and throw an error. 1425 | if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); 1426 | return 0; 1427 | } 1428 | value += *p; 1429 | ++p; 1430 | } 1431 | } 1432 | return p; 1433 | } 1434 | 1435 | #ifdef TIXML_USE_STL 1436 | void TiXmlText::StreamIn( std::istream * in, TIXML_STRING * tag ) 1437 | { 1438 | while ( in->good() ) 1439 | { 1440 | int c = in->peek(); 1441 | if ( !cdata && (c == '<' ) ) 1442 | { 1443 | return; 1444 | } 1445 | if ( c <= 0 ) 1446 | { 1447 | TiXmlDocument* document = GetDocument(); 1448 | if ( document ) 1449 | document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); 1450 | return; 1451 | } 1452 | 1453 | (*tag) += (char) c; 1454 | in->get(); // "commits" the peek made above 1455 | 1456 | if ( cdata && c == '>' && tag->size() >= 3 ) { 1457 | size_t len = tag->size(); 1458 | if ( (*tag)[len-2] == ']' && (*tag)[len-3] == ']' ) { 1459 | // terminator of cdata. 1460 | return; 1461 | } 1462 | } 1463 | } 1464 | } 1465 | #endif 1466 | 1467 | const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) 1468 | { 1469 | value = ""; 1470 | TiXmlDocument* document = GetDocument(); 1471 | 1472 | if ( data ) 1473 | { 1474 | data->Stamp( p, encoding ); 1475 | location = data->Cursor(); 1476 | } 1477 | 1478 | const char* const startTag = ""; 1480 | 1481 | if ( cdata || StringEqual( p, startTag, false, encoding ) ) 1482 | { 1483 | cdata = true; 1484 | 1485 | if ( !StringEqual( p, startTag, false, encoding ) ) 1486 | { 1487 | document->SetError( TIXML_ERROR_PARSING_CDATA, p, data, encoding ); 1488 | return 0; 1489 | } 1490 | p += strlen( startTag ); 1491 | 1492 | // Keep all the white space, ignore the encoding, etc. 1493 | while ( p && *p 1494 | && !StringEqual( p, endTag, false, encoding ) 1495 | ) 1496 | { 1497 | value += *p; 1498 | ++p; 1499 | } 1500 | 1501 | TIXML_STRING dummy; 1502 | p = ReadText( p, &dummy, false, endTag, false, encoding ); 1503 | return p; 1504 | } 1505 | else 1506 | { 1507 | bool ignoreWhite = true; 1508 | 1509 | const char* end = "<"; 1510 | p = ReadText( p, &value, ignoreWhite, end, false, encoding ); 1511 | if ( p ) 1512 | return p-1; // don't truncate the '<' 1513 | return 0; 1514 | } 1515 | } 1516 | 1517 | #ifdef TIXML_USE_STL 1518 | void TiXmlDeclaration::StreamIn( std::istream * in, TIXML_STRING * tag ) 1519 | { 1520 | while ( in->good() ) 1521 | { 1522 | int c = in->get(); 1523 | if ( c <= 0 ) 1524 | { 1525 | TiXmlDocument* document = GetDocument(); 1526 | if ( document ) 1527 | document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); 1528 | return; 1529 | } 1530 | (*tag) += (char) c; 1531 | 1532 | if ( c == '>' ) 1533 | { 1534 | // All is well. 1535 | return; 1536 | } 1537 | } 1538 | } 1539 | #endif 1540 | 1541 | const char* TiXmlDeclaration::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding _encoding ) 1542 | { 1543 | p = SkipWhiteSpace( p, _encoding ); 1544 | // Find the beginning, find the end, and look for 1545 | // the stuff in-between. 1546 | TiXmlDocument* document = GetDocument(); 1547 | if ( !p || !*p || !StringEqual( p, "SetError( TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding ); 1550 | return 0; 1551 | } 1552 | if ( data ) 1553 | { 1554 | data->Stamp( p, _encoding ); 1555 | location = data->Cursor(); 1556 | } 1557 | p += 5; 1558 | 1559 | version = ""; 1560 | encoding = ""; 1561 | standalone = ""; 1562 | 1563 | while ( p && *p ) 1564 | { 1565 | if ( *p == '>' ) 1566 | { 1567 | ++p; 1568 | return p; 1569 | } 1570 | 1571 | p = SkipWhiteSpace( p, _encoding ); 1572 | if ( StringEqual( p, "version", true, _encoding ) ) 1573 | { 1574 | TiXmlAttribute attrib; 1575 | p = attrib.Parse( p, data, _encoding ); 1576 | version = attrib.Value(); 1577 | } 1578 | else if ( StringEqual( p, "encoding", true, _encoding ) ) 1579 | { 1580 | TiXmlAttribute attrib; 1581 | p = attrib.Parse( p, data, _encoding ); 1582 | encoding = attrib.Value(); 1583 | } 1584 | else if ( StringEqual( p, "standalone", true, _encoding ) ) 1585 | { 1586 | TiXmlAttribute attrib; 1587 | p = attrib.Parse( p, data, _encoding ); 1588 | standalone = attrib.Value(); 1589 | } 1590 | else 1591 | { 1592 | // Read over whatever it is. 1593 | while( p && *p && *p != '>' && !IsWhiteSpace( *p ) ) 1594 | ++p; 1595 | } 1596 | } 1597 | return 0; 1598 | } 1599 | 1600 | bool TiXmlText::Blank() const 1601 | { 1602 | for ( unsigned i=0; i 2 | 3 | success 4 | 5 | 6 | 114148 7 | Jim Berets 8 | VP, Product Management, Black Duck. I'm responsible for openhub.net as well as Black Duck's enterprise products. If you have any questions, comments, or concerns regarding Open Hub, please post them on our forum or email us at info@openhub.net. 9 | jberets 10 | 2010-10-06T16:15:18Z 11 | 2013-07-10T19:20:03Z 12 | http://www.blackducksoftware.com 13 | jberets 14 | https://www.openhub.net/accounts/jberets.xml 15 | https://www.openhub.net/accounts/jberets 16 | http://www.gravatar.com/avatar.php?gravatar_id=a444dc76772d5e41bb2a5df997163123 17 | ddb45a02aab29ac46a9a1fa5740a1ea2e2b183a0 18 | 0 19 | Burlington, MA, USA 20 | US 21 | 42.5047161 22 | -71.1956205 23 | 24 | 1 25 | 670286 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /examples/ApiExample.java: -------------------------------------------------------------------------------- 1 | /* 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2013 Black Duck Software, Inc. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | 24 | This is an example of using the Open Hub API from Java. 25 | Detailed information can be found at the Open Hub website: 26 | 27 | https://github.com/blackducksoftware/ohloh_api 28 | 29 | This examples retrieves a account and simply shows the name associated. 30 | 31 | Pass your Open Hub API key as the first parameter to this example. 32 | Open Hub API keys are free. If you do not have one, you can obtain one 33 | at the Open Hub website: 34 | 35 | https://www.openhub.net/accounts//api_keys/new 36 | 37 | Pass the email address of the account as the second parameter to this script. 38 | */ 39 | 40 | import java.net.*; 41 | import java.security.*; 42 | import java.io.*; 43 | import java.util.*; 44 | import org.w3c.dom.*; 45 | import javax.xml.parsers.*; 46 | 47 | public class ApiExample 48 | { 49 | private static final char[] hexChars ={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; 50 | 51 | public static void usage() 52 | { 53 | System.out.println("Usage:"); 54 | System.out.println("java ApiExample [api_key] [user_email]"); 55 | } 56 | 57 | public ApiExample(String apiKey, String userEmail) 58 | { 59 | initiate(apiKey, userEmail); 60 | } 61 | 62 | public void initiate(String apiKey, String userEmail) 63 | { 64 | System.out.println("Initialising request."); 65 | 66 | // Calculate MD5 digest from the email address. 67 | String emailDigest = calculateDigest(userEmail); 68 | 69 | try 70 | { 71 | // Request XML file. 72 | URL url = new URL("https://www.openhub.net/accounts/" + emailDigest + ".xml?api_key=" + apiKey + "&v=1"); 73 | URLConnection con = url.openConnection(); 74 | 75 | // Check for status OK. 76 | if (con.getHeaderField("Status").startsWith("200")) 77 | { 78 | System.out.println("Request succeeded."); 79 | } 80 | else 81 | { 82 | System.out.println("Request failed. Possibly wrong API key?"); 83 | return; 84 | } 85 | System.out.println("Looking up name.."); 86 | 87 | // Create a document from the URL's input stream, and parse. 88 | DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); 89 | Document doc = builder.parse(con.getInputStream()); 90 | 91 | NodeList responseNodes = doc.getElementsByTagName("response"); 92 | for (int i = 0; i < responseNodes.getLength(); i++) 93 | { 94 | Element element = (Element)responseNodes.item(i); 95 | 96 | // First check for the status code inside the XML file. It is 97 | // most likely, though, that if the request would have failed, 98 | // it is already returned earlier. 99 | NodeList statusList = element.getElementsByTagName("status"); 100 | if (statusList.getLength() == 1) 101 | { 102 | Node statusNode = statusList.item(0); 103 | 104 | // Check if the text inidicates that the request was 105 | // successful. 106 | if (!statusNode.getTextContent().equals("success")) 107 | { 108 | System.out.println("Failed. " + statusNode.getTextContent()); 109 | return; 110 | } 111 | } 112 | 113 | Element resultElement = (Element)element.getElementsByTagName("result").item(0); 114 | // We assume we only have one account result here. 115 | Element accountElement = (Element)resultElement.getElementsByTagName("account").item(0); 116 | 117 | if (accountElement != null) 118 | { 119 | // Lookup name. 120 | String realName = accountElement.getElementsByTagName("name").item(0).getTextContent(); 121 | System.out.println("Located the real name: " + realName); 122 | } 123 | } 124 | } 125 | catch (Exception e) 126 | { 127 | e.printStackTrace(); 128 | } 129 | } 130 | 131 | public String calculateDigest(String email) 132 | { 133 | return hexStringFromBytes(calculateHash(email.getBytes())); 134 | } 135 | 136 | private byte[] calculateHash(byte[] dataToHash) 137 | { 138 | try 139 | { 140 | // Calculate MD5 digest. 141 | MessageDigest md = MessageDigest.getInstance("MD5"); 142 | md.update(dataToHash, 0, dataToHash.length); 143 | return md.digest(); 144 | } 145 | catch (NoSuchAlgorithmException e) 146 | { 147 | e.printStackTrace(); 148 | } 149 | return null; 150 | } 151 | 152 | public String hexStringFromBytes(byte[] b) 153 | { 154 | // Conversion from bytes to String. 155 | String hex = ""; 156 | 157 | int msb; 158 | 159 | int lsb = 0; 160 | int i; 161 | 162 | for (i = 0; i < b.length; i++) 163 | { 164 | msb = ((int)b[i] & 0x000000FF) / 16; 165 | 166 | lsb = ((int)b[i] & 0x000000FF) % 16; 167 | hex = hex + hexChars[msb] + hexChars[lsb]; 168 | } 169 | return hex; 170 | } 171 | 172 | public static void main(String[] args) 173 | { 174 | if (args.length == 2) 175 | { 176 | // Simply pass arguments. 177 | new ApiExample(args[0], args[1]); 178 | } 179 | else 180 | { 181 | // Show usage information. 182 | usage(); 183 | } 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | ## Open Hub API Examples # 2 | Some basic [Open Hub](https://www.openhub.net) API samples to help you get started. For information on the Open Hub API, please see the [documentation](/README.md). The Open Hub API has some restrictions, so please review the complete [Terms of Use](http://blog.openhub.net/terms-2) before you begin. 3 | 4 | ### Examples are available in: ### 5 | * BASH 6 | 7 | Uses `curl` to pull an [Account](/reference/account.md) from Open Hub and `openssl` to create MD5 hex of the email address. A simple sed hack parses the XML response into name:value pairs. The example demonstrates data retrieval using email address lookup. Pass your API key and the email address of the Account you are requsting as parameters to the script: 8 | 9 | `./account_sample.sh YOUR_API_KEY_HERE rluckey@blackducksoftware.com` 10 | 11 | The script isn’t very robust — `sed` is not the world’s best XML parser — but it does return a non-zero exit code if the record is not found or some other problem occurs. 12 | 13 | * Ruby 14 | 15 | Performs the same email-based account lookup, but uses more rigorous error handling and parsing to create a structured XML document object. Using the `REXML` library, you can build a more robust interface to the Open Hub API. 16 | 17 | Execute the script by passing your API key and an email address as parameters: 18 | 19 | `ruby account_sample.rb YOUR_API_KEY_HERE rluckey@blackducksoftware.com` 20 | 21 | * Python 22 | 23 | Performs a similar account lookup on Open Hub. It requires `urllib`, `hashlib` and `elementtree`. 24 | 25 | Execute the script by passing your API key and an email address as parameters: 26 | 27 | `./account_sample.py YOUR_API_KEY_HERE rluckey@blackducksoftware.com` 28 | 29 | Many thanks to [Thijs Triemstra](https://www.openhub.net/accounts/3953) for contributing this sample. 30 | 31 | * Perl 32 | 33 | Performs a similar account lookup on Open Hub. It requires the `LWP::Simple`, `Digest::MD5`, and `XML::Simple` libraries. 34 | 35 | Execute the script by passing your API key and an email address as parameters: 36 | 37 | `./account_sample.pl YOUR_API_KEY_HERE rluckey@blackducksoftware.com` 38 | 39 | Many thanks to [Yanick Champoux](https://www.openhub.net/accounts/12933) for contributing this sample. 40 | 41 | * Java 42 | 43 | Uses Java’s networking capabilities to pull an [Account](/reference/account.md) from Open Hub. It demonstrates how to generate an MD5 hash of an email address to use as a lookup key, then uses DOM to parse the XML response. 44 | 45 | Pass your API key and the email address of the Account you are requesting as parameters: 46 | 47 | `javac ApiExample.java` 48 | 49 | `java ApiExample YOUR_API_KEY_HERE rluckey@blackducksoftware.com` 50 | 51 | * C++ 52 | 53 | The C++ example is a bit more involved, because it must include code for networking, MD5 hashing, and XML parsing. The example includes source for some small libraries to create a self-contained program. 54 | 55 | The code was written for Visual Studio 2005, but it also compiles and runs on Mac OS X, and should work on Linux. Let us know if you encounter trouble on your platform. 56 | 57 | To build with Visual Studio 2005: 58 | * Open solution file `ApiExample.cpp/build/vs2005/ohlohExample.sln` 59 | * Right-click the solution and choose *Build*. 60 | 61 | To build on Linux or Mac OS X, *cd to ApiExample.cpp* and run the build script: 62 | 63 | `./compile.sh` 64 | 65 | You can then run the executable called `ApiExample` and pass it your API key and an email address: 66 | 67 | `./bin/ApiExample YOUR_API_KEY_HERE rluckey@blackducksoftware.com` 68 | 69 | Many thanks to [Lars ‘Levia’ Wesselius](https://www.openhub.net/accounts/739) for providing the sample code in both C++ and Java! 70 | 71 | * PHP 72 | 73 | Paul Scott has created a full-featured PHP class for accessing the Open Hub API, complete with documentation. You can find it at the [PHP Classes](http://www.phpclasses.org/browse/package/4261.html) website. 74 | 75 | 76 | Your feedback on these examples will benefit everyone, and we’re eager for input on improvements. 77 | We’d also appreciate help translating the samples into more languages. 78 | 79 | Please don’t hesitate to contact us at info@openhub.net. 80 | -------------------------------------------------------------------------------- /examples/account_sample.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | =pod 4 | 5 | =head1 NAME 6 | 7 | account_sample.pl - Simple example of using the Open Hub API from Perl 8 | 9 | =head1 SYNOPSIS 10 | 11 | account_sample.pl api_key email 12 | 13 | =head1 DESCRIPTION 14 | 15 | This is a small example of how to use the Open Hub API from Perl, 16 | mimicking the Ruby example - account_sample.rb 17 | 18 | Detailed information about the Open Hub API can be found at 19 | https://github.com/blackducksoftware/ohloh_api 20 | 21 | The script takes an API key and the email address of a developer 22 | registered on Open Hub as parameters, and prints out all the 23 | information of that account. 24 | 25 | =head1 EXAMPLE 26 | 27 | ./account_sample.pl YOUR_API_KEY_HERE robin@openhub.net 28 | 29 | =head1 DEPENDENCIES 30 | 31 | This script uses 32 | L (to query the Open Hub website), 33 | L (to MD5s the email address as requested by the API) 34 | and 35 | L (to parse the server's answer). 36 | 37 | =head1 VERSION 38 | 39 | This documentation refers to account_sample version 0.1 40 | 41 | =head1 AUTHOR 42 | 43 | Yanick Champoux (yanick@cpan.org) 44 | 45 | =head1 LICENCE AND COPYRIGHT 46 | 47 | Copyright (c) 2007 Yanick Champoux (yanick@cpan.org). All rights reserved. 48 | 49 | This module is free software; you can redistribute it and/or 50 | modify it under the same terms as Perl itself. See perldoc perlartistic. 51 | 52 | This program is distributed in the hope that it will be useful, 53 | but WITHOUT ANY WARRANTY; without even the implied warranty of 54 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 55 | 56 | =cut 57 | 58 | use strict; 59 | use warnings; 60 | 61 | use LWP::Simple; 62 | use Digest::MD5 qw/ md5_hex /; 63 | use XML::Simple; 64 | 65 | my $VERSION = '0.01'; 66 | my $API_VERSION = 1; 67 | 68 | die_usage() unless @ARGV == 2; 69 | 70 | my ( $api_key, $email ) = @ARGV; 71 | 72 | my $email_md5 = md5_hex($email); 73 | 74 | ### let's build the request url 75 | # first the base url 76 | my $url = 'https://www.openhub.net/'; 77 | # then the email "page" we want 78 | $url .= "accounts/$email_md5.xml"; 79 | # and finally the API version and the api key 80 | $url .= '?' . join '&' => "v=$API_VERSION", "api_key=$api_key"; 81 | 82 | # request the url from the server 83 | my $response = get $url or die "Open Hub server didn't return anything\n"; 84 | 85 | # parse the XML response 86 | my $xml = eval { XMLin($response) } or die "Server didn't return valid XML\n"; 87 | 88 | # was the request a success? 89 | die "request didn't succeed: $xml->{error}\n" 90 | unless $xml->{status} eq 'success'; 91 | 92 | # make an alias to the info we want 93 | my %account = %{ $xml->{result}{account} }; 94 | 95 | # now we print the info for the account 96 | 97 | for my $attr ( 98 | qw/ id name created_at updated_at homepage_url 99 | avatar_url posts_count location country_code 100 | latitude longitude / 101 | ) { 102 | 103 | # only print the attribute if it exist 104 | printf "%-20s: %s\n", $attr, $account{$attr} 105 | if defined $account{$attr} and not ref $account{$attr}; 106 | } 107 | 108 | # print the kudo information 109 | printf "%-20s: %s\n", 'kudo rank', $account{kudo_score}{kudo_rank} 110 | if $account{kudo_score}; 111 | 112 | exit; 113 | 114 | ### utility functions ###################################### 115 | 116 | sub die_usage { 117 | die "usage: $0 api_key email\n"; 118 | } 119 | 120 | __END__ 121 | -------------------------------------------------------------------------------- /examples/account_sample.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | """ 4 | The MIT License (MIT) 5 | 6 | Copyright (c) 2013 Thijs Triemstra 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in 16 | all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | THE SOFTWARE. 25 | """ 26 | 27 | """ 28 | This is an example of using the Open Hub API from Python. 29 | 30 | Detailed information can be found on GitHub: 31 | 32 | https://github.com/blackducksoftware/ohloh_api 33 | 34 | This example uses the ElementTree library for XML parsing 35 | (included in Python 2.5 and newer): 36 | 37 | http://effbot.org/zone/element-index.htm 38 | 39 | This example retrieves basic Open Hub account information 40 | and outputs it as simple name: value pairs. 41 | 42 | Pass your Open Hub API key as the first parameter to this script. 43 | Open Hub API keys are free. If you do not have one, you can obtain one 44 | at the Open Hub website: 45 | 46 | https://www.openhub.net/accounts//api_keys/new 47 | 48 | Pass the email address of the account as the second parameter to this script. 49 | """ 50 | 51 | import sys, urllib, hashlib 52 | # import ElementTree based on the python version 53 | try: 54 | import elementtree.ElementTree as ET 55 | except ImportError: 56 | import xml.etree.ElementTree as ET 57 | 58 | # We pass the MD5 hash of the email address 59 | email = hashlib.md5() 60 | email.update(sys.argv[2]) 61 | 62 | # Connect to the Open Hub website and retrieve the account data. 63 | params = urllib.urlencode({'api_key': sys.argv[1], 'v': 1}) 64 | url = "https://www.openhub.net/accounts/%s.xml?%s" % (email.hexdigest(), params) 65 | f = urllib.urlopen(url) 66 | 67 | # Parse the response into a structured XML object 68 | tree = ET.parse(f) 69 | 70 | # Did Open Hub return an error? 71 | elem = tree.getroot() 72 | error = elem.find("error") 73 | if error != None: 74 | print 'Open Hub returned:', ET.tostring(error), 75 | sys.exit() 76 | 77 | # Output all the immediate child properties of an Account 78 | for node in elem.find("result/account"): 79 | if node.tag == "kudo_score": 80 | print "%s:" % node.tag 81 | for score in elem.find("result/account/kudo_score"): 82 | print "\t%s:\t%s" % (score.tag, score.text) 83 | else: 84 | print "%s:\t%s" % (node.tag, node.text) 85 | -------------------------------------------------------------------------------- /examples/account_sample.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'net/https' 3 | require 'rexml/document' 4 | require 'digest/md5' 5 | 6 | # The MIT License (MIT) 7 | # 8 | # Copyright (c) 2013 Black Duck Software, Inc. 9 | # 10 | # Permission is hereby granted, free of charge, to any person obtaining a copy 11 | # of this software and associated documentation files (the "Software"), to deal 12 | # in the Software without restriction, including without limitation the rights 13 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | # copies of the Software, and to permit persons to whom the Software is 15 | # furnished to do so, subject to the following conditions: 16 | # 17 | # The above copyright notice and this permission notice shall be included in 18 | # all copies or substantial portions of the Software. 19 | # 20 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | # THE SOFTWARE. 27 | 28 | # This is an example of using the Open Hub API from Ruby. 29 | # Detailed information can be found at the Open Hub website: 30 | # 31 | # https://github.com/blackducksoftware/ohloh_api 32 | # 33 | # This example uses the REXML library for XML parsing: 34 | # 35 | # http://www.germane-software.com/software/rexml/ 36 | # 37 | 38 | # This example retrieves basic Open Hub account information 39 | # and outputs it as simple name: value pairs. 40 | # 41 | # Pass your Open Hub API key as the first parameter to this script. 42 | # Open Hub API keys are free. If you do not have one, you can obtain one 43 | # at the Open Hub website: 44 | # 45 | # https://www.openhub.net/accounts//api_keys/new 46 | # 47 | # Pass the email address of the account as the second parameter to this script. 48 | 49 | unless ARGV[0] =~ /[\w]+/ and ARGV[1] =~ /.+@.+\..+/ 50 | STDERR.puts "Usage: #{__FILE__} [api_key] [email]" 51 | exit 1 52 | end 53 | 54 | api_key = ARGV[0] 55 | email = ARGV[1] 56 | 57 | # 58 | # Connect to the Open Hub website and retrieve the account data. 59 | # 60 | 61 | # We pass the MD5 hash of the email address 62 | email_md5 = Digest::MD5.hexdigest(email).to_s 63 | 64 | uri = URI("https://www.openhub.net/accounts/#{email_md5}.xml?v=1&api_key=#{api_key}") 65 | http = Net::HTTP.new(uri.host, uri.port) 66 | http.use_ssl = true 67 | response = http.get(uri.request_uri) 68 | 69 | # HTTP OK? 70 | if response.code != '200' 71 | STDERR.puts "#{response.code} - #{response.message}" 72 | exit 1 73 | end 74 | 75 | # Parse the response into a structured XML object 76 | xml = REXML::Document.new(response.body) 77 | 78 | # Did Open Hub return an error? 79 | error = xml.root.get_elements('/response/error').first 80 | if error 81 | STDERR.puts "#{error.text}" 82 | exit 1 83 | end 84 | 85 | # Output all the immediate child properties of an Account 86 | xml.root.get_elements('/response/result/account').first.each_element do |element| 87 | puts "#{element.name}:\t#{element.text}" unless element.has_elements? 88 | end 89 | 90 | # The kudo_rank element may not be present. 91 | # Check for it, and default to 1 if it is missing. 92 | xml_kudo_rank = xml.root.get_elements('/response/result/account/kudo_score/kudo_rank').first 93 | kudo_rank = xml_kudo_rank ? xml_kudo_rank.text.to_i : 1 94 | puts "kudo_rank:\t#{kudo_rank}" 95 | -------------------------------------------------------------------------------- /examples/account_sample.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # The MIT License (MIT) 4 | # 5 | # Copyright (c) 2013 Black Duck Software, Inc. 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in 15 | # all copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | # THE SOFTWARE. 24 | 25 | # This is an example of using the Open Hub API from Bash. 26 | # Detailed information can be found on GitHub: 27 | # 28 | # https://github.com/blackducksoftware/ohloh_api 29 | # 30 | 31 | # This example retrieves basic Open Hub account information 32 | # and outputs it as simple name: value pairs. 33 | # 34 | # Pass your Open Hub API key as the first parameter to this script. 35 | # Open Hub API keys are free. If you do not have one, you can obtain one 36 | # at the Open Hub website: 37 | # 38 | # https://www.openhub.net/accounts//api_keys/new 39 | # 40 | # Pass the email address of the account as the second parameter to this script. 41 | 42 | usage() { 43 | echo >&2 "Usage: $0 [api_key] [email]" 44 | exit 1 45 | } 46 | 47 | echo $1 | grep -q -E -e'.+' || usage 48 | API_KEY=$1 49 | 50 | echo $2 | grep -q -E -e'.+@.+\..+' || usage 51 | EMAIL_MD5=`echo -n $2 | openssl md5 | cut -f2 -d" "` 52 | 53 | # Pass the MD5 hash of the email address to Open Hub. 54 | # A quick-and-dirty sed filter converts the XML response to name:value pairs 55 | # 56 | # We use the --fail option so that curl will return a non-zero exit status if Open Hub returns an error. 57 | # This also means that the error message text returned from Open Hub will be suppressed from the output. 58 | curl --fail -s "https://www.openhub.net/accounts/$EMAIL_MD5.xml?v=1&api_key=$API_KEY" | sed -n 's/ *<\(.*\)>\(.*\)<\/\1>$/\1: \2/ p' 59 | 60 | # Forward along the exit status from curl 61 | exit $PIPESTATUS 62 | -------------------------------------------------------------------------------- /examples/oauth2/README.md: -------------------------------------------------------------------------------- 1 | ## Using OAuth 2.0 with the Open Hub API 2 | 3 | ### What is OAuth 2.0? 4 | 5 | [OAuth 2.0](http://oauth.net/2) is the next evolution of the OAuth protocol. It is an open protocol that allows applications and websites to share sensitive data, without requiring you to release your password. Using OAuth, you can permit third-party applications to read from your Open Hub account without having to share your password. 6 | 7 | Instead of handing out your Open Hub account password to a third-party application, you visit the Open Hub website directly and grant that application permission to access your Open Hub account. You can revoke this permission any time you change your mind. 8 | 9 | ### Using OAuth 2.0 10 | 11 | In order to become Open Hub OAuth consumer, you'd need to get your key and secret from your [API Keys](https://www.openhub.net/accounts/me/api_keys) page. 12 | 13 | The application [ohloh_oauth2_sinatra.rb](/examples/oauth2/ohloh_oauth2_sinatra.rb) is a simple [Sinatra](http://www.sinatrarb.com/) based example using the [oauth2 gem](https://github.com/intridea/oauth2) that fetches authenticated user's [account](/reference/account.md) xml. 14 | 15 | ### Developer Information 16 | 17 | OAuth 2.0 is an optional, additional feature of the Open Hub API that can be used to integrate Open Hub users on your website using their authenticated identity. You can read public data from Open Hub at any time using only your application’s Open Hub API Key. 18 | -------------------------------------------------------------------------------- /examples/oauth2/ohloh_oauth2_sinatra.rb: -------------------------------------------------------------------------------- 1 | require 'oauth2' 2 | require 'sinatra' 3 | 4 | enable :sessions 5 | CALLBACK_URL = 'http://localhost:9292/callback' 6 | 7 | # Assumes that you have set OpenHub_KEY and OpenHub_SECRET environment 8 | # variables to values from your API keys page. 9 | before do 10 | @client = OAuth2::Client.new(ENV['OpenHub_KEY'], ENV['OpenHub_SECRET'], 11 | site: 'https://www.openhub.net', 12 | token_method: :post) 13 | end 14 | 15 | def access_token 16 | OAuth2::AccessToken.new(@client, session[:access_token], refresh_token: session[:refresh_token]) 17 | end 18 | 19 | get '/login' do 20 | redirect @client.auth_code.authorize_url(redirect_uri: CALLBACK_URL) 21 | end 22 | 23 | get '/callback' do 24 | new_token = @client.auth_code.get_token(params[:code], redirect_uri: CALLBACK_URL) 25 | session[:access_token] = new_token.token 26 | session[:refresh_token] = new_token.refresh_token 27 | 28 | access_token.get('accounts/me.xml').body 29 | end 30 | -------------------------------------------------------------------------------- /reference/account.md: -------------------------------------------------------------------------------- 1 | ## Account 2 | 3 | An Account represents an Open Hub member. Some Account data is private, and cannot be accessed through the Open Hub API. 4 | 5 | ### Properties 6 | + __id__ 7 | The unique ID for the Account. 8 | 9 | + __name__ 10 | The public name for this Account. 11 | 12 | + __about__ 13 | A short description about this account. 14 | 15 | + __login__ 16 | The Login handle for this account. 17 | 18 | + __created_at__ 19 | The time at which this Account was originally created on Open Hub. 20 | 21 | + __updated_at__ 22 | The time at which this Account record was last modified. 23 | 24 | + __homepage_url__ 25 | An optional URL to a member’s home page, such as a blog. 26 | 27 | + __twitter_account__ 28 | An optional Twitter handle for this account. 29 | 30 | + __url__ 31 | A URL, returning details about this account in XML format. 32 | 33 | + __html_url__ 34 | A URL to the profile's Home page for this account. 35 | 36 | + __avatar_url__ 37 | A URL to the profile image displayed on Open Hub pages. Currently, this is an URL to the Gravatar free image hosting service, which will resolves to a default image if the account holder is not a Gravatar member. Images are 80×80 by default. 38 | 39 | + __email_sha1__ 40 | The SHA1 hex digest of the account email address. 41 | 42 | + __posts_count__ 43 | The number of posts made to the Open Hub forums by this account. 44 | 45 | + __location__ 46 | An optional text description of this account holder’s claimed location. This text has been validated by either the Google or Yahoo geocoder web service, but the precision is variable. 47 | 48 | + __country_code__ 49 | A string representing the account holder’s country. This field is derived from location using either the Google or Yahoo geocoder web service. If you use this data, read the important note below. 50 | 51 | + __latitude__ and __longitude__ 52 | Floating-point values representing the account’s latitude and longitude, suitable for use with the Google Maps API. They are available only when the account has specified a valid location. 53 | 54 | + __kudo_score__ 55 | If this account has a KudoScore, it will appear here. New accounts may not have a KudoScore. The Open Hub web site displays these accounts with a default KudoRank of 1. 56 | 57 | + __languages__ 58 | Only available when requesting an accounts details, this node will not be returned as part of a search result list. This node contains the total language experience for this account grouped by language.Eachnode contains the following children: 59 | - __@color__ 60 | This is the Open Hub color code for this language. If you will be displaying this data in your application it is highly recommended you use the colors returned here as these are the same colors Open Hub uses to display specific languages. 61 | - __name__ 62 | The Open Hub code name for this language, e.g. C# will be csharp and C++ will be cpp. 63 | - __experience_months__ 64 | The total number of months that Open Hub has computed as experience in this language for the current Account. 65 | - __total_commits__ 66 | The total number of commits made by the current Account that contained code in the current Language. 67 | - __total_lines_changed__ 68 | The total number of lines changed by the current Account that contained code in the current Language. 69 | - __comment_ratio__ 70 | The ratio of comment lines to code lines in commits made by the current Account for the current Language. 71 | 72 | ```xml 73 | 74 | 75 | javascript 76 | 24 77 | 116 78 | 563,931 79 | 23.4% 80 | 81 | 82 | css 83 | 20 84 | 83 85 | 74,705 86 | 4.3% 87 | 88 | 89 | html 90 | 19 91 | 62 92 | 27,875 93 | 20.5% 94 | 95 | 96 | ``` 97 | 98 | + __badges__ 99 | Lists the badges awarded to the account holder. All accounts have a Kudo Score of at least 1, so the Kudo Rank badge will always appear here. Badges are listed with these attributes: 100 | - __name__ 101 | The name of the badge 102 | - __level__ 103 | The numeric value of the level for the badge. Some badges are "binary", such as the Project Manager or the Organization Manager badges. These are awarded when the account holder manages a project or organization, respectively. For these types of badges, the level is '0' 104 | - __description__ 105 | This is the description of the badge that is used for tool tips on Open Hub 106 | - __image_url__ 107 | This is the URL of a 64x64 pixel icon of the badge image 108 | - __pips_url__ 109 | This is the URL of a 15x64 pixel icon of the pips based on the level. This will be empty when the level is 0. 110 | 111 | ### Making API Calls 112 | 113 | #### Individual account 114 | To get a single Account: 115 | ```shell 116 | curl https://www.openhub.net/accounts/{account_id}.xml 117 | ``` 118 | 119 | You can also retrieve an Account using the MD5 hash of the email address, if you know it: 120 | ```shell 121 | curl https://www.openhub.net/accounts/{email_md5_hash}.xml 122 | ``` 123 | 124 | Read more about email-based queries [here](/email_lookup.md). 125 | 126 | #### Collection of accounts 127 | To get a list of all Accounts: 128 | ```shell 129 | curl https://www.openhub.net/accounts.xml 130 | ``` 131 | 132 | The account collection method supports the standard [collection request parameters](/README.md#collection-requests) with the following details: 133 | 134 | + __query__ 135 | If supplied, only accounts matching the query string will be returned. Only the name field is searched. 136 | + __sort__ 137 | Account collections support the following sort options: 138 | - __created_at (default)__ 139 | Recently created, first 140 | - __name__ 141 | - __updated_at__ 142 | Recently updated, first 143 | 144 | ### A Note about Country Codes 145 | Open Hub preferentially uses the [Google Maps API](http://www.google.com/apis/maps/documentation/index.html) geocoder to resolve location names entered by users. `country_code` values obtained from the Google Maps API use two-letter abbreviations. 146 | 147 | However, Google’s coverage is not complete, and not all countries can be resolved. For countries that cannot be resolved by the Google geocoder, Open Hub falls back to the Yahoo geocoder. These countries include the United Kingdom and China. `country_code` values obtained from Yahoo are full country names, not two-letter abbreviations. 148 | 149 | For this reason, there are two data formats intermingled in country_code. Open Hub does not use this data internally, so the data has not been cleaned and unified. 150 | -------------------------------------------------------------------------------- /reference/activity_fact.md: -------------------------------------------------------------------------------- 1 | ## ActivityFact 2 | An ActivityFact is a pre-computed collection of statistics about [Project](/reference/project.md) source code. It summarizes changes to lines of code, commits, and contributors in a single month. 3 | 4 | [SizeFacts](/reference/size_fact.md) contain the running totals of ActivityFacts. 5 | 6 | An ActivityFact is derived from lower-level statistics contained in an [Analysis](/reference/analysis.md). ActivityFacts are updated whenever a [Project](/reference/project.md) is re-analyzed. 7 | 8 | ActivityFacts are availabled only after Open Hub has downloaded and analyzed the project source code. 9 | 10 | ### Properties 11 | 12 | + __month__ 13 | Indicates the month covered by this ActivityFact. Only the year and month fields are significant. This ActivityFact record includes all development activity that occured during this month. 14 | + __code_added__ 15 | The total new lines of code added, excluding comments and blanks, during this month. 16 | + __code_removed__ 17 | The total lines of code removed, excluding comments and blanks, during this month. 18 | + __comments_added__ 19 | The total lines of new comments added during this month. 20 | + __comments_removed__ 21 | The total lines of comments removed during this month. 22 | + __blanks_added__ 23 | The total blank lines added during this month. 24 | + __blanks_removed__ 25 | The total blank lines removed during this month. 26 | + __commits__ 27 | The number of commits made during this month. 28 | + __contributors__ 29 | The number of contributors who made at least one commit during this month. 30 | 31 | ### Collection URL 32 | To get all ActivityFacts for a particular [Analysis](/reference/analysis.md): 33 | ```shell 34 | curl https://www.openhub.net/p/{project_id}/analyses/{analysis_id}/activity_facts.xml 35 | ``` 36 | If you do not know the ID of the current best Analysis for a Project, you can use the `latest` as a shortcut for latest published analysis. 37 | ```shell 38 | curl https://www.openhub.net/p/{project_id}/analyses/latest/activity_facts.xml 39 | ``` 40 | 41 | The call returns one Activity for each month, starting at the first month in which any code exists, and ending at the current month. If Open Hub has not created a new Analysis for this Project in a long time, the ActivityFacts for the months following the time of the last Analysis will contain zeros. 42 | 43 | The results cannot be paginated or filtered. Results are sorted chronologically. 44 | -------------------------------------------------------------------------------- /reference/affiliated_committers.md: -------------------------------------------------------------------------------- 1 | ##Affiliated Committers 2 | People that are part of an organization and commit to its projects 3 | 4 | 5 | ### Properties 6 | 7 | + __affiliator__ 8 | + __name__ Name of the user account 9 | + __kudos__ Kudos obtained by the user account 10 | + __level__ Level of the user account 11 | + __most_commits__ 12 | + __project__ Name of the project to which the committer has made most commits to 13 | + __commits__ No of commits made to the most committed project 14 | + __most_recent_commit__ 15 | + __project__ Name of the project last to committed by the affiliator 16 | + __date__ Date of the last commit 17 | + __detailed_page_url__ This page's relative url 18 | 19 | 20 | ### URL 21 | 22 | ```shell 23 | https://www.openhub.net/orgs/{org_name}/affiliated_committers.xml?api_key={api_key}&page={number} 24 | ``` 25 | 26 | #### Example 27 | 28 | ```ruby 29 | https://www.openhub.net/orgs/mozilla/affiliated_committers.xml?api_key=some_example_api_key&page=2 30 | ``` 31 | -------------------------------------------------------------------------------- /reference/analysis.md: -------------------------------------------------------------------------------- 1 | ## Analysis 2 | 3 | An Analysis is a pre-computed collection of statistics about [Project](/reference/project.md) source code and contributors. 4 | 5 | An individual Analysis never changes. When a Project’s source code is modified, a completely new Analysis is generated for that Project. Eventually, old analyses are deleted from the database. Therefore, you should always obtain the ID of the best current analysis from the project record before requesting an analysis. 6 | 7 | The Analysis object described here contains only a few top-level metrics. Detailed, historical metrics are contained within child objects of an Analysis, which will be exposed through the API at a later date. 8 | 9 | ### Properties 10 | 11 | + __id__ 12 | The unique ID for the Analysis. 13 | + __url__ 14 | A URL, returning details about this Analysis in XML format. 15 | + __project_id__ 16 | The unique ID of the Project measured by this Analysis. 17 | + __updated_at__ 18 | The time at which this Analysis record was last modified. 19 | + __oldest_code_set_time__ 20 | The time at which Open Hub queried the source control system for the source code measured by this Analysis. All commits which occured at or before this time are included. Note that the Analysis might also include some activity after this time if the project includes many [Repositories](/reference/repository.md), because not all Repositories are updated at the same time. The logged_at time is the most pessimistic time among all the Repositories included in the Project. 21 | + __min_month__ 22 | Open Hub groups most historical statistics ([ActivityFacts](/reference/activity_fact.md) and [SizeFacts](/reference/size_fact.md)) into monthly totals. min_month indicates the first month for which Open Hub has monthly historical statistics available for this project. This is typically the date of the first project commit, truncated to the beginning of its calendar month. Only the year and month fields are significant. 23 | + __max_month__ 24 | The last month for which monthly historical statistics are available for this project. Depending on when this analysis was prepared, max_month usually refers to the current month, but it may be slightly older. Only the year and month fields are significant. Open Hub’s monthly statistics for max_month are usually smaller than other months because the complete month has not yet elapsed, and it reflects ongoing development work. 25 | + __twelve_month_contributor_count__ 26 | The number of contributors who made at least one commit to the project source code in the twelve months leading up to and including `max_month`. 27 | + __total_contributor_count__ 28 | The total number of contributors who made at least one commit to the project source code leading up to and including `max_month`. 29 | + __twelve_month_commit_count__ 30 | The number of commits to the project source code in the twelve months leading up to and including `max_month`. 31 | + __total_commit_count__ 32 | The total number of commits to the project source code leading up to and including `max_month`. 33 | + __total_code_lines__ 34 | The most recent total count of all source code lines. Blank lines and comment lines are excluded. 35 | + __main_language_id__ 36 | The unique ID of the most common programming language used in this project. XML and HTML are ignored when making this determination. 37 | + __main_language_name__ 38 | The name of the most common programming language used in this project. XML and HTML are ignored when making this determination. 39 | + __factoids__ 40 | The factoids for the current Analysis will be included under this node. 41 | 42 | ```xml 43 | 44 | Very large, active development team 45 | Mature, well-established codebase 46 | Increasing year-over-year development activity 47 | Few source code comments 48 | 49 | ``` 50 | 51 | + __language__ 52 | The language breakdown chart for the current Analysis will be included under this node. The node will have the following children: 53 | - _@graph_url_ 54 | This is the url to the PNG image that depicts the language breakdown for the current Analysis. The colors referenced in each languages @color attribute will be used in this image. 55 | - _language_ 56 | Not every language will have a entry. Open Hub will will combine languages that do not make up a significant percentage into a aggregate entry “N Other”. This entry can be identified by either its @color, always “000000″ or @id, always “”. 57 | Each language will contain the following data 58 | - @color The color code that Open Hub uses to represent this language on the website. This color is also used in the language breakdown graph image. 59 | - @percentage The percentage of lines of code that the current language represents in the current Analysis 60 | - @id The Open Hub language id. 61 | 62 | ```xml 63 | 64 | C++ 65 | C 66 | JavaScript 67 | 28 Other 68 | 69 | ``` 70 | 71 | 72 | ### URL 73 | To get a particular Analysis for a single Project: 74 | ```shell 75 | curl https://www.openhub.net/p/{project_id}/analyses/{analysis_id}.xml 76 | ``` 77 | 78 | A shortcut to the current best Analysis for a single Project can be made by substituting `latest` for the analysis ID: 79 | ```shell 80 | curl https://www.openhub.net/p/{project_id}/analyses/latest.xml 81 | ``` 82 | -------------------------------------------------------------------------------- /reference/code_location.md: -------------------------------------------------------------------------------- 1 | ## Code Location 2 | A Code Location represents an individual source control repository. 3 | 4 | Once added to the Open Hub database, a Code Location is permanent and unique. 5 | 6 | A Code Location is added to a [Project](project.md) by creating an [Enlistment](enlistment.md), which links the Project to the Code Location. In this way, many Projects can share the same Code Location. 7 | 8 | Deleting an Enlistment from a Project does not delete a Code Location, nor will it interrupt Open Hub download activity against that Code Location. The Code Location and all of its source code and metrics remain in the Open Hub database; only the Enlistment link is modified. 9 | 10 | ### Properties 11 | 12 | + __id__ 13 | The unique ID of the Code Location. 14 | + __type__ 15 | The source control type. Supported values are: 16 | - _SvnRepository_ 17 | Subversion 18 | - _CvsRepository_ 19 | CVS 20 | - _GitRepository_ 21 | Git 22 | - _HgRepository_ 23 | Mercurial 24 | - _BzrRepository_ 25 | Bazaar 26 | 27 | + __url__ 28 | The public URL for the source control server. 29 | + __module_name__ 30 | For CVS repositories only, this is the module name. For Git repositories only, this is the branch name. For all other repository types, this element is omitted. 31 | + __username__ 32 | An optional username, if one is required to access the source control server. 33 | + __password__ 34 | An optional password, if one is required to access the source control server. 35 | + __logged_at__ 36 | The last time the Open Hub servers successfully queried the source control server for changes. 37 | + __commits__ 38 | The number of commits which the Open Hub servers have successfully downloaded from the source control server. 39 | + __ohloh_job_status__ 40 | If the most recent attempt by Open Hub to query the source control server for changes failed or was interrupted, this value will be `failed`. In all other cases it is `success`. 41 | 42 | ### URL 43 | Code Locations cannot be directly queried at this time. Access them by using the [Enlistments](enlistment.md) methods. 44 | -------------------------------------------------------------------------------- /reference/contributor_fact.md: -------------------------------------------------------------------------------- 1 | ## ContributorFact 2 | 3 | A ContributorFact contains a selection of high-level statistics about a person who commited source code to a [Project](/reference/project.md). One ContributorFact record exists for each contributor. 4 | 5 | A ContributorFact is part of an [Analysis](/reference/analysis.md), and is derived from lower-level statistics contained within the Analysis. 6 | 7 | A new ContributorFact is created for each Project contributor whenever a new Analysis is created for the Project. 8 | 9 | ContributorFacts only exist after Open Hub has downloaded and analyzed the project source code. 10 | 11 | ### Properties 12 | 13 | 14 | + __analysis_id__ 15 | The unique ID for the [Analysis](/reference/analysis.md) which provided the source data for this ContributorFact. 16 | + __contributor_id__ 17 | The ID for the person who contributed the code measured in this ContributorFact. The `contributor_id` is not globally unique. It is derived from the author name found in the source control server log, and is unique within the scope of an individual project only. 18 | + __contributor_name__ 19 | The name used by the author of this code when committing to the source control server. 20 | + __account_id__ 21 | If this contribution has been claimed by an Open Hub member, the element contains the unique ID of the Open Hub [Account](/reference/account.md). Otherwise, this element is omitted. 22 | + __account_name__ 23 | If this contribution has been claimed by an Open Hub member, this element contains the Account name. Otherwise, this element is omitted. 24 | + __primary_language_id__ 25 | The unique ID of the [Language](/reference/language.md) most often used by this contributor, measured by the number of code lines added. If this contributor has not committed any code in a language which Open Hub can recognize, this value will be null. 26 | + __primary_language_nice_name__ 27 | The `nice_name` of the Language specified by `primary_language_id`. 28 | + __comment_ratio__ 29 | The fraction of new lines added by this contributor which are comments. Note that Open Hub does not track the net lines of current code attributable to an specific individual. This statistic merely sums over all new lines added, and does not consider whether the added lines were later removed by this contributor or any other. 30 | + __first_commit_time__ 31 | The time of the first commit by this contributor. 32 | + __last_commit_time__ 33 | The time of the last commit by this contributor. 34 | + __man_months__ 35 | The total number of calendar months in which this contributor made at least one commit. Note that this is not simply the number of months between `first_commit_time` and `last_commit_time`: months in which there was no activity for this contributor are not counted. 36 | + __commits__ 37 | The total number of commits made by this contributor. 38 | + __contributor_language_facts__ 39 | A collection of [ContributorLanguageFacts](/reference/contributor_language_fact.md) may be included here, covering statistics in individual [Languages](/reference/language.md). This collection is only present when ContributorFacts are queried individually. 40 | 41 | ### URL 42 | To get a single ContributorFact based on the latest Analysis for a Project: 43 | ```shell 44 | curl https://www.openhub.net/p/{project_id}/contributors/{contributor_id}.xml 45 | ``` 46 | This ContributorFact will include within it a collection of [ContributorLanguageFacts](/reference/contributor_language_fact.md) covering statistics for individual languages. 47 | 48 | ### Collection URL 49 | To get a list of all ContributorFacts based on the lastest Analysis for a Project: 50 | ```shell 51 | curl https://www.openhub.net/p/{project_id}/contributors.xml 52 | ``` 53 | ContributorFacts returned from this call will not include ContributorLanguageFacts. Those can be obtained by retrieving ContributorFacts individually only. 54 | 55 | The project collection request supports the standard [collection request parameters](/README.md#collection-requests), with the following details: 56 | 57 | + __query__ 58 | If supplied, only ContributorFacts with a matching `contributor_name` will be returned. Open Hub account names are not matched. 59 | + __sort__ 60 | ContributorFact collections support the following sort options: 61 | - __name__ 62 | - __kudo_position__ 63 | - __commits__ 64 | Highest commits, first 65 | - __commits_12_mo (default)__ 66 | Highest commits in past twelve months, first 67 | - __language__ 68 | - __latest_commit__ 69 | - __newest__ 70 | - __oldest__ 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /reference/contributor_language_fact.md: -------------------------------------------------------------------------------- 1 | ## ContributorLanguageFact 2 | 3 | A ContributorLanguageFact contains a selection of [Language](/reference/language.md)-specific statistics about a single person who commited source code to a [Project](/reference/project.md). 4 | 5 | One ContributorFact record exists for each Language used by a contributor. 6 | 7 | The ContributorLanguageFact is very similar to a [ContributorFact](/reference/contributor_fact.md). The difference is that a ContributorLanguageFact contains statistics for a particular Language only, while a ContributorFact contains summary statistics across all languages used by the contributor. 8 | 9 | A ContributorLanguageFact is part of an Analysis, and is derived from lower-level statistics contained within the [Analysis](/reference/analysis.md). New ContributorLanguageFacts are created for each Project contributor whenever a new Analysis is created for the Project. 10 | 11 | ContributorLanguageFacts only exist after Open Hub has downloaded and analyzed the project source code. 12 | 13 | ### Properties 14 | 15 | + __analysis_id__ 16 | The unique ID for the [Analysis](/reference/analysis.md) which provided the source data for this ContributorFact. 17 | + __contributor_id__ 18 | The ID for the person who contributed the code measured in this ContributorLanguageFact. The `contributor_id` is not globally unique. It is derived from the author name found in the source control server log, and is unique within the scope of an individual project only. 19 | + __contributor_name__ 20 | The name used by the author of this code when committing to the source control server. 21 | + __language_id__ 22 | The unique ID of the [Language](/reference/language.md) measured. 23 | + __language_nice_name__ 24 | The `nice_name` of the Language measured. 25 | + __comment_ratio__ 26 | The fraction of new lines added by this contributor in this language which are comments. Note that Open Hub does not track the net lines of current code attributable to an specific individual. This statistic merely sums over all new lines added, and does not consider whether the added lines were later removed by this contributor or any other. 27 | + __man_months__ 28 | The total number of calendar months in which this contributor made at least one commit using this Language. Months in which there was no activity in this Language for this contributor are not counted. 29 | + __commits__ 30 | The total number of commits made in this Language by this contributor. 31 | 32 | ### Collection URL 33 | To get a list of all ContributorLanguageFacts for a particular contributor, based on the lastest Analysis for a Project: 34 | ```shell 35 | curl https://www.openhub.net/p/{project_id}/contributors/{contributor_id}.xml 36 | ``` 37 | This is the same URL used to obtain a [ContributorFact](/reference/contributor_fact.md). The ContributorFact returned by this call will include within it a collection of ContributorLanguageFacts. 38 | -------------------------------------------------------------------------------- /reference/enlistment.md: -------------------------------------------------------------------------------- 1 | ## Enlistment 2 | An Enlistment joins a [Project](/reference/project.md) to a source control [Code Location](/reference/code_location.md). 3 | 4 | Once added to the Open Hub database, a Code Location is permanent. However, Enlistments to that Code Location may be added or removed at any time. Many Projects may share a single CodeLocation. 5 | 6 | ### Properties 7 | 8 | + __id__ 9 | The unique ID of the Enlistment. 10 | + __project_id__ 11 | The unique ID of the [Project](/reference/project.md). 12 | + __code_location__ 13 | The [Code Location](/reference/code_location.md) record will be included in full here. 14 | 15 | ### URL 16 | To get a single Enlistment 17 | ```shell 18 | curl GET https://www.openhub.net/p/{project_id}/enlistments/{enlistment_id}.xml 19 | ``` 20 | 21 | ### Collection URL 22 | To get a list of all enlistments for a particular project: 23 | ``` shell 24 | curl https://www.openhub.net/p/{project_id}/enlistments.xml 25 | ``` 26 | 27 | The Enlistment collection method supports the standard [collection request parameters](/README.md#collection-requests) with the following details: 28 | 29 | + __query__ 30 | If supplied, enlistments with a code_location URL matching the query string will be returned. 31 | + __sort__ 32 | Enlistment collections support the following sort options: 33 | - __module_name__ 34 | - __project__ 35 | - __type__ 36 | - __url (default)__ 37 | 38 | 39 | -------------------------------------------------------------------------------- /reference/factoid.md: -------------------------------------------------------------------------------- 1 | ## Factoid 2 | 3 | A Factoid is a short, high-level bullet point delivering a simple observation about a [Project](/reference/project.md). Factoids are derived from an Analysis, and new Factoids are created for a Project every time a new [Analysis](/reference/analysis.md) is created. 4 | 5 | On the Open Hub web site, Factoids are rendered in the Nutshell section of the project summary page. Factoids also are available in several of the sharing widgets available for embedding on websites. 6 | 7 | A Project has factoids only if Open Hub has downloaded and analyzed its source code. 8 | 9 | ### Properties 10 | + __id__ 11 | The unique ID for the Factoid. Factoid IDs change every time the Project is reanalyzed, so it’s unwise to store these IDs for long periods. 12 | 13 | + __analysis_id__ 14 | The unique ID of the [analysis](/reference/analysis.md) used to calculate this factoid. 15 | 16 | + __type__ 17 | The Factoid type. The possible types are defined below. 18 | 19 | + __description__ 20 | A short, human-readable description. This is the bullet point text which appears on the Open Hub project page. 21 | 22 | + __severity__ 23 | An integer from -3 to +3 which rates the relative severity of the factoid. Negative numbers generally indicate bad news, positive numbers generally indicate good news. Open Hub uses these numbers to select icons to display beside the factoids. All factoids of the same type have the save severity. 24 | 25 | ### Collection URL 26 | To get a list of all current Factoids for a particular Project: 27 | ```shell 28 | curl https://www.openhub.net/p/{project_id}/factoids.xml 29 | ``` 30 | The collection request does not support any filtering, sorting or paging. You will always receive the entire collection of factoids, ordered by descending priority. 31 | 32 | ### Factoid Types 33 | 34 | + __FactoidActivityDecreasing__ 35 | During the last twelve calendar months, there were at least 25% fewer commits to this project than in the prior twelve calendar months. 36 | 37 | + __FactoidActivityStable__ 38 | During the last twelve calendar months, the commit count was within +/- 25% of the count for the prior twelve calendar months. 39 | 40 | + __FactoidActivityIncreasing__ 41 | During the last twelve calendar months, there were at least 25% more commits to this project than in the prior twelve calendar months. 42 | 43 | + __FactoidAgeYoung__ 44 | The source control repository is less than 1 year old. 45 | 46 | + __FactoidAgeEstablished__ 47 | The source control repository is 1 to 3 years old. 48 | 49 | + __FactoidAgeOld__ 50 | The source control repository is 3 to 5 years old. 51 | 52 | + __FactoidAgeVeryOld__ 53 | The source control repository is 5 years old or older. 54 | 55 | + __FactoidCommentsVeryLow__ 56 | Compared to all other projects written in the same language, the comment ratio for this project is in the bottom 10%. 57 | 58 | + __FactoidCommentsLow__ 59 | Compared to all other projects written in the same language, the comment ratio for this project is in the bottom 33% but not in the bottom 10%. 60 | 61 | + __FactoidCommentsAverage__ 62 | Compared to all other projects written in the same language, the comment ratio for this project is in the middle 33%. 63 | 64 | + __FactoidCommentsHigh__ 65 | Compared to all other projects written in the same language, the comment ratio for this project is in the top 33% but not in the top 10%. 66 | 67 | + __FactoidCommentsVeryHigh__ 68 | Compared to all other projects written in the same language, the comment ratio for this project is in the top 10%. 69 | 70 | + __FactoidTeamSizeZero__ 71 | No commits were made to this project in the last 12 months. 72 | 73 | + __FactoidTeamSizeOne__ 74 | Only a single contributor made commits to this project in the last 12 months. 75 | 76 | + __FactoidTeamSizeSmall__ 77 | Two or three contributors made commits to this project in the last 12 months. 78 | 79 | + __FactoidTeamSizeAverage__ 80 | 4 to 6 contributors made commits to this project in the last 12 months. 81 | 82 | + __FactoidTeamSizeLarge__ 83 | 7 to 27 contributors made commits to this project in the last 12 months. 84 | 85 | + __FactoidTeamSizeVeryLarge__ 86 | 28 or more contributors made commits to this project in the last 12 months. 87 | 88 | __Note about "mostly written in"__ - "... is mostly written in" bullet point listed in the Nutshell section of project summaries and in widgets displaying factoid information is not technically a factoid. This element is actually the `main_language_name` property on an [analysis](/reference/analysis.md). 89 | -------------------------------------------------------------------------------- /reference/kudo.md: -------------------------------------------------------------------------------- 1 | ## Kudo 2 | A Kudo is a simple gesture of thanks, praise, or endorsement from an Open Hub [account](/reference/account.md) to another person. An account may send Kudos to as many people as desired. 3 | 4 | Kudos can be sent directly to another Open Hub account, or they may be sent to a contributor on a Project who does not have an Open Hub account. This flexibility makes Kudo records slightly complex. 5 | 6 | When a Kudo is sent directly to an Open Hub Account, the recipient is identified by `receiver_account_id`. 7 | 8 | When a Kudo is sent to a contributor on a Project who does not have an Account, the Kudo record contains both `contributor_id` and `project_id`, which together uniquely identify the recipient. 9 | 10 | Ocassionally, an Open Hub Account holder may claim to be a Project contributor who has some existing Kudos. When this happens, the existing Kudos become linked to the Account, and the Kudos will now have all three properties: `receiver_account_id`, `contributor_id`, and `project_id`. 11 | 12 | ### Properties 13 | + __created_at__ 14 | The time at which this Kudo was sent. 15 | + __sender_account_id__ 16 | The unique ID of the [Account](account.md) sending this Kudo. 17 | + __sender_account_name__ 18 | The name of the [Account](account.md) sending this Kudo. 19 | + __receiver_account_id__ 20 | If this Kudo can be linked to an Account, this is the unique ID of the Account receiving this Kudo. Otherwise, this element is omitted. 21 | + __receiver_account_name__ 22 | If this kudo can be linked to an Account, this is the name of the Account receiving this Kudo. Otherwise, this element is omitted. 23 | + __project_id__ 24 | If this Kudo was sent to a Project contributor instead of an Account, this is the unique ID of the [Project](project.md). Otherwise, this element is omitted. 25 | + __project_name__ 26 | If this Kudo was sent to a Project contributor instead of an Account, this is the Project name. Otherwise, this element is omitted. 27 | + __contributor_id__ 28 | If this Kudo was sent to a Project contributor instead of an Account, this is the unique ID of the contributor. Otherwise, this element is omitted. 29 | + __contributor_name__ 30 | If this Kudo was sent to a Project contributor instead of an account, this is the name which appears in the source control logs. Otherwise, this element is omitted. 31 | 32 | ### Collection URL 33 | To get a list of all Kudos received by an Account: 34 | ```shell 35 | curl https://www.openhub.net/accounts/{account_id}/kudos.xml 36 | ``` 37 | To get a list of all Kudos sent by an Account: 38 | ```shell 39 | curl https://www.openhub.net/accounts/{account_id}/kudos/sent.xml 40 | ``` 41 | These methods do not support any sorting, filtering, or paging options. You will always receive the complete list of all Kudos, sorted from new to old. 42 | 43 | If you do not know the Account ID, you can also query for Kudos using the MD5 hash of the email address. Read more about email-based queries [here](/email_lookup.md). 44 | 45 | -------------------------------------------------------------------------------- /reference/kudo_score.md: -------------------------------------------------------------------------------- 1 | ## Kudo Score 2 | 3 | Every night, a KudoScore is generated for every Open Hub Account and Project contributor (collectively called ‘participants’ here). These scores are derived from the [Kudos](kudo.md) sent between participants. You can read a general outline of the KudoRank algorithm [here](http://blog.openhub.net/kudos/). 4 | 5 | Not everyone has a KudoScore. Because KudoScores are calculated only once per day, new Accounts and contributors may not have a kudo score. On the Open Hub web site, unscored Accounts and contributors are displayed with a default KudoRank of 1. 6 | 7 | ### Properties 8 | 9 | + __kudo_rank__ 10 | The KudoRank, which is an integer from 1 to 10. Higher ranks are better. KudoRanks are assigned on a curve, with a certain fraction of people receiving each KudoRank. 11 | + __position__ 12 | An integer which orders all participants. The person with `position` equals 1 is the highest-ranked person on Open Hub. 13 | 14 | ### URL 15 | KudoScores cannot be queried directly. They are always returned within an [Account](account.md) record. 16 | -------------------------------------------------------------------------------- /reference/language.md: -------------------------------------------------------------------------------- 1 | ## Language 2 | 3 | A Language record contains the name and various statistics related to a programming language. 4 | 5 | Language statistics are updated daily. 6 | 7 | ### Properties 8 | 9 | + __id__ 10 | The unique ID of the language. 11 | + __name__ 12 | A short, unique name for the language. Primarily for internal Open Hub use. 13 | + __nice_name__ 14 | A human-friendly name for the language. 15 | + __category__ 16 | Either code, markup, or build, which indicates that the language is either a “standard” programming language, a document markup language such as XML, or a build script such as a makefile. 17 | + __code__ 18 | The total net lines of code, excluding comments and blank lines, written in this language across all projects on Open Hub. 19 | + __comments__ 20 | The total net comment lines written in this language across all projects on Open Hub. 21 | + __blanks__ 22 | The total net blank lines in this language across all projects on Open Hub. 23 | + __comment_ratio__ 24 | A precomputed floating-point value for the percent of lines in this language that are comments, across all projects on Open Hub. 25 | + __projects__ 26 | The total number of Projects on Open Hub which currently include at least one line in this language. 27 | + __contributors__ 28 | The total number of contributors on Open Hub who have written at least one line of code in this language that still exists today. 29 | + __commits__ 30 | The total number of commits on Open Hub which include at least one line in this language. 31 | 32 | ### Collection URL 33 | To get a paginated list of all Languages: 34 | ```shell 35 | curl https://www.openhub.net/languages.xml 36 | ``` 37 | The Language collection request supports the standard [collection request parameters](/README.md#collection-requests), with the following sort options: 38 | 39 | + __total__ 40 | Results are sort by the total source lines, including comments and blanks, from highest to lowest. 41 | + __code__ 42 | Results are sorted by code lines only from highest to lowest. 43 | + __projects__ 44 | Results are sorted by the number of projects, from highest to lowest. 45 | + __comment_ratio__ 46 | Results are sorted by comment_ratio from highest to lowest. 47 | Results are sorted by the number of Projects, from highest to lowest. 48 | + __contributors__ 49 | Results are sorted by the number of contributors, from highest to lowest 50 | + __commits__ 51 | Results are sorted by the number of commits, from highest to lowest. 52 | + __name (default)__ 53 | Results are sorted alphabetically by nice_name. 54 | -------------------------------------------------------------------------------- /reference/organization-collection.md: -------------------------------------------------------------------------------- 1 | ##Organization 2 | An organization is an entity which contains a collection of projects and accounts. 3 | 4 | 5 | ### Properties 6 | + __name__ Organization Name 7 | + __url__ XML Api URL for the current organization. 8 | + __html_url__ The URL for the current organization page on Open Hub. 9 | + __created_at__ The time at which the organization was initially added to Open Hub. 10 | + __updated_at__ The time of most recent modification to the organization record. 11 | + __description__ The optional description of the current organization, currently limited to 800 characters. 12 | + __homepage_url__ An optional URL for the home page of the organization, e.g Apache Software Foundation (www.apache.org) 13 | + __url_name__ A short, unique, handle for the current organization. e.g for url_name as 'apache' the equivalent web link is www.openhub.net/orgs/apache 14 | + __small_logo_url__ An url to the organization’s 32×32 pixels logo image. 15 | + __medium_logo_url__ An url to the organization’s 64×64 pixels logo image. 16 | + __type__ The type of the organizations(Non-profit/commercial/Government/Educational). 17 | + __projects_count__ The number of portfolio projects under the organization. 18 | + __affiliated_committers__ The count of number of committers affiliated to the organization. 19 | 20 | 21 | ### Collection URL 22 | ```shell 23 | https://www.openhub.net/orgs.xml?api_key={api_key}&page={number}&sort={projects}&query={keyword} 24 | ``` 25 | 26 | The organization collection request supports the standard [collection request parameters](/README.md#collection-requests), with the following details: 27 | 28 | + __query__ If supplied, only organizations matching the query string will be returned. 29 | 30 | - An organization match occurs if its name, description, or any of its tags contain the query string. 31 | 32 | + __sort__ Organization collection supports the following sort options : 33 | 34 | - __name__ Sort by organization name. 35 | - __projects_count__ Sort by number of portfolio projects in the organization. 36 | - __created_at__ Sort by the organization created date/time. 37 | - __updated_at__ Sort by organization record's last updated date/time. 38 | 39 | + __page__ Results page for the organization collection xml api. 40 | 41 | - The first page of results are displayed when the API is queried without passing a 'page' parameter in the url. 42 | - Successive pages of results can be queried using ```page=1``` upto ```page=n``` 43 | 44 | #### Example 45 | 46 | ```ruby 47 | https://www.openhub.net/orgs.xml?api_key=some_example_api_key&page=2&sort=projects_count&query=java 48 | ``` 49 | -------------------------------------------------------------------------------- /reference/organization.md: -------------------------------------------------------------------------------- 1 | ### Organization 2 | An organization is an entity which contains a collection of projects and accounts. 3 | 4 | 5 | ### Properties 6 | + __name__ Organization Name 7 | + __url__ XML API URL for the organization. 8 | + __html_url__ The URL for the organization page on Open Hub. 9 | + __created_at__ The time at which the organization was initially added to Open Hub. 10 | + __updated_at__ The time of most recent modification to the organization record. 11 | + __description__ The optional description of the organization, currently limited to 800 characters. 12 | + __homepage_url__ An optional URL for the home page of the organization, e.g Apache Software Foundation (www.apache.org) 13 | + __url_name__ A short, unique, handle for the organization. e.g for url_name as 'apache' the equivalent web link is www.openhub.net/orgs/apache 14 | + __small_logo_url__ An url to the organization’s 32×32 pixels logo image. 15 | + __medium_logo_url__ An url to the organization’s 64×64 pixels logo image. 16 | + __type__ The type of the organization(Non-profit/Commercial/Government/Educational). 17 | + __inforgraphic_details__ Details presented in the organization page inforgraphic image 18 | + __outside_committers__ 19 | + __outside_committers_commits__ 20 | + __projects_having_outside_commits__ 21 | + __portfolio_projects__ 22 | + __affiliators__ 23 | + __affiliators_committing_to_portfolio_projects__ 24 | + __affiliator_commits_to_portfolio_projects__ 25 | + __affiliators_commiting_projects__ 26 | + __outside_projects__ 27 | + __outside_projects_commits__ 28 | + __affiliators_committing_to_outside_projects__ 29 | + __portfolio_projects__ First 10 Portfolio Projects for the requested organization 30 | + __project__ Each project in the list with the following details 31 | + __name__ 32 | + __activity__ 33 | + __primary_language__ 34 | + __i_use_this__ 35 | + __community_rating__ 36 | + __twelve_mo_activity_and_year_on_year_change__ 37 | + __commits__ 38 | + __change_in_commits__ 39 | + __percentage_change_in_commits__ 40 | + __contributors__ 41 | + __change_in_contributors__ 42 | + __percentage_change_in_committers__ 43 | + __detailed_page_url__ Url for paginated listing of all portfolio projects 44 | + __outside_projects__ First 10 Outside Projects for the requested organization. 45 | + __project__ Each project in the list with the following details 46 | + __name__ 47 | + __activity__ 48 | + __claimed_by__ 49 | + __i_use_this__ 50 | + __community_rating__ 51 | + __affiliates_contributing__ 52 | + __commits_by_current_affiliates__ 53 | + __detailed_page_url__ Url for paginated listing of all outside projects 54 | + __outside_committers__ First 10 Outside Committers for the requested organization 55 | + __contributor__ Each account in the list with the following details 56 | + __name__ 57 | + __kudos__ 58 | + __level__ 59 | + __affiliated_with__ 60 | + __contributions_to_portfolio_projects__ 61 | + __projects__ 62 | + __twelve_mo_commits__ 63 | + __detailed_page_url__ Url for paginated listing of all outside committers 64 | + __affiliated_committers__ First 10 Affiliated Committers for the requested organization 65 | + __affiliator__ Each account in the list with the following details 66 | + __name__ 67 | + __kudos__ 68 | + __level__ 69 | + __most_commits__ 70 | + __project__ 71 | + __commits__ 72 | + __most_recent_commit__ 73 | + __project__ 74 | + __date__ 75 | + __detailed_page_url__ Url for paginated listing of all affiliated committers 76 | 77 | 78 | ### URL 79 | ```shell 80 | https://www.openhub.net/orgs/{org_url_name}.xml?api_key={api_key}&view={view_option} 81 | ``` 82 | 83 | view_option will return the requested organization related data-table(maximum of 10 records) 84 | 85 | - The view option can be one of the following four ````portfolio_projects````, ````outside_projects````, ````affiliated_committers```` or ````outside_committers```` 86 | 87 | #### Examples 88 | 89 | ```ruby 90 | https://www.openhub.net/orgs/mozilla.xml?api_key=some_example_api_key&view=portfolio_projects 91 | ``` 92 | 93 | ```ruby 94 | https://www.openhub.net/orgs/mozilla.xml?api_key=some_example_api_key&view=outside_projects 95 | ``` 96 | 97 | ```ruby 98 | https://www.openhub.net/orgs/mozilla.xml?api_key=some_example_api_key&view=affiliated_committers 99 | ``` 100 | 101 | ```ruby 102 | https://www.openhub.net/orgs/mozilla.xml?api_key=some_example_api_key&view=outside_committers 103 | ``` 104 | -------------------------------------------------------------------------------- /reference/outside_committers.md: -------------------------------------------------------------------------------- 1 | ##Outside Committers 2 | People that are not part of an organization but commit to its projects 3 | 4 | 5 | ### Properties 6 | 7 | + __contributor__ 8 | + __name__ Name of the user account 9 | + __kudos__ Kudos obtained by the user account 10 | + __level__ Level of the user account 11 | + __affiliated_with__ Organization to which the user is affiliated to 12 | + __contributions_to_portfolio_projects__ 13 | + __projects__ Names of the portfolio projects to which the contributor commits to 14 | + __twelve_mo_commits__ Commits made by the contributor to portfolio projects in the last 12 months 15 | + __detailed_page_url__ This page's relative url 16 | 17 | 18 | ### URL 19 | 20 | ```shell 21 | https://www.openhub.net/orgs/{org_name}/outside_committers.xml?api_key={api_key}&page={number} 22 | ``` 23 | 24 | #### Example 25 | 26 | ```ruby 27 | https://www.openhub.net/orgs/mozilla/outside_committers.xml?api_key=some_example_api_key&page=2 28 | ``` 29 | -------------------------------------------------------------------------------- /reference/outside_projects.md: -------------------------------------------------------------------------------- 1 | ##Outside Projects 2 | Projects that are not part of an organization but are commtted to by its members 3 | 4 | 5 | ### Properties 6 | 7 | + __project__ 8 | + __name__ Name of the project 9 | + __activity__ Project's activity level like low, high etc.. 10 | + __primary_language__ The primary language in which the projects repos have code in 11 | + __i_use_this__ Number of people who mark that they use this 12 | + __community_rating__ Average rating of the project as rated by openhub users 13 | + __affiliates_contributing__ No of people that belong to the organization that commit to outside projects 14 | + __commits_by_current_affiliates__ No of commits made by the organization people to outside projects 15 | + __detailed_page_url__ This page's relative url 16 | 17 | 18 | ### URL 19 | 20 | ```shell 21 | https://www.openhub.net/orgs/{org_name}/outside_projects.xml?api_key={api_key}&page={number} 22 | ``` 23 | 24 | #### Example 25 | 26 | ```ruby 27 | https://www.openhub.net/orgs/mozilla/outside_projects.xml?api_key=some_example_api_key&page=2 28 | ``` 29 | -------------------------------------------------------------------------------- /reference/portfolio_projects.md: -------------------------------------------------------------------------------- 1 | ##Portfolio Projects 2 | Projects that belong to a specific organization 3 | 4 | 5 | ### Properties 6 | 7 | + __project__ 8 | + __name__ Name of the project 9 | + __activity__ Project's activity level like low, high etc.. 10 | + __primary_language__ The primary language in which the projects repos have code in 11 | + __i_use_this__ Number of people who mark that they use this 12 | + __community_rating__ Average rating of the project as rated by openhub users 13 | + __twelve_mo_activity_and_year_on_year_change__ Last 12 months activity compared with previous 12 months activity 14 | + __commits__ No of commits in the last 12 months 15 | + __change_in_commits__ Diff between no of commits in this 12 months and the previous 12 months before that 16 | + __percentage_change_in_commits__ % measure of change in commits 17 | + __contributors__ No of contributors in the last 12 months 18 | + __change_in_contributors__ Diff between no of committers in this 12 months and the previous 12 months before that 19 | + __percentage_change_in_committers__ % measure of change in contributors 20 | + __detailed_page_url__ This page's relative url 21 | 22 | 23 | ### URL 24 | 25 | ```shell 26 | https://www.openhub.net/orgs/{org_name}/projects.xml?api_key={api_key}&page={number} 27 | ``` 28 | 29 | #### Example 30 | 31 | ```ruby 32 | https://www.openhub.net/orgs/mozilla/projects.xml?api_key=some_example_api_key&page=2 33 | ``` -------------------------------------------------------------------------------- /reference/position.md: -------------------------------------------------------------------------------- 1 | ## Position 2 | A position represents a contribution or series of contributions that an account holder has made to a project within Open Hub. It corresponds to a committer ID for a source code repository for a particular project. 3 | 4 | ### Properties 5 | 6 | + __title__ 7 | An optional field that contains the title for this position. Example: “Lead Developer”. This field is filled in by the account holder. 8 | + __organization__ 9 | An optional field that contains the organization name for this position. This field will be filled in if the account holder has designated that this position’s contributions were made on behalf of an organization. Example: “IBM Corporation”. 10 | + __html_url__ 11 | The url to the contributor page on Open Hub. 12 | + __created_at__ 13 | The time at which this Position was originally created on Open Hub. 14 | + __started_at__ 15 | Optional field that contains the time at which this position was started. This field may be filled in by the account holder if this position is not backed by commits (e.g. the user contributed documentation to the projects wiki or authored and submitted a patch committed by a project maintainer). 16 | + __ended_at__ 17 | Option field that contains the time at which this position was ended. This field may be filled in by the account holder if the position is not backed by commits. 18 | + __sparkline_url__ 19 | The url to the sparkline that represents the account holder’s commit activity for the current position. 20 | + __commits__ 21 | The total number of commits made by the account holder at this position. 22 | + __project__ 23 | The Project that this position is attached to. This node will contain all of the properties for the specific [project](project.md). 24 | 25 | ### URL 26 | To get positions for an account: 27 | ```shell 28 | curl https://www.openhub.net/accounts/{account_id}/positions.xml 29 | ``` 30 | -------------------------------------------------------------------------------- /reference/project.md: -------------------------------------------------------------------------------- 1 | ## ProjectH 2 | A Project represents a collection of source code, documentation, and web sites treated together as a unit. It’s what most people might call an ‘application’ or ‘library’. 3 | 4 | ### Properties 5 | + __id__ 6 | The unique ID for the Project. 7 | + __name__ 8 | The project name. Currently limited to 40 characters, and must be unique on Open Hub. 9 | + __created_at__ 10 | The time at which this Project was initially added to the Open Hub database. 11 | + __updated_at__ 12 | The time of the most recent modification of this Project record. 13 | + __description__ 14 | An optional description. Currently limited to 800 characters. 15 | + __homepage_url__ 16 | An optional URL to the project home page. 17 | + __download_url__ 18 | An optional URL to a website hosting project downloads. 19 | + __vanity_name__ 20 | A short, unique name for this project. This name is used in Open Hub project URLs. 21 | + __medium_logo_url__ 22 | An url to the project’s 64×64 pixels logo image. 23 | + __small_logo_url__ 24 | An url to the project’s 32×32 pixels logo image. 25 | + __user_count__ 26 | The number of users currently using this project. 27 | + __average_rating__ 28 | A floating point value from 1.0 to 5.0, representing the average value of all user ratings. 1.0 is the worst possible rating and 5.0 is the highest possible rating. Will be null if no users have rated this project. 29 | + __rating_count__ 30 | The number of users who have rated this project. 31 | + __review_count__ 32 | The number of users who have reviewed this project. 33 | + __analysis_id__ 34 | The unique ID of the current best [Analysis](analysis.md) for this project. If the project has never been analyzed, this element will be empty. 35 | + __analysis__ 36 | For convenience, the current best Analysis for the project is included in this element. This object is present only when you have requested a single project — if the project was returned as part of a collection, the analysis object will not be present. 37 | + __url__ 38 | The xml api url for the current Project. 39 | + __html_url__ 40 | The url to the current Projects details page on Open Hub. 41 | + __factoids__ 42 | The factoids for the current analysis of the project will be included under this node. 43 | 44 | ```xml 45 | 46 | Very large, active development team 47 | Mature, well-established codebase 48 | Increasing year-over-year development activity 49 | Few source code comments 50 | 51 | ``` 52 | 53 | + __tags__ 54 | The tags for the current project will be included under this node. 55 | 56 | ```xml 57 | 58 | ruby 59 | gem 60 | web 61 | 62 | ``` 63 | 64 | + __language__ 65 | The language breakdown chart for the current Analysis will be included under this node. The node will have the following children: 66 | - __@graph_url__ 67 | This is the url to the PNG image that depicts the language breakdown for the current Analysis. The colors referenced in each languages @color attribute will be used in this image. 68 | - __language__ 69 | Not every language will have a entry. Open Hub will combine languages that do not make up a significant percentage into a aggregate entry “N Other”. This entry can be identified by either its @color, always “000000″ or @id, always “”. 70 | Each language will contain the following data 71 | - @color The color code that Open Hub uses to represent this language on the website. This color is also used in the language breakdown graph image. 72 | - @percentage The percentage of lines of code that the current language represents in the current Analysis 73 | - @id The Open Hub language id. 74 | 75 | ```xml 76 | 77 | C++ 78 | C 79 | JavaScript 80 | 28 Other 81 | 82 | ``` 83 | 84 | + __similar_projects__ 85 | The similar projects with regards to the tags will be included under this node. 86 | - __id__ 87 | The unique ID for the Project. 88 | - __name__ 89 | Full Name of the project 90 | - __vanity_url__ 91 | A short, unique name for this project. This name is used in openhub project URLs. 92 | 93 | ```xml 94 | 95 | 96 | 1 97 | Ruby 98 | ruby 99 | 100 | 101 | ``` 102 | 103 | + __licenses__ 104 | The Licenses for the current project will be included under this node. 105 | - __name__ 106 | Full Name of the License 107 | - __vanity_url__ 108 | A human-friendly name of the License 109 | 110 | ```xml 111 | 112 | 113 | mit 114 | MIT License 115 | 116 | 117 | ``` 118 | 119 | + __project_activity_index__ 120 | The Project Activity Index (PAI) level 121 | - __value__ 122 | The numerical value for the activity level. The values may be one of 123 | + 0 (NA) 124 | + 10 (New) 125 | + 20 (Inactive) 126 | + 30 (Very Low) 127 | + 40 (Low) 128 | + 50 (Moderate) 129 | + 60 (High) 130 | + 70 (Very High) 131 | - __description__ 132 | The text description of the value as defined above 133 | 134 | ```xml 135 | 136 | 70 137 | Very High 138 | 139 | ``` 140 | 141 | + __links__ 142 | The links associated with the current project. Homepage and Download links are not included here. 143 | - __category__ 144 | Link category on Open Hub 145 | - __title__ 146 | - __url__ 147 | 148 | 149 | ```xml 150 | 151 | 152 | Documentation 153 | http://www.luckytips.co.nr/firefox 154 | Tips n Tricks 155 | 156 | 157 | ``` 158 | 159 | ### URL 160 | To get a single Project, including its current best Analysis: 161 | ```shell 162 | curl https://www.openhub.net/p/{project_id}.xml 163 | ``` 164 | 165 | ### Collection URL 166 | To get a list of all Projects, not including their Analyses: 167 | ```shell 168 | curl https://www.openhub.net/p.xml 169 | ``` 170 | The Project collection request supports the standard [collection request parameters](/README.md#collection-requests), with the following details: 171 | 172 | + __query__ 173 | If supplied, only Projects matching the query string will be returned. A Project matches if its name, description, or any of its tags contain the query string. 174 | + __sort__ 175 | Project collections support the following sort options: 176 | 177 | - __new__ 178 | - __rating__ 179 | - __active_committers__ 180 | Highest active committers in past 12 months, first 181 | - __activity_level__ 182 | - __stack_count__ 183 | - __stack_count_reverse (default)__ 184 | - __id__ 185 | - __name__ 186 | - __name_length__ 187 | Length of project name. Shorter name, first 188 | - __updated_at__ 189 | - __relevance__ 190 | 191 | 192 | 193 | -------------------------------------------------------------------------------- /reference/size_fact.md: -------------------------------------------------------------------------------- 1 | ## SizeFact 2 | A SizeFact is a pre-computed collection of statistics about [Project](project.md) source code. It provides monthly running totals of lines of code, commits, and developer effort. 3 | 4 | SizeFacts contain the running totals of [ActivityFacts](activity_fact.md). 5 | 6 | A SizeFact is derived from lower-level statistics contained in an [Analysis](analysis.md). SizeFacts are updated whenever a [Project](project.md) is re-analyzed. 7 | 8 | SizeFacts are availabled only after Open Hub has downloaded and analyzed the project source code. 9 | 10 | ### Properties 11 | 12 | + __month__ 13 | Indicates the month covered by this SizeFact. Only the year and month fields are significant. This SizeFact record includes all development activity that occured during this month. 14 | + __code__ 15 | The total net lines of code, excluding comments and blanks, as of the end of this month. 16 | + __comments__ 17 | The total net lines of comments as of the end of this month. 18 | + __blanks__ 19 | The total net blank lines as of the end of this month. 20 | + __comment_ratio__ 21 | The fraction of net lines which are comments as of the end of this month. 22 | + __commits__ 23 | The cumulative total number commits to the project source control, including this month. 24 | + __man_months__ 25 | The cumulative total months of effort expended by all contributors on this project, including this month. For instance, if 1 contributor has worked for 3 months and 2 developers have each worked for 5 months, man_months will be 13. This is the running total of the [ActivityFact](activity_fact.md) `contributors` property. 26 | 27 | ### Collection URL 28 | To get all SizeFacts for a particular [Analysis](analysis.md): 29 | ```shell 30 | curl https://www.openhub.net/p/{project_id}/analyses/{analysis_id}/size_facts.xml 31 | ``` 32 | If you do not know the ID of the current best Analysis for a Project, you can use the following shortcut: 33 | ```shell 34 | curl https://www.openhub.net/p/{project_id}/analyses/latest/size_facts.xml 35 | ``` 36 | 37 | The call returns one SizeFact for each month, starting at the first month in which any code exists, and ending at the month in which Open Hub last created a new Analysis for this Project. Typically, the collection ends at the current month, but if the Project has not been re-analyzed in a while, the collection may end sooner. 38 | 39 | The results cannot be paginated or filtered. Results are sorted chronologically. 40 | -------------------------------------------------------------------------------- /reference/stack.md: -------------------------------------------------------------------------------- 1 | ## Stack 2 | 3 | A Stack represents a collection of Projects used by a single person. A Stack belongs to an [Account](account.md)./, 4 | 5 | A Stack contains zero or more [StackEntries](stack_entry.md), each of which links the Stack to a single [Project](project.md). 6 | 7 | ### Properties 8 | 9 | + __id__ 10 | The unique ID for the Stack. 11 | + __title__ 12 | The name of the Stack. 13 | + __description__ 14 | A short description about this Stack. 15 | + __updated_at__ 16 | The most recent time at which any Projects were added to or removed from this Stack. 17 | + __project_count__ 18 | The total number of Projects currently contained in this Stack. 19 | + __stack_entries__ 20 | A collection of zero or more [StackEntries](stack_entry.md). If the Stack object was returned in response to a collection request (/projects/x/stacks.xml), you will receive only a single StackEntry corresponding to the Project in question. 21 | + __account_id__ 22 | The unique ID of the [Account](account.md) which owns this Stack. 23 | + __account__ 24 | For convenience, a full [Account](account.md) object may be included here. 25 | 26 | ### Collection URL 27 | To get a list of all Stacks for a particular Project: 28 | ```shell 29 | GET https://www.openhub.net/p/{project_id}/stacks.xml 30 | ``` 31 | The Stacks returned in this collection will each contain only a single [StackEntry](stack_entry.md), corresponding to the Project in question. 32 | 33 | Each Stack in the result will also include an Account object. 34 | 35 | The Stack collection is paginated, and supports the standard [collection request parameters](/README.md#collection-requests) with the following details: 36 | 37 | + __query__ 38 | If supplied, only Stacks owned by Accounts with names matching the query string will be returned. 39 | + __sort__ 40 | Stack collections support the following sort options: 41 | - __id__ 42 | - __name__ (default) 43 | - __created_at__ Time at which the Project was added to the stack 44 | - __project_count__ 45 | 46 | 47 | -------------------------------------------------------------------------------- /reference/stack_entry.md: -------------------------------------------------------------------------------- 1 | ## StackEntry 2 | 3 | A StackEntry joins a [Stack](stack.md) to a [Project](project.md). 4 | 5 | ### Properties 6 | 7 | + __id__ 8 | The unique ID for the StackEntry. 9 | + __created_at__ 10 | The time at which this Project was added to this Stack. 11 | + __stack_id__ 12 | The unique ID of the Stack which contains this StackEntry. 13 | + __project_id__ 14 | The unique ID of the Project. 15 | + __project__ 16 | For convenience, a full Project object may be included here. If the Stack object was returned in response to an Account Stack request (/accounts/x/stacks/default.xml), the Project objects will be present. 17 | 18 | ### URL 19 | StackEntry object cannot be queried directly. They are included in a response to queries or [stacks](stack.md). 20 | --------------------------------------------------------------------------------