You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kendarorg cbbfd9502c
1 year ago
NugetTesterApplication Update. Started working with nuget 3.5 and PHP 7 3 years ago
nuget_exes #73: Last rework with final test 1 year ago
src #73: Last rework with final test 1 year ago
tests v3.0.7.0 6 years ago
.gitignore Ignore snupkg files (symbols) 1 year ago Rename phase 2 6 years ago Update 1 year ago
test.bat #73: Last rework with final test 1 year ago

PhpNuget V.


This is born to have my personal repository for nuget, on my cheapo PHP hosting. With support for complex OData queries.

Verified on:

  • PHP 5.3.17-IIS 7
  • PHP 5.3.21-IIS 7
  • PHP 5.5.8-Apache 2.0 (Windows 8 Pro)
  • PHP 5.6-IIS 8
  • PHP 5.4.2-Apache 2.0 (OpenSuse 13.1)
  • PHP 5.3.3-Apache 2.2 (CentOS 6.5)
  • PHP 7.0.14-Apache 2.4 (Windows 10 Home)
  • PHP 7.3.5-Apache 2.4 (Windows 7 Pro)


Notes for everybody

  • When installing the MySql version the db must be present with the user configured!
  • The module php_curl must be present and configured inside the php.ini
  • The max size for uploads and post should be set on php.ini, with according values. I usually set the following values
    • post_max_size=20M
    • upload_max_filesize=20M

Notes for Apache With Red Hat Linux

On Red Hat Linux the mod_rewrite must be enabled on the application directory since most features depends on it. This can be achieved modifying


Then on the definition of the phpnuget directory, change the AllowOverride from “None” to “All”


<Directory "/var/www/html/phpnugetdir">
    Options Indexes FollowSymLinks
    AllowOverride None
    Order allow,deny
    Allow from all


<Directory "/var/www/html/phpnugetdir">
    Options Indexes FollowSymLinks
    AllowOverride All
    Order allow,deny
    Allow from all

And then restart Apache

sudo service httpd restart

This should be enough to let everything works

Notes for Apache on Windows

If php is unable to load curl-related functions copy the following files from the php directory to “C:\Windows\System”. You can verify this by downloading a file from the official nuget repository via the manage packages page.

  • libeay32.dll
  • libsasl.dll
  • ssleay32.dll
  • libssh2

Prerequisites For IIS

These steps are NOT needed if your hosting already configured PHP

  • Create the website with a standard web.config
  • Install PHP for IIS (see at the end of this document ‘Installation of PHP for IIS’)
  • Mark the location of php-cgi.exe


  • Download from
  • Extract somewhere
  • Copy the content of the directory “src” in the location you choose for the server. DO NOT COPY THE WEB.CONFIG IF IN IIS
  • Enable write/read/delete access on
    • db: Directory where all databases and packages are stored
    • settings.php
    • Web.Config
    • .htaccess
  • Verify to have write permissions on the “db” directory.
  • Eventually set the environment variables for custom data directories. This will override the setting in the setup page
    • UPLOAD_DIR: Where the files will be uploaded
    • DATA_DIR: For txt based version where the plain text db files will be saved
  • Open the setup page at http://myhost/mynuget/setup.php and follow the wizard. The value will be prefilled
    • Admin UserId: the user that will be created (or updated) as admin
    • Admin Password: the password (on update will be overwritten)
    • Admin Email: ...
    • Password Regex: The regex that will be used to verify the password (default min 8 chars, max 40)
    • Password Description: The error to show when the password is not matching the regex
    • Application path: If the website is “http://host/nuget” will be “nuget”. If the website is “http://host” will be empty.
    • Data Root: The directory in which the txt db will be placed. It’s usually a subdir of the website but can be changed.
    • Packages Root: The directory in which the uploaded packages will be placed. It’s usually a subdir of the website but can be changed.
    • php-cgi.exe: To allow the configuration of php under IIS.
    • Allow GRAVATAR usage: Allow the search for gravatar icon to be shown on users.
    • Allow package update via Upload: Default disabled, if enabled it is possible to overwrite the packages BUT THIS IS NOT A STANDARD BEHAVIOUR.
    • Allow package delete: Default disabled. LEAVING IT ENABLED IS NOT A STANDARD BEHAVIOUR
  • When using the mysql installation
    • Check the “Use mysql” and fill the configuration data
    • NOTE: Import from txt db does not yet work!!!
  • If under IIS set the path of ‘php-cgi.exe’ (leave blank if your hosting already configured PHP)
  • Change the password, email and login of the administration without worries.
  • Rename the setup.php to setup.bak FOR SECURITY REASONS
  • Remove write access on
    • settings.php
    • Web.Config
    • .htaccess
  • Now open http://myhost/mynuget and see the gallery
  • Happy Nugetting!

