Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Add method dispatching and validate upload-pack. Port is created but …

…not used yet
  • Loading branch information...
commit 8db0f4303cbaad81dd38ffb46ae5245f4641674f 1 parent 471b4a7
Andrew Thompson authored February 07, 2011

Showing 1 changed file with 72 additions and 12 deletions. Show diff stats Hide diff stats

  1. 84  elibs/git_client.erl
84  elibs/git_client.erl
@@ -2,7 +2,8 @@
2 2
 -behaviour(gen_server).
3 3
 
4 4
 -record(state, {
5  
-    socket
  5
+    socket,
  6
+    port
6 7
   }).
7 8
 
8 9
 %% ------------------------------------------------------------------
@@ -38,17 +39,17 @@ handle_call(_Request, _From, State) ->
38 39
 handle_cast(_Msg, State) ->
39 40
   {noreply, State}.
40 41
 
41  
-handle_info({_SocketType, Socket, Packet}, #state{socket = Socket} = State) ->
42  
-  case Packet of
43  
-    <<_:4/binary, "git", _:1/binary, Rest/binary>> ->
44  
-      [Command, Args] = binary:split(Rest, <<" ">>),
45  
-      io:format("git command ~p; args ~p~n", [Command, Args]),
46  
-      {noreply, State};
47  
-    _ ->
48  
-      gen_tcp:send(Socket, "Invalid method declaration. Upgrade to the latest git.\n"),
49  
-      gen_tcp:close(Socket),
50  
-      {stop, normal, State}
51  
-  end;
  42
+
  43
+%handle_info({_SocketTyoe, Socket
  44
+handle_info({_SocketType, Socket, <<_Length:4/binary, "git", _:1/binary, Rest/binary>>}, #state{socket = Socket} = State) ->
  45
+  [Method, Other] = binary:split(Rest, <<" ">>),
  46
+  [Args, <<"host=", Host/binary>>, <<>>] = binary:split(Other, <<0>>, [global]),
  47
+  io:format("git method ~p; args ~p host ~p~n", [Method, Args, Host]),
  48
+  dispatch_method(Method, Host, Args, State);
  49
+handle_info({_SocketType, Socket, _Packet}, #state{socket = Socket} = State) ->
  50
+  gen_tcp:send(Socket, "Invalid method declaration. Upgrade to the latest git.\n"),
  51
+  gen_tcp:close(Socket),
  52
+  {stop, normal, State};
52 53
 handle_info(_Info, State) ->
53 54
   io:format("unhandled info ~p~n", [_Info]),
54 55
   {noreply, State}.
@@ -63,3 +64,62 @@ code_change(_OldVsn, State, _Extra) ->
63 64
 %% Internal Function Definitions
64 65
 %% ------------------------------------------------------------------
65 66
 
  67
+dispatch_method(<<"upload-pack">>, Host, Path, #state{socket = Sock} = State) ->
  68
+  try conf:convert_path(binary_to_list(Host), binary_to_list(Path)) of
  69
+    {ok, FullPath} ->
  70
+      case repo_existance(FullPath) of
  71
+        false ->
  72
+          throw(nomatch);
  73
+        RealPath ->
  74
+          GitDaemonExportOkFilePath = filename:join([RealPath, "git-daemon-export-ok"]),
  75
+          case filelib:is_regular(GitDaemonExportOkFilePath) of
  76
+            true ->
  77
+              %% all validated, yay
  78
+              io:format("ready to do an upload-pack~n"),
  79
+              Port = make_port(Sock, "upload-pack", Host, Path, RealPath),
  80
+              {noreply, State#state{port = Port}};
  81
+            false ->
  82
+              throw({noexport, RealPath})
  83
+          end
  84
+      end;
  85
+    {error, nomatch} ->
  86
+      throw(nomatch)
  87
+  catch
  88
+    throw:nomatch ->
  89
+      error_logger:info_msg("no repo match: ~p~n", [Path]),
  90
+      gen_tcp:send(Sock, "003b\n*********'\n\nNo matching repositories found.\n\n*********"),
  91
+      gen_tcp:close(Sock),
  92
+      {stop, normal, State};
  93
+    throw:{noexport, RealPath} ->
  94
+      error_logger:info_msg("permission denied to repo: ~p~n", [RealPath]),
  95
+      gen_tcp:send(Sock, "0048\n*********'\n\nPermission denied. Repository is not public.\n\n*********"),
  96
+      gen_tcp:close(Sock),
  97
+      {stop, normal, State}
  98
+  end;
  99
+dispatch_method(<<"receive-pack">>, _Host, _Args, #state{socket = Sock} = State) ->
  100
+  %% TODO make this message include the actual repo
  101
+  gen_tcp:send(Sock, "006d\n*********'\n\nYou can't push to git://github.com/user/repo.git\nUse git@github.com:user/repo.git\n\n*********"),
  102
+  gen_tcp:close(Sock),
  103
+  {stop, normal, State};
  104
+dispatch_method(_Method, _Host, _Args, #state{socket = Sock} = State) ->
  105
+  gen_tcp:send(Sock, "Invalid method declaration. Upgrade to the latest git.\n"),
  106
+  gen_tcp:close(Sock),
  107
+  {stop, normal, State}.
  108
+
  109
+repo_existance(Path) ->
  110
+  case filelib:is_dir(Path) of
  111
+    true ->
  112
+      Path;
  113
+    _ ->
  114
+      case filelib:is_dir(Path ++ ".git") of
  115
+        true ->
  116
+          Path ++ ".git";
  117
+        _ ->
  118
+          false
  119
+      end
  120
+  end.
  121
+
  122
+make_port(Sock, Method, _Host, _Path, FullPath) ->
  123
+  Command = lists:flatten(["git ", Method, " ", FullPath]),
  124
+  open_port({spawn, Command}, [binary]).
  125
+

0 notes on commit 8db0f43

Please sign in to comment.
Something went wrong with that request. Please try again.