4141#ifdef WIN32
4242#include <io.h>
4343#endif
44- #if ! defined(WIN32 )
44+ #if defined(__linux__ )
4545#include <limits.h>
4646#endif
4747#include <stdio.h>
4848#include <errno.h>
49+ #if defined(__linux__ )
50+ #include <sys/inotify.h>
51+ #endif
4952
5053struct dir_entry {
5154 lws_list_ptr next ; /* sorted by mtime */
@@ -73,6 +76,10 @@ struct vhd_deaddrop {
7376 int filelist_version ;
7477
7578 unsigned long long max_size ;
79+
80+ #if defined(__linux__ )
81+ int inotify_fd ;
82+ #endif
7683};
7784
7885struct pss_deaddrop {
@@ -81,7 +88,7 @@ struct pss_deaddrop {
8188 struct lws * wsi ;
8289 char result [LWS_PRE + LWS_RECOMMENDED_MIN_HEADER_SPACE ];
8390 char filename [256 ];
84- char user [32 ];
91+ char user [64 ];
8592 unsigned long long file_length ;
8693 lws_filefd_type fd ;
8794 int response_code ;
@@ -220,6 +227,9 @@ static int
220227file_upload_cb (void * data , const char * name , const char * filename ,
221228 char * buf , int _len , enum lws_spa_fileupload_states state )
222229{
230+ lwsl_warn ("%s: entered, state %d, pss->user: '%s'\n" , __func__ ,
231+ state , ((struct pss_deaddrop * )data )-> user );
232+
223233 struct pss_deaddrop * pss = (struct pss_deaddrop * )data ;
224234 char filename2 [256 ];
225235 size_t len = (size_t )_len ;
@@ -229,19 +239,19 @@ file_upload_cb(void *data, const char *name, const char *filename,
229239
230240 switch (state ) {
231241 case LWS_UFS_OPEN :
232- /* Require an authenticated user to upload */
242+ /* REQUIRE an authenticated user on the upload POST itself */
233243 if (!pss -> user [0 ]) {
234244 pss -> response_code = HTTP_STATUS_FORBIDDEN ;
235- lwsl_warn ("%s: unauthenticated upload forbidden\n" ,
236- __func__ );
245+ lwsl_wsi_warn (pss -> wsi , "%s: no authenticated user (pss %p)\n" , __func__ , pss );
237246 return -1 ;
238247 }
239248
240249 lws_urldecode (filename2 , filename , sizeof (filename2 ) - 1 );
241250 lws_filename_purify_inplace (filename2 );
242251 lws_filename_purify_inplace (pss -> user );
243252
244- /* New filename format: upload_dir/user_originalfilename~ */
253+ /* Server is authoritative: construct filename from authenticated
254+ * user and the base filename from the request. */
245255 lws_snprintf (pss -> filename , sizeof (pss -> filename ),
246256 "%s/%s_%s~" , pss -> vhd -> upload_dir ,
247257 pss -> user , filename2 );
@@ -338,17 +348,48 @@ callback_deaddrop(struct lws *wsi, enum lws_callback_reasons reason,
338348 uint8_t buf [LWS_PRE + LWS_RECOMMENDED_MIN_HEADER_SPACE ],
339349 * start = & buf [LWS_PRE ], * p = start ,
340350 * end = & buf [sizeof (buf ) - 1 ];
341- #if ! defined(WIN32 )
351+ #if defined(__linux__ )
342352 char path [512 ], resolved_path [PATH_MAX ];
343353#else
344354 char path [512 ];
345355#endif
346356 char fname [256 ], * wp ;
347357 const char * cp ;
348- int n , m , was ;
358+ int n , m , was , uri_len ;
359+ char * uri_ptr ;
360+ #if defined(__linux__ )
361+ char ev_buf [1024 ];
362+ #endif
349363
350364 switch (reason ) {
351365
366+ case LWS_CALLBACK_HTTP :
367+ {
368+ int meth ;
369+ // pss->user[0] = '\0';
370+
371+ m = lws_hdr_copy (wsi , pss -> user , sizeof (pss -> user ),
372+ WSI_TOKEN_HTTP_AUTHORIZATION );
373+
374+ if (m > 0 )
375+ lwsl_wsi_warn (wsi , "%s: upload auth user (pss %p): '%s'\n" ,
376+ __func__ , (void * )pss , pss -> user );
377+ else
378+ lwsl_wsi_warn (wsi , "%s: HTTP: no auth (%d)\n" , __func__ , m );
379+
380+
381+ meth = lws_http_get_uri_and_method (wsi , & uri_ptr , & uri_len );
382+ if (meth != LWSHUMETH_POST || !uri_ptr )
383+ break ;
384+ if (!strstr (uri_ptr , "/upload/" ))
385+ break ;
386+
387+ pss -> vhd = vhd ;
388+ pss -> wsi = wsi ;
389+
390+ break ;
391+ }
392+
352393 case LWS_CALLBACK_PROTOCOL_INIT : /* per vhost */
353394 lws_protocol_vh_priv_zalloc (lws_get_vhost (wsi ),
354395 lws_get_protocol (wsi ),
@@ -359,6 +400,9 @@ callback_deaddrop(struct lws *wsi, enum lws_callback_reasons reason,
359400 lws_get_protocol (wsi ));
360401 if (!vhd )
361402 return 0 ;
403+ #if defined(__linux__ )
404+ vhd -> inotify_fd = -1 ;
405+ #endif
362406
363407 vhd -> context = lws_get_context (wsi );
364408 vhd -> vh = lws_get_vhost (wsi );
@@ -372,6 +416,27 @@ callback_deaddrop(struct lws *wsi, enum lws_callback_reasons reason,
372416 return 0 ;
373417 }
374418
419+ #if defined(__linux__ )
420+ /*
421+ * Set up inotify on the upload dir and adopt it into the
422+ * lws event loop on our vhost, so we can be told about
423+ * external changes to the dir contents
424+ */
425+ vhd -> inotify_fd = inotify_init1 (IN_NONBLOCK );
426+ if (vhd -> inotify_fd >= 0 ) {
427+ if (inotify_add_watch (vhd -> inotify_fd , vhd -> upload_dir ,
428+ IN_CLOSE_WRITE | IN_DELETE |
429+ IN_MOVED_FROM | IN_MOVED_TO ) >= 0 )
430+ lws_adopt_descriptor_vhost (vhd -> vh ,
431+ LWS_ADOPT_RAW_FILE_DESC ,
432+ (lws_sock_file_fd_type )vhd -> inotify_fd ,
433+ vhd -> protocol -> name , NULL );
434+ else
435+ lwsl_err ("%s: inotify_add_watch failed\n" ,
436+ __func__ );
437+ }
438+ #endif
439+
375440 scan_upload_dir (vhd );
376441
377442 lwsl_notice (" deaddrop: vh %s, upload dir %s, max size %llu\n" ,
@@ -380,8 +445,22 @@ callback_deaddrop(struct lws *wsi, enum lws_callback_reasons reason,
380445 break ;
381446
382447 case LWS_CALLBACK_PROTOCOL_DESTROY :
383- if (vhd )
448+ if (vhd ) {
384449 lwsac_free (& vhd -> lwsac_head );
450+ #if defined(__linux__ )
451+ if (vhd -> inotify_fd != -1 )
452+ close (vhd -> inotify_fd );
453+ #endif
454+ }
455+ break ;
456+
457+ case LWS_CALLBACK_RAW_RX_FILE :
458+ #if defined(__linux__ )
459+ /* inotify has told us something changed in the upload dir */
460+ n = (int )read (lws_get_socket_fd (wsi ), ev_buf , sizeof (ev_buf ));
461+ lwsl_info ("%s: inotify event (%d), rescanning upload dir\n" , __func__ , n );
462+ scan_upload_dir (vhd );
463+ #endif
385464 break ;
386465
387466 /* WS-related */
@@ -395,11 +474,12 @@ callback_deaddrop(struct lws *wsi, enum lws_callback_reasons reason,
395474
396475 m = lws_hdr_copy (wsi , pss -> user , sizeof (pss -> user ),
397476 WSI_TOKEN_HTTP_AUTHORIZATION );
477+
398478 if (m > 0 )
399- lwsl_info ( "%s: basic auth user: %s \n" ,
400- __func__ , pss -> user );
479+ lwsl_wsi_warn ( wsi , "%s: upload auth user (pss %p): '%s' \n" ,
480+ __func__ , ( void * ) pss , pss -> user );
401481 else
402- pss -> user [ 0 ] = '\0' ;
482+ lwsl_wsi_warn ( wsi , "%s: HTTP: no auth (%d)\n" , __func__ , m ) ;
403483
404484 start_sending_dir (pss );
405485 lws_callback_on_writable (wsi );
@@ -455,7 +535,7 @@ callback_deaddrop(struct lws *wsi, enum lws_callback_reasons reason,
455535 lws_snprintf (path , sizeof (path ), "%s/%s" , vhd -> upload_dir ,
456536 fname );
457537
458- #if ! defined(WIN32 )
538+ #if defined(__linux__ )
459539 if (!realpath (path , resolved_path )) {
460540 lwsl_warn ("%s: delete: realpath failed %s\n" , __func__ , path );
461541 break ;
@@ -492,6 +572,13 @@ callback_deaddrop(struct lws *wsi, enum lws_callback_reasons reason,
492572
493573 m = 5 ;
494574 while (m -- && pss -> dire ) {
575+ int is_yours = !strcmp (pss -> user , pss -> dire -> user ) &&
576+ pss -> user [0 ];
577+
578+ lwsl_warn ("[Deaddrop Debug] File: '%s', Owner: '%s', WS User: '%s', Is Yours: %d\n" ,
579+ (const char * )& pss -> dire [1 ], pss -> dire -> user ,
580+ pss -> user , is_yours );
581+
495582 p += lws_snprintf ((char * )p , lws_ptr_diff_size_t (end , p ),
496583 "%c{\"name\":\"%s\", "
497584 "\"size\":%llu,"
@@ -500,9 +587,7 @@ callback_deaddrop(struct lws *wsi, enum lws_callback_reasons reason,
500587 pss -> first ? ' ' : ',' ,
501588 (const char * )& pss -> dire [1 ],
502589 pss -> dire -> size ,
503- (unsigned long long )pss -> dire -> mtime ,
504- !strcmp (pss -> user , pss -> dire -> user ) &&
505- pss -> user [0 ]);
590+ (unsigned long long )pss -> dire -> mtime , is_yours );
506591 pss -> first = 0 ;
507592 pss -> dire = lp_to_dir_entry (pss -> dire -> next , next );
508593 }
@@ -546,8 +631,6 @@ callback_deaddrop(struct lws *wsi, enum lws_callback_reasons reason,
546631
547632 /* create the POST argument parser if not already existing */
548633 if (!pss -> spa ) {
549- pss -> vhd = vhd ;
550- pss -> wsi = wsi ;
551634 pss -> spa = lws_spa_create (wsi , param_names ,
552635 LWS_ARRAY_SIZE (param_names ),
553636 1024 , file_upload_cb , pss );
@@ -556,15 +639,7 @@ callback_deaddrop(struct lws *wsi, enum lws_callback_reasons reason,
556639
557640 pss -> filename [0 ] = '\0' ;
558641 pss -> file_length = 0 ;
559- /* catchall */
560642 pss -> response_code = HTTP_STATUS_SERVICE_UNAVAILABLE ;
561-
562- m = lws_hdr_copy (wsi , pss -> user , sizeof (pss -> user ),
563- WSI_TOKEN_HTTP_AUTHORIZATION );
564- if (m > 0 )
565- lwsl_info ("basic auth user: %s\n" , pss -> user );
566- else
567- pss -> user [0 ] = '\0' ;
568643 }
569644
570645 /* let it parse the POST data */
0 commit comments