Daily usage

Simple package

nuget push mypackage.nupkg myApiKey http://myhost/mynuget/upload

Symbol package without packageType in nuspec

Specifying a different API (the url must be registered through the API key).

nuget push mypackage.nupkg myApiKey http://myhost/mynuget/uploadsymbol

Symbol package with packageType in nuspec

Can be used the standard command, adding inside the nuspec the following part

<?xml version="1.0" encoding="utf-8"?>
<package xmlns="">
      <packageType name="SymbolsPackage" />
  • To search items the syntax follow the OData specification (more or less). Some example
    • Id eq 'NUnit': Search for all packages with id equals to NUnit
    • substringof('Microsoft',Author): Search for all packages with Microsoft between the authors
    • Version gt '': Search for all packages with version greater than
  • All search blocks can be grouped with parenthesis and with ‘and’ and ‘or’ keywords.
  • The keywords are
    • gt/gte: Greater/Greater equal
    • lt/lte: Lower/Lower equal
    • eq/neq: Equal/Not Equals
    • substringof: Check if the first parameter is contained in the second parameter


Note that the symbol packages are visible only through the “Packages” UI function. Deleting a package will result in deleting its associated symbols.

Simple user

  • Must be registered to upload/modify packages
  • Can only edit the packages that he uploaded
  • When an user upload for the first time a package with a certain id, then all versions will be owned by the same user. No other users but the administrators could modify or upload packages with the same id.
  • The token available to access the API for the upload can be regenerated by any user.
  • The API token can be used with our without the curly braces.
  • The users will see in their list of packages only the packages that they uploaded.

For the administrators

  • They can add/remove/enable users
  • They can add/modify any package. When a package uploaded initially by another user is uploaded by the administrator, the ownership of the package will be kept the same.
  • It is possible to download packages from external sources. It will be sufficent to insert the address from which the packages would be taken, specifying where should be put the identifier and the version of the package to download locally (through the @ID and @VERSION tags)
  • When the database is corrupted it can be regenerated through “Refresh packages db from packages directory.” mind that all the packages will become owned by the administrators.
  • It would be possible to upload the packages directly on the ‘db/packages’ directory and then run the “Refresh packages db from packages directory.". All packages not yet present on the database will be loaded.

The Api

The nuget API is based more or less on the OData protocol. All of the api lsited that returns a collection support the usage of parameters

  • $skip: Optional. The number of items to skip. Default to 0.
  • $top: Optional. The number of items returned. Default to 10.

Api V1

  • /api/v1: Retrieves the root for the entities that will be used by the API. No parameters.
  • /api/v1/package/[package-id]/[package-version]: (GET) Download the specified package. No parameters.
  • /api/v1/package/[package-id]/[package-version]?apiKey=xxx&setPrerelease: (POST) Set the package as listed.
    • apiKey: Mandatory. The api key of the user. Must match the one of the user that firstly inserted the package or the user must be Admin
    • setPrerelease: Optional. If present will set the package as release (without touching the listed flag) THIS IS SPECIFIC FOR phpnuget
  • /api/v1/package/[package-id]/[package-version]?apiKey=xxx&setPrerelease: (DELETE) Set the package as not listed.
    • apiKey: Mandatory. The api key of the user. Must match the one of the user that firstly inserted the package or the user must be Admin
    • setPrerelease: Optional. If present will set the package as prerelease (without touching the listed flag) THIS IS SPECIFIC FOR phpnuget
  • /api/v1/$metadata: Retrieves the OData metadata, the actions allowed and the entities specifications. No parameters.
  • /api/v1/FindPackagesById(): Search for packages by id, returns all packages with a certain id ordered by version descending
    • Id: Mandatory parameter, specify the identifier of the package (e.g. Angular-UI-Router)
  • /api/v1/FindPackagesById()/$count: Count all packages with a certain id ordered by version descending. Same parameters as ‘FindPackagesById()’
  • /api/v1/Search(): Search for packages satisfyng the query with a certain id ordered by version descending
    • $filter: Optional. The query that will be used for the search, see ‘Daily usage’ for the syntax
    • $orderby: Optional. List of fields for the order by. e.g. ‘Id desc, Version, Author asc’ will order by Id descending, then by Version ascending (the default) then by Author ascending.
    • searchTerm: Optional. Equivalent to write ‘substringof('searchTerm',Id) or substringof('searchTerm',Name)’
    • targetFramework: Optional. Target framework required, the result will contain the matching packages and the ones without framework specified.
    • includePrerelease: Optional. If set to ‘true’ include event the prereleases (the ones with the flag set by hand on package editing or the ones with versions that contains alphabetic characters, e.g. is not prerelease but 1.0.beta is)
  • /api/v1/Search()/$count: Count all packages satisfyng the query. Same parameters as ‘FindPackagesById()’
  • /api/v1/Packages(): Same as Search()
  • /api/v1/Packages()/$count: Same as Search()/$count
  • /api/v1/Packages: Same as Search()
  • /api/v1/Packages/$count: Same as Search()/$count
  • /api/v1/Packages(Id=’[package-id]',Version=’[package-id]'): Retruns the data for the single package

