2
2
* liveprops.c: mod_dav_svn live property provider functions for Subversion
4
4
* ====================================================================
5
* Copyright (c) 2000-2008 CollabNet. All rights reserved.
7
* This software is licensed as described in the file COPYING, which
8
* you should have received as part of this distribution. The terms
9
* are also available at http://subversion.tigris.org/license-1.html.
10
* If newer versions of this license are posted there, you may use a
11
* newer version instead, at your option.
13
* This software consists of voluntary contributions made by many
14
* individuals. For exact contribution history, see the revision
15
* history and logs, available at http://subversion.tigris.org/.
5
* Licensed to the Apache Software Foundation (ASF) under one
6
* or more contributor license agreements. See the NOTICE file
7
* distributed with this work for additional information
8
* regarding copyright ownership. The ASF licenses this file
9
* to you under the Apache License, Version 2.0 (the
10
* "License"); you may not use this file except in compliance
11
* with the License. You may obtain a copy of the License at
13
* http://www.apache.org/licenses/LICENSE-2.0
15
* Unless required by applicable law or agreed to in writing,
16
* software distributed under the License is distributed on an
17
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18
* KIND, either express or implied. See the License for the
19
* specific language governing permissions and limitations
16
21
* ====================================================================
265
271
static dav_prop_insert
266
insert_prop(const dav_resource *resource,
268
dav_prop_insert what,
269
apr_text_header *phdr)
272
insert_prop_internal(const dav_resource *resource,
274
dav_prop_insert what,
275
apr_text_header *phdr,
276
apr_pool_t *scratch_pool,
277
apr_pool_t *result_pool)
271
279
const char *value = NULL;
273
apr_pool_t *response_pool = resource->pool;
274
apr_pool_t *p = resource->info->pool;
275
281
const dav_liveprop_spec *info;
277
283
svn_error_t *serr;
316
322
/* ### for now, our global VCC has no such property. */
317
323
if (resource->type == DAV_RESOURCE_TYPE_PRIVATE
318
&& resource->info->restype == DAV_SVN_RESTYPE_VCC)
324
&& (resource->info->restype == DAV_SVN_RESTYPE_VCC
325
|| resource->info->restype == DAV_SVN_RESTYPE_ME))
320
327
return DAV_PROP_INSERT_NOTSUPP;
334
341
if (0 != get_last_modified_time(&datestring, &timeval,
335
resource, format, p))
342
resource, format, scratch_pool))
337
344
return DAV_PROP_INSERT_NOTDEF;
340
value = apr_xml_quote_string(p, datestring, 1);
347
value = apr_xml_quote_string(scratch_pool, datestring, 1);
349
356
/* ### for now, our global VCC has no such property. */
350
357
if (resource->type == DAV_RESOURCE_TYPE_PRIVATE
351
&& resource->info->restype == DAV_SVN_RESTYPE_VCC)
358
&& (resource->info->restype == DAV_SVN_RESTYPE_VCC
359
|| resource->info->restype == DAV_SVN_RESTYPE_ME))
353
361
return DAV_PROP_INSERT_NOTSUPP;
366
374
root object might be an ID root -or- a revision root. */
367
375
serr = svn_fs_node_created_rev(&committed_rev,
368
376
resource->info->root.root,
369
resource->info->repos_path, p);
377
resource->info->repos_path,
370
379
if (serr != NULL)
372
/* ### what to do? */
381
ap_log_rerror(APLOG_MARK, APLOG_ERR, serr->apr_err,
383
"Can't get created-rev of '%s': "
385
resource->info->repos_path,
373
387
svn_error_clear(serr);
374
388
value = "###error###";
396
415
if (last_author == NULL)
397
416
return DAV_PROP_INSERT_NOTDEF;
399
value = apr_xml_quote_string(p, last_author->data, 1);
418
value = apr_xml_quote_string(scratch_pool, last_author->data, 1);
414
433
return DAV_PROP_INSERT_NOTSUPP;
416
435
serr = svn_fs_file_length(&len, resource->info->root.root,
417
resource->info->repos_path, p);
436
resource->info->repos_path, scratch_pool);
418
437
if (serr != NULL)
420
439
svn_error_clear(serr);
438
457
return DAV_PROP_INSERT_NOTSUPP;
440
459
if (resource->type == DAV_RESOURCE_TYPE_PRIVATE
441
&& resource->info->restype == DAV_SVN_RESTYPE_VCC)
460
&& (resource->info->restype == DAV_SVN_RESTYPE_VCC
461
|| resource->info->restype == DAV_SVN_RESTYPE_ME))
443
463
return DAV_PROP_INSERT_NOTSUPP;
455
475
if ((serr = svn_fs_node_prop(&pval, resource->info->root.root,
456
476
resource->info->repos_path,
457
SVN_PROP_MIME_TYPE, p)))
477
SVN_PROP_MIME_TYPE, scratch_pool)))
459
479
svn_error_clear(serr);
469
489
mime_type = "text/plain";
471
if ((serr = svn_mime_type_validate(mime_type, p)))
491
if ((serr = svn_mime_type_validate(mime_type, scratch_pool)))
473
493
/* Probably serr->apr == SVN_ERR_BAD_MIME_TYPE, but
474
494
there's no point even checking. No matter what the
486
506
case DAV_PROPID_getetag:
487
507
if (resource->type == DAV_RESOURCE_TYPE_PRIVATE
488
&& resource->info->restype == DAV_SVN_RESTYPE_VCC)
508
&& (resource->info->restype == DAV_SVN_RESTYPE_VCC
509
|| resource->info->restype == DAV_SVN_RESTYPE_ME))
490
511
return DAV_PROP_INSERT_NOTSUPP;
493
value = dav_svn__getetag(resource, p);
514
value = dav_svn__getetag(resource, scratch_pool);
496
517
case DAV_PROPID_auto_version:
510
531
return DAV_PROP_INSERT_NOTSUPP;
511
532
value = dav_svn__build_uri(resource->info->repos, DAV_SVN__BUILD_URI_BC,
512
533
resource->info->root.rev, NULL,
513
1 /* add_href */, p);
534
1 /* add_href */, scratch_pool);
516
537
case DAV_PROPID_checked_in:
517
538
/* only defined for VCRs (in the public space and in a BC space) */
518
539
/* ### note that a VCC (a special VCR) is defined as _PRIVATE for now */
519
540
if (resource->type == DAV_RESOURCE_TYPE_PRIVATE
520
&& resource->info->restype == DAV_SVN_RESTYPE_VCC)
541
&& (resource->info->restype == DAV_SVN_RESTYPE_VCC
542
|| resource->info->restype == DAV_SVN_RESTYPE_ME))
522
544
svn_revnum_t revnum;
524
serr = svn_fs_youngest_rev(&revnum, resource->info->repos->fs, p);
546
serr = svn_fs_youngest_rev(&revnum, resource->info->repos->fs,
525
548
if (serr != NULL)
527
/* ### what to do? */
550
ap_log_rerror(APLOG_MARK, APLOG_ERR, serr->apr_err,
552
"Can't get youngest revision in '%s': "
554
svn_fs_path(resource->info->repos->fs,
528
557
svn_error_clear(serr);
529
558
value = "###error###";
532
561
s = dav_svn__build_uri(resource->info->repos,
533
562
DAV_SVN__BUILD_URI_BASELINE,
534
revnum, NULL, 0 /* add_href */, p);
535
value = apr_psprintf(p, "<D:href>%s</D:href>",
536
apr_xml_quote_string(p, s, 1));
563
revnum, NULL, 0 /* add_href */, scratch_pool);
564
value = apr_psprintf(scratch_pool, "<D:href>%s</D:href>",
565
apr_xml_quote_string(scratch_pool, s, 1));
538
567
else if (resource->type != DAV_RESOURCE_TYPE_REGULAR)
545
574
svn_revnum_t rev_to_use =
546
575
dav_svn__get_safe_cr(resource->info->root.root,
547
resource->info->repos_path, p);
576
resource->info->repos_path, scratch_pool);
549
578
s = dav_svn__build_uri(resource->info->repos,
550
579
DAV_SVN__BUILD_URI_VERSION,
551
580
rev_to_use, resource->info->repos_path,
552
0 /* add_href */, p);
553
value = apr_psprintf(p, "<D:href>%s</D:href>",
554
apr_xml_quote_string(p, s, 1));
581
0 /* add_href */, scratch_pool);
582
value = apr_psprintf(scratch_pool, "<D:href>%s</D:href>",
583
apr_xml_quote_string(scratch_pool, s, 1));
563
592
return DAV_PROP_INSERT_NOTSUPP;
564
593
value = dav_svn__build_uri(resource->info->repos, DAV_SVN__BUILD_URI_VCC,
565
594
SVN_IGNORED_REVNUM, NULL,
566
1 /* add_href */, p);
595
1 /* add_href */, scratch_pool);
569
598
case DAV_PROPID_version_name:
574
603
return DAV_PROP_INSERT_NOTSUPP;
576
605
if (resource->type == DAV_RESOURCE_TYPE_PRIVATE
577
&& resource->info->restype == DAV_SVN_RESTYPE_VCC)
606
&& (resource->info->restype == DAV_SVN_RESTYPE_VCC
607
|| resource->info->restype == DAV_SVN_RESTYPE_ME))
579
609
return DAV_PROP_INSERT_NOTSUPP;
582
612
if (resource->baselined)
584
614
/* just the revision number for baselines */
585
value = apr_psprintf(p, "%ld",
615
value = apr_psprintf(scratch_pool, "%ld",
586
616
resource->info->root.rev);
593
623
root object might be an ID root -or- a revision root. */
594
624
serr = svn_fs_node_created_rev(&committed_rev,
595
625
resource->info->root.root,
596
resource->info->repos_path, p);
626
resource->info->repos_path,
597
628
if (serr != NULL)
599
/* ### what to do? */
630
ap_log_rerror(APLOG_MARK, APLOG_ERR, serr->apr_err,
632
"Can't get created-rev of '%s': "
634
resource->info->repos_path,
600
636
svn_error_clear(serr);
601
637
value = "###error###";
605
641
/* Convert the revision into a quoted string */
606
s = apr_psprintf(p, "%ld", committed_rev);
607
value = apr_xml_quote_string(p, s, 1);
642
s = apr_psprintf(scratch_pool, "%ld", committed_rev);
643
value = apr_xml_quote_string(scratch_pool, s, 1);
618
654
/* drop the leading slash, so it is relative */
619
655
s = resource->info->repos_path + 1;
620
value = apr_xml_quote_string(p, s, 1);
656
value = apr_xml_quote_string(scratch_pool, s, 1);
623
659
case SVN_PROPID_md5_checksum:
627
663
|| resource->type == DAV_RESOURCE_TYPE_WORKING
628
664
|| resource->type == DAV_RESOURCE_TYPE_VERSION))
666
svn_node_kind_t kind;
630
667
svn_checksum_t *checksum;
632
serr = svn_fs_file_checksum(&checksum, svn_checksum_md5,
633
resource->info->root.root,
634
resource->info->repos_path, TRUE, p);
669
serr = svn_fs_check_path(&kind, resource->info->root.root,
670
resource->info->repos_path, scratch_pool);
671
if (!serr && kind == svn_node_file)
672
serr = svn_fs_file_checksum(&checksum, svn_checksum_md5,
673
resource->info->root.root,
674
resource->info->repos_path, TRUE,
635
676
if (serr != NULL)
637
/* ### what to do? */
678
ap_log_rerror(APLOG_MARK, APLOG_ERR, serr->apr_err,
680
"Can't fetch or compute MD5 checksum of '%s': "
682
resource->info->repos_path,
638
684
svn_error_clear(serr);
639
685
value = "###error###";
643
value = svn_checksum_to_cstring(checksum, p);
689
if (kind != svn_node_file)
690
return DAV_PROP_INSERT_NOTSUPP;
692
value = svn_checksum_to_cstring(checksum, scratch_pool);
646
695
return DAV_PROP_INSERT_NOTSUPP;
653
702
case SVN_PROPID_repository_uuid:
654
serr = svn_fs_get_uuid(resource->info->repos->fs, &value, p);
703
serr = svn_fs_get_uuid(resource->info->repos->fs, &value, scratch_pool);
655
704
if (serr != NULL)
657
/* ### what to do? */
706
ap_log_rerror(APLOG_MARK, APLOG_ERR, serr->apr_err,
708
"Can't fetch UUID of '%s': "
710
svn_fs_path(resource->info->repos->fs, scratch_pool),
658
712
svn_error_clear(serr);
659
713
value = "###error###";
672
726
serr = svn_fs_node_proplist(&proplist,
673
727
resource->info->root.root,
674
resource->info->repos_path, p);
728
resource->info->repos_path, scratch_pool);
675
729
if (serr != NULL)
677
/* ### what to do? */
731
ap_log_rerror(APLOG_MARK, APLOG_ERR, serr->apr_err,
733
"Can't fetch proplist of '%s': "
735
resource->info->repos_path,
678
737
svn_error_clear(serr);
679
738
value = "###error###";
683
742
propcount = apr_hash_count(proplist);
684
value = apr_psprintf(p, "%u", propcount);
743
value = apr_psprintf(scratch_pool, "%u", propcount);
700
759
if (what == DAV_PROP_INSERT_NAME
701
760
|| (what == DAV_PROP_INSERT_VALUE && *value == '\0')) {
702
s = apr_psprintf(response_pool, "<lp%d:%s/>" DEBUG_CR, global_ns,
761
s = apr_psprintf(result_pool, "<lp%d:%s/>" DEBUG_CR, global_ns,
705
764
else if (what == DAV_PROP_INSERT_VALUE) {
706
s = apr_psprintf(response_pool, "<lp%d:%s>%s</lp%d:%s>" DEBUG_CR,
765
s = apr_psprintf(result_pool, "<lp%d:%s>%s</lp%d:%s>" DEBUG_CR,
707
766
global_ns, info->name, value, global_ns, info->name);
710
769
/* assert: what == DAV_PROP_INSERT_SUPPORTED */
711
s = apr_psprintf(response_pool,
770
s = apr_psprintf(result_pool,
712
771
"<D:supported-live-property D:name=\"%s\" "
713
772
"D:namespace=\"%s\"/>" DEBUG_CR,
714
773
info->name, namespace_uris[info->ns]);
716
apr_text_append(response_pool, phdr, s);
775
apr_text_append(result_pool, phdr, s);
718
777
/* we inserted whatever was asked for */
781
static dav_prop_insert
782
insert_prop(const dav_resource *resource,
784
dav_prop_insert what,
785
apr_text_header *phdr)
787
apr_pool_t *result_pool = resource->pool;
788
apr_pool_t *scratch_pool;
791
/* Create subpool and destroy on return, because mod_dav doesn't provide
792
scratch pool for insert_prop() callback. */
793
scratch_pool = svn_pool_create(result_pool);
795
rv = insert_prop_internal(resource, propid, what, phdr,
796
scratch_pool, result_pool);
798
svn_pool_destroy(scratch_pool);
724
803
is_writable(const dav_resource *resource, int propid)
851
pool = resource->info->pool;
852
subpool = svn_pool_create(pool);
853
resource->info->pool = subpool;
929
iterpool = svn_pool_create(resource->pool);
855
930
for (spec = props; spec->name != NULL; ++spec)
857
svn_pool_clear(subpool);
858
(void) insert_prop(resource, spec->propid, what, phdr);
932
svn_pool_clear(iterpool);
933
(void) insert_prop_internal(resource, spec->propid, what, phdr,
934
iterpool, resource->pool);
861
resource->info->pool = pool;
862
svn_pool_destroy(subpool);
936
svn_pool_destroy(iterpool);
864
938
/* ### we know the others aren't defined as liveprops */