@@ -62,6 +62,12 @@ public function read($default = null, callable $fn = null)
62
62
*/
63
63
public function readHidden ($ default = null , callable $ fn = null )
64
64
{
65
+ // @codeCoverageIgnoreStart
66
+ if ('\\' === \DIRECTORY_SEPARATOR ) {
67
+ return $ this ->readHiddenWinOS ($ default , $ fn );
68
+ }
69
+ // @codeCoverageIgnoreEnd
70
+
65
71
\shell_exec ('stty -echo ' );
66
72
$ in = $ this ->read ($ default , $ fn );
67
73
\shell_exec ('stty echo ' );
@@ -70,4 +76,31 @@ public function readHidden($default = null, callable $fn = null)
70
76
71
77
return $ in ;
72
78
}
79
+
80
+ /**
81
+ * Read a line from configured stream (or terminal) but don't echo it back.
82
+ *
83
+ * @codeCoverageIgnore
84
+ *
85
+ * @param callable|null $fn The validator/sanitizer callback.
86
+ *
87
+ * @return mixed
88
+ */
89
+ private function readHiddenWinOS ($ default = null , callable $ fn = null )
90
+ {
91
+ $ cmd = 'powershell -Command ' . \implode ('; ' , \array_filter ([
92
+ '$pword = Read-Host -AsSecureString ' ,
93
+ '$pword = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($pword) ' ,
94
+ '$pword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($pword) ' ,
95
+ 'echo $pword ' ,
96
+ ]));
97
+
98
+ $ in = \rtrim (\shell_exec ($ cmd ), "\r\n" );
99
+
100
+ if ('' === $ in && null !== $ default ) {
101
+ return $ default ;
102
+ }
103
+
104
+ return $ fn ? $ fn ($ in ) : $ in ;
105
+ }
73
106
}
0 commit comments