Api V2

All v1 APIs are present, remind to replace the v1 in the previous section with v2!

  • /api/v2/symbolpackage/[package-id]/[package-version]: (GET) Download the specified symbol package. No parameters.
  • /api/v2/FindPackageById(): Same as FindPackagesById()
  • /api/v2/GetUpdates(): Search for packages satisfyng the query with a certain id ordered by version descending
    • packageIds: Optional. Pipe (|) separated list of package ids
    • versions: Optional. Pipe (|) separated list of package versions, their position is matching with the ones in packageIds
    • targetFrameworks: Optional. Pipe (|) separated list of package target frameworks, their position is matching with the ones in packageIds. If the framework is not specified in the package then it will be returned anyway
    • includePrerelease: Optional. If set to ‘true’ include event the prereleases (the ones with the flag set by hand on package editing or the ones with versions that contains alphabetic characters, e.g. is not prerelease but 1.0.beta is)
    • includeAllVersions: Not supported yet
    • versionConstraints: Not supported yet
  • /api/v2/GetUpdates()/$count: Count all packages satisfyng the query. Same parameters as ‘FindPackagesById()’
  • /api/v2/$batch: Executes the queries/action following the OData batch specifications.

Api V3

As soon as the guys from nuget defines it. Actually is work in progress, trying to follow the “working” example on

Other entry points

  • /packages?q=term1 term2: Given the terms passed in ‘q’ a search is made checking that the Id or Name of the package corespond to at least one of the term passed as parameter
  • /api?id=[package-id]&version=[package-version]: To download a package
  • /api?id=[package-id]&version=[package-version]&symbol=true: To download a package symbol
  • /uploadsymbol: (POST) Upload a symbol package
  • /upload: (POST) Upload a package

Installation of PHP for IIS

Installation for IIS 8

Tested on Windows 8 pro X64 bit and Windows 8.1 pro X64

