{"action":"created","comment":{"url":"https://api.github.com/repos/emccode/libstorage/pulls/comments/60136161","id":60136161,"diff_hunk":"@@ -0,0 +1,201 @@\n+/*\n+Package filters is a piece of thievery as the LDAP filter parsing code was\n+lifted serepticiously from\n+https://github.com/tonnerre/go-ldap/blob/master/ldap.go. The code was reused\n+this way as opposed to imports in order to modify it heavily for the needs of\n+the project.\n+*/\n+package filters\n+\n+import (\n+\t\"bytes\"\n+\t\"net/url\"\n+\n+\t\"github.com/akutz/goof\"\n+\n+\t\"github.com/emccode/libstorage/api/types/filters\"\n+)\n+\n+const (\n+\tfilterAnd               = filters.FilterAnd\n+\tfilterOr                = filters.FilterOr\n+\tfilterNot               = filters.FilterNot\n+\tfilterPresent           = filters.FilterPresent\n+\tfilterEqualityMatch     = filters.FilterEqualityMatch\n+\tfilterSubstrings        = filters.FilterSubstrings\n+\tfilterSubstringsPrefix  = filters.FilterSubstringsPrefix\n+\tfilterSubstringsPostfix = filters.FilterSubstringsPostfix\n+\tfilterGreaterOrEqual    = filters.FilterGreaterOrEqual\n+\tfilterLessOrEqual       = filters.FilterLessOrEqual\n+\tfilterApproxMatch       = filters.FilterApproxMatch\n+)\n+\n+var filterMap = map[filters.FilterOperator]string{\n+\tfilterAnd:            \"And\",\n+\tfilterOr:             \"Or\",\n+\tfilterNot:            \"Not\",\n+\tfilterEqualityMatch:  \"Equality Match\",\n+\tfilterSubstrings:     \"Substrings\",\n+\tfilterGreaterOrEqual: \"Greater Or Equal\",\n+\tfilterLessOrEqual:    \"Less Or Equal\",\n+\tfilterPresent:        \"Present\",\n+\tfilterApproxMatch:    \"Approx Match\",\n+}\n+\n+var (\n+\terrCharZeroNotLParen = goof.New(\"filter does not start with an '()'\")\n+\terrUnexpectedEOF     = goof.New(\"unexpected end of filter\")\n+\terrCompile           = goof.New(\"error compiling filter\")\n+\terrParse             = goof.New(\"error parsing filter\")\n+)\n+\n+// CompileFilter compiles a filter string.\n+func CompileFilter(s string) (*filters.Filter, error) {\n+\n+\tes, err := url.QueryUnescape(s)\n+\tif err != nil {\n+\t\treturn nil, err\n+\t}\n+\ts = es\n+\n+\tif len(s) == 0 || s[0] != '(' {\n+\t\treturn nil, errCharZeroNotLParen\n+\t}\n+\n+\tf, pos, err := compileFilter(s, 1)\n+\tif err != nil {\n+\t\treturn nil, err\n+\t}\n+\n+\tif pos != len(s) {\n+\t\treturn nil, goof.WithField(\n+\t\t\t\"extra\", s[pos:],\n+\t\t\t\"finished compiling filter with extra at end\")\n+\t}\n+\n+\treturn f, nil\n+}\n+\n+func compileFilterSet(\n+\ts string, pos int, parent *filters.Filter) (int, error) {\n+\n+\tfor pos < len(s) && s[pos] == '(' {\n+\t\tchild, new_pos, err := compileFilter(s, pos+1)\n+\t\tif err != nil {\n+\t\t\treturn pos, err\n+\t\t}\n+\t\tpos = new_pos\n+\t\tparent.Children = append(parent.Children, child)\n+\t}\n+\n+\tif pos == len(s) {\n+\t\treturn pos, errUnexpectedEOF\n+\t}\n+\n+\treturn pos + 1, nil\n+}\n+\n+func compileFilter(s string, pos int) (*filters.Filter, int, error) {\n+\n+\tswitch s[pos] {\n+\tcase '(':\n+\t\tf, new_pos, err := compileFilter(s, pos+1)\n+\t\tnew_pos++\n+\t\treturn f, new_pos, err\n+\n+\tcase '&':\n+\t\tf := &filters.Filter{Op: filterAnd}\n+\t\tnew_pos, err := compileFilterSet(s, pos+1, f)\n+\t\treturn f, new_pos, err\n+\n+\tcase '|':\n+\t\tf := &filters.Filter{Op: filterOr}\n+\t\tnew_pos, err := compileFilterSet(s, pos+1, f)\n+\t\treturn f, new_pos, err\n+\n+\tcase '!':\n+\t\tf := &filters.Filter{Op: filterNot}\n+\t\tchild, new_pos, err := compileFilter(s, pos+1)","path":"api/utils/filters/filters.go","position":118,"original_position":118,"commit_id":"6acbdbf417322c931020772a070e56ead8a0ada7","original_commit_id":"6acbdbf417322c931020772a070e56ead8a0ada7","user":{"login":"houndci-bot","id":6697940,"avatar_url":"https://avatars.githubusercontent.com/u/6697940?v=3","gravatar_id":"","url":"https://api.github.com/users/houndci-bot","html_url":"https://github.com/houndci-bot","followers_url":"https://api.github.com/users/houndci-bot/followers","following_url":"https://api.github.com/users/houndci-bot/following{/other_user}","gists_url":"https://api.github.com/users/houndci-bot/gists{/gist_id}","starred_url":"https://api.github.com/users/houndci-bot/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/houndci-bot/subscriptions","organizations_url":"https://api.github.com/users/houndci-bot/orgs","repos_url":"https://api.github.com/users/houndci-bot/repos","events_url":"https://api.github.com/users/houndci-bot/events{/privacy}","received_events_url":"https://api.github.com/users/houndci-bot/received_events","type":"User","site_admin":false},"body":"don't use underscores in Go names; var new_pos should be newPos","created_at":"2016-04-18T21:19:19Z","updated_at":"2016-04-18T21:19:19Z","html_url":"https://github.com/emccode/libstorage/pull/25#discussion_r60136161","pull_request_url":"https://api.github.com/repos/emccode/libstorage/pulls/25","_links":{"self":{"href":"https://api.github.com/repos/emccode/libstorage/pulls/comments/60136161"},"html":{"href":"https://github.com/emccode/libstorage/pull/25#discussion_r60136161"},"pull_request":{"href":"https://api.github.com/repos/emccode/libstorage/pulls/25"}}},"pull_request":{"url":"https://api.github.com/repos/emccode/libstorage/pulls/25","id":66693919,"html_url":"https://github.com/emccode/libstorage/pull/25","diff_url":"https://github.com/emccode/libstorage/pull/25.diff","patch_url":"https://github.com/emccode/libstorage/pull/25.patch","issue_url":"https://api.github.com/repos/emccode/libstorage/issues/25","number":25,"state":"open","locked":false,"title":"WiP - Introducing a Filters Library","user":{"login":"akutz","id":101085,"avatar_url":"https://avatars.githubusercontent.com/u/101085?v=3","gravatar_id":"","url":"https://api.github.com/users/akutz","html_url":"https://github.com/akutz","followers_url":"https://api.github.com/users/akutz/followers","following_url":"https://api.github.com/users/akutz/following{/other_user}","gists_url":"https://api.github.com/users/akutz/gists{/gist_id}","starred_url":"https://api.github.com/users/akutz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/akutz/subscriptions","organizations_url":"https://api.github.com/users/akutz/orgs","repos_url":"https://api.github.com/users/akutz/repos","events_url":"https://api.github.com/users/akutz/events{/privacy}","received_events_url":"https://api.github.com/users/akutz/received_events","type":"User","site_admin":false},"body":"This patch adds support for parsing ABNF LDAP filter strings in order to support filters via the URL as an argument of the query string argument named \"filter\".\r\n\r\n@dvonthenen, what are your thoughts on this? Notice via the `filters_test.go` file how we actually parse them. I think it would work.","created_at":"2016-04-15T19:38:21Z","updated_at":"2016-04-18T21:19:19Z","closed_at":null,"merged_at":null,"merge_commit_sha":"491e05b6891fb66d4ffe78a23a7068b0d675c6f6","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/emccode/libstorage/pulls/25/commits","review_comments_url":"https://api.github.com/repos/emccode/libstorage/pulls/25/comments","review_comment_url":"https://api.github.com/repos/emccode/libstorage/pulls/comments{/number}","comments_url":"https://api.github.com/repos/emccode/libstorage/issues/25/comments","statuses_url":"https://api.github.com/repos/emccode/libstorage/statuses/6acbdbf417322c931020772a070e56ead8a0ada7","head":{"label":"akutz:feature/filters","ref":"feature/filters","sha":"6acbdbf417322c931020772a070e56ead8a0ada7","user":{"login":"akutz","id":101085,"avatar_url":"https://avatars.githubusercontent.com/u/101085?v=3","gravatar_id":"","url":"https://api.github.com/users/akutz","html_url":"https://github.com/akutz","followers_url":"https://api.github.com/users/akutz/followers","following_url":"https://api.github.com/users/akutz/following{/other_user}","gists_url":"https://api.github.com/users/akutz/gists{/gist_id}","starred_url":"https://api.github.com/users/akutz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/akutz/subscriptions","organizations_url":"https://api.github.com/users/akutz/orgs","repos_url":"https://api.github.com/users/akutz/repos","events_url":"https://api.github.com/users/akutz/events{/privacy}","received_events_url":"https://api.github.com/users/akutz/received_events","type":"User","site_admin":false},"repo":{"id":46155336,"name":"libstorage","full_name":"akutz/libstorage","owner":{"login":"akutz","id":101085,"avatar_url":"https://avatars.githubusercontent.com/u/101085?v=3","gravatar_id":"","url":"https://api.github.com/users/akutz","html_url":"https://github.com/akutz","followers_url":"https://api.github.com/users/akutz/followers","following_url":"https://api.github.com/users/akutz/following{/other_user}","gists_url":"https://api.github.com/users/akutz/gists{/gist_id}","starred_url":"https://api.github.com/users/akutz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/akutz/subscriptions","organizations_url":"https://api.github.com/users/akutz/orgs","repos_url":"https://api.github.com/users/akutz/repos","events_url":"https://api.github.com/users/akutz/events{/privacy}","received_events_url":"https://api.github.com/users/akutz/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/akutz/libstorage","description":"LibStorage provides a vendor agnostic storage orchestration model, API, and reference client and server implementations.","fork":true,"url":"https://api.github.com/repos/akutz/libstorage","forks_url":"https://api.github.com/repos/akutz/libstorage/forks","keys_url":"https://api.github.com/repos/akutz/libstorage/keys{/key_id}","collaborators_url":"https://api.github.com/repos/akutz/libstorage/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/akutz/libstorage/teams","hooks_url":"https://api.github.com/repos/akutz/libstorage/hooks","issue_events_url":"https://api.github.com/repos/akutz/libstorage/issues/events{/number}","events_url":"https://api.github.com/repos/akutz/libstorage/events","assignees_url":"https://api.github.com/repos/akutz/libstorage/assignees{/user}","branches_url":"https://api.github.com/repos/akutz/libstorage/branches{/branch}","tags_url":"https://api.github.com/repos/akutz/libstorage/tags","blobs_url":"https://api.github.com/repos/akutz/libstorage/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/akutz/libstorage/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/akutz/libstorage/git/refs{/sha}","trees_url":"https://api.github.com/repos/akutz/libstorage/git/trees{/sha}","statuses_url":"https://api.github.com/repos/akutz/libstorage/statuses/{sha}","languages_url":"https://api.github.com/repos/akutz/libstorage/languages","stargazers_url":"https://api.github.com/repos/akutz/libstorage/stargazers","contributors_url":"https://api.github.com/repos/akutz/libstorage/contributors","subscribers_url":"https://api.github.com/repos/akutz/libstorage/subscribers","subscription_url":"https://api.github.com/repos/akutz/libstorage/subscription","commits_url":"https://api.github.com/repos/akutz/libstorage/commits{/sha}","git_commits_url":"https://api.github.com/repos/akutz/libstorage/git/commits{/sha}","comments_url":"https://api.github.com/repos/akutz/libstorage/comments{/number}","issue_comment_url":"https://api.github.com/repos/akutz/libstorage/issues/comments{/number}","contents_url":"https://api.github.com/repos/akutz/libstorage/contents/{+path}","compare_url":"https://api.github.com/repos/akutz/libstorage/compare/{base}...{head}","merges_url":"https://api.github.com/repos/akutz/libstorage/merges","archive_url":"https://api.github.com/repos/akutz/libstorage/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/akutz/libstorage/downloads","issues_url":"https://api.github.com/repos/akutz/libstorage/issues{/number}","pulls_url":"https://api.github.com/repos/akutz/libstorage/pulls{/number}","milestones_url":"https://api.github.com/repos/akutz/libstorage/milestones{/number}","notifications_url":"https://api.github.com/repos/akutz/libstorage/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/akutz/libstorage/labels{/name}","releases_url":"https://api.github.com/repos/akutz/libstorage/releases{/id}","deployments_url":"https://api.github.com/repos/akutz/libstorage/deployments","created_at":"2015-11-14T01:05:44Z","updated_at":"2016-03-22T14:53:15Z","pushed_at":"2016-04-18T21:19:06Z","git_url":"git://github.com/akutz/libstorage.git","ssh_url":"git@github.com:akutz/libstorage.git","clone_url":"https://github.com/akutz/libstorage.git","svn_url":"https://github.com/akutz/libstorage","homepage":"","size":779,"stargazers_count":0,"watchers_count":0,"language":"Go","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"emccode:master","ref":"master","sha":"871a256af9a1e4e8a1f00ab65e6726e939ef2ffb","user":{"login":"emccode","id":8659750,"avatar_url":"https://avatars.githubusercontent.com/u/8659750?v=3","gravatar_id":"","url":"https://api.github.com/users/emccode","html_url":"https://github.com/emccode","followers_url":"https://api.github.com/users/emccode/followers","following_url":"https://api.github.com/users/emccode/following{/other_user}","gists_url":"https://api.github.com/users/emccode/gists{/gist_id}","starred_url":"https://api.github.com/users/emccode/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/emccode/subscriptions","organizations_url":"https://api.github.com/users/emccode/orgs","repos_url":"https://api.github.com/users/emccode/repos","events_url":"https://api.github.com/users/emccode/events{/privacy}","received_events_url":"https://api.github.com/users/emccode/received_events","type":"Organization","site_admin":false},"repo":{"id":46084622,"name":"libstorage","full_name":"emccode/libstorage","owner":{"login":"emccode","id":8659750,"avatar_url":"https://avatars.githubusercontent.com/u/8659750?v=3","gravatar_id":"","url":"https://api.github.com/users/emccode","html_url":"https://github.com/emccode","followers_url":"https://api.github.com/users/emccode/followers","following_url":"https://api.github.com/users/emccode/following{/other_user}","gists_url":"https://api.github.com/users/emccode/gists{/gist_id}","starred_url":"https://api.github.com/users/emccode/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/emccode/subscriptions","organizations_url":"https://api.github.com/users/emccode/orgs","repos_url":"https://api.github.com/users/emccode/repos","events_url":"https://api.github.com/users/emccode/events{/privacy}","received_events_url":"https://api.github.com/users/emccode/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/emccode/libstorage","description":"libStorage provides a vendor agnostic storage orchestration model, API, and reference client and server implementations.","fork":false,"url":"https://api.github.com/repos/emccode/libstorage","forks_url":"https://api.github.com/repos/emccode/libstorage/forks","keys_url":"https://api.github.com/repos/emccode/libstorage/keys{/key_id}","collaborators_url":"https://api.github.com/repos/emccode/libstorage/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/emccode/libstorage/teams","hooks_url":"https://api.github.com/repos/emccode/libstorage/hooks","issue_events_url":"https://api.github.com/repos/emccode/libstorage/issues/events{/number}","events_url":"https://api.github.com/repos/emccode/libstorage/events","assignees_url":"https://api.github.com/repos/emccode/libstorage/assignees{/user}","branches_url":"https://api.github.com/repos/emccode/libstorage/branches{/branch}","tags_url":"https://api.github.com/repos/emccode/libstorage/tags","blobs_url":"https://api.github.com/repos/emccode/libstorage/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/emccode/libstorage/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/emccode/libstorage/git/refs{/sha}","trees_url":"https://api.github.com/repos/emccode/libstorage/git/trees{/sha}","statuses_url":"https://api.github.com/repos/emccode/libstorage/statuses/{sha}","languages_url":"https://api.github.com/repos/emccode/libstorage/languages","stargazers_url":"https://api.github.com/repos/emccode/libstorage/stargazers","contributors_url":"https://api.github.com/repos/emccode/libstorage/contributors","subscribers_url":"https://api.github.com/repos/emccode/libstorage/subscribers","subscription_url":"https://api.github.com/repos/emccode/libstorage/subscription","commits_url":"https://api.github.com/repos/emccode/libstorage/commits{/sha}","git_commits_url":"https://api.github.com/repos/emccode/libstorage/git/commits{/sha}","comments_url":"https://api.github.com/repos/emccode/libstorage/comments{/number}","issue_comment_url":"https://api.github.com/repos/emccode/libstorage/issues/comments{/number}","contents_url":"https://api.github.com/repos/emccode/libstorage/contents/{+path}","compare_url":"https://api.github.com/repos/emccode/libstorage/compare/{base}...{head}","merges_url":"https://api.github.com/repos/emccode/libstorage/merges","archive_url":"https://api.github.com/repos/emccode/libstorage/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/emccode/libstorage/downloads","issues_url":"https://api.github.com/repos/emccode/libstorage/issues{/number}","pulls_url":"https://api.github.com/repos/emccode/libstorage/pulls{/number}","milestones_url":"https://api.github.com/repos/emccode/libstorage/milestones{/number}","notifications_url":"https://api.github.com/repos/emccode/libstorage/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/emccode/libstorage/labels{/name}","releases_url":"https://api.github.com/repos/emccode/libstorage/releases{/id}","deployments_url":"https://api.github.com/repos/emccode/libstorage/deployments","created_at":"2015-11-12T22:22:37Z","updated_at":"2016-04-15T20:35:04Z","pushed_at":"2016-04-18T21:19:06Z","git_url":"git://github.com/emccode/libstorage.git","ssh_url":"git@github.com:emccode/libstorage.git","clone_url":"https://github.com/emccode/libstorage.git","svn_url":"https://github.com/emccode/libstorage","homepage":"","size":717,"stargazers_count":5,"watchers_count":5,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":6,"mirror_url":null,"open_issues_count":3,"forks":6,"open_issues":3,"watchers":5,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/emccode/libstorage/pulls/25"},"html":{"href":"https://github.com/emccode/libstorage/pull/25"},"issue":{"href":"https://api.github.com/repos/emccode/libstorage/issues/25"},"comments":{"href":"https://api.github.com/repos/emccode/libstorage/issues/25/comments"},"review_comments":{"href":"https://api.github.com/repos/emccode/libstorage/pulls/25/comments"},"review_comment":{"href":"https://api.github.com/repos/emccode/libstorage/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/emccode/libstorage/pulls/25/commits"},"statuses":{"href":"https://api.github.com/repos/emccode/libstorage/statuses/6acbdbf417322c931020772a070e56ead8a0ada7"}}}}