This guid is adapted from

  1. download php for windows
  2. extract downloaded zip ( C:/php )
  3. download [php manager[( for IIS ( its an extension for managing PHP from IIS control panel )
  4. open php manager and click on register new php installation
  5. choose php-cgi.exe and click ok (usually is inside ‘C:\Program Files (x86)\PHP\v5.3\php-cgi.exe’)
  6. now check phpinfo and choose error reporting
  7. open your favorite code editor and type

and save this as hello.php ( or anything ) on c:inetpubwwwroot and open http://localhost/hello.php

now IIS is serving PHP now in next tutorial i will show you how to set up MySQL in windows

Features of PHP manger

  • Register PHP with IIS
  • Validate and properly configure existing PHP installations
  • Run multiple PHP versions side by side on the same server and even within the same web site
  • Check PHP runtime configuration and environment (output of phpinfo() function)
  • Configure various PHP settings
  • Enable or disable PHP extensions
  • Remotely manage PHP configuration in php.ini file.
  • Easily install, configure, manage and troubleshoot one or many PHP versions on the same IIS server.
  • Get updated packages
  • Support viewing the profile in gallery, “nuget like”
  • Delete packages (when configured)




  • Add robots.txt
  • Import v3.0.0.0 txt database on MySQL


  • Add Email token to reset users passwords
  • Upload multiple nupkg
  • Align the Settings::ResultsPerPage in all the views



    • Support for symbol packages

    • Support for chocolatey usePackageRepositoryOptimizations
    • Added support for env.variables for db and packages directories

    • Various fix and improvement:
      • Gravatar support
      • Download through proxy
      • Header fix
      • gitignore issues with htaccess, settings, phpstorm

    • Fix code indentation

    • Fix responsive navbar to display correctly on medium and large screens

    • Clean up bootstrap forms by using bootstrap best practice horizontal form templates

    • Move copyright notice out of bottom navbar and into separate container to save vertical space

    • Move incorrectly placed link tag from document body to document head
    • Move Bootstrap CSS to assets/css folder for consistency

    • Add functionality to mobile navigation
    • Include BootstrapJS
    • Include jQuery
    • Make search form into input group for clarity
    • Link navbar brand to site home for consistency

    • Unify identation to tabs, size 4
    • Unify EOL characters to LF
    • Remove trainling whitespace

    • Construct missing bootstrap grid elements in templating files
    • Add styles for vertical row spacing
    • Unify indentation and trim whitespace

    • Added navbar-specific styles to style.css
    • removed _navbar.php file and integrated code into _header.php
    • removed _navbar.php include from index.php
    • cleaned up _header.php (code indentation)

    • remove inline styles from index.php
    • add and link separate css/style.css file to assets folder

    • Fix bug on delete for textdb version

    • Correct visualization of packages on MySQL
    • Error not finding javascript files
    • Correct ordering of packages
    • Showing exception texts on file upload errors

    • Added MySQL as storage engine

    • Added “count” value on all packages requests for nuget 3.5
    • Verified compatibility with Nuget.exe 2.8, 3.4, 3.5
    • Compatibility with PHP7

    • Added wait dialogs for long operations (update, upload from external nuget and refresh packages)

    • Added support for .net 4.5.2
    • Internal refactoring for net framework selection

    • Fixed inconsistency on boolean parameters inside packages update
    • Fixed special case for uploading files
    • Added test application for txt based db
    • Added separation between data directory and packages directory
    • Added regex to verify the password and error description

    • Support for packages deletion
    • Resolved setup issue on IIS with a new URLRewrite module managedfusion-rewriter
    • Specific override for data root
    • Support Packages(Id='AngularJS.Core’,Version='1.2.14’) on v1 and v2 API
    • Support for downloads count

    • Release notes not considered
    • Escaped license url
    • Fix on package refresh

    • Nuget Package Explorer compatibility: Added support for standard upload
    • Nuget Package Explorer compatibility: Added support $inlinecount parameter (nuget 2.8)
    • Fix on path initialization
    • Empty packages upload not allowed anymore
    • Fixed duplicate packages upload via CLI/Nuget Package Explorer
    • Fixed “Listed” flag inconsistencies
    • Fixed “Group by” clause in database
    • Added favicon to the website
    • Default of includePrerelease to false
    • Added define('ALLOWPACKAGEUPDATE', true/false) in settings.php to deny (default) or allow the packages update
    • Added support for listed/unlisted Api
    • Fixed includePreRelease on Update packages

    • Support for $batch requests (hopefully working)
    • Support for Nuget v3 protocol (started the implementation)

    • Added “lazy” package refresh to avoid php timeout
    • Added version lable on footer

    • Users were not allowed to be made adiministrators by the administrators
    • Replaced htmlentities with htmlspecialchars
    • HttpUtils: use readfile instead of require_once

    • Removed typo on phpnugetobjectsearch.php

    • Modified the hint to register Api Key
    • Added download link while browsing packages

    • Support for ne/neq (thanks petero!)
    • Support for null value in OData queries
    • Aligned to semantic versioning for pre-releases (
    • Fixed a bug for the OData queries not recognizing external types
    • Uploading a package with “-” into the name will result in a pre-release package
    • Field “Is Pre Release” is now honoured correctly
    • Fixed bug for free text fields not correctly shown on packages list when containing html tags
    • Some typos
    • Fixed issue when searching for not standard queries from gallery, fallback to all words under or clause

    • Added “tolower” function (thanks petero-dk!)
    • Added “startswith”, “endswith” and “toupper”
    • Fixed issue when calling functions passing a field name as second parameter.
    • Added tests for substringof and tolower

    • Fixed bug caused by wrong order of execution of sort, group by, select in Db engine

    • UI improved with AngularJS
    • Improved the search engine with better OData query support
    • Changed the database fields (manual import only)
    • Downloading of packages from other repositories
    • Better support for the standard nuget server behaviours

    • Added support for GetPackageById
    • General improvements and bugfixing
    • Support for installation on IIS

    • Added interface to edit packages
    • Added mod_rewrite support via .htaccess
    • Simplified the whole structure of the program